~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/FileManager/FileExplorer.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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:
 
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
    }
 
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
    }
 
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:
 
106
    DirTraverseFind(const wxString& wildcard) : m_files(), m_wildcard(wildcard) { }
 
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
    }
 
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
    }
 
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:
 
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:
 
142
    wxFEDropTarget(FileExplorer *fe):wxDropTarget()
 
143
    {
 
144
        m_fe=fe;
 
145
        m_data_object=new FEDataObject();
 
146
        SetDataObject(m_data_object);
 
147
    }
 
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
    }
 
182
    virtual bool OnDrop(wxCoord /*x*/, wxCoord /*y*/, int /*tab*/, wxWindow */*wnd*/)
 
183
    {
 
184
        return true;
 
185
    }
 
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
 
 
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
 
 
210
FileTreeCtrl::FileTreeCtrl() { }
 
211
 
 
212
FileTreeCtrl::FileTreeCtrl(wxWindow *parent): wxTreeCtrl(parent) {}
 
213
 
 
214
FileTreeCtrl::~FileTreeCtrl()
 
215
{
 
216
}
 
217
 
 
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
 
 
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
 
 
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
    SetImages();
 
340
    ReadConfig();
 
341
    if(m_Loc->GetCount()>m_favdirs.GetCount())
 
342
    {
 
343
        m_Loc->Select(m_favdirs.GetCount());
 
344
        m_root=m_Loc->GetString(m_favdirs.GetCount());
 
345
    } else
 
346
    {
 
347
        m_root=wxFileName::GetPathSeparator();
 
348
        m_Loc->Append(m_root);
 
349
        m_Loc->Select(0);
 
350
    }
 
351
    if(m_WildCards->GetCount()>0)
 
352
        m_WildCards->Select(0);
 
353
    SetRootFolder(m_root);
 
354
 
 
355
    SetSizer(bs);
 
356
}
 
357
 
 
358
FileExplorer::~FileExplorer()
 
359
{
 
360
    m_kill=true;
 
361
    m_updatetimer->Stop();
 
362
    delete m_dir_monitor;
 
363
    WriteConfig();
 
364
    UpdateAbort();
 
365
    delete m_update_queue;
 
366
    delete m_updatetimer;
 
367
}
 
368
 
 
369
 
 
370
bool FileExplorer::SetRootFolder(wxString root)
 
371
{
 
372
    UpdateAbort();
 
373
    if(root[root.Len()-1]!=wxFileName::GetPathSeparator())
 
374
        root=root+wxFileName::GetPathSeparator();
 
375
#ifdef __WXMSW__
 
376
    wxFileName fnroot=wxFileName(root);
 
377
    if(fnroot.GetVolume().IsEmpty())
 
378
    {
 
379
        fnroot.SetVolume(wxFileName(::wxGetCwd()).GetVolume());
 
380
        root=fnroot.GetFullPath();//(wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR)+fnroot.GetFullName();
 
381
    }
 
382
#endif
 
383
    wxDir dir(root);
 
384
    if (!dir.IsOpened())
 
385
    {
 
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);
 
389
        return false;
 
390
    }
 
391
    m_root=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());
 
401
    Layout();
 
402
 
 
403
    return true;
 
404
//    return AddTreeItems(m_Tree->GetRootItem());
 
405
 
 
406
}
 
407
 
 
408
// find a file in the filesystem below a selected root
 
409
void FileExplorer::FindFile(const wxString &findfilename, const wxTreeItemId &ti)
 
410
{
 
411
    wxString path=GetFullPath(ti);
 
412
 
 
413
    wxDir dir(path);
 
414
 
 
415
    if (!dir.IsOpened())
 
416
    {
 
417
        // deal with the error here - wxDir would already log an error message
 
418
        // explaining the exact reason for the failure
 
419
        return;
 
420
    }
 
421
    wxString filename;
 
422
    int flags=wxDIR_FILES|wxDIR_DIRS;
 
423
    if(m_show_hidden)
 
424
        flags|=wxDIR_HIDDEN;
 
425
 
 
426
    DirTraverseFind dtf(findfilename);
 
427
    m_findmatchcount=dir.Traverse(dtf,wxEmptyString,flags);
 
428
    m_findmatch=dtf.GetMatches();
 
429
}
 
430
 
 
431
// focus the item in the tree.
 
432
void FileExplorer::FocusFile(const wxTreeItemId &ti)
 
433
{
 
434
    m_Tree->SetFocus();
 
435
    m_Tree->UnselectAll();
 
436
    m_Tree->SelectItem(ti);
 
437
    m_Tree->EnsureVisible(ti);
 
438
}
 
439
 
 
440
wxTreeItemId FileExplorer::GetNextExpandedNode(wxTreeItemId ti)
 
441
{
 
442
    wxTreeItemId next_ti;
 
443
    if(!ti.IsOk())
 
444
    {
 
445
        return m_Tree->GetRootItem();
 
446
    }
 
447
    if(m_Tree->IsExpanded(ti))
 
448
    {
 
449
        wxTreeItemIdValue cookie;
 
450
        next_ti=m_Tree->GetFirstChild(ti,cookie);
 
451
        while(next_ti.IsOk())
 
452
        {
 
453
            if(m_Tree->IsExpanded(next_ti))
 
454
                return next_ti;
 
455
            next_ti=m_Tree->GetNextChild(ti,cookie);
 
456
        }
 
457
    }
 
458
    next_ti=m_Tree->GetNextSibling(ti);
 
459
    while(next_ti.IsOk())
 
460
    {
 
461
        if(m_Tree->IsExpanded(next_ti))
 
462
            return next_ti;
 
463
        next_ti=m_Tree->GetNextSibling(next_ti);
 
464
    }
 
465
    return m_Tree->GetRootItem();
 
466
}
 
467
 
 
468
bool FileExplorer::GetItemFromPath(const wxString &path, wxTreeItemId &ti)
 
469
{
 
470
    ti=m_Tree->GetRootItem();
 
471
    do
 
472
    {
 
473
        if(path==GetFullPath(ti))
 
474
            return true;
 
475
        ti=GetNextExpandedNode(ti);
 
476
    } while(ti!=m_Tree->GetRootItem());
 
477
    return false;
 
478
}
 
479
 
 
480
 
 
481
void FileExplorer::GetExpandedNodes(wxTreeItemId ti, Expansion *exp)
 
482
{
 
483
    exp->name=m_Tree->GetItemText(ti);
 
484
    wxTreeItemIdValue cookie;
 
485
    wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
 
486
    while(ch.IsOk())
 
487
    {
 
488
        if(m_Tree->IsExpanded(ch))
 
489
        {
 
490
            Expansion *e=new Expansion();
 
491
            GetExpandedNodes(ch,e);
 
492
            exp->children.push_back(e);
 
493
        }
 
494
        ch=m_Tree->GetNextChild(ti,cookie);
 
495
    }
 
496
}
 
497
 
 
498
void FileExplorer::GetExpandedPaths(wxTreeItemId ti,wxArrayString &paths)
 
499
{
 
500
    if(!ti.IsOk())
 
501
    {
 
502
        wxMessageBox(_("node error"));
 
503
        return;
 
504
    }
 
505
    if(m_Tree->IsExpanded(ti))
 
506
        paths.Add(GetFullPath(ti));
 
507
    wxTreeItemIdValue cookie;
 
508
    wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
 
509
    while(ch.IsOk())
 
510
    {
 
511
        if(m_Tree->IsExpanded(ch))
 
512
            GetExpandedPaths(ch,paths);
 
513
        ch=m_Tree->GetNextChild(ti,cookie);
 
514
    }
 
515
}
 
516
 
 
517
void FileExplorer::RefreshExpanded(wxTreeItemId ti)
 
518
{
 
519
    if(m_Tree->IsExpanded(ti))
 
520
        m_update_queue->Add(ti);
 
521
    wxTreeItemIdValue cookie;
 
522
    wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
 
523
    while(ch.IsOk())
 
524
    {
 
525
        if(m_Tree->IsExpanded(ch))
 
526
            RefreshExpanded(ch);
 
527
        ch=m_Tree->GetNextChild(ti,cookie);
 
528
    }
 
529
    m_updatetimer->Start(10,true);
 
530
 
 
531
}
 
532
 
 
533
void FileExplorer::Refresh(wxTreeItemId ti)
 
534
{
 
535
    //    Expansion e;
 
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);
 
541
}
 
542
 
 
543
void FileExplorer::UpdateAbort()
 
544
{
 
545
    if(!m_update_active)
 
546
        return;
 
547
    delete m_updater;
 
548
    m_update_active=false;
 
549
    m_updatetimer->Stop();
 
550
}
 
551
 
 
552
void FileExplorer::ResetDirMonitor()
 
553
{
 
554
    wxArrayString paths;
 
555
    GetExpandedPaths(m_Tree->GetRootItem(),paths);
 
556
    m_dir_monitor->ChangePaths(paths);
 
557
}
 
558
 
 
559
void FileExplorer::OnDirMonitor(wxDirectoryMonitorEvent &e)
 
560
{
 
561
    if(m_kill)
 
562
        return;
 
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)
 
566
    {
 
567
//        LogMessage(_("directory change read error"));
 
568
    }
 
569
    wxTreeItemId ti;
 
570
    if(GetItemFromPath(e.m_mon_dir,ti))
 
571
    {
 
572
        m_update_queue->Add(ti);
 
573
        m_updatetimer->Start(100,true);
 
574
    }
 
575
}
 
576
 
 
577
void FileExplorer::OnTimerCheckUpdates(wxTimerEvent &/*e*/)
 
578
{
 
579
    if(m_kill)
 
580
        return;
 
581
    if(m_update_active)
 
582
        return;
 
583
    wxTreeItemId ti;
 
584
    while(m_update_queue->Pop(ti))
 
585
    {
 
586
        if(!ti.IsOk())
 
587
            continue;
 
588
        m_updater_cancel=false;
 
589
        m_updater=new FileExplorerUpdater(this);
 
590
        m_updated_node=ti;
 
591
        m_update_active=true;
 
592
        m_updater->Update(m_updated_node);
 
593
        break;
 
594
    }
 
595
}
 
596
 
 
597
bool FileExplorer::ValidateRoot()
 
598
{
 
599
    wxTreeItemId ti=m_Tree->GetRootItem();
 
600
    while(true)
 
601
    {
 
602
    if(!ti.IsOk())
 
603
        break;
 
604
    if(m_Tree->GetItemImage(ti)!=fvsFolder)
 
605
        break;
 
606
    if(!wxFileName::DirExists(GetFullPath(ti)))
 
607
        break;
 
608
    return true;
 
609
    }
 
610
    return false;
 
611
}
 
612
 
 
613
void FileExplorer::OnUpdateTreeItems(wxCommandEvent &/*e*/)
 
614
{
 
615
    if(m_kill)
 
616
        return;
 
617
    m_updater->Wait();
 
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)
 
622
    {
 
623
        m_VCS_Type->SetLabel(m_updater->m_vcs_type);
 
624
        if (m_updater->m_vcs_type == wxEmptyString)
 
625
        {
 
626
            m_VCS_Control->Clear();
 
627
            m_Box_VCS_Control->Hide(true);
 
628
            m_commit = _T("");
 
629
        }
 
630
        else if (m_commit == wxEmptyString)
 
631
        {
 
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);
 
638
        }
 
639
        Layout();
 
640
    }
 
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)
 
644
        delete m_updater;
 
645
        m_updater=NULL;
 
646
        m_update_active=false;
 
647
        ResetDirMonitor();
 
648
        if(ValidateRoot())
 
649
        {
 
650
            m_update_queue->Add(m_Tree->GetRootItem());
 
651
            m_updatetimer->Start(10,true);
 
652
        }
 
653
        return;
 
654
    }
 
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)
 
660
    {
 
661
        m_Tree->Freeze();
 
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++)
 
665
        {
 
666
    //        cbMessageBox(it->name);
 
667
            wxTreeItemIdValue cookie;
 
668
            wxTreeItemId ch=m_Tree->GetFirstChild(ti,cookie);
 
669
            while(ch.IsOk())
 
670
            {
 
671
                if(it->name==m_Tree->GetItemText(ch))
 
672
                {
 
673
                    m_Tree->Delete(ch);
 
674
                    break;
 
675
                }
 
676
                ch=m_Tree->GetNextChild(ti,cookie);
 
677
            }
 
678
        }
 
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++)
 
682
        {
 
683
    //        cbMessageBox(it->name);
 
684
            wxTreeItemId newitem=m_Tree->AppendItem(ti,it->name,it->state);
 
685
            m_Tree->SetItemHasChildren(newitem,it->state==fvsFolder);
 
686
        }
 
687
        m_Tree->SortChildren(ti);
 
688
        m_Tree->Thaw();
 
689
    }
 
690
    if(!m_Tree->IsExpanded(ti))
 
691
    {
 
692
        m_update_expand=true;
 
693
        m_Tree->Expand(ti);
 
694
    }
 
695
    delete m_updater;
 
696
    m_updater=NULL;
 
697
    m_update_active=false;
 
698
    m_updatetimer->Start(10,true);
 
699
    // Restart the monitor (TODO: move this elsewhere??)
 
700
    ResetDirMonitor();
 
701
}
 
702
 
 
703
void FileExplorer::SetImages()
 
704
{
 
705
    wxImageList *m_pImages = cbProjectTreeImages::MakeImageList();
 
706
    m_Tree->SetImageList(m_pImages);
 
707
 
 
708
//    // make sure tree is not "frozen"
 
709
//    UnfreezeTree(true);
 
710
}
 
711
 
 
712
wxString FileExplorer::GetFullPath(const wxTreeItemId &ti)
 
713
{
 
714
    if (!ti.IsOk())
 
715
        return wxEmptyString;
 
716
    wxFileName path(m_root);
 
717
    if (ti!=m_Tree->GetRootItem())
 
718
    {
 
719
        std::vector<wxTreeItemId> vti;
 
720
        vti.push_back(ti);
 
721
        wxTreeItemId pti=m_Tree->GetItemParent(vti[0]);
 
722
        if (!pti.IsOk())
 
723
            return wxEmptyString;
 
724
        while (pti != m_Tree->GetRootItem())
 
725
        {
 
726
            vti.insert(vti.begin(), pti);
 
727
            pti=m_Tree->GetItemParent(pti);
 
728
        }
 
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();
 
738
    }
 
739
    return path.GetFullPath();
 
740
}
 
741
 
 
742
void FileExplorer::OnExpand(wxTreeEvent &event)
 
743
{
 
744
    if(m_updated_node==event.GetItem() && m_update_expand)
 
745
    {
 
746
        m_update_expand=false;
 
747
        return;
 
748
    }
 
749
    m_update_queue->Add(event.GetItem());
 
750
    m_updatetimer->Start(10,true);
 
751
    event.Veto();
 
752
    //AddTreeItems(event.GetItem());
 
753
}
 
754
 
 
755
void FileExplorer::ReadConfig()
 
756
{
 
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"));
 
761
    int len=0;
 
762
    cfg->Read(_T("FileExplorer/FavRootList/Len"), &len);
 
763
    for(int i=0;i<len;i++)
 
764
    {
 
765
        wxString ref=wxString::Format(_T("FileExplorer/FavRootList/I%i"),i);
 
766
        wxString loc;
 
767
        FavoriteDir fav;
 
768
        cfg->Read(ref+_T("/alias"), &fav.alias);
 
769
        cfg->Read(ref+_T("/path"), &fav.path);
 
770
        m_Loc->Append(fav.alias);
 
771
        m_favdirs.Add(fav);
 
772
    }
 
773
    len=0;
 
774
    cfg->Read(_T("FileExplorer/RootList/Len"), &len);
 
775
    for(int i=0;i<len;i++)
 
776
    {
 
777
        wxString ref=wxString::Format(_T("FileExplorer/RootList/I%i"),i);
 
778
        wxString loc;
 
779
        cfg->Read(ref, &loc);
 
780
        m_Loc->Append(loc);
 
781
    }
 
782
    len=0;
 
783
    cfg->Read(_T("FileExplorer/WildMask/Len"), &len);
 
784
    for(int i=0;i<len;i++)
 
785
    {
 
786
        wxString ref=wxString::Format(_T("FileExplorer/WildMask/I%i"),i);
 
787
        wxString wild;
 
788
        cfg->Read(ref, &wild);
 
789
        m_WildCards->Append(wild);
 
790
    }
 
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);
 
797
}
 
798
 
 
799
void FileExplorer::WriteConfig()
 
800
{
 
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"));
 
806
    //cfg->Clear();
 
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++)
 
810
    {
 
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);
 
814
    }
 
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++)
 
818
    {
 
819
        wxString ref=wxString::Format(_T("FileExplorer/RootList/I%i"),i);
 
820
        cfg->Write(ref, m_Loc->GetString(m_favdirs.GetCount()+i));
 
821
    }
 
822
    count=static_cast<int>(m_Loc->GetCount());
 
823
    cfg->Write(_T("FileExplorer/WildMask/Len"), count);
 
824
    for(int i=0;i<count;i++)
 
825
    {
 
826
        wxString ref=wxString::Format(_T("FileExplorer/WildMask/I%i"),i);
 
827
        cfg->Write(ref, m_WildCards->GetString(i));
 
828
    }
 
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);
 
835
}
 
836
 
 
837
void FileExplorer::OnEnterWild(wxCommandEvent &/*event*/)
 
838
{
 
839
    wxString wild=m_WildCards->GetValue();
 
840
    for(size_t i=0;i<m_WildCards->GetCount();i++)
 
841
    {
 
842
        wxString cmp;
 
843
        cmp=m_WildCards->GetString(i);
 
844
        if(cmp==wild)
 
845
        {
 
846
            m_WildCards->Delete(i);
 
847
            m_WildCards->Insert(wild,0);
 
848
            m_WildCards->SetSelection(0);
 
849
            RefreshExpanded(m_Tree->GetRootItem());
 
850
            return;
 
851
        }
 
852
    }
 
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());
 
858
}
 
859
 
 
860
void FileExplorer::OnChooseWild(wxCommandEvent &/*event*/)
 
861
{
 
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);
 
867
//    event.Skip(true);
 
868
//    cbMessageBox(wild);
 
869
    m_WildCards->SetSelection(0);
 
870
    RefreshExpanded(m_Tree->GetRootItem());
 
871
}
 
872
 
 
873
void FileExplorer::OnEnterLoc(wxCommandEvent &/*event*/)
 
874
{
 
875
    wxString loc=m_Loc->GetValue();
 
876
    if(!SetRootFolder(loc))
 
877
        return;
 
878
    for(size_t i=0;i<m_Loc->GetCount();i++)
 
879
    {
 
880
        wxString cmp;
 
881
        if(i<m_favdirs.GetCount())
 
882
            cmp=m_favdirs[i].path;
 
883
        else
 
884
            cmp=m_Loc->GetString(i);
 
885
        if(cmp==m_root)
 
886
        {
 
887
            if(i>=m_favdirs.GetCount())
 
888
            {
 
889
                m_Loc->Delete(i);
 
890
                m_Loc->Insert(m_root,m_favdirs.GetCount());
 
891
            }
 
892
            m_Loc->SetSelection(m_favdirs.GetCount());
 
893
            return;
 
894
        }
 
895
    }
 
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());
 
900
}
 
901
 
 
902
void FileExplorer::OnChooseLoc(wxCommandEvent &event)
 
903
{
 
904
    wxString loc;
 
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)
 
908
    if(event.GetInt()<0)
 
909
        return;
 
910
    if(event.GetInt()>=static_cast<int>(m_favdirs.GetCount()))
 
911
        loc=m_Loc->GetValue();
 
912
    else
 
913
        loc=m_favdirs[event.GetInt()].path;
 
914
    if(!SetRootFolder(loc))
 
915
        return;
 
916
    if(event.GetInt()>=static_cast<int>(m_favdirs.GetCount()))
 
917
    {
 
918
        m_Loc->Delete(event.GetInt());
 
919
        m_Loc->Insert(m_root,m_favdirs.GetCount());
 
920
        m_Loc->SetSelection(m_favdirs.GetCount());
 
921
    }
 
922
    else
 
923
    {
 
924
        for(size_t i=m_favdirs.GetCount();i<m_Loc->GetCount();i++)
 
925
        {
 
926
            wxString cmp;
 
927
            cmp=m_Loc->GetString(i);
 
928
            if(cmp==m_root)
 
929
            {
 
930
                m_Loc->Delete(i);
 
931
                m_Loc->Insert(m_root,m_favdirs.GetCount());
 
932
                m_Loc->SetSelection(event.GetInt());
 
933
                return;
 
934
            }
 
935
        }
 
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());
 
940
    }
 
941
}
 
942
 
 
943
void FileExplorer::OnSetLoc(wxCommandEvent &/*event*/)
 
944
{
 
945
    wxString loc=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
 
946
    if(!SetRootFolder(loc))
 
947
        return;
 
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());
 
951
}
 
952
 
 
953
void FileExplorer::OnVCSChangesCheck(wxCommandEvent &/*event*/)
 
954
{
 
955
    Refresh(m_Tree->GetRootItem());
 
956
}
 
957
 
 
958
void FileExplorer::OnVCSControl(wxCommandEvent &/*event*/)
 
959
{
 
960
    wxString commit = m_VCS_Control->GetString(m_VCS_Control->GetSelection());
 
961
    if (commit == _T("Select commit..."))
 
962
    {
 
963
        CommitBrowser *cm = new CommitBrowser(this, GetFullPath(m_Tree->GetRootItem()), m_VCS_Type->GetLabel());
 
964
        if(cm->ShowModal() == wxID_OK)
 
965
        {
 
966
            commit = cm->GetSelectedCommit();
 
967
            cm->Destroy();
 
968
            if (commit != wxEmptyString)
 
969
            {
 
970
                unsigned int i=0;
 
971
                for (; i<m_VCS_Control->GetCount(); ++i)
 
972
                {
 
973
                    if (m_VCS_Control->GetString(i) == commit)
 
974
                    {
 
975
                        m_VCS_Control->SetSelection(i);
 
976
                        break;
 
977
                    }
 
978
                }
 
979
                if (i == m_VCS_Control->GetCount())
 
980
                    m_VCS_Control->Append(commit);
 
981
                m_VCS_Control->SetSelection(m_VCS_Control->GetCount()-1);
 
982
            }
 
983
        }
 
984
        else
 
985
            commit = wxEmptyString;
 
986
    }
 
987
    if (commit!=wxEmptyString)
 
988
    {
 
989
        m_commit = commit;
 
990
        Refresh(m_Tree->GetRootItem());
 
991
    } else
 
992
    {
 
993
        unsigned int i=0;
 
994
        for (; i<m_VCS_Control->GetCount(); ++i)
 
995
        {
 
996
            if (m_VCS_Control->GetString(i) == m_commit)
 
997
                m_VCS_Control->SetSelection(i);
 
998
                break;
 
999
        }
 
1000
    }
 
1001
}
 
1002
 
 
1003
void FileExplorer::OnOpenInEditor(wxCommandEvent &/*event*/)
 
1004
{
 
1005
    for(int i=0;i<m_ticount;i++)
 
1006
    {
 
1007
        if (IsBrowsingVCSTree())
 
1008
        {
 
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());
 
1021
            else
 
1022
                DoOpenInEditor(path.GetFullPath());
 
1023
        }
 
1024
        else
 
1025
        {
 
1026
            wxFileName path(GetFullPath(m_selectti[i]));
 
1027
            wxString filename=path.GetFullPath();
 
1028
            if(!path.FileExists())
 
1029
                continue;
 
1030
            DoOpenInEditor(filename);
 
1031
        }
 
1032
    }
 
1033
    if (m_vcs_file_loader==0 && !m_vcs_file_loader_queue.empty())
 
1034
    {
 
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);
 
1038
    }
 
1039
}
 
1040
 
 
1041
void FileExplorer::OnVCSDiff(wxCommandEvent &event)
 
1042
{
 
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..."))
 
1051
    {
 
1052
        wxString diff_paths;
 
1053
        for(int i=0;i<m_ticount;i++)
 
1054
        {
 
1055
            wxFileName path(GetFullPath(m_selectti[i]));
 
1056
            path.MakeRelativeTo(GetRootFolder());
 
1057
            if (path != wxEmptyString)
 
1058
                diff_paths+=_T(" \"") + path.GetFullPath() + _T("\"");
 
1059
        }
 
1060
        CommitBrowser *cm = new CommitBrowser(this, GetFullPath(m_Tree->GetRootItem()), m_VCS_Type->GetLabel(), diff_paths);
 
1061
        if(cm->ShowModal() == wxID_OK)
 
1062
        {
 
1063
            comp_commit = cm->GetSelectedCommit();
 
1064
        }
 
1065
        else
 
1066
            return;
 
1067
    }
 
1068
    wxString diff_paths = wxEmptyString;
 
1069
    for(int i=0;i<m_ticount;i++)
 
1070
    {
 
1071
        wxFileName path(GetFullPath(m_selectti[i]));
 
1072
        path.MakeRelativeTo(GetRootFolder());
 
1073
        if (path != wxEmptyString)
 
1074
            diff_paths+=_T(" \"") + path.GetFullPath() + _T("\"");
 
1075
    }
 
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())
 
1085
    {
 
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);
 
1089
    }
 
1090
}
 
1091
 
 
1092
void FileExplorer::OnVCSFileLoaderComplete(wxCommandEvent& /*event*/)
 
1093
{
 
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())
 
1099
    {
 
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);
 
1103
    }
 
1104
}
 
1105
 
 
1106
void FileExplorer::DoOpenInEditor(const wxString &filename)
 
1107
{
 
1108
    EditorManager* em = Manager::Get()->GetEditorManager();
 
1109
    EditorBase* eb = em->IsOpen(filename);
 
1110
    if (eb)
 
1111
    {
 
1112
        // open files just get activated
 
1113
        eb->Activate();
 
1114
        return;
 
1115
    } else
 
1116
        em->Open(filename);
 
1117
}
 
1118
 
 
1119
void FileExplorer::OnActivate(wxTreeEvent &event)
 
1120
{
 
1121
    if (IsBrowsingVCSTree())
 
1122
    {
 
1123
        //TODO: Should just retrieve the file and use the same mimetype handling as a regular file
 
1124
        wxCommandEvent e;
 
1125
        m_ticount=m_Tree->GetSelections(m_selectti);
 
1126
        OnOpenInEditor(e);
 
1127
        return;
 
1128
    }
 
1129
    wxString filename=GetFullPath(event.GetItem());
 
1130
    if(m_Tree->GetItemImage(event.GetItem())==fvsFolder)
 
1131
    {
 
1132
        event.Skip(true);
 
1133
        return;
 
1134
    }
 
1135
    EditorManager* em = Manager::Get()->GetEditorManager();
 
1136
    EditorBase* eb = em->IsOpen(filename);
 
1137
    if (eb)
 
1138
    {
 
1139
        // open files just get activated
 
1140
        eb->Activate();
 
1141
        return;
 
1142
    }
 
1143
 
 
1144
    // Use Mime handler to open file
 
1145
    cbMimePlugin* plugin = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile(filename);
 
1146
    if (!plugin)
 
1147
    {
 
1148
        wxString msg;
 
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
 
1152
    }
 
1153
    else if (plugin->OpenFile(filename) != 0)
 
1154
    {
 
1155
        const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
 
1156
        wxString msg;
 
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);
 
1159
    }
 
1160
 
 
1161
//    if(!em->IsOpen(file))
 
1162
//        em->Open(file);
 
1163
 
 
1164
}
 
1165
 
 
1166
 
 
1167
void FileExplorer::OnKeyDown(wxKeyEvent &event)
 
1168
{
 
1169
    if(event.GetKeyCode() == WXK_DELETE)
 
1170
    {
 
1171
        if (IsBrowsingVCSTree())
 
1172
        {
 
1173
            wxCommandEvent event2;
 
1174
            OnDelete(event2);
 
1175
        }
 
1176
    }
 
1177
}
 
1178
 
 
1179
 
 
1180
bool FileExplorer::IsBrowsingVCSTree()
 
1181
{
 
1182
    return m_commit != _T("Working copy") && m_commit != wxEmptyString;
 
1183
}
 
1184
 
 
1185
bool FileExplorer::IsBrowsingWorkingCopy()
 
1186
{
 
1187
    return m_commit == _T("Working copy") && m_commit != wxEmptyString;
 
1188
}
 
1189
 
 
1190
void FileExplorer::OnRightClick(wxTreeEvent &event)
 
1191
{
 
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
 
1195
    {
 
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);
 
1200
        m_Tree->Update();
 
1201
    }
 
1202
    FileTreeData* ftd = new FileTreeData(0, FileTreeData::ftdkUndefined);
 
1203
    ftd->SetKind(FileTreeData::ftdkFile);
 
1204
    if(m_ticount>0)
 
1205
    {
 
1206
        if(m_ticount==1)
 
1207
        {
 
1208
            int img = m_Tree->GetItemImage(m_selectti[0]);
 
1209
            if(img==fvsFolder)
 
1210
            {
 
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())
 
1216
                {
 
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..."));
 
1221
                }
 
1222
            } else
 
1223
            {
 
1224
                if (!IsBrowsingVCSTree())
 
1225
                    Popup->Append(ID_FILERENAME,_("&Rename..."));
 
1226
            }
 
1227
        }
 
1228
        if(IsFilesOnly(m_selectti))
 
1229
        {
 
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..."));
 
1234
        }
 
1235
        if (!IsBrowsingVCSTree())
 
1236
        {
 
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"));
 
1241
        }
 
1242
        if ( IsBrowsingVCSTree() || IsBrowsingWorkingCopy() )
 
1243
        {
 
1244
            if (IsBrowsingWorkingCopy())
 
1245
                Popup->Append(ID_FILEDIFF,_("&Diff"));
 
1246
            else
 
1247
                Popup->Append(ID_FILEDIFF,_("&Diff previous"));
 
1248
            wxMenu *diff_menu = new wxMenu();
 
1249
            unsigned int n = m_VCS_Control->GetCount();
 
1250
            if (n>10)
 
1251
                n=10;
 
1252
            if (IsBrowsingWorkingCopy())
 
1253
            {
 
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));
 
1257
            }
 
1258
            else
 
1259
            {
 
1260
                for (unsigned int i = 0; i<n; ++i)
 
1261
                    diff_menu->Append(ID_FILEDIFF1 + i, m_VCS_Control->GetString(i));
 
1262
            }
 
1263
            Popup->AppendSubMenu(diff_menu,_("Diff against"));
 
1264
        }
 
1265
    }
 
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);
 
1274
    if(m_ticount>1)
 
1275
    {
 
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);
 
1281
    }
 
1282
    else if ( m_ticount > 0)
 
1283
    {
 
1284
        wxString filepath = GetFullPath(m_selectti[0]);
 
1285
        ftd->SetFolder(filepath);
 
1286
    }
 
1287
    if(m_ticount>0)
 
1288
        Manager::Get()->GetPluginManager()->AskPluginsForModuleMenu(mtUnknown, Popup, ftd);
 
1289
    delete ftd;
 
1290
    Popup->AppendSeparator();
 
1291
    Popup->AppendSubMenu(viewpop,_("&Settings"));
 
1292
    Popup->Append(ID_FILEREFRESH,_("Re&fresh"));
 
1293
    wxWindow::PopupMenu(Popup);
 
1294
    delete Popup;
 
1295
}
 
1296
 
 
1297
void FileExplorer::OnNewFile(wxCommandEvent &/*event*/)
 
1298
{
 
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)
 
1302
        return;
 
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))
 
1308
    {
 
1309
        wxFile fileobj;
 
1310
        if(fileobj.Create(newfile))
 
1311
        {
 
1312
            fileobj.Close();
 
1313
            Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
 
1314
        }
 
1315
        else
 
1316
            cbMessageBox(_("File Creation Failed"),_("Error"));
 
1317
    }
 
1318
    else
 
1319
        cbMessageBox(_("File/Directory Already Exists with Name ")+name, _("Error"));
 
1320
}
 
1321
 
 
1322
void FileExplorer::OnAddFavorite(wxCommandEvent &/*event*/)
 
1323
{
 
1324
    FavoriteDir fav;
 
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)
 
1330
        return;
 
1331
    wxString name=ted.GetValue();
 
1332
    fav.alias=name;
 
1333
    m_favdirs.Insert(fav,0);
 
1334
    m_Loc->Insert(name,0);
 
1335
}
 
1336
 
 
1337
void FileExplorer::OnNewFolder(wxCommandEvent &/*event*/)
 
1338
{
 
1339
    wxString workingdir=GetFullPath(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
 
1340
    wxTextEntryDialog te(this,_("New Directory Name: "));
 
1341
    if(te.ShowModal()!=wxID_OK)
 
1342
        return;
 
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))
 
1348
    {
 
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()
 
1352
    }
 
1353
    else
 
1354
        cbMessageBox(_("A file or directory already exists with name ")+name);
 
1355
}
 
1356
 
 
1357
void FileExplorer::OnDuplicate(wxCommandEvent &/*event*/)
 
1358
{
 
1359
    m_ticount=m_Tree->GetSelections(m_selectti);
 
1360
    for(int i=0;i<m_ticount;i++)
 
1361
    {
 
1362
        wxFileName path(GetFullPath(m_selectti[i]));  //SINGLE: m_Tree->GetSelection()
 
1363
        if(wxFileName::FileExists(path.GetFullPath())||wxFileName::DirExists(path.GetFullPath()))
 
1364
        {
 
1365
            if(!PromptSaveOpenFile(_("File is modified, press Yes to save before duplication, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
 
1366
                continue;
 
1367
            int j=1;
 
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)))
 
1372
            {
 
1373
                j++;
 
1374
                destpath=path.GetPathWithSep()+path.GetName()+wxString::Format(_T("(%i)"),j);
 
1375
                if(path.GetExt()!=wxEmptyString)
 
1376
                    destpath+=_T(".")+path.GetExt();
 
1377
            }
 
1378
            if(j==100)
 
1379
            {
 
1380
                cbMessageBox(_("Too many copies of file or directory"));
 
1381
                continue;
 
1382
            }
 
1383
 
 
1384
#ifdef __WXMSW__
 
1385
            wxArrayString output;
 
1386
            wxString cmdline;
 
1387
            if(wxFileName::FileExists(path.GetFullPath()))
 
1388
                cmdline=_T("cmd /c copy /Y \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
 
1389
            else
 
1390
                cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
 
1391
            int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
 
1392
#else
 
1393
            wxString cmdline=_T("/bin/cp -r -b \"")+path.GetFullPath()+_T("\" \"")+destpath+_T("\"");
 
1394
            int hresult=::wxExecute(cmdline,wxEXEC_SYNC);
 
1395
#endif
 
1396
            if(hresult)
 
1397
                MessageBox(m_Tree,_("Command '")+cmdline+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
 
1398
        }
 
1399
    }
 
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?)
 
1402
}
 
1403
 
 
1404
 
 
1405
void FileExplorer::CopyFiles(const wxString &destination, const wxArrayString &selectedfiles)
 
1406
{
 
1407
    for(unsigned int i=0;i<selectedfiles.Count();i++)
 
1408
    {
 
1409
        wxString path=selectedfiles[i];
 
1410
        wxFileName destpath;
 
1411
        destpath.Assign(destination,wxFileName(path).GetFullName());
 
1412
        if(destpath.SameAs(path))
 
1413
            continue;
 
1414
        if(wxFileName::FileExists(path)||wxFileName::DirExists(path))
 
1415
        {
 
1416
            if(!PromptSaveOpenFile(_("File is modified, press Yes to save before duplication, No to copy unsaved file or Cancel to skip file"),wxFileName(path)))
 
1417
                continue;
 
1418
#ifdef __WXMSW__
 
1419
            wxArrayString output;
 
1420
            wxString cmdline;
 
1421
            if(wxFileName::FileExists(path))
 
1422
                cmdline=_T("cmd /c copy /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
 
1423
            else
 
1424
                cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
 
1425
            int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
 
1426
#else
 
1427
            int hresult=::wxExecute(_T("/bin/cp -r -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
 
1428
#endif
 
1429
            if(hresult)
 
1430
                MessageBox(m_Tree,_("Copying '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
 
1431
        }
 
1432
    }
 
1433
}
 
1434
 
 
1435
void FileExplorer::OnCopy(wxCommandEvent &/*event*/)
 
1436
{
 
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.
 
1442
    {
 
1443
        selectedfiles.Add(GetFullPath(m_selectti[i]));  //SINGLE: m_Tree->GetSelection()
 
1444
    }
 
1445
    if(dd.ShowModal()==wxID_CANCEL)
 
1446
        return;
 
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?)
 
1450
}
 
1451
 
 
1452
void FileExplorer::MoveFiles(const wxString &destination, const wxArrayString &selectedfiles)
 
1453
{
 
1454
    for(unsigned int i=0;i<selectedfiles.Count();i++)
 
1455
    {
 
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.
 
1460
            continue;
 
1461
        if(wxFileName::FileExists(path)||wxFileName::DirExists(path))
 
1462
        {
 
1463
#ifdef __WXMSW__
 
1464
            wxArrayString output;
 
1465
            int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
 
1466
#else
 
1467
            int hresult=::wxExecute(_T("/bin/mv -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
 
1468
#endif
 
1469
            if(hresult)
 
1470
                MessageBox(m_Tree,_("Moving '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
 
1471
        }
 
1472
    }
 
1473
}
 
1474
 
 
1475
void FileExplorer::OnMove(wxCommandEvent &/*event*/)
 
1476
{
 
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)
 
1484
        return;
 
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?)
 
1488
}
 
1489
 
 
1490
wxArrayString FileExplorer::GetSelectedPaths()
 
1491
{
 
1492
    wxArrayString paths;
 
1493
    for(int i=0;i<m_ticount;i++)
 
1494
    {
 
1495
        wxString path(GetFullPath(m_selectti[i]));  //SINGLE: m_Tree->GetSelection()
 
1496
        paths.Add(path);
 
1497
    }
 
1498
    return paths;
 
1499
}
 
1500
 
 
1501
void FileExplorer::OnDelete(wxCommandEvent &/*event*/)
 
1502
{
 
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)
 
1510
        return;
 
1511
    for(unsigned int i=0;i<as.Count();i++)
 
1512
    {
 
1513
        wxString path=as[i];  //SINGLE: m_Tree->GetSelection()
 
1514
        if(wxFileName::FileExists(path))
 
1515
        {
 
1516
            //        EditorManager* em = Manager::Get()->GetEditorManager();
 
1517
            //        if(em->IsOpen(path))
 
1518
            //        {
 
1519
            //            cbMessageBox(_("Close file ")+path.GetFullPath()+_(" first"));
 
1520
            //            return;
 
1521
            //        }
 
1522
            if(!::wxRemoveFile(path))
 
1523
                MessageBox(m_Tree,_("Delete file '")+path+_("' failed"));
 
1524
        } else
 
1525
        if(wxFileName::DirExists(path))
 
1526
        {
 
1527
#ifdef __WXMSW__
 
1528
            wxArrayString output;
 
1529
            int hresult=::wxExecute(_T("cmd /c rmdir /S/Q \"")+path+_T("\""),output,wxEXEC_SYNC);
 
1530
#else
 
1531
            int hresult=::wxExecute(_T("/bin/rm -r -f \"")+path+_T("\""),wxEXEC_SYNC);
 
1532
#endif
 
1533
            if(hresult)
 
1534
                MessageBox(m_Tree,_("Delete directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
 
1535
        }
 
1536
    }
 
1537
    Refresh(m_Tree->GetRootItem());
 
1538
}
 
1539
 
 
1540
void FileExplorer::OnRename(wxCommandEvent &/*event*/)
 
1541
{
 
1542
    wxString path(GetFullPath(m_selectti[0]));  //SINGLE: m_Tree->GetSelection()
 
1543
    if(wxFileName::FileExists(path))
 
1544
    {
 
1545
        EditorManager* em = Manager::Get()->GetEditorManager();
 
1546
        if(em->IsOpen(path))
 
1547
        {
 
1548
            cbMessageBox(_("Close file first"));
 
1549
            return;
 
1550
        }
 
1551
        wxTextEntryDialog te(this,_("New name:"),_("Rename File"),wxFileName(path).GetFullName());
 
1552
        if(te.ShowModal()==wxID_CANCEL)
 
1553
            return;
 
1554
        wxFileName destpath(path);
 
1555
        destpath.SetFullName(te.GetValue());
 
1556
        if(!::wxRenameFile(path,destpath.GetFullPath()))
 
1557
            cbMessageBox(_("Rename failed"));
 
1558
    }
 
1559
    if(wxFileName::DirExists(path))
 
1560
    {
 
1561
        wxTextEntryDialog te(this,_("New name:"),_("Rename File"),wxFileName(path).GetFullName());
 
1562
        if(te.ShowModal()==wxID_CANCEL)
 
1563
            return;
 
1564
        wxFileName destpath(path);
 
1565
        destpath.SetFullName(te.GetValue());
 
1566
#ifdef __WXMSW__
 
1567
        wxArrayString output;
 
1568
        int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
 
1569
#else
 
1570
        int hresult=::wxExecute(_T("/bin/mv \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
 
1571
#endif
 
1572
        if(hresult)
 
1573
            MessageBox(m_Tree,_("Rename directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
 
1574
    }
 
1575
    Refresh(m_Tree->GetItemParent(m_selectti[0])); //SINGLE: m_Tree->GetSelection()
 
1576
}
 
1577
 
 
1578
void FileExplorer::OnExpandAll(wxCommandEvent &/*event*/)
 
1579
{
 
1580
    m_Tree->ExpandAllChildren(m_Tree->GetSelection());
 
1581
}
 
1582
 
 
1583
void FileExplorer::OnCollapseAll(wxCommandEvent &/*event*/)
 
1584
{
 
1585
    m_Tree->CollapseAllChildren(m_Tree->GetSelection());
 
1586
}
 
1587
 
 
1588
void FileExplorer::OnSettings(wxCommandEvent &/*event*/)
 
1589
{
 
1590
    FileBrowserSettings fbs(m_favdirs,NULL);
 
1591
    if(fbs.ShowModal()==wxID_OK)
 
1592
    {
 
1593
        size_t count=m_favdirs.GetCount();
 
1594
        for(size_t i=0;i<count;i++)
 
1595
            m_Loc->Delete(0);
 
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);
 
1600
    }
 
1601
 
 
1602
}
 
1603
 
 
1604
void FileExplorer::OnShowHidden(wxCommandEvent &/*event*/)
 
1605
{
 
1606
    m_show_hidden=!m_show_hidden;
 
1607
    Refresh(m_Tree->GetRootItem());
 
1608
}
 
1609
 
 
1610
void FileExplorer::OnParseCVS(wxCommandEvent &/*event*/)
 
1611
{
 
1612
    m_parse_cvs=!m_parse_cvs;
 
1613
    //cfg->Clear();
 
1614
    Refresh(m_Tree->GetRootItem());
 
1615
}
 
1616
 
 
1617
void FileExplorer::OnParseSVN(wxCommandEvent &/*event*/)
 
1618
{
 
1619
    m_parse_svn=!m_parse_svn;
 
1620
    Refresh(m_Tree->GetRootItem());
 
1621
}
 
1622
 
 
1623
void FileExplorer::OnParseGIT(wxCommandEvent &/*event*/)
 
1624
{
 
1625
    m_parse_git=!m_parse_git;
 
1626
    Refresh(m_Tree->GetRootItem());
 
1627
}
 
1628
 
 
1629
void FileExplorer::OnParseHG(wxCommandEvent &/*event*/)
 
1630
{
 
1631
    m_parse_hg=!m_parse_hg;
 
1632
    Refresh(m_Tree->GetRootItem());
 
1633
}
 
1634
 
 
1635
void FileExplorer::OnParseBZR(wxCommandEvent &/*event*/)
 
1636
{
 
1637
    m_parse_bzr=!m_parse_bzr;
 
1638
    Refresh(m_Tree->GetRootItem());
 
1639
}
 
1640
 
 
1641
void FileExplorer::OnUpButton(wxCommandEvent &/*event*/)
 
1642
{
 
1643
    wxFileName loc(m_root);
 
1644
    loc.RemoveLastDir();
 
1645
    SetRootFolder(loc.GetFullPath()); //TODO: Check if this is always the root folder
 
1646
}
 
1647
 
 
1648
void FileExplorer::OnRefresh(wxCommandEvent &/*event*/)
 
1649
{
 
1650
    if(m_Tree->GetItemImage(m_selectti[0])==fvsFolder) //SINGLE: m_Tree->GetSelection()
 
1651
        Refresh(m_selectti[0]); //SINGLE: m_Tree->GetSelection()
 
1652
    else
 
1653
        Refresh(m_Tree->GetRootItem());
 
1654
}
 
1655
 
 
1656
//TODO: Set copy cursor state if necessary
 
1657
void FileExplorer::OnBeginDragTreeItem(wxTreeEvent &event)
 
1658
{
 
1659
//    SetCursor(wxCROSS_CURSOR);
 
1660
//    if(IsInSelection(event.GetItem()))
 
1661
//        return; // don't start a drag for an unselected item
 
1662
    if (!IsBrowsingVCSTree())
 
1663
        event.Allow();
 
1664
//    m_dragtest=GetFullPath(event.GetItem());
 
1665
    m_ticount=m_Tree->GetSelections(m_selectti);
 
1666
}
 
1667
 
 
1668
bool FileExplorer::IsInSelection(const wxTreeItemId &ti)
 
1669
{
 
1670
    for(int i=0;i<m_ticount;i++)
 
1671
        if(ti==m_selectti[i])
 
1672
            return true;
 
1673
    return false;
 
1674
}
 
1675
 
 
1676
//TODO: End copy cursor state if necessary
 
1677
void FileExplorer::OnEndDragTreeItem(wxTreeEvent &event)
 
1678
{
 
1679
//    SetCursor(wxCursor(wxCROSS_CURSOR));
 
1680
    if(m_Tree->GetItemImage(event.GetItem())!=fvsFolder) //can only copy to folders
 
1681
        return;
 
1682
    for(int i=0;i<m_ticount;i++)
 
1683
    {
 
1684
        wxString path(GetFullPath(m_selectti[i]));
 
1685
        wxFileName destpath;
 
1686
        if(!event.GetItem().IsOk())
 
1687
            return;
 
1688
        destpath.Assign(GetFullPath(event.GetItem()),wxFileName(path).GetFullName());
 
1689
        if(destpath.SameAs(path))
 
1690
            continue;
 
1691
        if(wxFileName::DirExists(path)||wxFileName::FileExists(path))
 
1692
        {
 
1693
            if(!::wxGetKeyState(WXK_CONTROL))
 
1694
            {
 
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)))
 
1697
                        continue;
 
1698
#ifdef __WXMSW__
 
1699
                wxArrayString output;
 
1700
                int hresult=::wxExecute(_T("cmd /c move /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),output,wxEXEC_SYNC);
 
1701
#else
 
1702
                int hresult=::wxExecute(_T("/bin/mv -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
 
1703
#endif
 
1704
                if(hresult)
 
1705
                    MessageBox(m_Tree,_("Move directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
 
1706
            } else
 
1707
            {
 
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)))
 
1710
                        continue;
 
1711
#ifdef __WXMSW__
 
1712
                wxArrayString output;
 
1713
                wxString cmdline;
 
1714
                if(wxFileName::FileExists(path))
 
1715
                    cmdline=_T("cmd /c copy /Y \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
 
1716
                else
 
1717
                    cmdline=_T("cmd /c xcopy /S/E/Y/H/I \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\"");
 
1718
                int hresult=::wxExecute(cmdline,output,wxEXEC_SYNC);
 
1719
#else
 
1720
                int hresult=::wxExecute(_T("/bin/cp -r -b \"")+path+_T("\" \"")+destpath.GetFullPath()+_T("\""),wxEXEC_SYNC);
 
1721
#endif
 
1722
                if(hresult)
 
1723
                    MessageBox(m_Tree,_("Copy directory '")+path+_("' failed with error ")+wxString::Format(_T("%i"),hresult));
 
1724
            }
 
1725
        }
 
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
 
1727
//            return;
 
1728
    }
 
1729
    Refresh(m_Tree->GetRootItem());
 
1730
}
 
1731
 
 
1732
void FileExplorer::OnAddToProject(wxCommandEvent &/*event*/)
 
1733
{
 
1734
    wxArrayString files;
 
1735
    wxString file;
 
1736
    for(int i=0;i<m_ticount;i++)
 
1737
    {
 
1738
        file=GetFullPath(m_selectti[i]);
 
1739
        if(wxFileName::FileExists(file))
 
1740
            files.Add(file);
 
1741
    }
 
1742
    wxArrayInt prompt;
 
1743
    Manager::Get()->GetProjectManager()->AddMultipleFilesToProject(files, NULL, prompt);
 
1744
    Manager::Get()->GetProjectManager()->GetUI().RebuildTree();
 
1745
}
 
1746
 
 
1747
bool FileExplorer::IsFilesOnly(wxArrayTreeItemIds tis)
 
1748
{
 
1749
    for(size_t i=0;i<tis.GetCount();i++)
 
1750
        if(m_Tree->GetItemImage(tis[i])==fvsFolder)
 
1751
            return false;
 
1752
    return true;
 
1753
}