1
#include "FileExplorer.h"
3
#include <wx/filename.h>
4
#include <wx/aui/aui.h>
9
#include <wx/imaglist.h>
11
#include <cbproject.h>
12
#include <configmanager.h>
13
#include <projectmanager.h>
20
#include "se_globals.h"
21
#include "CommitBrowser.h"
23
#include <wx/arrimpl.cpp> // this is a magic incantation which must be done!
24
WX_DEFINE_OBJARRAY(VCSstatearray);
26
int ID_UPDATETIMER=wxNewId();
27
int ID_FILETREE=wxNewId();
28
int ID_FILELOC=wxNewId();
29
int ID_FILEWILD=wxNewId();
30
int ID_SETLOC=wxNewId();
31
int ID_VCSCONTROL=wxNewId();
32
int ID_VCSTYPE=wxNewId();
33
int ID_VCSCHANGESCHECK = wxNewId();
35
int ID_OPENINED=wxNewId();
36
int ID_FILENEWFILE=wxNewId();
37
int ID_FILENEWFOLDER=wxNewId();
38
int ID_FILEMAKEFAV=wxNewId();
39
int ID_FILECOPY=wxNewId();
40
int ID_FILEDUP=wxNewId();
41
int ID_FILEMOVE=wxNewId();
42
int ID_FILEDELETE=wxNewId();
43
int ID_FILERENAME=wxNewId();
44
int ID_FILEEXPANDALL=wxNewId();
45
int ID_FILECOLLAPSEALL=wxNewId();
46
int ID_FILESETTINGS=wxNewId();
47
int ID_FILESHOWHIDDEN=wxNewId();
48
int ID_FILEPARSECVS=wxNewId();
49
int ID_FILEPARSESVN=wxNewId();
50
int ID_FILEPARSEHG=wxNewId();
51
int ID_FILEPARSEBZR=wxNewId();
52
int ID_FILEPARSEGIT=wxNewId();
53
int ID_FILE_UPBUTTON=wxNewId();
54
int ID_FILEREFRESH=wxNewId();
55
int ID_FILEADDTOPROJECT=wxNewId();
57
int ID_FILEDIFF=wxNewId();
58
// 10 additional ID's reserved for FILE DIFF items
59
int ID_FILEDIFF1=wxNewId();
60
int ID_FILEDIFF2=wxNewId();
61
int ID_FILEDIFF3=wxNewId();
62
int ID_FILEDIFF4=wxNewId();
63
int ID_FILEDIFF5=wxNewId();
64
int ID_FILEDIFF6=wxNewId();
65
int ID_FILEDIFF7=wxNewId();
66
int ID_FILEDIFF8=wxNewId();
67
int ID_FILEDIFF9=wxNewId();
68
int ID_FILEDIFF10=wxNewId();
75
void Add(const wxTreeItemId &ti)
77
for(std::list<wxTreeItemId>::iterator it=qdata.begin();it!=qdata.end();it++)
87
bool Pop(wxTreeItemId &ti)
100
std::list<wxTreeItemId> qdata;
104
class DirTraverseFind : public wxDirTraverser {
106
DirTraverseFind(const wxString& wildcard) : m_files(), m_wildcard(wildcard) { }
107
virtual wxDirTraverseResult OnFile(const wxString& filename)
109
if(WildCardListMatch(m_wildcard,filename,true))
110
m_files.Add(filename);
111
return wxDIR_CONTINUE;
113
virtual wxDirTraverseResult OnDir(const wxString& dirname)
115
if(WildCardListMatch(m_wildcard,dirname,true))
116
m_files.Add(dirname);
117
return wxDIR_CONTINUE;
119
wxArrayString& GetMatches() {return m_files;}
121
wxArrayString m_files;
126
class FEDataObject:public wxDataObjectComposite
129
FEDataObject():wxDataObjectComposite()
131
m_file=new wxFileDataObject;
134
wxFileDataObject *m_file;
139
class wxFEDropTarget: public wxDropTarget
142
wxFEDropTarget(FileExplorer *fe):wxDropTarget()
145
m_data_object=new FEDataObject();
146
SetDataObject(m_data_object);
148
virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
151
if(m_data_object->GetReceivedFormat().GetType()==wxDF_FILENAME )
153
wxArrayString as=m_data_object->m_file->GetFilenames();
154
wxTreeCtrl *tree=m_fe->m_Tree;
156
wxTreeItemId id=tree->HitTest(wxPoint(x,y),flags);
159
if(tree->GetItemImage(id)!=fvsFolder)
161
if(!(flags&(wxTREE_HITTEST_ONITEMICON|wxTREE_HITTEST_ONITEMLABEL)))
165
m_fe->CopyFiles(m_fe->GetFullPath(id),as);
170
m_fe->MoveFiles(m_fe->GetFullPath(id),as);
175
// if(sizeof(wxFileDataObject)!=m_data_object->GetDataSize(wxDF_FILENAME))
177
// wxMessageBox(wxString::Format(_("Drop files %i,%i"),sizeof(wxFileDataObject),m_data_object->GetDataSize(wxDF_FILENAME)));
178
// return wxDragCancel;
182
virtual bool OnDrop(wxCoord /*x*/, wxCoord /*y*/, int /*tab*/, wxWindow */*wnd*/)
186
virtual wxDragResult OnDragOver(wxCoord /*x*/, wxCoord /*y*/, wxDragResult def)
191
FEDataObject *m_data_object;
197
BEGIN_EVENT_TABLE(FileTreeCtrl, wxTreeCtrl)
198
// EVT_TREE_ITEM_ACTIVATED(ID_FILETREE, FileTreeCtrl::OnActivate) //double click -
199
EVT_KEY_DOWN(FileTreeCtrl::OnKeyDown)
202
IMPLEMENT_DYNAMIC_CLASS(FileTreeCtrl, wxTreeCtrl)
204
FileTreeCtrl::FileTreeCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos,
205
const wxSize& size, long style,
206
const wxValidator& validator,
207
const wxString& name)
208
: wxTreeCtrl(parent,id,pos,size,style,validator,name) {}
210
FileTreeCtrl::FileTreeCtrl() { }
212
FileTreeCtrl::FileTreeCtrl(wxWindow *parent): wxTreeCtrl(parent) {}
214
FileTreeCtrl::~FileTreeCtrl()
218
void FileTreeCtrl::OnKeyDown(wxKeyEvent &event)
220
if(event.GetKeyCode()==WXK_DELETE)
221
::wxPostEvent(GetParent(),event);
226
int FileTreeCtrl::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2)
228
if((GetItemImage(item1)==fvsFolder)>(GetItemImage(item2)==fvsFolder))
230
if((GetItemImage(item1)==fvsFolder)<(GetItemImage(item2)==fvsFolder))
232
if((GetItemImage(item1)==fvsVcNonControlled)<(GetItemImage(item2)==fvsVcNonControlled))
234
if((GetItemImage(item1)==fvsVcNonControlled)<(GetItemImage(item2)==fvsVcNonControlled))
236
return (GetItemText(item1).CmpNoCase(GetItemText(item2)));
239
BEGIN_EVENT_TABLE(FileExplorer, wxPanel)
240
EVT_TIMER(ID_UPDATETIMER, FileExplorer::OnTimerCheckUpdates)
241
EVT_MONITOR_NOTIFY(wxID_ANY, FileExplorer::OnDirMonitor)
242
EVT_COMMAND(0, wxEVT_NOTIFY_UPDATE_COMPLETE, FileExplorer::OnUpdateTreeItems)
243
EVT_COMMAND(0, wxEVT_NOTIFY_LOADER_UPDATE_COMPLETE, FileExplorer::OnVCSFileLoaderComplete)
244
// EVT_COMMAND(0, wxEVT_NOTIFY_EXEC_REQUEST, FileExplorer::OnExecRequest)
245
EVT_TREE_BEGIN_DRAG(ID_FILETREE, FileExplorer::OnBeginDragTreeItem)
246
EVT_TREE_END_DRAG(ID_FILETREE, FileExplorer::OnEndDragTreeItem)
247
EVT_BUTTON(ID_FILE_UPBUTTON, FileExplorer::OnUpButton)
248
EVT_MENU(ID_SETLOC, FileExplorer::OnSetLoc)
249
EVT_MENU(ID_OPENINED, FileExplorer::OnOpenInEditor)
250
EVT_MENU(ID_FILENEWFILE, FileExplorer::OnNewFile)
251
EVT_MENU(ID_FILENEWFOLDER,FileExplorer::OnNewFolder)
252
EVT_MENU(ID_FILEMAKEFAV,FileExplorer::OnAddFavorite)
253
EVT_MENU(ID_FILECOPY,FileExplorer::OnCopy)
254
EVT_MENU(ID_FILEDUP,FileExplorer::OnDuplicate)
255
EVT_MENU(ID_FILEMOVE,FileExplorer::OnMove)
256
EVT_MENU(ID_FILEDELETE,FileExplorer::OnDelete)
257
EVT_MENU(ID_FILERENAME,FileExplorer::OnRename)
258
EVT_MENU(ID_FILEEXPANDALL,FileExplorer::OnExpandAll)
259
EVT_MENU(ID_FILECOLLAPSEALL,FileExplorer::OnCollapseAll)
260
EVT_MENU(ID_FILESETTINGS,FileExplorer::OnSettings)
261
EVT_MENU(ID_FILESHOWHIDDEN,FileExplorer::OnShowHidden)
262
EVT_MENU(ID_FILEPARSECVS,FileExplorer::OnParseCVS)
263
EVT_MENU(ID_FILEPARSESVN,FileExplorer::OnParseSVN)
264
EVT_MENU(ID_FILEPARSEHG,FileExplorer::OnParseHG)
265
EVT_MENU(ID_FILEPARSEBZR,FileExplorer::OnParseBZR)
266
EVT_MENU(ID_FILEPARSEGIT,FileExplorer::OnParseGIT)
267
EVT_MENU(ID_FILEREFRESH,FileExplorer::OnRefresh)
268
EVT_MENU(ID_FILEADDTOPROJECT,FileExplorer::OnAddToProject)
269
EVT_MENU_RANGE(ID_FILEDIFF, ID_FILEDIFF+10, FileExplorer::OnVCSDiff)
270
EVT_KEY_DOWN(FileExplorer::OnKeyDown)
271
EVT_TREE_ITEM_EXPANDING(ID_FILETREE, FileExplorer::OnExpand)
272
//EVT_TREE_ITEM_COLLAPSED(id, func) //delete the children
273
EVT_TREE_ITEM_ACTIVATED(ID_FILETREE, FileExplorer::OnActivate) //double click - open file / expand folder (the latter is a default just need event.skip)
274
EVT_TREE_ITEM_MENU(ID_FILETREE, FileExplorer::OnRightClick) //right click open context menu -- interpreter actions, rename, delete, copy, properties, set as root etc
275
EVT_COMBOBOX(ID_FILELOC, FileExplorer::OnChooseLoc) //location selected from history of combo box - set as root
276
EVT_COMBOBOX(ID_FILEWILD, FileExplorer::OnChooseWild) //location selected from history of combo box - set as root
277
//EVT_TEXT(ID_FILELOC, FileExplorer::OnLocChanging) //provide autotext hint for dir name in combo box
278
EVT_TEXT_ENTER(ID_FILELOC, FileExplorer::OnEnterLoc) //location entered in combo box - set as root
279
EVT_TEXT_ENTER(ID_FILEWILD, FileExplorer::OnEnterWild) //location entered in combo box - set as root ** BUG RIDDEN
280
EVT_CHOICE(ID_VCSCONTROL, FileExplorer::OnVCSControl)
281
EVT_CHECKBOX(ID_VCSCHANGESCHECK, FileExplorer::OnVCSChangesCheck)
284
FileExplorer::FileExplorer(wxWindow *parent,wxWindowID id,
285
const wxPoint& pos, const wxSize& size,
286
long style, const wxString& name):
287
wxPanel(parent,id,pos,size,style, name)
290
m_update_queue=new UpdateQueue;
292
m_updatetimer=new wxTimer(this,ID_UPDATETIMER);
293
m_update_active=false;
294
m_updater_cancel=false;
295
m_update_expand=false;
296
m_dir_monitor=new wxDirectoryMonitor(this,wxArrayString());
297
m_dir_monitor->Start();
298
m_droptarget=new wxFEDropTarget(this);
307
wxBoxSizer* bs = new wxBoxSizer(wxVERTICAL);
308
wxBoxSizer* bsh = new wxBoxSizer(wxHORIZONTAL);
309
wxBoxSizer* bshloc = new wxBoxSizer(wxHORIZONTAL);
310
m_Box_VCS_Control = new wxBoxSizer(wxVERTICAL);
311
wxBoxSizer *box_vcs_top = new wxBoxSizer(wxHORIZONTAL);
312
m_Tree = new FileTreeCtrl(this, ID_FILETREE);
313
m_Tree->SetIndent(m_Tree->GetIndent()/2);
314
m_Tree->SetDropTarget(m_droptarget);
315
m_Loc = new wxComboBox(this,ID_FILELOC,_T(""),wxDefaultPosition,wxDefaultSize,0,NULL,wxTE_PROCESS_ENTER|wxCB_DROPDOWN);
316
m_WildCards = new wxComboBox(this,ID_FILEWILD,_T(""),wxDefaultPosition,wxDefaultSize,0,NULL,wxTE_PROCESS_ENTER|wxCB_DROPDOWN);
317
m_UpButton = new wxButton(this,ID_FILE_UPBUTTON,_("^"),wxDefaultPosition,wxDefaultSize,wxBU_EXACTFIT);
318
bshloc->Add(m_Loc, 1, wxEXPAND);
319
bshloc->Add(m_UpButton, 0, wxEXPAND);
320
bs->Add(bshloc, 0, wxEXPAND);
321
bsh->Add(new wxStaticText(this,wxID_ANY,_("Mask: ")),0,wxALIGN_CENTRE);
322
bsh->Add(m_WildCards,1);
323
bs->Add(bsh, 0, wxEXPAND);
325
m_VCS_Control = new wxChoice(this,ID_VCSCONTROL);
326
m_VCS_Type = new wxStaticText(this,ID_VCSTYPE,_T(""));
327
m_VCS_ChangesOnly = new wxCheckBox(this, ID_VCSCHANGESCHECK, _T("Show changed files only"));
328
box_vcs_top->Add(m_VCS_Type,0,wxALIGN_CENTER);
329
box_vcs_top->Add(m_VCS_Control,1,wxEXPAND);
330
m_Box_VCS_Control->Add(box_vcs_top, 0, wxEXPAND);
331
m_Box_VCS_Control->Add(m_VCS_ChangesOnly, 0, wxEXPAND);
332
m_Box_VCS_Control->Hide(true);
333
bs->Add(m_Box_VCS_Control, 0, wxEXPAND);
335
bs->Add(m_Tree, 1, wxEXPAND | wxALL);
341
if(m_Loc->GetCount()>m_favdirs.GetCount())
343
m_Loc->Select(m_favdirs.GetCount());
344
m_root=m_Loc->GetString(m_favdirs.GetCount());
347
m_root=wxFileName::GetPathSeparator();
348
m_Loc->Append(m_root);
351
if(m_WildCards->GetCount()>0)
352
m_WildCards->Select(0);
353
SetRootFolder(m_root);
358
FileExplorer::~FileExplorer()
361
m_updatetimer->Stop();
362
delete m_dir_monitor;
365
delete m_update_queue;
366
delete m_updatetimer;
370
bool FileExplorer::SetRootFolder(wxString root)
373
if(root[root.Len()-1]!=wxFileName::GetPathSeparator())
374
root=root+wxFileName::GetPathSeparator();
376
wxFileName fnroot=wxFileName(root);
377
if(fnroot.GetVolume().IsEmpty())
379
fnroot.SetVolume(wxFileName(::wxGetCwd()).GetVolume());
380
root=fnroot.GetFullPath();//(wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR)+fnroot.GetFullName();
386
// deal with the error here - wxDir would already log an error message
387
// explaining the exact reason of the failure
388
m_Loc->SetValue(m_root);
392
m_VCS_Control->Clear();
393
m_commit = wxEmptyString;
394
m_VCS_Type->SetLabel(wxEmptyString);
395
m_Box_VCS_Control->Hide(true);
396
m_Loc->SetValue(m_root);
397
m_Tree->DeleteAllItems();
398
m_Tree->AddRoot(m_root,fvsFolder);
399
m_Tree->SetItemHasChildren(m_Tree->GetRootItem());
400
m_Tree->Expand(m_Tree->GetRootItem());
404
// return AddTreeItems(m_Tree->GetRootItem());
408
// find a file in the filesystem below a selected root
409
void FileExplorer::FindFile(const wxString &findfilename, const wxTreeItemId &ti)
411
wxString path=GetFullPath(ti);
417
// deal with the error here - wxDir would already log an error message
418
// explaining the exact reason for the failure
422
int flags=wxDIR_FILES|wxDIR_DIRS;
426
DirTraverseFind dtf(findfilename);
427
m_findmatchcount=dir.Traverse(dtf,wxEmptyString,flags);
428
m_findmatch=dtf.GetMatches();
431
// focus the item in the tree.
432
void FileExplorer::FocusFile(const wxTreeItemId &ti)
435
m_Tree->UnselectAll();
436
m_Tree->SelectItem(ti);
437
m_Tree->EnsureVisible(ti);
440
wxTreeItemId FileExplorer::GetNextExpandedNode(wxTreeItemId ti)
442
wxTreeItemId next_ti;
445
return m_Tree->GetRootItem();
447
if(m_Tree->IsExpanded(ti))
449
wxTreeItemIdValue cookie;
450
next_ti=m_Tree->GetFirstChild(ti,cookie);
451
while(next_ti.IsOk())
453
if(m_Tree->IsExpanded(next_ti))
455
next_ti=m_Tree->GetNextChild(ti,cookie);
458
next_ti=m_Tree->GetNextSibling(ti);
459
while(next_ti.IsOk())
461
if(m_Tree->IsExpanded(next_ti))
463
next_ti=m_Tree->GetNextSibling(next_ti);
465
return m_Tree->GetRootItem();
468
bool FileExplorer::GetItemFromPath(const wxString &path, wxTreeItemId &ti)
470
ti=m_Tree->GetRootItem();
473
if(path==GetFullPath(ti))
475
ti=GetNextExpandedNode(ti);
476
} while(ti!=m_Tree->GetRootItem());
481
void FileExplorer::GetExpandedNodes(wxTreeItemId ti, Expansion *exp)
483
exp->name=m_Tree->GetItemText(ti);
484
wxTreeItemIdValue cookie;
485
wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
488
if(m_Tree->IsExpanded(ch))
490
Expansion *e=new Expansion();
491
GetExpandedNodes(ch,e);
492
exp->children.push_back(e);
494
ch=m_Tree->GetNextChild(ti,cookie);
498
void FileExplorer::GetExpandedPaths(wxTreeItemId ti,wxArrayString &paths)
502
wxMessageBox(_("node error"));
505
if(m_Tree->IsExpanded(ti))
506
paths.Add(GetFullPath(ti));
507
wxTreeItemIdValue cookie;
508
wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
511
if(m_Tree->IsExpanded(ch))
512
GetExpandedPaths(ch,paths);
513
ch=m_Tree->GetNextChild(ti,cookie);
517
void FileExplorer::RefreshExpanded(wxTreeItemId ti)
519
if(m_Tree->IsExpanded(ti))
520
m_update_queue->Add(ti);
521
wxTreeItemIdValue cookie;
522
wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
525
if(m_Tree->IsExpanded(ch))
527
ch=m_Tree->GetNextChild(ti,cookie);
529
m_updatetimer->Start(10,true);
533
void FileExplorer::Refresh(wxTreeItemId ti)
536
// GetExpandedNodes(ti,&e);
537
// RecursiveRebuild(ti,&e);
538
//m_updating_node=ti;//m_Tree->GetRootItem();
539
m_update_queue->Add(ti);
540
m_updatetimer->Start(10,true);
543
void FileExplorer::UpdateAbort()
548
m_update_active=false;
549
m_updatetimer->Stop();
552
void FileExplorer::ResetDirMonitor()
555
GetExpandedPaths(m_Tree->GetRootItem(),paths);
556
m_dir_monitor->ChangePaths(paths);
559
void FileExplorer::OnDirMonitor(wxDirectoryMonitorEvent &e)
563
// TODO: Apparently creating log messages during Code::Blocks shutdown can create segfaults
564
// LogMessage(wxString::Format(_T("Dir Event: %s,%i,%s"),e.m_mon_dir.c_str(),e.m_event_type,e.m_info_uri.c_str()));
565
if(e.m_event_type==MONITOR_TOO_MANY_CHANGES)
567
// LogMessage(_("directory change read error"));
570
if(GetItemFromPath(e.m_mon_dir,ti))
572
m_update_queue->Add(ti);
573
m_updatetimer->Start(100,true);
577
void FileExplorer::OnTimerCheckUpdates(wxTimerEvent &/*e*/)
584
while(m_update_queue->Pop(ti))
588
m_updater_cancel=false;
589
m_updater=new FileExplorerUpdater(this);
591
m_update_active=true;
592
m_updater->Update(m_updated_node);
597
bool FileExplorer::ValidateRoot()
599
wxTreeItemId ti=m_Tree->GetRootItem();
604
if(m_Tree->GetItemImage(ti)!=fvsFolder)
606
if(!wxFileName::DirExists(GetFullPath(ti)))
613
void FileExplorer::OnUpdateTreeItems(wxCommandEvent &/*e*/)
618
wxTreeItemId ti=m_updated_node;
619
bool viewing_commit = (m_updater->m_vcs_commit_string != wxEmptyString) &&
620
(m_updater->m_vcs_commit_string != _T("Working copy"));
621
if (ti == m_Tree->GetRootItem() && !viewing_commit)
623
m_VCS_Type->SetLabel(m_updater->m_vcs_type);
624
if (m_updater->m_vcs_type == wxEmptyString)
626
m_VCS_Control->Clear();
627
m_Box_VCS_Control->Hide(true);
630
else if (m_commit == wxEmptyString)
632
m_VCS_Control->Clear();
633
m_VCS_Control->Append(_T("Working copy"));
634
m_VCS_Control->Append(_T("Select commit..."));
635
m_VCS_Control->SetSelection(0);
636
m_commit = _T("Working copy");
637
m_Box_VCS_Control->Show(true);
641
if(m_updater_cancel || !ti.IsOk())
642
{ //NODE WAS DELETED - REFRESH NOW!
643
//TODO: Should only need to clean up and restart the timer (no need to change queue)
646
m_update_active=false;
650
m_update_queue->Add(m_Tree->GetRootItem());
651
m_updatetimer->Start(10,true);
655
// cbMessageBox(_T("Node OK"));
656
// m_Tree->DeleteChildren(ti);
657
FileDataVec &removers=m_updater->m_removers;
658
FileDataVec &adders=m_updater->m_adders;
659
if(removers.size()>0||adders.size()>0)
662
//LOOP THROUGH THE REMOVERS LIST AND REMOVE THOSE ITEMS FROM THE TREE
663
// cbMessageBox(_T("Removers"));
664
for(FileDataVec::iterator it=removers.begin();it!=removers.end();it++)
666
// cbMessageBox(it->name);
667
wxTreeItemIdValue cookie;
668
wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
671
if(it->name==m_Tree->GetItemText(ch))
676
ch=m_Tree->GetNextChild(ti,cookie);
679
//LOOP THROUGH THE ADDERS LIST AND ADD THOSE ITEMS TO THE TREE
680
// cbMessageBox(_T("Adders"));
681
for(FileDataVec::iterator it=adders.begin();it!=adders.end();it++)
683
// cbMessageBox(it->name);
684
wxTreeItemId newitem=m_Tree->AppendItem(ti,it->name,it->state);
685
m_Tree->SetItemHasChildren(newitem,it->state==fvsFolder);
687
m_Tree->SortChildren(ti);
690
if(!m_Tree->IsExpanded(ti))
692
m_update_expand=true;
697
m_update_active=false;
698
m_updatetimer->Start(10,true);
699
// Restart the monitor (TODO: move this elsewhere??)
703
void FileExplorer::SetImages()
705
wxImageList *m_pImages = cbProjectTreeImages::MakeImageList();
706
m_Tree->SetImageList(m_pImages);
708
// // make sure tree is not "frozen"
709
// UnfreezeTree(true);
712
wxString FileExplorer::GetFullPath(const wxTreeItemId &ti)
715
return wxEmptyString;
716
wxFileName path(m_root);
717
if (ti!=m_Tree->GetRootItem())
719
std::vector<wxTreeItemId> vti;
721
wxTreeItemId pti=m_Tree->GetItemParent(vti[0]);
723
return wxEmptyString;
724
while (pti != m_Tree->GetRootItem())
726
vti.insert(vti.begin(), pti);
727
pti=m_Tree->GetItemParent(pti);
729
//Complicated logic to deal with the fact that the selected item might
730
//be a partial path and not just a filename. It would be far simpler to
731
for (size_t i=0; i<vti.size() - 1; i++)
732
path.AppendDir(m_Tree->GetItemText(vti[i]));
733
wxFileName last_part(m_Tree->GetItemText(vti[vti.size()-1]));
734
wxArrayString as = last_part.GetDirs();
735
for (size_t i=0;i<as.size();i++)
736
path.AppendDir(as[i]);
737
path = wxFileName(path.GetFullPath(), last_part.GetFullName()).GetFullPath();
739
return path.GetFullPath();
742
void FileExplorer::OnExpand(wxTreeEvent &event)
744
if(m_updated_node==event.GetItem() && m_update_expand)
746
m_update_expand=false;
749
m_update_queue->Add(event.GetItem());
750
m_updatetimer->Start(10,true);
752
//AddTreeItems(event.GetItem());
755
void FileExplorer::ReadConfig()
757
//IMPORT SETTINGS FROM LEGACY SHELLEXTENSIONS PLUGIN - TODO: REMOVE IN NEXT VERSION
758
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("ShellExtensions"));
759
if(!cfg->Exists(_("FileExplorer/ShowHidenFiles")))
760
cfg = Manager::Get()->GetConfigManager(_T("FileManager"));
762
cfg->Read(_T("FileExplorer/FavRootList/Len"), &len);
763
for(int i=0;i<len;i++)
765
wxString ref=wxString::Format(_T("FileExplorer/FavRootList/I%i"),i);
768
cfg->Read(ref+_T("/alias"), &fav.alias);
769
cfg->Read(ref+_T("/path"), &fav.path);
770
m_Loc->Append(fav.alias);
774
cfg->Read(_T("FileExplorer/RootList/Len"), &len);
775
for(int i=0;i<len;i++)
777
wxString ref=wxString::Format(_T("FileExplorer/RootList/I%i"),i);
779
cfg->Read(ref, &loc);
783
cfg->Read(_T("FileExplorer/WildMask/Len"), &len);
784
for(int i=0;i<len;i++)
786
wxString ref=wxString::Format(_T("FileExplorer/WildMask/I%i"),i);
788
cfg->Read(ref, &wild);
789
m_WildCards->Append(wild);
791
cfg->Read(_T("FileExplorer/ParseCVS"), &m_parse_cvs);
792
cfg->Read(_T("FileExplorer/ParseSVN"), &m_parse_svn);
793
cfg->Read(_T("FileExplorer/ParseHG"), &m_parse_hg);
794
cfg->Read(_T("FileExplorer/ParseBZR"), &m_parse_bzr);
795
cfg->Read(_T("FileExplorer/ParseGIT"), &m_parse_git);
796
cfg->Read(_T("FileExplorer/ShowHiddenFiles"), &m_show_hidden);
799
void FileExplorer::WriteConfig()
801
//DISCARD SETTINGS FROM LEGACY SHELLEXTENSIONS PLUGIN - TODO: REMOVE IN NEXT VERSION
802
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("ShellExtensions"));
803
if(cfg->Exists(_("FileExplorer/ShowHidenFiles")))
804
cfg->DeleteSubPath(_("FileExplorer"));
805
cfg = Manager::Get()->GetConfigManager(_T("FileManager"));
807
int count=static_cast<int>(m_favdirs.GetCount());
808
cfg->Write(_T("FileExplorer/FavRootList/Len"), count);
809
for(int i=0;i<count;i++)
811
wxString ref=wxString::Format(_T("FileExplorer/FavRootList/I%i"),i);
812
cfg->Write(ref+_T("/alias"), m_favdirs[i].alias);
813
cfg->Write(ref+_T("/path"), m_favdirs[i].path);
815
count=static_cast<int>(m_Loc->GetCount())-static_cast<int>(m_favdirs.GetCount());
816
cfg->Write(_T("FileExplorer/RootList/Len"), count);
817
for(int i=0;i<count;i++)
819
wxString ref=wxString::Format(_T("FileExplorer/RootList/I%i"),i);
820
cfg->Write(ref, m_Loc->GetString(m_favdirs.GetCount()+i));
822
count=static_cast<int>(m_Loc->GetCount());
823
cfg->Write(_T("FileExplorer/WildMask/Len"), count);
824
for(int i=0;i<count;i++)
826
wxString ref=wxString::Format(_T("FileExplorer/WildMask/I%i"),i);
827
cfg->Write(ref, m_WildCards->GetString(i));
829
cfg->Write(_T("FileExplorer/ParseCVS"), m_parse_cvs);
830
cfg->Write(_T("FileExplorer/ParseSVN"), m_parse_svn);
831
cfg->Write(_T("FileExplorer/ParseHG"), m_parse_hg);
832
cfg->Write(_T("FileExplorer/ParseBZR"), m_parse_bzr);
833
cfg->Write(_T("FileExplorer/ParseGIT"), m_parse_git);
834
cfg->Write(_T("FileExplorer/ShowHiddenFiles"), m_show_hidden);
837
void FileExplorer::OnEnterWild(wxCommandEvent &/*event*/)
839
wxString wild=m_WildCards->GetValue();
840
for(size_t i=0;i<m_WildCards->GetCount();i++)
843
cmp=m_WildCards->GetString(i);
846
m_WildCards->Delete(i);
847
m_WildCards->Insert(wild,0);
848
m_WildCards->SetSelection(0);
849
RefreshExpanded(m_Tree->GetRootItem());
853
m_WildCards->Insert(wild,0);
854
if(m_WildCards->GetCount()>10)
855
m_WildCards->Delete(10);
856
m_WildCards->SetSelection(0);
857
RefreshExpanded(m_Tree->GetRootItem());
860
void FileExplorer::OnChooseWild(wxCommandEvent &/*event*/)
862
// Beware on win32 that if user opens drop down, then types a wildcard the combo box
863
// event will contain a -1 selection and an empty string item. Harmless in current code.
864
wxString wild=m_WildCards->GetValue();
865
m_WildCards->Delete(m_WildCards->GetSelection());
866
m_WildCards->Insert(wild,0);
868
// cbMessageBox(wild);
869
m_WildCards->SetSelection(0);
870
RefreshExpanded(m_Tree->GetRootItem());
873
void FileExplorer::OnEnterLoc(wxCommandEvent &/*event*/)
875
wxString loc=m_Loc->GetValue();
876
if(!SetRootFolder(loc))
878
for(size_t i=0;i<m_Loc->GetCount();i++)
881
if(i<m_favdirs.GetCount())
882
cmp=m_favdirs[i].path;
884
cmp=m_Loc->GetString(i);
887
if(i>=m_favdirs.GetCount())
890
m_Loc->Insert(m_root,m_favdirs.GetCount());
892
m_Loc->SetSelection(m_favdirs.GetCount());
896
m_Loc->Insert(m_root,m_favdirs.GetCount());
897
if(m_Loc->GetCount()>10+m_favdirs.GetCount())
898
m_Loc->Delete(10+m_favdirs.GetCount());
899
m_Loc->SetSelection(m_favdirs.GetCount());
902
void FileExplorer::OnChooseLoc(wxCommandEvent &event)
905
// on WIN32 if the user opens the drop down, but then types a path instead, this event
906
// fires with an empty string, so we have no choice but to return null. This event
907
// doesn't happen on Linux (the drop down closes when the user starts typing)
910
if(event.GetInt()>=static_cast<int>(m_favdirs.GetCount()))
911
loc=m_Loc->GetValue();
913
loc=m_favdirs[event.GetInt()].path;
914
if(!SetRootFolder(loc))
916
if(event.GetInt()>=static_cast<int>(m_favdirs.GetCount()))
918
m_Loc->Delete(event.GetInt());
919
m_Loc->Insert(m_root,m_favdirs.GetCount());
920
m_Loc->SetSelection(m_favdirs.GetCount());
924
for(size_t i=m_favdirs.GetCount();i<m_Loc->GetCount();i++)
927
cmp=m_Loc->GetString(i);
931
m_Loc->Insert(m_root,m_favdirs.GetCount());
932
m_Loc->SetSelection(event.GetInt());
936
m_Loc->Insert(m_root,m_favdirs.GetCount());
937
if(m_Loc->GetCount()>10+m_favdirs.GetCount())
938
m_Loc->Delete(10+m_favdirs.GetCount());
939
m_Loc->SetSelection(event.GetInt());
943
void FileExplorer::OnSetLoc(wxCommandEvent &/*event*/)
945
wxString loc=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
946
if(!SetRootFolder(loc))
948
m_Loc->Insert(m_root,m_favdirs.GetCount());
949
if(m_Loc->GetCount()>10+m_favdirs.GetCount())
950
m_Loc->Delete(10+m_favdirs.GetCount());
953
void FileExplorer::OnVCSChangesCheck(wxCommandEvent &/*event*/)
955
Refresh(m_Tree->GetRootItem());
958
void FileExplorer::OnVCSControl(wxCommandEvent &/*event*/)
960
wxString commit = m_VCS_Control->GetString(m_VCS_Control->GetSelection());
961
if (commit == _T("Select commit..."))
963
CommitBrowser *cm = new CommitBrowser(this, GetFullPath(m_Tree->GetRootItem()), m_VCS_Type->GetLabel());
964
if(cm->ShowModal() == wxID_OK)
966
commit = cm->GetSelectedCommit();
968
if (commit != wxEmptyString)
971
for (; i<m_VCS_Control->GetCount(); ++i)
973
if (m_VCS_Control->GetString(i) == commit)
975
m_VCS_Control->SetSelection(i);
979
if (i == m_VCS_Control->GetCount())
980
m_VCS_Control->Append(commit);
981
m_VCS_Control->SetSelection(m_VCS_Control->GetCount()-1);
985
commit = wxEmptyString;
987
if (commit!=wxEmptyString)
990
Refresh(m_Tree->GetRootItem());
994
for (; i<m_VCS_Control->GetCount(); ++i)
996
if (m_VCS_Control->GetString(i) == m_commit)
997
m_VCS_Control->SetSelection(i);
1003
void FileExplorer::OnOpenInEditor(wxCommandEvent &/*event*/)
1005
for(int i=0;i<m_ticount;i++)
1007
if (IsBrowsingVCSTree())
1009
wxFileName path(GetFullPath(m_selectti[i]));
1010
wxString original_path = path.GetFullPath();
1011
path.MakeRelativeTo(GetRootFolder());
1012
wxString name = path.GetFullName();
1013
wxString vcs_type = m_VCS_Type->GetLabel();
1014
name = vcs_type + _T("-") + m_commit.Mid(0,6) + _T("-") + name;
1015
path.SetFullName(name);
1016
wxFileName tmp = wxFileName(wxFileName::GetTempDir(),_T(""));
1017
tmp.AppendDir(_T("codeblocks-fm"));
1018
path.MakeAbsolute(tmp.GetFullPath());
1019
if(!path.FileExists())
1020
m_vcs_file_loader_queue.Add(_T("cat"), original_path, path.GetFullPath());
1022
DoOpenInEditor(path.GetFullPath());
1026
wxFileName path(GetFullPath(m_selectti[i]));
1027
wxString filename=path.GetFullPath();
1028
if(!path.FileExists())
1030
DoOpenInEditor(filename);
1033
if (m_vcs_file_loader==0 && !m_vcs_file_loader_queue.empty())
1035
LoaderQueueItem item = m_vcs_file_loader_queue.Pop();
1036
m_vcs_file_loader = new VCSFileLoader(this);
1037
m_vcs_file_loader->Update(item.op, item.source, item.destination, item.comp_commit);
1041
void FileExplorer::OnVCSDiff(wxCommandEvent &event)
1043
wxString comp_commit;
1044
if (event.GetId() == ID_FILEDIFF) //Diff with head (for working copy) or previous (for commit)
1045
comp_commit = _T("Previous");
1046
else //Otherwise diff against specific revision
1047
comp_commit = m_VCS_Control->GetString(event.GetId()-ID_FILEDIFF1);
1048
if (m_commit == _T("Working copy") && comp_commit == _T("Working copy"))
1049
comp_commit = _T("Previous");
1050
if (comp_commit == _T("Select commit..."))
1052
wxString diff_paths;
1053
for(int i=0;i<m_ticount;i++)
1055
wxFileName path(GetFullPath(m_selectti[i]));
1056
path.MakeRelativeTo(GetRootFolder());
1057
if (path != wxEmptyString)
1058
diff_paths+=_T(" \"") + path.GetFullPath() + _T("\"");
1060
CommitBrowser *cm = new CommitBrowser(this, GetFullPath(m_Tree->GetRootItem()), m_VCS_Type->GetLabel(), diff_paths);
1061
if(cm->ShowModal() == wxID_OK)
1063
comp_commit = cm->GetSelectedCommit();
1068
wxString diff_paths = wxEmptyString;
1069
for(int i=0;i<m_ticount;i++)
1071
wxFileName path(GetFullPath(m_selectti[i]));
1072
path.MakeRelativeTo(GetRootFolder());
1073
if (path != wxEmptyString)
1074
diff_paths+=_T(" \"") + path.GetFullPath() + _T("\"");
1076
wxFileName tmp = wxFileName(wxFileName::GetTempDir(),_T(""));
1077
wxFileName root_path(GetRootFolder());
1078
wxString name = root_path.GetName();
1079
wxString vcs_type = m_VCS_Type->GetLabel();
1080
tmp.AppendDir(_T("codeblocks-fm"));
1081
name = _T("diff-") + vcs_type + _T("-") + m_commit.Mid(0,7) +_T("~") + comp_commit + _T("-") + name + _T(".patch");
1082
wxString dest_tmp_path = wxFileName(tmp.GetFullPath(), name).GetFullPath();
1083
m_vcs_file_loader_queue.Add(_T("diff"), diff_paths, dest_tmp_path, comp_commit);
1084
if (m_vcs_file_loader==0 && !m_vcs_file_loader_queue.empty())
1086
LoaderQueueItem item = m_vcs_file_loader_queue.Pop();
1087
m_vcs_file_loader = new VCSFileLoader(this);
1088
m_vcs_file_loader->Update(item.op, item.source, item.destination, item.comp_commit);
1092
void FileExplorer::OnVCSFileLoaderComplete(wxCommandEvent& /*event*/)
1094
m_vcs_file_loader->Wait();
1095
DoOpenInEditor(m_vcs_file_loader->m_destination_path);
1096
delete m_vcs_file_loader;
1097
m_vcs_file_loader = 0;
1098
if (!m_vcs_file_loader_queue.empty())
1100
LoaderQueueItem item = m_vcs_file_loader_queue.Pop();
1101
m_vcs_file_loader = new VCSFileLoader(this);
1102
m_vcs_file_loader->Update(item.op, item.source, item.destination, item.comp_commit);
1106
void FileExplorer::DoOpenInEditor(const wxString &filename)
1108
EditorManager* em = Manager::Get()->GetEditorManager();
1109
EditorBase* eb = em->IsOpen(filename);
1112
// open files just get activated
1119
void FileExplorer::OnActivate(wxTreeEvent &event)
1121
if (IsBrowsingVCSTree())
1123
//TODO: Should just retrieve the file and use the same mimetype handling as a regular file
1125
m_ticount=m_Tree->GetSelections(m_selectti);
1129
wxString filename=GetFullPath(event.GetItem());
1130
if(m_Tree->GetItemImage(event.GetItem())==fvsFolder)
1135
EditorManager* em = Manager::Get()->GetEditorManager();
1136
EditorBase* eb = em->IsOpen(filename);
1139
// open files just get activated
1144
// Use Mime handler to open file
1145
cbMimePlugin* plugin = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile(filename);
1149
msg.Printf(_("Could not open file '%s'.\nNo handler registered for this type of file."), filename.c_str());
1150
LogErrorMessage(msg);
1151
// em->Open(filename); //should never need to open the file from here
1153
else if (plugin->OpenFile(filename) != 0)
1155
const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1157
msg.Printf(_("Could not open file '%s'.\nThe registered handler (%s) could not open it."), filename.c_str(), info ? info->title.c_str() : wxString(_("<Unknown plugin>")).c_str());
1158
LogErrorMessage(msg);
1161
// if(!em->IsOpen(file))
1167
void FileExplorer::OnKeyDown(wxKeyEvent &event)
1169
if(event.GetKeyCode() == WXK_DELETE)
1171
if (IsBrowsingVCSTree())
1173
wxCommandEvent event2;
1180
bool FileExplorer::IsBrowsingVCSTree()
1182
return m_commit != _T("Working copy") && m_commit != wxEmptyString;
1185
bool FileExplorer::IsBrowsingWorkingCopy()
1187
return m_commit == _T("Working copy") && m_commit != wxEmptyString;
1190
void FileExplorer::OnRightClick(wxTreeEvent &event)
1192
wxMenu* Popup = new wxMenu();
1193
m_ticount=m_Tree->GetSelections(m_selectti);
1194
if(!IsInSelection(event.GetItem())) //replace the selection with right clicked item if right clicked item isn't in the selection
1196
for(int i=0;i<m_ticount;i++)
1197
m_Tree->SelectItem(m_selectti[i],false);
1198
m_Tree->SelectItem(event.GetItem());
1199
m_ticount=m_Tree->GetSelections(m_selectti);
1202
FileTreeData* ftd = new FileTreeData(0, FileTreeData::ftdkUndefined);
1203
ftd->SetKind(FileTreeData::ftdkFile);
1208
int img = m_Tree->GetItemImage(m_selectti[0]);
1211
ftd->SetKind(FileTreeData::ftdkFolder);
1212
Popup->Append(ID_SETLOC,_("Make roo&t"));
1213
Popup->Append(ID_FILEEXPANDALL,_("Expand all children")); //TODO: check availability in wx2.8 for win32 (not avail wx2.6)
1214
Popup->Append(ID_FILECOLLAPSEALL,_("Collapse all children")); //TODO: check availability in wx2.8 for win32 (not avail wx2.6)
1215
if (!IsBrowsingVCSTree())
1217
Popup->Append(ID_FILEMAKEFAV,_("Add to favorites"));
1218
Popup->Append(ID_FILENEWFILE,_("New file..."));
1219
Popup->Append(ID_FILENEWFOLDER,_("New directory..."));
1220
Popup->Append(ID_FILERENAME,_("&Rename..."));
1224
if (!IsBrowsingVCSTree())
1225
Popup->Append(ID_FILERENAME,_("&Rename..."));
1228
if(IsFilesOnly(m_selectti))
1230
Popup->Append(ID_OPENINED,_("&Open in CB editor"));
1231
if (!IsBrowsingVCSTree())
1232
if(Manager::Get()->GetProjectManager()->GetActiveProject())
1233
Popup->Append(ID_FILEADDTOPROJECT,_("&Add to active project..."));
1235
if (!IsBrowsingVCSTree())
1237
Popup->Append(ID_FILEDUP,_("&Duplicate"));
1238
Popup->Append(ID_FILECOPY,_("&Copy to..."));
1239
Popup->Append(ID_FILEMOVE,_("&Move to..."));
1240
Popup->Append(ID_FILEDELETE,_("D&elete"));
1242
if ( IsBrowsingVCSTree() || IsBrowsingWorkingCopy() )
1244
if (IsBrowsingWorkingCopy())
1245
Popup->Append(ID_FILEDIFF,_("&Diff"));
1247
Popup->Append(ID_FILEDIFF,_("&Diff previous"));
1248
wxMenu *diff_menu = new wxMenu();
1249
unsigned int n = m_VCS_Control->GetCount();
1252
if (IsBrowsingWorkingCopy())
1254
diff_menu->Append(ID_FILEDIFF1, _("Head"));
1255
for (unsigned int i = 1; i<n; ++i)
1256
diff_menu->Append(ID_FILEDIFF1 + i, m_VCS_Control->GetString(i));
1260
for (unsigned int i = 0; i<n; ++i)
1261
diff_menu->Append(ID_FILEDIFF1 + i, m_VCS_Control->GetString(i));
1263
Popup->AppendSubMenu(diff_menu,_("Diff against"));
1266
wxMenu *viewpop=new wxMenu();
1267
viewpop->Append(ID_FILESETTINGS,_("Favorite directories..."));
1268
viewpop->AppendCheckItem(ID_FILESHOWHIDDEN,_("Show &hidden files"))->Check(m_show_hidden);
1269
// viewpop->AppendCheckItem(ID_FILEPARSECVS,_("CVS decorators"))->Check(m_parse_cvs);
1270
viewpop->AppendCheckItem(ID_FILEPARSESVN,_("SVN integration"))->Check(m_parse_svn);
1271
viewpop->AppendCheckItem(ID_FILEPARSEHG,_("Hg integration"))->Check(m_parse_hg);
1272
viewpop->AppendCheckItem(ID_FILEPARSEBZR,_("Bzr integration"))->Check(m_parse_bzr);
1273
viewpop->AppendCheckItem(ID_FILEPARSEGIT,_("Git integration"))->Check(m_parse_git);
1276
ftd->SetKind(FileTreeData::ftdkVirtualGroup);
1277
wxString pathlist = GetFullPath(m_selectti[0]);
1278
for(int i=1;i<m_ticount;i++)
1279
pathlist += _T("*") + GetFullPath(m_selectti[i]); //passing a '*' separated list of files/directories to any plugin takers
1280
ftd->SetFolder(pathlist);
1282
else if ( m_ticount > 0)
1284
wxString filepath = GetFullPath(m_selectti[0]);
1285
ftd->SetFolder(filepath);
1288
Manager::Get()->GetPluginManager()->AskPluginsForModuleMenu(mtUnknown, Popup, ftd);
1290
Popup->AppendSeparator();
1291
Popup->AppendSubMenu(viewpop,_("&Settings"));
1292
Popup->Append(ID_FILEREFRESH,_("Re&fresh"));
1293
wxWindow::PopupMenu(Popup);
1297
void FileExplorer::OnNewFile(wxCommandEvent &/*event*/)
1299
wxString workingdir=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1300
wxTextEntryDialog te(this,_("Name Your New File: "));
1301
if(te.ShowModal()!=wxID_OK)
1303
wxString name=te.GetValue();
1304
wxFileName file(workingdir);
1305
file.Assign(file.GetFullPath(),name);
1306
wxString newfile=file.GetFullPath();
1307
if(!wxFileName::FileExists(newfile) &&!wxFileName::DirExists(newfile))
1310
if(fileobj.Create(newfile))
1313
Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1316
cbMessageBox(_("File Creation Failed"),_("Error"));
1319
cbMessageBox(_("File/Directory Already Exists with Name ")+name, _("Error"));
1322
void FileExplorer::OnAddFavorite(wxCommandEvent &/*event*/)
1325
fav.path=GetFullPath(m_selectti[0]);
1326
if(fav.path[fav.path.Len()-1]!=wxFileName::GetPathSeparator())
1327
fav.path=fav.path+wxFileName::GetPathSeparator();
1328
wxTextEntryDialog ted(NULL,_("Enter an alias for this directory:"),_("Add Favorite Directory"),fav.path);
1329
if(ted.ShowModal()!=wxID_OK)
1331
wxString name=ted.GetValue();
1333
m_favdirs.Insert(fav,0);
1334
m_Loc->Insert(name,0);
1337
void FileExplorer::OnNewFolder(wxCommandEvent &/*event*/)
1339
wxString workingdir=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1340
wxTextEntryDialog te(this,_("New Directory Name: "));
1341
if(te.ShowModal()!=wxID_OK)
1343
wxString name=te.GetValue();
1344
wxFileName dir(workingdir);
1345
dir.Assign(dir.GetFullPath(),name);
1346
wxString mkd=dir.GetFullPath();
1347
if(!wxFileName::DirExists(mkd) &&!wxFileName::FileExists(mkd))
1349
if (!dir.Mkdir(mkd))
1350
cbMessageBox(_("A directory could not be created with name ")+name);
1351
Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1354
cbMessageBox(_("A file or directory already exists with name ")+name);
1357
void FileExplorer::OnDuplicate(wxCommandEvent &/*event*/)
1359
m_ticount=m_Tree->GetSelections(m_selectti);
1360
for(int i=0;i<m_ticount;i++)
1362
wxFileName path(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1363
if(wxFileName::FileExists(path.GetFullPath())||wxFileName::DirExists(path.GetFullPath()))
1365
if(!PromptSaveOpenFile(_("File is modified, press Yes to save before duplication, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
1368
wxString destpath(path.GetPathWithSep()+path.GetName()+wxString::Format(_T("(%i)"),j));
1369
if(path.GetExt()!=wxEmptyString)
1370
destpath+=_T(".")+path.GetExt();
1371
while(j<100 && (wxFileName::FileExists(destpath) || wxFileName::DirExists(destpath)))
1374
destpath=path.GetPathWithSep()+path.GetName()+wxString::Format(_T("(%i)"),j);
1375
if(path.GetExt()!=wxEmptyString)
1376
destpath+=_T(".")+path.GetExt();
1380
cbMessageBox(_("Too many copies of file or directory"));
1385
wxArrayString output;
1387
if(wxFileName::FileExists(path.GetFullPath()))
1388
cmdline=_T("cmd /c copy /Y \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
1390
cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
1391
int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
1393
wxString cmdline=_T("/bin/cp -r -b \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
1394
int hresult=::wxExecute(cmdline,wxEXEC_SYNC);
1397
MessageBox(m_Tree,_("Command '")+cmdline+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1400
Refresh(m_Tree->GetRootItem()); //TODO: Can probably be more efficient than this
1401
//TODO: Reselect item in new location?? (what it outside root scope?)
1405
void FileExplorer::CopyFiles(const wxString &destination, const wxArrayString &selectedfiles)
1407
for(unsigned int i=0;i<selectedfiles.Count();i++)
1409
wxString path=selectedfiles[i];
1410
wxFileName destpath;
1411
destpath.Assign(destination,wxFileName(path).GetFullName());
1412
if(destpath.SameAs(path))
1414
if(wxFileName::FileExists(path)||wxFileName::DirExists(path))
1416
if(!PromptSaveOpenFile(_("File is modified, press Yes to save before duplication, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
1419
wxArrayString output;
1421
if(wxFileName::FileExists(path))
1422
cmdline=_T("cmd /c copy /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1424
cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1425
int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
1427
int hresult=::wxExecute(_T("/bin/cp -r -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1430
MessageBox(m_Tree,_("Copying '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1435
void FileExplorer::OnCopy(wxCommandEvent &/*event*/)
1437
wxDirDialog dd(this,_("Copy to"));
1438
dd.SetPath(GetFullPath(m_Tree->GetRootItem()));
1439
wxArrayString selectedfiles;
1440
m_ticount=m_Tree->GetSelections(m_selectti);
1441
for(int i=0;i<m_ticount;i++) // really important not to rely on TreeItemId ater modal dialogs because file updates can change the file tree in the background.
1443
selectedfiles.Add(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1445
if(dd.ShowModal()==wxID_CANCEL)
1447
CopyFiles(dd.GetPath(),selectedfiles);
1448
// Refresh(m_Tree->GetRootItem()); //TODO: Use this if monitoring not available
1449
//TODO: Reselect item in new location?? (what if outside root scope?)
1452
void FileExplorer::MoveFiles(const wxString &destination, const wxArrayString &selectedfiles)
1454
for(unsigned int i=0;i<selectedfiles.Count();i++)
1456
wxString path=selectedfiles[i];
1457
wxFileName destpath;
1458
destpath.Assign(destination,wxFileName(path).GetFullName());
1459
if(destpath.SameAs(path)) //TODO: Log message that can't copy over self.
1461
if(wxFileName::FileExists(path)||wxFileName::DirExists(path))
1464
wxArrayString output;
1465
int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
1467
int hresult=::wxExecute(_T("/bin/mv -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1470
MessageBox(m_Tree,_("Moving '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1475
void FileExplorer::OnMove(wxCommandEvent &/*event*/)
1477
wxDirDialog dd(this,_("Move to"));
1478
wxArrayString selectedfiles;
1479
m_ticount=m_Tree->GetSelections(m_selectti);
1480
for(int i=0;i<m_ticount;i++)
1481
selectedfiles.Add(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1482
dd.SetPath(GetFullPath(m_Tree->GetRootItem()));
1483
if(dd.ShowModal()==wxID_CANCEL)
1485
MoveFiles(dd.GetPath(),selectedfiles);
1486
// Refresh(m_Tree->GetRootItem()); //TODO: Can probably be more efficient than this
1487
//TODO: Reselect item in new location?? (what if outside root scope?)
1490
wxArrayString FileExplorer::GetSelectedPaths()
1492
wxArrayString paths;
1493
for(int i=0;i<m_ticount;i++)
1495
wxString path(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1501
void FileExplorer::OnDelete(wxCommandEvent &/*event*/)
1503
m_ticount=m_Tree->GetSelections(m_selectti);
1504
wxArrayString as=GetSelectedPaths();
1505
wxString prompt=_("Your are about to delete\n\n");
1506
for(unsigned int i=0;i<as.Count();i++)
1507
prompt+=as[i]+_("\n");
1508
prompt+=_("\nAre you sure?");
1509
if(MessageBox(m_Tree,prompt,_("Delete"),wxYES_NO)!=wxID_YES)
1511
for(unsigned int i=0;i<as.Count();i++)
1513
wxString path=as[i]; //SINGLE: m_Tree->GetSelection()
1514
if(wxFileName::FileExists(path))
1516
// EditorManager* em = Manager::Get()->GetEditorManager();
1517
// if(em->IsOpen(path))
1519
// cbMessageBox(_("Close file ")+path.GetFullPath()+_(" first"));
1522
if(!::wxRemoveFile(path))
1523
MessageBox(m_Tree,_("Delete file '")+path+_("' failed"));
1525
if(wxFileName::DirExists(path))
1528
wxArrayString output;
1529
int hresult=::wxExecute(_T("cmd /c rmdir /S/Q \"")+path+_T("\""),output,wxEXEC_SYNC);
1531
int hresult=::wxExecute(_T("/bin/rm -r -f \"")+path+_T("\""),wxEXEC_SYNC);
1534
MessageBox(m_Tree,_("Delete directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1537
Refresh(m_Tree->GetRootItem());
1540
void FileExplorer::OnRename(wxCommandEvent &/*event*/)
1542
wxString path(GetFullPath(m_selectti[0])); //SINGLE: m_Tree->GetSelection()
1543
if(wxFileName::FileExists(path))
1545
EditorManager* em = Manager::Get()->GetEditorManager();
1546
if(em->IsOpen(path))
1548
cbMessageBox(_("Close file first"));
1551
wxTextEntryDialog te(this,_("New name:"),_("Rename File"),wxFileName(path).GetFullName());
1552
if(te.ShowModal()==wxID_CANCEL)
1554
wxFileName destpath(path);
1555
destpath.SetFullName(te.GetValue());
1556
if(!::wxRenameFile(path,destpath.GetFullPath()))
1557
cbMessageBox(_("Rename failed"));
1559
if(wxFileName::DirExists(path))
1561
wxTextEntryDialog te(this,_("New name:"),_("Rename File"),wxFileName(path).GetFullName());
1562
if(te.ShowModal()==wxID_CANCEL)
1564
wxFileName destpath(path);
1565
destpath.SetFullName(te.GetValue());
1567
wxArrayString output;
1568
int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
1570
int hresult=::wxExecute(_T("/bin/mv \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1573
MessageBox(m_Tree,_("Rename directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1575
Refresh(m_Tree->GetItemParent(m_selectti[0])); //SINGLE: m_Tree->GetSelection()
1578
void FileExplorer::OnExpandAll(wxCommandEvent &/*event*/)
1580
m_Tree->ExpandAllChildren(m_Tree->GetSelection());
1583
void FileExplorer::OnCollapseAll(wxCommandEvent &/*event*/)
1585
m_Tree->CollapseAllChildren(m_Tree->GetSelection());
1588
void FileExplorer::OnSettings(wxCommandEvent &/*event*/)
1590
FileBrowserSettings fbs(m_favdirs,NULL);
1591
if(fbs.ShowModal()==wxID_OK)
1593
size_t count=m_favdirs.GetCount();
1594
for(size_t i=0;i<count;i++)
1596
m_favdirs=fbs.m_favdirs;
1597
count=m_favdirs.GetCount();
1598
for(size_t i=0;i<count;i++)
1599
m_Loc->Insert(m_favdirs[i].alias,i);
1604
void FileExplorer::OnShowHidden(wxCommandEvent &/*event*/)
1606
m_show_hidden=!m_show_hidden;
1607
Refresh(m_Tree->GetRootItem());
1610
void FileExplorer::OnParseCVS(wxCommandEvent &/*event*/)
1612
m_parse_cvs=!m_parse_cvs;
1614
Refresh(m_Tree->GetRootItem());
1617
void FileExplorer::OnParseSVN(wxCommandEvent &/*event*/)
1619
m_parse_svn=!m_parse_svn;
1620
Refresh(m_Tree->GetRootItem());
1623
void FileExplorer::OnParseGIT(wxCommandEvent &/*event*/)
1625
m_parse_git=!m_parse_git;
1626
Refresh(m_Tree->GetRootItem());
1629
void FileExplorer::OnParseHG(wxCommandEvent &/*event*/)
1631
m_parse_hg=!m_parse_hg;
1632
Refresh(m_Tree->GetRootItem());
1635
void FileExplorer::OnParseBZR(wxCommandEvent &/*event*/)
1637
m_parse_bzr=!m_parse_bzr;
1638
Refresh(m_Tree->GetRootItem());
1641
void FileExplorer::OnUpButton(wxCommandEvent &/*event*/)
1643
wxFileName loc(m_root);
1644
loc.RemoveLastDir();
1645
SetRootFolder(loc.GetFullPath()); //TODO: Check if this is always the root folder
1648
void FileExplorer::OnRefresh(wxCommandEvent &/*event*/)
1650
if(m_Tree->GetItemImage(m_selectti[0])==fvsFolder) //SINGLE: m_Tree->GetSelection()
1651
Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1653
Refresh(m_Tree->GetRootItem());
1656
//TODO: Set copy cursor state if necessary
1657
void FileExplorer::OnBeginDragTreeItem(wxTreeEvent &event)
1659
// SetCursor(wxCROSS_CURSOR);
1660
// if(IsInSelection(event.GetItem()))
1661
// return; // don't start a drag for an unselected item
1662
if (!IsBrowsingVCSTree())
1664
// m_dragtest=GetFullPath(event.GetItem());
1665
m_ticount=m_Tree->GetSelections(m_selectti);
1668
bool FileExplorer::IsInSelection(const wxTreeItemId &ti)
1670
for(int i=0;i<m_ticount;i++)
1671
if(ti==m_selectti[i])
1676
//TODO: End copy cursor state if necessary
1677
void FileExplorer::OnEndDragTreeItem(wxTreeEvent &event)
1679
// SetCursor(wxCursor(wxCROSS_CURSOR));
1680
if(m_Tree->GetItemImage(event.GetItem())!=fvsFolder) //can only copy to folders
1682
for(int i=0;i<m_ticount;i++)
1684
wxString path(GetFullPath(m_selectti[i]));
1685
wxFileName destpath;
1686
if(!event.GetItem().IsOk())
1688
destpath.Assign(GetFullPath(event.GetItem()),wxFileName(path).GetFullName());
1689
if(destpath.SameAs(path))
1691
if(wxFileName::DirExists(path)||wxFileName::FileExists(path))
1693
if(!::wxGetKeyState(WXK_CONTROL))
1695
if(wxFileName::FileExists(path))
1696
if(!PromptSaveOpenFile(_("File is modified, press Yes to save before move, No to move unsaved file or Cancel to skip file"),wxFileName(path)))
1699
wxArrayString output;
1700
int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
1702
int hresult=::wxExecute(_T("/bin/mv -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1705
MessageBox(m_Tree,_("Move directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1708
if(wxFileName::FileExists(path))
1709
if(!PromptSaveOpenFile(_("File is modified, press Yes to save before copy, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
1712
wxArrayString output;
1714
if(wxFileName::FileExists(path))
1715
cmdline=_T("cmd /c copy /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1717
cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1718
int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
1720
int hresult=::wxExecute(_T("/bin/cp -r -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1723
MessageBox(m_Tree,_("Copy directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1726
// if(!PromptSaveOpenFile(_T("File is modified, press \"Yes\" to save before move/copy, \"No\" to move/copy unsaved file or \"Cancel\" to abort the operation"),path)) //TODO: specify move or copy depending on whether CTRL held down
1729
Refresh(m_Tree->GetRootItem());
1732
void FileExplorer::OnAddToProject(wxCommandEvent &/*event*/)
1734
wxArrayString files;
1736
for(int i=0;i<m_ticount;i++)
1738
file=GetFullPath(m_selectti[i]);
1739
if(wxFileName::FileExists(file))
1743
Manager::Get()->GetProjectManager()->AddMultipleFilesToProject(files, NULL, prompt);
1744
Manager::Get()->GetProjectManager()->GetUI().RebuildTree();
1747
bool FileExplorer::IsFilesOnly(wxArrayTreeItemIds tis)
1749
for(size_t i=0;i<tis.GetCount();i++)
1750
if(m_Tree->GetItemImage(tis[i])==fvsFolder)