1 #include "FileExplorer.h"
2 #include <wx/dir.h>
3 #include <wx/filename.h>
4 #include <wx/aui/aui.h>
5
6 #include <sdk.h>
7 #ifndef CB_PRECOMP
8 #include <wx/dnd.h>
9 #include <wx/imaglist.h>
10
11 #include <cbproject.h>
12 #include <configmanager.h>
13 #include <projectmanager.h>
14 #endif
15
16 #include <list>
17 #include <vector>
18 #include <iostream>
19
20 #include "se_globals.h"
21 #include "CommitBrowser.h"
22
23 #include <wx/arrimpl.cpp> // this is a magic incantation which must be done!
24 WX_DEFINE_OBJARRAY(VCSstatearray);
25
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();
34
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();
56
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();
69 //
70
71
72 class UpdateQueue
73 {
74 public:
Add(const wxTreeItemId & ti)75 void Add(const wxTreeItemId &ti)
76 {
77 for(std::list<wxTreeItemId>::iterator it=qdata.begin();it!=qdata.end();it++)
78 {
79 if(*it==ti)
80 {
81 qdata.erase(it);
82 break;
83 }
84 }
85 qdata.push_front(ti);
86 }
Pop(wxTreeItemId & ti)87 bool Pop(wxTreeItemId &ti)
88 {
89 if(qdata.empty())
90 return false;
91 ti=qdata.front();
92 qdata.pop_front();
93 return true;
94 }
Clear()95 void Clear()
96 {
97 qdata.clear();
98 }
99 private:
100 std::list<wxTreeItemId> qdata;
101 };
102
103
104 class DirTraverseFind : public wxDirTraverser {
105 public:
DirTraverseFind(const wxString & wildcard)106 DirTraverseFind(const wxString& wildcard) : m_files(), m_wildcard(wildcard) { }
OnFile(const wxString & filename)107 virtual wxDirTraverseResult OnFile(const wxString& filename)
108 {
109 if(WildCardListMatch(m_wildcard,filename,true))
110 m_files.Add(filename);
111 return wxDIR_CONTINUE;
112 }
OnDir(const wxString & dirname)113 virtual wxDirTraverseResult OnDir(const wxString& dirname)
114 {
115 if(WildCardListMatch(m_wildcard,dirname,true))
116 m_files.Add(dirname);
117 return wxDIR_CONTINUE;
118 }
GetMatches()119 wxArrayString& GetMatches() {return m_files;}
120 private:
121 wxArrayString m_files;
122 wxString m_wildcard;
123 };
124
125
126 class FEDataObject:public wxDataObjectComposite
127 {
128 public:
FEDataObject()129 FEDataObject():wxDataObjectComposite()
130 {
131 m_file=new wxFileDataObject;
132 Add(m_file,true);
133 }
134 wxFileDataObject *m_file;
135
136 };
137
138
139 class wxFEDropTarget: public wxDropTarget
140 {
141 public:
wxFEDropTarget(FileExplorer * fe)142 wxFEDropTarget(FileExplorer *fe):wxDropTarget()
143 {
144 m_fe=fe;
145 m_data_object=new FEDataObject();
146 SetDataObject(m_data_object);
147 }
OnData(wxCoord x,wxCoord y,wxDragResult def)148 virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
149 {
150 GetData();
151 if(m_data_object->GetReceivedFormat().GetType()==wxDF_FILENAME )
152 {
153 wxArrayString as=m_data_object->m_file->GetFilenames();
154 wxTreeCtrl *tree=m_fe->m_Tree;
155 int flags;
156 wxTreeItemId id=tree->HitTest(wxPoint(x,y),flags);
157 if(!id.IsOk())
158 return wxDragCancel;
159 if(tree->GetItemImage(id)!=fvsFolder)
160 return wxDragCancel;
161 if(!(flags&(wxTREE_HITTEST_ONITEMICON|wxTREE_HITTEST_ONITEMLABEL)))
162 return wxDragCancel;
163 if(def==wxDragCopy)
164 {
165 m_fe->CopyFiles(m_fe->GetFullPath(id),as);
166 return def;
167 }
168 if(def==wxDragMove)
169 {
170 m_fe->MoveFiles(m_fe->GetFullPath(id),as);
171 return def;
172 }
173 return wxDragCancel;
174 }
175 // if(sizeof(wxFileDataObject)!=m_data_object->GetDataSize(wxDF_FILENAME))
176 // {
177 // wxMessageBox(wxString::Format(_("Drop files %i,%i"),sizeof(wxFileDataObject),m_data_object->GetDataSize(wxDF_FILENAME)));
178 // return wxDragCancel;
179 // }
180 return wxDragCancel;
181 }
OnDrop(wxCoord,wxCoord,int,wxWindow *)182 virtual bool OnDrop(wxCoord /*x*/, wxCoord /*y*/, int /*tab*/, wxWindow */*wnd*/)
183 {
184 return true;
185 }
OnDragOver(wxCoord,wxCoord,wxDragResult def)186 virtual wxDragResult OnDragOver(wxCoord /*x*/, wxCoord /*y*/, wxDragResult def)
187 {
188 return def;
189 }
190 private:
191 FEDataObject *m_data_object;
192 FileExplorer *m_fe;
193 };
194
195
196
BEGIN_EVENT_TABLE(FileTreeCtrl,wxTreeCtrl)197 BEGIN_EVENT_TABLE(FileTreeCtrl, wxTreeCtrl)
198 // EVT_TREE_ITEM_ACTIVATED(ID_FILETREE, FileTreeCtrl::OnActivate) //double click -
199 EVT_KEY_DOWN(FileTreeCtrl::OnKeyDown)
200 END_EVENT_TABLE()
201
202 IMPLEMENT_DYNAMIC_CLASS(FileTreeCtrl, wxTreeCtrl)
203
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) {}
209
FileTreeCtrl()210 FileTreeCtrl::FileTreeCtrl() { }
211
FileTreeCtrl(wxWindow * parent)212 FileTreeCtrl::FileTreeCtrl(wxWindow *parent): wxTreeCtrl(parent) {}
213
~FileTreeCtrl()214 FileTreeCtrl::~FileTreeCtrl()
215 {
216 }
217
OnKeyDown(wxKeyEvent & event)218 void FileTreeCtrl::OnKeyDown(wxKeyEvent &event)
219 {
220 if(event.GetKeyCode()==WXK_DELETE)
221 ::wxPostEvent(GetParent(),event);
222 else
223 event.Skip(true);
224 }
225
OnCompareItems(const wxTreeItemId & item1,const wxTreeItemId & item2)226 int FileTreeCtrl::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2)
227 {
228 if((GetItemImage(item1)==fvsFolder)>(GetItemImage(item2)==fvsFolder))
229 return -1;
230 if((GetItemImage(item1)==fvsFolder)<(GetItemImage(item2)==fvsFolder))
231 return 1;
232 if((GetItemImage(item1)==fvsVcNonControlled)<(GetItemImage(item2)==fvsVcNonControlled))
233 return -1;
234 if((GetItemImage(item1)==fvsVcNonControlled)<(GetItemImage(item2)==fvsVcNonControlled))
235 return 1;
236 return (GetItemText(item1).CmpNoCase(GetItemText(item2)));
237 }
238
BEGIN_EVENT_TABLE(FileExplorer,wxPanel)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)
282 END_EVENT_TABLE()
283
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)
288 {
289 m_kill=false;
290 m_update_queue=new UpdateQueue;
291 m_updater=NULL;
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);
299
300 m_show_hidden=false;
301 m_parse_cvs=false;
302 m_parse_hg=false;
303 m_parse_bzr=false;
304 m_parse_git=false;
305 m_parse_svn=false;
306 m_vcs_file_loader=0;
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);
324
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);
334
335 bs->Add(m_Tree, 1, wxEXPAND | wxALL);
336
337 SetAutoLayout(TRUE);
338
339 m_TreeImages = cbProjectTreeImages::MakeImageList(16, *this);
340 m_Tree->SetImageList(m_TreeImages.get());
341
342 ReadConfig();
343 if(m_Loc->GetCount()>m_favdirs.GetCount())
344 {
345 m_Loc->Select(m_favdirs.GetCount());
346 m_root=m_Loc->GetString(m_favdirs.GetCount());
347 } else
348 {
349 m_root=wxFileName::GetPathSeparator();
350 m_Loc->Append(m_root);
351 m_Loc->Select(0);
352 }
353 if(m_WildCards->GetCount()>0)
354 m_WildCards->Select(0);
355 SetRootFolder(m_root);
356
357 SetSizer(bs);
358 }
359
~FileExplorer()360 FileExplorer::~FileExplorer()
361 {
362 m_kill=true;
363 m_updatetimer->Stop();
364 delete m_dir_monitor;
365 WriteConfig();
366 UpdateAbort();
367 delete m_update_queue;
368 delete m_updatetimer;
369 }
370
371
SetRootFolder(wxString root)372 bool FileExplorer::SetRootFolder(wxString root)
373 {
374 UpdateAbort();
375 if(root[root.Len()-1]!=wxFileName::GetPathSeparator())
376 root=root+wxFileName::GetPathSeparator();
377 #ifdef __WXMSW__
378 wxFileName fnroot=wxFileName(root);
379 if(fnroot.GetVolume().IsEmpty())
380 {
381 fnroot.SetVolume(wxFileName(::wxGetCwd()).GetVolume());
382 root=fnroot.GetFullPath();//(wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR)+fnroot.GetFullName();
383 }
384 #endif
385 wxDir dir(root);
386 if (!dir.IsOpened())
387 {
388 // deal with the error here - wxDir would already log an error message
389 // explaining the exact reason of the failure
390 m_Loc->SetValue(m_root);
391 return false;
392 }
393 m_root=root;
394 m_VCS_Control->Clear();
395 m_commit = wxEmptyString;
396 m_VCS_Type->SetLabel(wxEmptyString);
397 m_Box_VCS_Control->Hide(true);
398 m_Loc->SetValue(m_root);
399 m_Tree->DeleteAllItems();
400 m_Tree->AddRoot(m_root,fvsFolder);
401 m_Tree->SetItemHasChildren(m_Tree->GetRootItem());
402 m_Tree->Expand(m_Tree->GetRootItem());
403 Layout();
404
405 return true;
406 // return AddTreeItems(m_Tree->GetRootItem());
407
408 }
409
410 // find a file in the filesystem below a selected root
FindFile(const wxString & findfilename,const wxTreeItemId & ti)411 void FileExplorer::FindFile(const wxString &findfilename, const wxTreeItemId &ti)
412 {
413 wxString path=GetFullPath(ti);
414
415 wxDir dir(path);
416
417 if (!dir.IsOpened())
418 {
419 // deal with the error here - wxDir would already log an error message
420 // explaining the exact reason for the failure
421 return;
422 }
423 wxString filename;
424 int flags=wxDIR_FILES|wxDIR_DIRS;
425 if(m_show_hidden)
426 flags|=wxDIR_HIDDEN;
427
428 DirTraverseFind dtf(findfilename);
429 m_findmatchcount=dir.Traverse(dtf,wxEmptyString,flags);
430 m_findmatch=dtf.GetMatches();
431 }
432
433 // focus the item in the tree.
FocusFile(const wxTreeItemId & ti)434 void FileExplorer::FocusFile(const wxTreeItemId &ti)
435 {
436 m_Tree->SetFocus();
437 m_Tree->UnselectAll();
438 m_Tree->SelectItem(ti);
439 m_Tree->EnsureVisible(ti);
440 }
441
GetNextExpandedNode(wxTreeItemId ti)442 wxTreeItemId FileExplorer::GetNextExpandedNode(wxTreeItemId ti)
443 {
444 wxTreeItemId next_ti;
445 if(!ti.IsOk())
446 {
447 return m_Tree->GetRootItem();
448 }
449 if(m_Tree->IsExpanded(ti))
450 {
451 wxTreeItemIdValue cookie;
452 next_ti=m_Tree->GetFirstChild(ti,cookie);
453 while(next_ti.IsOk())
454 {
455 if(m_Tree->IsExpanded(next_ti))
456 return next_ti;
457 next_ti=m_Tree->GetNextChild(ti,cookie);
458 }
459 }
460 next_ti=m_Tree->GetNextSibling(ti);
461 while(next_ti.IsOk())
462 {
463 if(m_Tree->IsExpanded(next_ti))
464 return next_ti;
465 next_ti=m_Tree->GetNextSibling(next_ti);
466 }
467 return m_Tree->GetRootItem();
468 }
469
GetItemFromPath(const wxString & path,wxTreeItemId & ti)470 bool FileExplorer::GetItemFromPath(const wxString &path, wxTreeItemId &ti)
471 {
472 ti=m_Tree->GetRootItem();
473 do
474 {
475 if(path==GetFullPath(ti))
476 return true;
477 ti=GetNextExpandedNode(ti);
478 } while(ti!=m_Tree->GetRootItem());
479 return false;
480 }
481
482
GetExpandedNodes(wxTreeItemId ti,Expansion * exp)483 void FileExplorer::GetExpandedNodes(wxTreeItemId ti, Expansion *exp)
484 {
485 exp->name=m_Tree->GetItemText(ti);
486 wxTreeItemIdValue cookie;
487 wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
488 while(ch.IsOk())
489 {
490 if(m_Tree->IsExpanded(ch))
491 {
492 Expansion *e=new Expansion();
493 GetExpandedNodes(ch,e);
494 exp->children.push_back(e);
495 }
496 ch=m_Tree->GetNextChild(ti,cookie);
497 }
498 }
499
GetExpandedPaths(wxTreeItemId ti,wxArrayString & paths)500 void FileExplorer::GetExpandedPaths(wxTreeItemId ti,wxArrayString &paths)
501 {
502 if(!ti.IsOk())
503 {
504 wxMessageBox(_("node error"));
505 return;
506 }
507 if(m_Tree->IsExpanded(ti))
508 paths.Add(GetFullPath(ti));
509 wxTreeItemIdValue cookie;
510 wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
511 while(ch.IsOk())
512 {
513 if(m_Tree->IsExpanded(ch))
514 GetExpandedPaths(ch,paths);
515 ch=m_Tree->GetNextChild(ti,cookie);
516 }
517 }
518
RefreshExpanded(wxTreeItemId ti)519 void FileExplorer::RefreshExpanded(wxTreeItemId ti)
520 {
521 if(m_Tree->IsExpanded(ti))
522 m_update_queue->Add(ti);
523 wxTreeItemIdValue cookie;
524 wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
525 while(ch.IsOk())
526 {
527 if(m_Tree->IsExpanded(ch))
528 RefreshExpanded(ch);
529 ch=m_Tree->GetNextChild(ti,cookie);
530 }
531 m_updatetimer->Start(10,true);
532
533 }
534
Refresh(wxTreeItemId ti)535 void FileExplorer::Refresh(wxTreeItemId ti)
536 {
537 // Expansion e;
538 // GetExpandedNodes(ti,&e);
539 // RecursiveRebuild(ti,&e);
540 //m_updating_node=ti;//m_Tree->GetRootItem();
541 m_update_queue->Add(ti);
542 m_updatetimer->Start(10,true);
543 }
544
UpdateAbort()545 void FileExplorer::UpdateAbort()
546 {
547 if(!m_update_active)
548 return;
549 delete m_updater;
550 m_update_active=false;
551 m_updatetimer->Stop();
552 }
553
ResetDirMonitor()554 void FileExplorer::ResetDirMonitor()
555 {
556 wxArrayString paths;
557 GetExpandedPaths(m_Tree->GetRootItem(),paths);
558 m_dir_monitor->ChangePaths(paths);
559 }
560
OnDirMonitor(wxDirectoryMonitorEvent & e)561 void FileExplorer::OnDirMonitor(wxDirectoryMonitorEvent &e)
562 {
563 if(m_kill)
564 return;
565 // TODO: Apparently creating log messages during Code::Blocks shutdown can create segfaults
566 // 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()));
567 if(e.m_event_type==MONITOR_TOO_MANY_CHANGES)
568 {
569 // LogMessage(_("directory change read error"));
570 }
571 wxTreeItemId ti;
572 if(GetItemFromPath(e.m_mon_dir,ti))
573 {
574 m_update_queue->Add(ti);
575 m_updatetimer->Start(100,true);
576 }
577 }
578
OnTimerCheckUpdates(wxTimerEvent &)579 void FileExplorer::OnTimerCheckUpdates(wxTimerEvent &/*e*/)
580 {
581 if(m_kill)
582 return;
583 if(m_update_active)
584 return;
585 wxTreeItemId ti;
586 while(m_update_queue->Pop(ti))
587 {
588 if(!ti.IsOk())
589 continue;
590 m_updater_cancel=false;
591 m_updater=new FileExplorerUpdater(this);
592 m_updated_node=ti;
593 m_update_active=true;
594 m_updater->Update(m_updated_node);
595 break;
596 }
597 }
598
ValidateRoot()599 bool FileExplorer::ValidateRoot()
600 {
601 wxTreeItemId ti=m_Tree->GetRootItem();
602 while(true)
603 {
604 if(!ti.IsOk())
605 break;
606 if(m_Tree->GetItemImage(ti)!=fvsFolder)
607 break;
608 if(!wxFileName::DirExists(GetFullPath(ti)))
609 break;
610 return true;
611 }
612 return false;
613 }
614
OnUpdateTreeItems(wxCommandEvent &)615 void FileExplorer::OnUpdateTreeItems(wxCommandEvent &/*e*/)
616 {
617 if(m_kill)
618 return;
619 m_updater->Wait();
620 wxTreeItemId ti=m_updated_node;
621 bool viewing_commit = (m_updater->m_vcs_commit_string != wxEmptyString) &&
622 (m_updater->m_vcs_commit_string != _T("Working copy"));
623 if (ti == m_Tree->GetRootItem() && !viewing_commit)
624 {
625 m_VCS_Type->SetLabel(m_updater->m_vcs_type);
626 if (m_updater->m_vcs_type == wxEmptyString)
627 {
628 m_VCS_Control->Clear();
629 m_Box_VCS_Control->Hide(true);
630 m_commit = _T("");
631 }
632 else if (m_commit == wxEmptyString)
633 {
634 m_VCS_Control->Clear();
635 m_VCS_Control->Append(_T("Working copy"));
636 m_VCS_Control->Append(_T("Select commit..."));
637 m_VCS_Control->SetSelection(0);
638 m_commit = _T("Working copy");
639 m_Box_VCS_Control->Show(true);
640 }
641 Layout();
642 }
643 if(m_updater_cancel || !ti.IsOk())
644 { //NODE WAS DELETED - REFRESH NOW!
645 //TODO: Should only need to clean up and restart the timer (no need to change queue)
646 delete m_updater;
647 m_updater=NULL;
648 m_update_active=false;
649 ResetDirMonitor();
650 if(ValidateRoot())
651 {
652 m_update_queue->Add(m_Tree->GetRootItem());
653 m_updatetimer->Start(10,true);
654 }
655 return;
656 }
657 // cbMessageBox(_T("Node OK"));
658 // m_Tree->DeleteChildren(ti);
659 FileDataVec &removers=m_updater->m_removers;
660 FileDataVec &adders=m_updater->m_adders;
661 if(removers.size()>0||adders.size()>0)
662 {
663 m_Tree->Freeze();
664 //LOOP THROUGH THE REMOVERS LIST AND REMOVE THOSE ITEMS FROM THE TREE
665 // cbMessageBox(_T("Removers"));
666 for(FileDataVec::iterator it=removers.begin();it!=removers.end();it++)
667 {
668 // cbMessageBox(it->name);
669 wxTreeItemIdValue cookie;
670 wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
671 while(ch.IsOk())
672 {
673 if(it->name==m_Tree->GetItemText(ch))
674 {
675 m_Tree->Delete(ch);
676 break;
677 }
678 ch=m_Tree->GetNextChild(ti,cookie);
679 }
680 }
681 //LOOP THROUGH THE ADDERS LIST AND ADD THOSE ITEMS TO THE TREE
682 // cbMessageBox(_T("Adders"));
683 for(FileDataVec::iterator it=adders.begin();it!=adders.end();it++)
684 {
685 // cbMessageBox(it->name);
686 wxTreeItemId newitem=m_Tree->AppendItem(ti,it->name,it->state);
687 m_Tree->SetItemHasChildren(newitem,it->state==fvsFolder);
688 }
689 m_Tree->SortChildren(ti);
690 m_Tree->Thaw();
691 }
692 if(!m_Tree->IsExpanded(ti))
693 {
694 m_update_expand=true;
695 m_Tree->Expand(ti);
696 }
697 delete m_updater;
698 m_updater=NULL;
699 m_update_active=false;
700 m_updatetimer->Start(10,true);
701 // Restart the monitor (TODO: move this elsewhere??)
702 ResetDirMonitor();
703 }
704
GetFullPath(const wxTreeItemId & ti)705 wxString FileExplorer::GetFullPath(const wxTreeItemId &ti)
706 {
707 if (!ti.IsOk())
708 return wxEmptyString;
709 wxFileName path(m_root);
710 if (ti!=m_Tree->GetRootItem())
711 {
712 std::vector<wxTreeItemId> vti;
713 vti.push_back(ti);
714 wxTreeItemId pti=m_Tree->GetItemParent(vti[0]);
715 if (!pti.IsOk())
716 return wxEmptyString;
717 while (pti != m_Tree->GetRootItem())
718 {
719 vti.insert(vti.begin(), pti);
720 pti=m_Tree->GetItemParent(pti);
721 }
722 //Complicated logic to deal with the fact that the selected item might
723 //be a partial path and not just a filename. It would be far simpler to
724 for (size_t i=0; i<vti.size() - 1; i++)
725 path.AppendDir(m_Tree->GetItemText(vti[i]));
726 wxFileName last_part(m_Tree->GetItemText(vti[vti.size()-1]));
727 wxArrayString as = last_part.GetDirs();
728 for (size_t i=0;i<as.size();i++)
729 path.AppendDir(as[i]);
730 path = wxFileName(path.GetFullPath(), last_part.GetFullName()).GetFullPath();
731 }
732 return path.GetFullPath();
733 }
734
OnExpand(wxTreeEvent & event)735 void FileExplorer::OnExpand(wxTreeEvent &event)
736 {
737 if(m_updated_node==event.GetItem() && m_update_expand)
738 {
739 m_update_expand=false;
740 return;
741 }
742 m_update_queue->Add(event.GetItem());
743 m_updatetimer->Start(10,true);
744 event.Veto();
745 //AddTreeItems(event.GetItem());
746 }
747
ReadConfig()748 void FileExplorer::ReadConfig()
749 {
750 //IMPORT SETTINGS FROM LEGACY SHELLEXTENSIONS PLUGIN - TODO: REMOVE IN NEXT VERSION
751 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("ShellExtensions"));
752 if(!cfg->Exists(_("FileExplorer/ShowHidenFiles")))
753 cfg = Manager::Get()->GetConfigManager(_T("FileManager"));
754 int len=0;
755 cfg->Read(_T("FileExplorer/FavRootList/Len"), &len);
756 for(int i=0;i<len;i++)
757 {
758 wxString ref=wxString::Format(_T("FileExplorer/FavRootList/I%i"),i);
759 wxString loc;
760 FavoriteDir fav;
761 cfg->Read(ref+_T("/alias"), &fav.alias);
762 cfg->Read(ref+_T("/path"), &fav.path);
763 m_Loc->Append(fav.alias);
764 m_favdirs.Add(fav);
765 }
766 len=0;
767 cfg->Read(_T("FileExplorer/RootList/Len"), &len);
768 for(int i=0;i<len;i++)
769 {
770 wxString ref=wxString::Format(_T("FileExplorer/RootList/I%i"),i);
771 wxString loc;
772 cfg->Read(ref, &loc);
773 m_Loc->Append(loc);
774 }
775 len=0;
776 cfg->Read(_T("FileExplorer/WildMask/Len"), &len);
777 for(int i=0;i<len;i++)
778 {
779 wxString ref=wxString::Format(_T("FileExplorer/WildMask/I%i"),i);
780 wxString wild;
781 cfg->Read(ref, &wild);
782 m_WildCards->Append(wild);
783 }
784 cfg->Read(_T("FileExplorer/ParseCVS"), &m_parse_cvs);
785 cfg->Read(_T("FileExplorer/ParseSVN"), &m_parse_svn);
786 cfg->Read(_T("FileExplorer/ParseHG"), &m_parse_hg);
787 cfg->Read(_T("FileExplorer/ParseBZR"), &m_parse_bzr);
788 cfg->Read(_T("FileExplorer/ParseGIT"), &m_parse_git);
789 cfg->Read(_T("FileExplorer/ShowHiddenFiles"), &m_show_hidden);
790 }
791
WriteConfig()792 void FileExplorer::WriteConfig()
793 {
794 //DISCARD SETTINGS FROM LEGACY SHELLEXTENSIONS PLUGIN - TODO: REMOVE IN NEXT VERSION
795 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("ShellExtensions"));
796 if(cfg->Exists(_("FileExplorer/ShowHidenFiles")))
797 cfg->DeleteSubPath(_("FileExplorer"));
798 cfg = Manager::Get()->GetConfigManager(_T("FileManager"));
799 //cfg->Clear();
800 int count=static_cast<int>(m_favdirs.GetCount());
801 cfg->Write(_T("FileExplorer/FavRootList/Len"), count);
802 for(int i=0;i<count;i++)
803 {
804 wxString ref=wxString::Format(_T("FileExplorer/FavRootList/I%i"),i);
805 cfg->Write(ref+_T("/alias"), m_favdirs[i].alias);
806 cfg->Write(ref+_T("/path"), m_favdirs[i].path);
807 }
808 count=static_cast<int>(m_Loc->GetCount())-static_cast<int>(m_favdirs.GetCount());
809 cfg->Write(_T("FileExplorer/RootList/Len"), count);
810 for(int i=0;i<count;i++)
811 {
812 wxString ref=wxString::Format(_T("FileExplorer/RootList/I%i"),i);
813 cfg->Write(ref, m_Loc->GetString(m_favdirs.GetCount()+i));
814 }
815 count=static_cast<int>(m_Loc->GetCount());
816 cfg->Write(_T("FileExplorer/WildMask/Len"), count);
817 for(int i=0;i<count;i++)
818 {
819 wxString ref=wxString::Format(_T("FileExplorer/WildMask/I%i"),i);
820 cfg->Write(ref, m_WildCards->GetString(i));
821 }
822 cfg->Write(_T("FileExplorer/ParseCVS"), m_parse_cvs);
823 cfg->Write(_T("FileExplorer/ParseSVN"), m_parse_svn);
824 cfg->Write(_T("FileExplorer/ParseHG"), m_parse_hg);
825 cfg->Write(_T("FileExplorer/ParseBZR"), m_parse_bzr);
826 cfg->Write(_T("FileExplorer/ParseGIT"), m_parse_git);
827 cfg->Write(_T("FileExplorer/ShowHiddenFiles"), m_show_hidden);
828 }
829
OnEnterWild(wxCommandEvent &)830 void FileExplorer::OnEnterWild(wxCommandEvent &/*event*/)
831 {
832 wxString wild=m_WildCards->GetValue();
833 for(size_t i=0;i<m_WildCards->GetCount();i++)
834 {
835 wxString cmp;
836 cmp=m_WildCards->GetString(i);
837 if(cmp==wild)
838 {
839 m_WildCards->Delete(i);
840 m_WildCards->Insert(wild,0);
841 m_WildCards->SetSelection(0);
842 RefreshExpanded(m_Tree->GetRootItem());
843 return;
844 }
845 }
846 m_WildCards->Insert(wild,0);
847 if(m_WildCards->GetCount()>10)
848 m_WildCards->Delete(10);
849 m_WildCards->SetSelection(0);
850 RefreshExpanded(m_Tree->GetRootItem());
851 }
852
OnChooseWild(wxCommandEvent &)853 void FileExplorer::OnChooseWild(wxCommandEvent &/*event*/)
854 {
855 // Beware on win32 that if user opens drop down, then types a wildcard the combo box
856 // event will contain a -1 selection and an empty string item. Harmless in current code.
857 wxString wild=m_WildCards->GetValue();
858 m_WildCards->Delete(m_WildCards->GetSelection());
859 m_WildCards->Insert(wild,0);
860 // event.Skip(true);
861 // cbMessageBox(wild);
862 m_WildCards->SetSelection(0);
863 RefreshExpanded(m_Tree->GetRootItem());
864 }
865
OnEnterLoc(wxCommandEvent &)866 void FileExplorer::OnEnterLoc(wxCommandEvent &/*event*/)
867 {
868 wxString loc=m_Loc->GetValue();
869 if(!SetRootFolder(loc))
870 return;
871 for(size_t i=0;i<m_Loc->GetCount();i++)
872 {
873 wxString cmp;
874 if(i<m_favdirs.GetCount())
875 cmp=m_favdirs[i].path;
876 else
877 cmp=m_Loc->GetString(i);
878 if(cmp==m_root)
879 {
880 if(i>=m_favdirs.GetCount())
881 {
882 m_Loc->Delete(i);
883 m_Loc->Insert(m_root,m_favdirs.GetCount());
884 }
885 m_Loc->SetSelection(m_favdirs.GetCount());
886 return;
887 }
888 }
889 m_Loc->Insert(m_root,m_favdirs.GetCount());
890 if(m_Loc->GetCount()>10+m_favdirs.GetCount())
891 m_Loc->Delete(10+m_favdirs.GetCount());
892 m_Loc->SetSelection(m_favdirs.GetCount());
893 }
894
OnChooseLoc(wxCommandEvent & event)895 void FileExplorer::OnChooseLoc(wxCommandEvent &event)
896 {
897 wxString loc;
898 // on WIN32 if the user opens the drop down, but then types a path instead, this event
899 // fires with an empty string, so we have no choice but to return null. This event
900 // doesn't happen on Linux (the drop down closes when the user starts typing)
901 if(event.GetInt()<0)
902 return;
903 if(event.GetInt()>=static_cast<int>(m_favdirs.GetCount()))
904 loc=m_Loc->GetValue();
905 else
906 loc=m_favdirs[event.GetInt()].path;
907 if(!SetRootFolder(loc))
908 return;
909 if(event.GetInt()>=static_cast<int>(m_favdirs.GetCount()))
910 {
911 m_Loc->Delete(event.GetInt());
912 m_Loc->Insert(m_root,m_favdirs.GetCount());
913 m_Loc->SetSelection(m_favdirs.GetCount());
914 }
915 else
916 {
917 for(size_t i=m_favdirs.GetCount();i<m_Loc->GetCount();i++)
918 {
919 wxString cmp;
920 cmp=m_Loc->GetString(i);
921 if(cmp==m_root)
922 {
923 m_Loc->Delete(i);
924 m_Loc->Insert(m_root,m_favdirs.GetCount());
925 m_Loc->SetSelection(event.GetInt());
926 return;
927 }
928 }
929 m_Loc->Insert(m_root,m_favdirs.GetCount());
930 if(m_Loc->GetCount()>10+m_favdirs.GetCount())
931 m_Loc->Delete(10+m_favdirs.GetCount());
932 m_Loc->SetSelection(event.GetInt());
933 }
934 }
935
OnSetLoc(wxCommandEvent &)936 void FileExplorer::OnSetLoc(wxCommandEvent &/*event*/)
937 {
938 wxString loc=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
939 if(!SetRootFolder(loc))
940 return;
941 m_Loc->Insert(m_root,m_favdirs.GetCount());
942 if(m_Loc->GetCount()>10+m_favdirs.GetCount())
943 m_Loc->Delete(10+m_favdirs.GetCount());
944 }
945
OnVCSChangesCheck(wxCommandEvent &)946 void FileExplorer::OnVCSChangesCheck(wxCommandEvent &/*event*/)
947 {
948 Refresh(m_Tree->GetRootItem());
949 }
950
OnVCSControl(wxCommandEvent &)951 void FileExplorer::OnVCSControl(wxCommandEvent &/*event*/)
952 {
953 wxString commit = m_VCS_Control->GetString(m_VCS_Control->GetSelection());
954 if (commit == _T("Select commit..."))
955 {
956 CommitBrowser *cm = new CommitBrowser(this, GetFullPath(m_Tree->GetRootItem()), m_VCS_Type->GetLabel());
957 if(cm->ShowModal() == wxID_OK)
958 {
959 commit = cm->GetSelectedCommit();
960 cm->Destroy();
961 if (commit != wxEmptyString)
962 {
963 unsigned int i=0;
964 for (; i<m_VCS_Control->GetCount(); ++i)
965 {
966 if (m_VCS_Control->GetString(i) == commit)
967 {
968 m_VCS_Control->SetSelection(i);
969 break;
970 }
971 }
972 if (i == m_VCS_Control->GetCount())
973 m_VCS_Control->Append(commit);
974 m_VCS_Control->SetSelection(m_VCS_Control->GetCount()-1);
975 }
976 }
977 else
978 commit = wxEmptyString;
979 }
980 if (commit!=wxEmptyString)
981 {
982 m_commit = commit;
983 Refresh(m_Tree->GetRootItem());
984 } else
985 {
986 unsigned int i=0;
987 for (; i<m_VCS_Control->GetCount(); ++i)
988 {
989 if (m_VCS_Control->GetString(i) == m_commit)
990 {
991 m_VCS_Control->SetSelection(i);
992 break;
993 }
994 }
995 }
996 }
997
OnOpenInEditor(wxCommandEvent &)998 void FileExplorer::OnOpenInEditor(wxCommandEvent &/*event*/)
999 {
1000 for(int i=0;i<m_ticount;i++)
1001 {
1002 if (IsBrowsingVCSTree())
1003 {
1004 wxFileName path(GetFullPath(m_selectti[i]));
1005 wxString original_path = path.GetFullPath();
1006 path.MakeRelativeTo(GetRootFolder());
1007 wxString name = path.GetFullName();
1008 wxString vcs_type = m_VCS_Type->GetLabel();
1009 name = vcs_type + _T("-") + m_commit.Mid(0,6) + _T("-") + name;
1010 path.SetFullName(name);
1011 wxFileName tmp = wxFileName(wxFileName::GetTempDir(),_T(""));
1012 tmp.AppendDir(_T("codeblocks-fm"));
1013 path.MakeAbsolute(tmp.GetFullPath());
1014 if(!path.FileExists())
1015 m_vcs_file_loader_queue.Add(_T("cat"), original_path, path.GetFullPath());
1016 else
1017 DoOpenInEditor(path.GetFullPath());
1018 }
1019 else
1020 {
1021 wxFileName path(GetFullPath(m_selectti[i]));
1022 wxString filename=path.GetFullPath();
1023 if(!path.FileExists())
1024 continue;
1025 DoOpenInEditor(filename);
1026 }
1027 }
1028 if (m_vcs_file_loader==0 && !m_vcs_file_loader_queue.empty())
1029 {
1030 LoaderQueueItem item = m_vcs_file_loader_queue.Pop();
1031 m_vcs_file_loader = new VCSFileLoader(this);
1032 m_vcs_file_loader->Update(item.op, item.source, item.destination, item.comp_commit);
1033 }
1034 }
1035
OnVCSDiff(wxCommandEvent & event)1036 void FileExplorer::OnVCSDiff(wxCommandEvent &event)
1037 {
1038 wxString comp_commit;
1039 if (event.GetId() == ID_FILEDIFF) //Diff with head (for working copy) or previous (for commit)
1040 comp_commit = _T("Previous");
1041 else //Otherwise diff against specific revision
1042 comp_commit = m_VCS_Control->GetString(event.GetId()-ID_FILEDIFF1);
1043 if (m_commit == _T("Working copy") && comp_commit == _T("Working copy"))
1044 comp_commit = _T("Previous");
1045 if (comp_commit == _T("Select commit..."))
1046 {
1047 wxString diff_paths;
1048 for(int i=0;i<m_ticount;i++)
1049 {
1050 wxFileName path(GetFullPath(m_selectti[i]));
1051 path.MakeRelativeTo(GetRootFolder());
1052 if (path != wxEmptyString)
1053 diff_paths+=_T(" \"") + path.GetFullPath() + _T("\"");
1054 }
1055 CommitBrowser *cm = new CommitBrowser(this, GetFullPath(m_Tree->GetRootItem()), m_VCS_Type->GetLabel(), diff_paths);
1056 if(cm->ShowModal() == wxID_OK)
1057 {
1058 comp_commit = cm->GetSelectedCommit();
1059 }
1060 else
1061 return;
1062 }
1063 wxString diff_paths = wxEmptyString;
1064 for(int i=0;i<m_ticount;i++)
1065 {
1066 wxFileName path(GetFullPath(m_selectti[i]));
1067 path.MakeRelativeTo(GetRootFolder());
1068 if (path != wxEmptyString)
1069 diff_paths+=_T(" \"") + path.GetFullPath() + _T("\"");
1070 }
1071 wxFileName tmp = wxFileName(wxFileName::GetTempDir(),_T(""));
1072 wxFileName root_path(GetRootFolder());
1073 wxString name = root_path.GetName();
1074 wxString vcs_type = m_VCS_Type->GetLabel();
1075 tmp.AppendDir(_T("codeblocks-fm"));
1076 name = _T("diff-") + vcs_type + _T("-") + m_commit.Mid(0,7) +_T("~") + comp_commit + _T("-") + name + _T(".patch");
1077 wxString dest_tmp_path = wxFileName(tmp.GetFullPath(), name).GetFullPath();
1078 m_vcs_file_loader_queue.Add(_T("diff"), diff_paths, dest_tmp_path, comp_commit);
1079 if (m_vcs_file_loader==0 && !m_vcs_file_loader_queue.empty())
1080 {
1081 LoaderQueueItem item = m_vcs_file_loader_queue.Pop();
1082 m_vcs_file_loader = new VCSFileLoader(this);
1083 m_vcs_file_loader->Update(item.op, item.source, item.destination, item.comp_commit);
1084 }
1085 }
1086
OnVCSFileLoaderComplete(wxCommandEvent &)1087 void FileExplorer::OnVCSFileLoaderComplete(wxCommandEvent& /*event*/)
1088 {
1089 m_vcs_file_loader->Wait();
1090 DoOpenInEditor(m_vcs_file_loader->m_destination_path);
1091 delete m_vcs_file_loader;
1092 m_vcs_file_loader = 0;
1093 if (!m_vcs_file_loader_queue.empty())
1094 {
1095 LoaderQueueItem item = m_vcs_file_loader_queue.Pop();
1096 m_vcs_file_loader = new VCSFileLoader(this);
1097 m_vcs_file_loader->Update(item.op, item.source, item.destination, item.comp_commit);
1098 }
1099 }
1100
DoOpenInEditor(const wxString & filename)1101 void FileExplorer::DoOpenInEditor(const wxString &filename)
1102 {
1103 EditorManager* em = Manager::Get()->GetEditorManager();
1104 EditorBase* eb = em->IsOpen(filename);
1105 if (eb)
1106 {
1107 // open files just get activated
1108 eb->Activate();
1109 return;
1110 } else
1111 em->Open(filename);
1112 }
1113
OnActivate(wxTreeEvent & event)1114 void FileExplorer::OnActivate(wxTreeEvent &event)
1115 {
1116 if (IsBrowsingVCSTree())
1117 {
1118 //TODO: Should just retrieve the file and use the same mimetype handling as a regular file
1119 wxCommandEvent e;
1120 m_ticount=m_Tree->GetSelections(m_selectti);
1121 OnOpenInEditor(e);
1122 return;
1123 }
1124 wxString filename=GetFullPath(event.GetItem());
1125 if(m_Tree->GetItemImage(event.GetItem())==fvsFolder)
1126 {
1127 event.Skip(true);
1128 return;
1129 }
1130 EditorManager* em = Manager::Get()->GetEditorManager();
1131 EditorBase* eb = em->IsOpen(filename);
1132 if (eb)
1133 {
1134 // open files just get activated
1135 eb->Activate();
1136 return;
1137 }
1138
1139 // Use Mime handler to open file
1140 cbMimePlugin* plugin = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile(filename);
1141 if (!plugin)
1142 {
1143 wxString msg;
1144 msg.Printf(_("Could not open file '%s'.\nNo handler registered for this type of file."), filename.c_str());
1145 LogErrorMessage(msg);
1146 // em->Open(filename); //should never need to open the file from here
1147 }
1148 else if (plugin->OpenFile(filename) != 0)
1149 {
1150 const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1151 wxString msg;
1152 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());
1153 LogErrorMessage(msg);
1154 }
1155
1156 // if(!em->IsOpen(file))
1157 // em->Open(file);
1158
1159 }
1160
1161
OnKeyDown(wxKeyEvent & event)1162 void FileExplorer::OnKeyDown(wxKeyEvent &event)
1163 {
1164 if(event.GetKeyCode() == WXK_DELETE)
1165 {
1166 if (IsBrowsingVCSTree())
1167 {
1168 wxCommandEvent event2;
1169 OnDelete(event2);
1170 }
1171 }
1172 }
1173
1174
IsBrowsingVCSTree()1175 bool FileExplorer::IsBrowsingVCSTree()
1176 {
1177 return m_commit != _T("Working copy") && m_commit != wxEmptyString;
1178 }
1179
IsBrowsingWorkingCopy()1180 bool FileExplorer::IsBrowsingWorkingCopy()
1181 {
1182 return m_commit == _T("Working copy") && m_commit != wxEmptyString;
1183 }
1184
OnRightClick(wxTreeEvent & event)1185 void FileExplorer::OnRightClick(wxTreeEvent &event)
1186 {
1187 wxMenu* Popup = new wxMenu();
1188 m_ticount=m_Tree->GetSelections(m_selectti);
1189 if(!IsInSelection(event.GetItem())) //replace the selection with right clicked item if right clicked item isn't in the selection
1190 {
1191 for(int i=0;i<m_ticount;i++)
1192 m_Tree->SelectItem(m_selectti[i],false);
1193 m_Tree->SelectItem(event.GetItem());
1194 m_ticount=m_Tree->GetSelections(m_selectti);
1195 m_Tree->Update();
1196 }
1197 FileTreeData* ftd = new FileTreeData(0, FileTreeData::ftdkUndefined);
1198 ftd->SetKind(FileTreeData::ftdkFile);
1199 if(m_ticount>0)
1200 {
1201 if(m_ticount==1)
1202 {
1203 int img = m_Tree->GetItemImage(m_selectti[0]);
1204 if(img==fvsFolder)
1205 {
1206 ftd->SetKind(FileTreeData::ftdkFolder);
1207 Popup->Append(ID_SETLOC,_("Make roo&t"));
1208 Popup->Append(ID_FILEEXPANDALL,_("Expand all children")); //TODO: check availability in wx2.8 for win32 (not avail wx2.6)
1209 Popup->Append(ID_FILECOLLAPSEALL,_("Collapse all children")); //TODO: check availability in wx2.8 for win32 (not avail wx2.6)
1210 if (!IsBrowsingVCSTree())
1211 {
1212 Popup->Append(ID_FILEMAKEFAV,_("Add to favorites"));
1213 Popup->Append(ID_FILENEWFILE,_("New file..."));
1214 Popup->Append(ID_FILENEWFOLDER,_("New directory..."));
1215 Popup->Append(ID_FILERENAME,_("&Rename..."));
1216 }
1217 } else
1218 {
1219 if (!IsBrowsingVCSTree())
1220 Popup->Append(ID_FILERENAME,_("&Rename..."));
1221 }
1222 }
1223 if(IsFilesOnly(m_selectti))
1224 {
1225 Popup->Append(ID_OPENINED,_("&Open in CB editor"));
1226 if (!IsBrowsingVCSTree())
1227 if(Manager::Get()->GetProjectManager()->GetActiveProject())
1228 Popup->Append(ID_FILEADDTOPROJECT,_("&Add to active project..."));
1229 }
1230 if (!IsBrowsingVCSTree())
1231 {
1232 Popup->Append(ID_FILEDUP,_("&Duplicate"));
1233 Popup->Append(ID_FILECOPY,_("&Copy to..."));
1234 Popup->Append(ID_FILEMOVE,_("&Move to..."));
1235 Popup->Append(ID_FILEDELETE,_("D&elete"));
1236 }
1237 if ( IsBrowsingVCSTree() || IsBrowsingWorkingCopy() )
1238 {
1239 if (IsBrowsingWorkingCopy())
1240 Popup->Append(ID_FILEDIFF,_("&Diff"));
1241 else
1242 Popup->Append(ID_FILEDIFF,_("&Diff previous"));
1243 wxMenu *diff_menu = new wxMenu();
1244 unsigned int n = m_VCS_Control->GetCount();
1245 if (n>10)
1246 n=10;
1247 if (IsBrowsingWorkingCopy())
1248 {
1249 diff_menu->Append(ID_FILEDIFF1, _("Head"));
1250 for (unsigned int i = 1; i<n; ++i)
1251 diff_menu->Append(ID_FILEDIFF1 + i, m_VCS_Control->GetString(i));
1252 }
1253 else
1254 {
1255 for (unsigned int i = 0; i<n; ++i)
1256 diff_menu->Append(ID_FILEDIFF1 + i, m_VCS_Control->GetString(i));
1257 }
1258 Popup->AppendSubMenu(diff_menu,_("Diff against"));
1259 }
1260 }
1261 wxMenu *viewpop=new wxMenu();
1262 viewpop->Append(ID_FILESETTINGS,_("Favorite directories..."));
1263 viewpop->AppendCheckItem(ID_FILESHOWHIDDEN,_("Show &hidden files"))->Check(m_show_hidden);
1264 // viewpop->AppendCheckItem(ID_FILEPARSECVS,_("CVS decorators"))->Check(m_parse_cvs);
1265 viewpop->AppendCheckItem(ID_FILEPARSESVN,_("SVN integration"))->Check(m_parse_svn);
1266 viewpop->AppendCheckItem(ID_FILEPARSEHG,_("Hg integration"))->Check(m_parse_hg);
1267 viewpop->AppendCheckItem(ID_FILEPARSEBZR,_("Bzr integration"))->Check(m_parse_bzr);
1268 viewpop->AppendCheckItem(ID_FILEPARSEGIT,_("Git integration"))->Check(m_parse_git);
1269 if(m_ticount>1)
1270 {
1271 ftd->SetKind(FileTreeData::ftdkVirtualGroup);
1272 wxString pathlist = GetFullPath(m_selectti[0]);
1273 for(int i=1;i<m_ticount;i++)
1274 pathlist += _T("*") + GetFullPath(m_selectti[i]); //passing a '*' separated list of files/directories to any plugin takers
1275 ftd->SetFolder(pathlist);
1276 }
1277 else if ( m_ticount > 0)
1278 {
1279 wxString filepath = GetFullPath(m_selectti[0]);
1280 ftd->SetFolder(filepath);
1281 }
1282 if(m_ticount>0)
1283 Manager::Get()->GetPluginManager()->AskPluginsForModuleMenu(mtUnknown, Popup, ftd);
1284 delete ftd;
1285 Popup->AppendSeparator();
1286 Popup->AppendSubMenu(viewpop,_("&Settings"));
1287 Popup->Append(ID_FILEREFRESH,_("Re&fresh"));
1288 wxWindow::PopupMenu(Popup);
1289 delete Popup;
1290 }
1291
OnNewFile(wxCommandEvent &)1292 void FileExplorer::OnNewFile(wxCommandEvent &/*event*/)
1293 {
1294 wxString workingdir=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1295 wxTextEntryDialog te(this,_("Name Your New File: "));
1296 if(te.ShowModal()!=wxID_OK)
1297 return;
1298 wxString name=te.GetValue();
1299 wxFileName file(workingdir);
1300 file.Assign(file.GetFullPath(),name);
1301 wxString newfile=file.GetFullPath();
1302 if(!wxFileName::FileExists(newfile) &&!wxFileName::DirExists(newfile))
1303 {
1304 wxFile fileobj;
1305 if(fileobj.Create(newfile))
1306 {
1307 fileobj.Close();
1308 Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1309 }
1310 else
1311 cbMessageBox(_("File Creation Failed"),_("Error"));
1312 }
1313 else
1314 cbMessageBox(_("File/Directory Already Exists with Name ")+name, _("Error"));
1315 }
1316
OnAddFavorite(wxCommandEvent &)1317 void FileExplorer::OnAddFavorite(wxCommandEvent &/*event*/)
1318 {
1319 FavoriteDir fav;
1320 fav.path=GetFullPath(m_selectti[0]);
1321 if(fav.path[fav.path.Len()-1]!=wxFileName::GetPathSeparator())
1322 fav.path=fav.path+wxFileName::GetPathSeparator();
1323 wxTextEntryDialog ted(NULL,_("Enter an alias for this directory:"),_("Add Favorite Directory"),fav.path);
1324 if(ted.ShowModal()!=wxID_OK)
1325 return;
1326 wxString name=ted.GetValue();
1327 fav.alias=name;
1328 m_favdirs.Insert(fav,0);
1329 m_Loc->Insert(name,0);
1330 }
1331
OnNewFolder(wxCommandEvent &)1332 void FileExplorer::OnNewFolder(wxCommandEvent &/*event*/)
1333 {
1334 wxString workingdir=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1335 wxTextEntryDialog te(this,_("New Directory Name: "));
1336 if(te.ShowModal()!=wxID_OK)
1337 return;
1338 wxString name=te.GetValue();
1339 wxFileName dir(workingdir);
1340 dir.Assign(dir.GetFullPath(),name);
1341 wxString mkd=dir.GetFullPath();
1342 if(!wxFileName::DirExists(mkd) &&!wxFileName::FileExists(mkd))
1343 {
1344 if (!dir.Mkdir(mkd))
1345 cbMessageBox(_("A directory could not be created with name ")+name);
1346 Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1347 }
1348 else
1349 cbMessageBox(_("A file or directory already exists with name ")+name);
1350 }
1351
OnDuplicate(wxCommandEvent &)1352 void FileExplorer::OnDuplicate(wxCommandEvent &/*event*/)
1353 {
1354 m_ticount=m_Tree->GetSelections(m_selectti);
1355 for(int i=0;i<m_ticount;i++)
1356 {
1357 wxFileName path(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1358 if(wxFileName::FileExists(path.GetFullPath())||wxFileName::DirExists(path.GetFullPath()))
1359 {
1360 if(!PromptSaveOpenFile(_("File is modified, press Yes to save before duplication, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
1361 continue;
1362 int j=1;
1363 wxString destpath(path.GetPathWithSep()+path.GetName()+wxString::Format(_T("(%i)"),j));
1364 if(path.GetExt()!=wxEmptyString)
1365 destpath+=_T(".")+path.GetExt();
1366 while(j<100 && (wxFileName::FileExists(destpath) || wxFileName::DirExists(destpath)))
1367 {
1368 j++;
1369 destpath=path.GetPathWithSep()+path.GetName()+wxString::Format(_T("(%i)"),j);
1370 if(path.GetExt()!=wxEmptyString)
1371 destpath+=_T(".")+path.GetExt();
1372 }
1373 if(j==100)
1374 {
1375 cbMessageBox(_("Too many copies of file or directory"));
1376 continue;
1377 }
1378
1379 #ifdef __WXMSW__
1380 wxArrayString output;
1381 wxString cmdline;
1382 if(wxFileName::FileExists(path.GetFullPath()))
1383 cmdline=_T("cmd /c copy /Y \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
1384 else
1385 cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
1386 int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
1387 #else
1388 wxString cmdline=_T("/bin/cp -r -b \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
1389 int hresult=::wxExecute(cmdline,wxEXEC_SYNC);
1390 #endif
1391 if(hresult)
1392 MessageBox(m_Tree,_("Command '")+cmdline+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1393 }
1394 }
1395 Refresh(m_Tree->GetRootItem()); //TODO: Can probably be more efficient than this
1396 //TODO: Reselect item in new location?? (what it outside root scope?)
1397 }
1398
1399
CopyFiles(const wxString & destination,const wxArrayString & selectedfiles)1400 void FileExplorer::CopyFiles(const wxString &destination, const wxArrayString &selectedfiles)
1401 {
1402 for(unsigned int i=0;i<selectedfiles.Count();i++)
1403 {
1404 wxString path=selectedfiles[i];
1405 wxFileName destpath;
1406 destpath.Assign(destination,wxFileName(path).GetFullName());
1407 if(destpath.SameAs(path))
1408 continue;
1409 if(wxFileName::FileExists(path)||wxFileName::DirExists(path))
1410 {
1411 if(!PromptSaveOpenFile(_("File is modified, press Yes to save before duplication, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
1412 continue;
1413 #ifdef __WXMSW__
1414 wxArrayString output;
1415 wxString cmdline;
1416 if(wxFileName::FileExists(path))
1417 cmdline=_T("cmd /c copy /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1418 else
1419 cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1420 int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
1421 #else
1422 int hresult=::wxExecute(_T("/bin/cp -r -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1423 #endif
1424 if(hresult)
1425 MessageBox(m_Tree,_("Copying '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1426 }
1427 }
1428 }
1429
OnCopy(wxCommandEvent &)1430 void FileExplorer::OnCopy(wxCommandEvent &/*event*/)
1431 {
1432 wxDirDialog dd(this,_("Copy to"));
1433 dd.SetPath(GetFullPath(m_Tree->GetRootItem()));
1434 wxArrayString selectedfiles;
1435 m_ticount=m_Tree->GetSelections(m_selectti);
1436 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.
1437 {
1438 selectedfiles.Add(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1439 }
1440 if(dd.ShowModal()==wxID_CANCEL)
1441 return;
1442 CopyFiles(dd.GetPath(),selectedfiles);
1443 // Refresh(m_Tree->GetRootItem()); //TODO: Use this if monitoring not available
1444 //TODO: Reselect item in new location?? (what if outside root scope?)
1445 }
1446
MoveFiles(const wxString & destination,const wxArrayString & selectedfiles)1447 void FileExplorer::MoveFiles(const wxString &destination, const wxArrayString &selectedfiles)
1448 {
1449 for(unsigned int i=0;i<selectedfiles.Count();i++)
1450 {
1451 wxString path=selectedfiles[i];
1452 wxFileName destpath;
1453 destpath.Assign(destination,wxFileName(path).GetFullName());
1454 if(destpath.SameAs(path)) //TODO: Log message that can't copy over self.
1455 continue;
1456 if(wxFileName::FileExists(path)||wxFileName::DirExists(path))
1457 {
1458 #ifdef __WXMSW__
1459 wxArrayString output;
1460 int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
1461 #else
1462 int hresult=::wxExecute(_T("/bin/mv -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1463 #endif
1464 if(hresult)
1465 MessageBox(m_Tree,_("Moving '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1466 }
1467 }
1468 }
1469
OnMove(wxCommandEvent &)1470 void FileExplorer::OnMove(wxCommandEvent &/*event*/)
1471 {
1472 wxDirDialog dd(this,_("Move to"));
1473 wxArrayString selectedfiles;
1474 m_ticount=m_Tree->GetSelections(m_selectti);
1475 for(int i=0;i<m_ticount;i++)
1476 selectedfiles.Add(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1477 dd.SetPath(GetFullPath(m_Tree->GetRootItem()));
1478 if(dd.ShowModal()==wxID_CANCEL)
1479 return;
1480 MoveFiles(dd.GetPath(),selectedfiles);
1481 // Refresh(m_Tree->GetRootItem()); //TODO: Can probably be more efficient than this
1482 //TODO: Reselect item in new location?? (what if outside root scope?)
1483 }
1484
GetSelectedPaths()1485 wxArrayString FileExplorer::GetSelectedPaths()
1486 {
1487 wxArrayString paths;
1488 for(int i=0;i<m_ticount;i++)
1489 {
1490 wxString path(GetFullPath(m_selectti[i])); //SINGLE: m_Tree->GetSelection()
1491 paths.Add(path);
1492 }
1493 return paths;
1494 }
1495
OnDelete(wxCommandEvent &)1496 void FileExplorer::OnDelete(wxCommandEvent &/*event*/)
1497 {
1498 m_ticount=m_Tree->GetSelections(m_selectti);
1499 wxArrayString as=GetSelectedPaths();
1500 wxString prompt=_("Your are about to delete\n\n");
1501 for(unsigned int i=0;i<as.Count();i++)
1502 prompt+=as[i]+_("\n");
1503 prompt+=_("\nAre you sure?");
1504 if(MessageBox(m_Tree,prompt,_("Delete"),wxYES_NO)!=wxID_YES)
1505 return;
1506 for(unsigned int i=0;i<as.Count();i++)
1507 {
1508 wxString path=as[i]; //SINGLE: m_Tree->GetSelection()
1509 if(wxFileName::FileExists(path))
1510 {
1511 // EditorManager* em = Manager::Get()->GetEditorManager();
1512 // if(em->IsOpen(path))
1513 // {
1514 // cbMessageBox(_("Close file ")+path.GetFullPath()+_(" first"));
1515 // return;
1516 // }
1517 if(!::wxRemoveFile(path))
1518 MessageBox(m_Tree,_("Delete file '")+path+_("' failed"));
1519 } else
1520 if(wxFileName::DirExists(path))
1521 {
1522 #ifdef __WXMSW__
1523 wxArrayString output;
1524 int hresult=::wxExecute(_T("cmd /c rmdir /S/Q \"")+path+_T("\""),output,wxEXEC_SYNC);
1525 #else
1526 int hresult=::wxExecute(_T("/bin/rm -r -f \"")+path+_T("\""),wxEXEC_SYNC);
1527 #endif
1528 if(hresult)
1529 MessageBox(m_Tree,_("Delete directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1530 }
1531 }
1532 Refresh(m_Tree->GetRootItem());
1533 }
1534
OnRename(wxCommandEvent &)1535 void FileExplorer::OnRename(wxCommandEvent &/*event*/)
1536 {
1537 wxString path(GetFullPath(m_selectti[0])); //SINGLE: m_Tree->GetSelection()
1538 if(wxFileName::FileExists(path))
1539 {
1540 EditorManager* em = Manager::Get()->GetEditorManager();
1541 if(em->IsOpen(path))
1542 {
1543 cbMessageBox(_("Close file first"));
1544 return;
1545 }
1546 wxTextEntryDialog te(this,_("New name:"),_("Rename File"),wxFileName(path).GetFullName());
1547 if(te.ShowModal()==wxID_CANCEL)
1548 return;
1549 wxFileName destpath(path);
1550 destpath.SetFullName(te.GetValue());
1551 if(!::wxRenameFile(path,destpath.GetFullPath()))
1552 cbMessageBox(_("Rename failed"));
1553 }
1554 if(wxFileName::DirExists(path))
1555 {
1556 wxTextEntryDialog te(this,_("New name:"),_("Rename File"),wxFileName(path).GetFullName());
1557 if(te.ShowModal()==wxID_CANCEL)
1558 return;
1559 wxFileName destpath(path);
1560 destpath.SetFullName(te.GetValue());
1561 #ifdef __WXMSW__
1562 wxArrayString output;
1563 int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
1564 #else
1565 int hresult=::wxExecute(_T("/bin/mv \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1566 #endif
1567 if(hresult)
1568 MessageBox(m_Tree,_("Rename directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1569 }
1570 Refresh(m_Tree->GetItemParent(m_selectti[0])); //SINGLE: m_Tree->GetSelection()
1571 }
1572
OnExpandAll(wxCommandEvent &)1573 void FileExplorer::OnExpandAll(wxCommandEvent &/*event*/)
1574 {
1575 m_Tree->ExpandAllChildren(m_Tree->GetSelection());
1576 }
1577
OnCollapseAll(wxCommandEvent &)1578 void FileExplorer::OnCollapseAll(wxCommandEvent &/*event*/)
1579 {
1580 m_Tree->CollapseAllChildren(m_Tree->GetSelection());
1581 }
1582
OnSettings(wxCommandEvent &)1583 void FileExplorer::OnSettings(wxCommandEvent &/*event*/)
1584 {
1585 FileBrowserSettings fbs(m_favdirs,NULL);
1586 if(fbs.ShowModal()==wxID_OK)
1587 {
1588 size_t count=m_favdirs.GetCount();
1589 for(size_t i=0;i<count;i++)
1590 m_Loc->Delete(0);
1591 m_favdirs=fbs.m_favdirs;
1592 count=m_favdirs.GetCount();
1593 for(size_t i=0;i<count;i++)
1594 m_Loc->Insert(m_favdirs[i].alias,i);
1595 }
1596
1597 }
1598
OnShowHidden(wxCommandEvent &)1599 void FileExplorer::OnShowHidden(wxCommandEvent &/*event*/)
1600 {
1601 m_show_hidden=!m_show_hidden;
1602 Refresh(m_Tree->GetRootItem());
1603 }
1604
OnParseCVS(wxCommandEvent &)1605 void FileExplorer::OnParseCVS(wxCommandEvent &/*event*/)
1606 {
1607 m_parse_cvs=!m_parse_cvs;
1608 //cfg->Clear();
1609 Refresh(m_Tree->GetRootItem());
1610 }
1611
OnParseSVN(wxCommandEvent &)1612 void FileExplorer::OnParseSVN(wxCommandEvent &/*event*/)
1613 {
1614 m_parse_svn=!m_parse_svn;
1615 Refresh(m_Tree->GetRootItem());
1616 }
1617
OnParseGIT(wxCommandEvent &)1618 void FileExplorer::OnParseGIT(wxCommandEvent &/*event*/)
1619 {
1620 m_parse_git=!m_parse_git;
1621 Refresh(m_Tree->GetRootItem());
1622 }
1623
OnParseHG(wxCommandEvent &)1624 void FileExplorer::OnParseHG(wxCommandEvent &/*event*/)
1625 {
1626 m_parse_hg=!m_parse_hg;
1627 Refresh(m_Tree->GetRootItem());
1628 }
1629
OnParseBZR(wxCommandEvent &)1630 void FileExplorer::OnParseBZR(wxCommandEvent &/*event*/)
1631 {
1632 m_parse_bzr=!m_parse_bzr;
1633 Refresh(m_Tree->GetRootItem());
1634 }
1635
OnUpButton(wxCommandEvent &)1636 void FileExplorer::OnUpButton(wxCommandEvent &/*event*/)
1637 {
1638 wxFileName loc(m_root);
1639 if (loc.GetDirCount())
1640 {
1641 loc.RemoveLastDir();
1642 SetRootFolder(loc.GetFullPath());
1643 }
1644 }
1645
OnRefresh(wxCommandEvent &)1646 void FileExplorer::OnRefresh(wxCommandEvent &/*event*/)
1647 {
1648 if(m_Tree->GetItemImage(m_selectti[0])==fvsFolder) //SINGLE: m_Tree->GetSelection()
1649 Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
1650 else
1651 Refresh(m_Tree->GetRootItem());
1652 }
1653
1654 //TODO: Set copy cursor state if necessary
OnBeginDragTreeItem(wxTreeEvent & event)1655 void FileExplorer::OnBeginDragTreeItem(wxTreeEvent &event)
1656 {
1657 // SetCursor(wxCROSS_CURSOR);
1658 // if(IsInSelection(event.GetItem()))
1659 // return; // don't start a drag for an unselected item
1660 if (!IsBrowsingVCSTree())
1661 event.Allow();
1662 // m_dragtest=GetFullPath(event.GetItem());
1663 m_ticount=m_Tree->GetSelections(m_selectti);
1664 }
1665
IsInSelection(const wxTreeItemId & ti)1666 bool FileExplorer::IsInSelection(const wxTreeItemId &ti)
1667 {
1668 for(int i=0;i<m_ticount;i++)
1669 if(ti==m_selectti[i])
1670 return true;
1671 return false;
1672 }
1673
1674 //TODO: End copy cursor state if necessary
OnEndDragTreeItem(wxTreeEvent & event)1675 void FileExplorer::OnEndDragTreeItem(wxTreeEvent &event)
1676 {
1677 // SetCursor(wxCursor(wxCROSS_CURSOR));
1678 if(m_Tree->GetItemImage(event.GetItem())!=fvsFolder) //can only copy to folders
1679 return;
1680 for(int i=0;i<m_ticount;i++)
1681 {
1682 wxString path(GetFullPath(m_selectti[i]));
1683 wxFileName destpath;
1684 if(!event.GetItem().IsOk())
1685 return;
1686 destpath.Assign(GetFullPath(event.GetItem()),wxFileName(path).GetFullName());
1687 if(destpath.SameAs(path))
1688 continue;
1689 if(wxFileName::DirExists(path)||wxFileName::FileExists(path))
1690 {
1691 if(!::wxGetKeyState(WXK_CONTROL))
1692 {
1693 if(wxFileName::FileExists(path))
1694 if(!PromptSaveOpenFile(_("File is modified, press Yes to save before move, No to move unsaved file or Cancel to skip file"),wxFileName(path)))
1695 continue;
1696 #ifdef __WXMSW__
1697 wxArrayString output;
1698 int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
1699 #else
1700 int hresult=::wxExecute(_T("/bin/mv -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1701 #endif
1702 if(hresult)
1703 MessageBox(m_Tree,_("Move directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1704 } else
1705 {
1706 if(wxFileName::FileExists(path))
1707 if(!PromptSaveOpenFile(_("File is modified, press Yes to save before copy, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
1708 continue;
1709 #ifdef __WXMSW__
1710 wxArrayString output;
1711 wxString cmdline;
1712 if(wxFileName::FileExists(path))
1713 cmdline=_T("cmd /c copy /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1714 else
1715 cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
1716 int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
1717 #else
1718 int hresult=::wxExecute(_T("/bin/cp -r -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
1719 #endif
1720 if(hresult)
1721 MessageBox(m_Tree,_("Copy directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
1722 }
1723 }
1724 // 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
1725 // return;
1726 }
1727 Refresh(m_Tree->GetRootItem());
1728 }
1729
OnAddToProject(wxCommandEvent &)1730 void FileExplorer::OnAddToProject(wxCommandEvent &/*event*/)
1731 {
1732 wxArrayString files;
1733 wxString file;
1734 for(int i=0;i<m_ticount;i++)
1735 {
1736 file=GetFullPath(m_selectti[i]);
1737 if(wxFileName::FileExists(file))
1738 files.Add(file);
1739 }
1740 wxArrayInt prompt;
1741 Manager::Get()->GetProjectManager()->AddMultipleFilesToProject(files, NULL, prompt);
1742 Manager::Get()->GetProjectManager()->GetUI().RebuildTree();
1743 }
1744
IsFilesOnly(wxArrayTreeItemIds tis)1745 bool FileExplorer::IsFilesOnly(wxArrayTreeItemIds tis)
1746 {
1747 for(size_t i=0;i<tis.GetCount();i++)
1748 if(m_Tree->GetItemImage(tis[i])==fvsFolder)
1749 return false;
1750 return true;
1751 }
1752