~ubuntu-branches/debian/sid/filezilla/sid

« back to all changes in this revision

Viewing changes to src/interface/sitemanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Cécile (Le_Vert)
  • Date: 2008-07-05 21:00:24 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080705210024-mvzp21zlyheschi6
Tags: 3.0.11.1-1
* wxWidgets 2.8 just entered unstable ! Upload to unstable.
* New upstream release.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
#include "filezillaapp.h"
7
7
#include "ipcmutex.h"
8
8
#include "wrapengine.h"
 
9
#include "conditionaldialog.h"
 
10
#include "window_state_manager.h"
 
11
#include <wx/dnd.h>
 
12
 
 
13
std::map<int, CSiteManagerItemData*> CSiteManager::m_idMap;
9
14
 
10
15
BEGIN_EVENT_TABLE(CSiteManager, wxDialogEx)
11
16
EVT_BUTTON(XRCID("wxID_OK"), CSiteManager::OnOK)
27
32
EVT_RADIOBUTTON(XRCID("ID_CHARSET_UTF8"), CSiteManager::OnCharsetChange)
28
33
EVT_RADIOBUTTON(XRCID("ID_CHARSET_CUSTOM"), CSiteManager::OnCharsetChange)
29
34
EVT_CHOICE(XRCID("ID_PROTOCOL"), CSiteManager::OnProtocolSelChanged)
 
35
EVT_BUTTON(XRCID("ID_COPY"), CSiteManager::OnCopySite)
 
36
EVT_TREE_BEGIN_DRAG(XRCID("ID_SITETREE"), CSiteManager::OnBeginDrag)
 
37
EVT_CHAR(CSiteManager::OnChar)
30
38
END_EVENT_TABLE()
31
39
 
 
40
class CSiteManagerDataObject : public wxDataObjectSimple
 
41
{
 
42
public:
 
43
        CSiteManagerDataObject()
 
44
                : wxDataObjectSimple(wxDataFormat(_T("FileZilla3SiteManagerObject")))
 
45
        {
 
46
        }
 
47
 
 
48
        // GTK doesn't like data size of 0
 
49
        virtual size_t GetDataSize() const { return 1; }
 
50
 
 
51
        virtual bool GetDataHere(void *buf) const { memset(buf, 0, 1); return true; }
 
52
 
 
53
        virtual bool SetData(size_t len, const void *buf) { return true; }
 
54
};
 
55
 
 
56
class CSiteManagerDropTarget : public wxDropTarget
 
57
{
 
58
public:
 
59
        CSiteManagerDropTarget(CSiteManager* pSiteManager)
 
60
                : wxDropTarget(new CSiteManagerDataObject())
 
61
        {
 
62
                m_pSiteManager = pSiteManager;
 
63
        }
 
64
 
 
65
        virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
 
66
        {
 
67
                ClearDropHighlight();
 
68
                if (def == wxDragError ||
 
69
                        def == wxDragNone ||
 
70
                        def == wxDragCancel)
 
71
                {
 
72
                        return def;
 
73
                }
 
74
 
 
75
                wxTreeItemId hit = GetHit(wxPoint(x, y));
 
76
                if (!hit)
 
77
                        return wxDragNone;
 
78
                if (hit == m_pSiteManager->m_dropSource)
 
79
                        return wxDragNone;
 
80
 
 
81
                const bool predefined = m_pSiteManager->IsPredefinedItem(hit);
 
82
                if (predefined)
 
83
                        return wxDragNone;
 
84
 
 
85
                wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
 
86
                if (pTree->GetItemData(hit))
 
87
                        return wxDragNone;
 
88
 
 
89
                wxTreeItemId item = hit;
 
90
                while (item != pTree->GetRootItem())
 
91
                {
 
92
                        if (item == m_pSiteManager->m_dropSource)
 
93
                        {
 
94
                                ClearDropHighlight();
 
95
                                return wxDragNone;
 
96
                        }
 
97
                        item = pTree->GetItemParent(item);
 
98
                }
 
99
 
 
100
                if (def == wxDragMove && pTree->GetItemParent(m_pSiteManager->m_dropSource) == hit)
 
101
                        return wxDragNone;
 
102
 
 
103
                if (!m_pSiteManager->MoveItems(m_pSiteManager->m_dropSource, hit, def == wxDragCopy))
 
104
                        return wxDragNone;
 
105
 
 
106
                return def;
 
107
        }
 
108
 
 
109
        virtual bool OnDrop(wxCoord x, wxCoord y)
 
110
        {
 
111
                ClearDropHighlight();
 
112
 
 
113
                wxTreeItemId hit = GetHit(wxPoint(x, y));
 
114
                if (!hit)
 
115
                        return false;
 
116
                if (hit == m_pSiteManager->m_dropSource)
 
117
                        return false;
 
118
 
 
119
                const bool predefined = m_pSiteManager->IsPredefinedItem(hit);
 
120
                if (predefined)
 
121
                        return false;
 
122
 
 
123
                wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
 
124
                if (pTree->GetItemData(hit))
 
125
                        return false;
 
126
 
 
127
                wxTreeItemId item = hit;
 
128
                while (item != pTree->GetRootItem())
 
129
                {
 
130
                        if (item == m_pSiteManager->m_dropSource)
 
131
                        {
 
132
                                ClearDropHighlight();
 
133
                                return false;
 
134
                        }
 
135
                        item = pTree->GetItemParent(item);
 
136
                }
 
137
 
 
138
                return true;
 
139
        }
 
140
 
 
141
        virtual void OnLeave()
 
142
        {
 
143
                ClearDropHighlight();
 
144
        }
 
145
 
 
146
        virtual wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def)
 
147
        {
 
148
                return OnDragOver(x, y, def);
 
149
        }
 
150
 
 
151
        wxTreeItemId GetHit(const wxPoint& point)
 
152
        {
 
153
                int flags = 0;
 
154
 
 
155
                wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
 
156
                wxTreeItemId hit = pTree->HitTest(point, flags);
 
157
 
 
158
                if (flags & (wxTREE_HITTEST_ABOVE | wxTREE_HITTEST_BELOW | wxTREE_HITTEST_NOWHERE | wxTREE_HITTEST_TOLEFT | wxTREE_HITTEST_TORIGHT))
 
159
                        return wxTreeItemId();
 
160
 
 
161
                return hit;
 
162
        }
 
163
 
 
164
        virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def)
 
165
        {
 
166
                if (def == wxDragError ||
 
167
                        def == wxDragNone ||
 
168
                        def == wxDragCancel)
 
169
                {
 
170
                        ClearDropHighlight();
 
171
                        return def;
 
172
                }
 
173
 
 
174
                wxTreeItemId hit = GetHit(wxPoint(x, y));
 
175
                if (!hit)
 
176
                {
 
177
                        ClearDropHighlight();
 
178
                        return wxDragNone;
 
179
                }
 
180
                if (hit == m_pSiteManager->m_dropSource)
 
181
                {
 
182
                        ClearDropHighlight();
 
183
                        return wxDragNone;
 
184
                }
 
185
 
 
186
                const bool predefined = m_pSiteManager->IsPredefinedItem(hit);
 
187
                if (predefined)
 
188
                {
 
189
                        ClearDropHighlight();
 
190
                        return wxDragNone;
 
191
                }
 
192
 
 
193
                wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
 
194
                CSiteManagerItemData* data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(hit));
 
195
                if (data)
 
196
                {
 
197
                        ClearDropHighlight();
 
198
                        return wxDragNone;
 
199
                }
 
200
 
 
201
                wxTreeItemId item = hit;
 
202
                while (item != pTree->GetRootItem())
 
203
                {
 
204
                        if (item == m_pSiteManager->m_dropSource)
 
205
                        {
 
206
                                ClearDropHighlight();
 
207
                                return wxDragNone;
 
208
                        }
 
209
                        item = pTree->GetItemParent(item);
 
210
                }
 
211
 
 
212
                if (def == wxDragMove && pTree->GetItemParent(m_pSiteManager->m_dropSource) == hit)
 
213
                {
 
214
                        ClearDropHighlight();
 
215
                        return wxDragNone;
 
216
                }
 
217
 
 
218
                DisplayDropHighlight(hit);
 
219
 
 
220
                return def;
 
221
        }
 
222
 
 
223
        void ClearDropHighlight()
 
224
        {
 
225
                if (m_dropHighlight == wxTreeItemId())
 
226
                        return;
 
227
 
 
228
                wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
 
229
                pTree->SetItemDropHighlight(m_dropHighlight, false);
 
230
                m_dropHighlight = wxTreeItemId();
 
231
        }
 
232
 
 
233
        void DisplayDropHighlight(wxTreeItemId item)
 
234
        {
 
235
                ClearDropHighlight();
 
236
 
 
237
                wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
 
238
                pTree->SetItemDropHighlight(item, true);
 
239
                m_dropHighlight = item;
 
240
        }
 
241
 
 
242
protected:
 
243
        CSiteManager* m_pSiteManager;
 
244
        wxTreeItemId m_dropHighlight;
 
245
};
 
246
 
32
247
CSiteManager::CSiteManager()
33
248
{
34
249
        m_pSiteManagerMutex = 0;
 
250
        m_pWindowStateManager = 0;
35
251
}
36
252
 
37
253
CSiteManager::~CSiteManager()
38
254
{
39
255
        delete m_pSiteManagerMutex;
 
256
 
 
257
        if (m_pWindowStateManager)
 
258
        {
 
259
                m_pWindowStateManager->Remember(OPTION_SITEMANAGER_POSITION);
 
260
                delete m_pWindowStateManager;
 
261
        }
40
262
}
41
263
 
42
 
bool CSiteManager::Create(wxWindow* parent)
 
264
bool CSiteManager::Create(wxWindow* parent, const CServer* pServer /*=0*/)
43
265
{
44
266
        m_pSiteManagerMutex = new CInterProcessMutex(MUTEX_SITEMANAGERGLOBAL, false);
45
267
        if (!m_pSiteManagerMutex->TryLock())
46
268
        {
47
269
                int answer = wxMessageBox(_("The Site Manager is opened in another instance of FileZilla 3.\nDo you want to continue? Any changes made in the Site Manager won't be saved then."),
48
270
                                                                  _("Site Manager already open"), wxYES_NO | wxICON_QUESTION);
49
 
                if (answer != wxYES)                                    
 
271
                if (answer != wxYES)
50
272
                        return false;
51
273
 
52
274
                delete m_pSiteManagerMutex;
53
275
                m_pSiteManagerMutex = 0;
54
276
        }
55
 
        SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
56
 
        SetParent(parent);
57
 
        CreateControls();
58
 
        wxGetApp().GetWrapEngine()->WrapRecursive(this, 1.33, "Site Manager");
59
 
        
60
 
        Load();
61
 
 
62
 
        XRCCTRL(*this, "ID_TRANSFERMODE_DEFAULT", wxRadioButton)->Update();
63
 
        XRCCTRL(*this, "ID_TRANSFERMODE_ACTIVE", wxRadioButton)->Update();
64
 
        XRCCTRL(*this, "ID_TRANSFERMODE_PASSIVE", wxRadioButton)->Update();
 
277
        CreateControls(parent);
65
278
 
66
279
        // Now create the imagelist for the site tree
67
280
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
72
285
        pImageList->Add(wxArtProvider::GetBitmap(_T("ART_FOLDERCLOSED"),  wxART_OTHER, wxSize(16, 16)));
73
286
        pImageList->Add(wxArtProvider::GetBitmap(_T("ART_FOLDER"),  wxART_OTHER, wxSize(16, 16)));
74
287
        pImageList->Add(wxArtProvider::GetBitmap(_T("ART_SERVER"),  wxART_OTHER, wxSize(16, 16)));
75
 
        
 
288
 
76
289
        pTree->AssignImageList(pImageList);
77
 
        
 
290
 
 
291
        Layout();
 
292
        wxGetApp().GetWrapEngine()->WrapRecursive(this, 1.33, "Site Manager");
 
293
 
 
294
        wxSize minSize = GetSizer()->GetMinSize();
 
295
 
 
296
        wxSize size = GetSize();
 
297
        wxSize clientSize = GetClientSize();
 
298
        SetMinSize(GetSizer()->GetMinSize() + size - clientSize);
 
299
        SetClientSize(minSize);
 
300
 
 
301
        Load();
 
302
 
 
303
        XRCCTRL(*this, "ID_TRANSFERMODE_DEFAULT", wxRadioButton)->Update();
 
304
        XRCCTRL(*this, "ID_TRANSFERMODE_ACTIVE", wxRadioButton)->Update();
 
305
        XRCCTRL(*this, "ID_TRANSFERMODE_PASSIVE", wxRadioButton)->Update();
 
306
 
78
307
        SetCtrlState();
79
 
                
 
308
 
 
309
        m_pWindowStateManager = new CWindowStateManager(this);
 
310
        m_pWindowStateManager->Restore(OPTION_SITEMANAGER_POSITION);
 
311
 
 
312
        pTree->SetDropTarget(new CSiteManagerDropTarget(this));
 
313
 
 
314
#ifdef __WXGTK__
 
315
        CSiteManagerItemData* data = 0;
 
316
        wxTreeItemId item = pTree->GetSelection();
 
317
        if (item.IsOk())
 
318
                data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(item));
 
319
        if (!data)
 
320
                XRCCTRL(*this, "wxID_OK", wxButton)->SetFocus();
 
321
#endif
 
322
 
 
323
        if (pServer)
 
324
                CopyAddServer(*pServer);
 
325
 
80
326
        return true;
81
327
}
82
328
 
83
 
void CSiteManager::CreateControls()
84
 
{       
85
 
        wxXmlResource::Get()->LoadDialog(this, GetParent(), _T("ID_SITEMANAGER"));
 
329
void CSiteManager::CreateControls(wxWindow* parent)
 
330
{
 
331
        wxXmlResource::Get()->LoadDialog(this, parent, _T("ID_SITEMANAGER"));
 
332
 
 
333
        wxChoice *pProtocol = XRCCTRL(*this, "ID_PROTOCOL", wxChoice);
 
334
        pProtocol->Append(CServer::GetProtocolName(FTP));
 
335
        pProtocol->Append(CServer::GetProtocolName(SFTP));
 
336
        pProtocol->Append(CServer::GetProtocolName(FTPS));
 
337
        pProtocol->Append(CServer::GetProtocolName(FTPES));
 
338
 
 
339
        wxChoice *pChoice = XRCCTRL(*this, "ID_SERVERTYPE", wxChoice);
 
340
        wxASSERT(pChoice);
 
341
        for (int i = 0; i < SERVERTYPE_MAX; i++)
 
342
                pChoice->Append(CServer::GetNameFromServerType((enum ServerType)i));
86
343
}
87
344
 
88
345
void CSiteManager::OnOK(wxCommandEvent& event)
91
348
                return;
92
349
 
93
350
        UpdateServer();
94
 
                
 
351
 
95
352
        Save();
96
 
        
 
353
 
 
354
        RememberLastSelected();
 
355
 
97
356
        EndModal(wxID_OK);
98
357
}
99
358
 
118
377
                wxBell();
119
378
                return;
120
379
        }
121
 
        
 
380
 
122
381
        if (!Verify())
123
382
        {
124
383
                wxBell();
126
385
        }
127
386
 
128
387
        UpdateServer();
129
 
                
 
388
 
130
389
        Save();
131
 
        
 
390
 
 
391
        RememberLastSelected();
 
392
 
132
393
        EndModal(wxID_YES);
133
394
}
134
395
 
135
 
bool CSiteManager::Load(TiXmlElement *pElement /*=0*/, wxTreeItemId treeId /*=wxTreeItemId()*/)
 
396
class CSiteManagerXmlHandler
 
397
{
 
398
public:
 
399
        virtual ~CSiteManagerXmlHandler() {};
 
400
 
 
401
        // Adds a folder and descents
 
402
        virtual bool AddFolder(const wxString& name, bool expanded) = 0;
 
403
        virtual bool AddSite(const wxString& name, CSiteManagerItemData* data) = 0;
 
404
 
 
405
        // Go up a level
 
406
        virtual bool LevelUp() = 0; // *Ding*
 
407
};
 
408
 
 
409
class CSiteManagerXmlHandler_Tree : public CSiteManagerXmlHandler
 
410
{
 
411
public:
 
412
        CSiteManagerXmlHandler_Tree(wxTreeCtrl* pTree, wxTreeItemId root, const wxString& lastSelection)
 
413
                : m_pTree(pTree), m_item(root)
 
414
        {
 
415
                if (!CSiteManager::UnescapeSitePath(lastSelection, m_lastSelection))
 
416
                        m_lastSelection.clear();
 
417
                m_wrong_sel_depth = 0;
 
418
        }
 
419
 
 
420
        virtual ~CSiteManagerXmlHandler_Tree()
 
421
        {
 
422
                m_pTree->SortChildren(m_item);
 
423
                m_pTree->Expand(m_item);
 
424
        }
 
425
 
 
426
        virtual bool AddFolder(const wxString& name, bool expanded)
 
427
        {
 
428
                wxTreeItemId newItem = m_pTree->AppendItem(m_item, name, 0, 0);
 
429
                m_pTree->SetItemImage(newItem, 1, wxTreeItemIcon_Expanded);
 
430
                m_pTree->SetItemImage(newItem, 1, wxTreeItemIcon_SelectedExpanded);
 
431
 
 
432
                m_item = newItem;
 
433
                m_expand.push_back(expanded);
 
434
 
 
435
                if (!m_wrong_sel_depth && !m_lastSelection.empty())
 
436
                {
 
437
                        const wxString& first = m_lastSelection.front();
 
438
                        if (first == name)
 
439
                        {
 
440
                                m_lastSelection.pop_front();
 
441
                                if (m_lastSelection.empty())
 
442
                                        m_pTree->SelectItem(newItem);
 
443
                        }
 
444
                        else
 
445
                                m_wrong_sel_depth++;
 
446
                }
 
447
                else
 
448
                        m_wrong_sel_depth++;
 
449
 
 
450
                return true;
 
451
        }
 
452
 
 
453
        virtual bool AddSite(const wxString& name, CSiteManagerItemData* data)
 
454
        {
 
455
                wxTreeItemId newItem = m_pTree->AppendItem(m_item, name, 2, 2, data);
 
456
 
 
457
                if (!m_wrong_sel_depth && !m_lastSelection.empty())
 
458
                {
 
459
                        const wxString& first = m_lastSelection.front();
 
460
                        if (first == name)
 
461
                        {
 
462
                                m_lastSelection.clear();
 
463
                                m_pTree->SelectItem(newItem);
 
464
                        }
 
465
                }
 
466
 
 
467
                return true;
 
468
        }
 
469
 
 
470
        virtual bool LevelUp()
 
471
        {
 
472
                if (m_wrong_sel_depth)
 
473
                        m_wrong_sel_depth--;
 
474
 
 
475
                if (!m_expand.empty())
 
476
                {
 
477
                        const bool expand = m_expand.back();
 
478
                        m_expand.pop_back();
 
479
                        if (expand)
 
480
                                m_pTree->Expand(m_item);
 
481
                }
 
482
                m_pTree->SortChildren(m_item);
 
483
 
 
484
                wxTreeItemId parent = m_pTree->GetItemParent(m_item);
 
485
                if (!parent)
 
486
                        return false;
 
487
 
 
488
                m_item = parent;
 
489
                return true;
 
490
        }
 
491
 
 
492
protected:
 
493
        wxTreeCtrl* m_pTree;
 
494
        wxTreeItemId m_item;
 
495
 
 
496
        std::list<wxString> m_lastSelection;
 
497
        int m_wrong_sel_depth;
 
498
 
 
499
        std::list<bool> m_expand;
 
500
};
 
501
 
 
502
bool CSiteManager::Load()
136
503
{
137
504
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
138
505
        if (!pTree)
139
506
                return false;
140
 
        
141
 
        if (!pElement || !treeId)
142
 
        {
143
 
                pTree->DeleteAllItems();
144
 
                treeId = pTree->AddRoot(_("My Sites"), 0, 0);
145
 
                pTree->SelectItem(treeId);
146
 
                pTree->SetItemImage(treeId, 1, wxTreeItemIcon_Expanded);
147
 
                pTree->SetItemImage(treeId, 1, wxTreeItemIcon_SelectedExpanded);
148
 
 
149
 
                // We have to synchronize access to sitemanager.xml so that multiple processed don't write 
150
 
                // to the same file or one is reading while the other one writes.
151
 
                CInterProcessMutex mutex(MUTEX_SITEMANAGER);
152
 
 
153
 
                wxFileName file(wxGetApp().GetSettingsDir(), _T("sitemanager.xml"));
154
 
                TiXmlElement* pDocument = GetXmlFile(file);
155
 
                if (!pDocument)
156
 
                {
157
 
                        wxString msg = wxString::Format(_("Could not load \"%s\", please make sure the file is valid and can be accessed.\nAny changes made in the Site Manager will not be saved."), file.GetFullPath().c_str());
158
 
                        wxMessageBox(msg, _("Error loading xml file"), wxICON_ERROR);
159
 
 
160
 
                        return false;
161
 
                }
162
 
                pElement = pDocument->FirstChildElement("Servers");
163
 
                if (!pElement)
164
 
                {
165
 
                        delete pDocument->GetDocument();
166
 
                        return true;
167
 
                }
168
 
 
169
 
                bool res = Load(pElement, treeId);
170
 
 
171
 
                delete pDocument->GetDocument();
172
 
 
173
 
                pTree->SortChildren(treeId);
174
 
                pTree->Expand(treeId);
175
 
                pTree->SelectItem(treeId);
176
 
                
177
 
                return res;
178
 
        }
179
 
        
 
507
 
 
508
        pTree->DeleteAllItems();
 
509
 
 
510
        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
 
511
        // to the same file or one is reading while the other one writes.
 
512
        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
 
513
 
 
514
        // Load default sites
 
515
        bool hasDefaultSites = LoadDefaultSites();
 
516
        if (hasDefaultSites)
 
517
                m_ownSites = pTree->AppendItem(pTree->GetRootItem(), _("My Sites"), 0, 0);
 
518
        else
 
519
                m_ownSites = pTree->AddRoot(_("My Sites"), 0, 0);
 
520
 
 
521
        wxTreeItemId treeId = m_ownSites;
 
522
        pTree->SetItemImage(treeId, 1, wxTreeItemIcon_Expanded);
 
523
        pTree->SetItemImage(treeId, 1, wxTreeItemIcon_SelectedExpanded);
 
524
 
 
525
        CXmlFile file(_T("sitemanager"));
 
526
        TiXmlElement* pDocument = file.Load();
 
527
        if (!pDocument)
 
528
        {
 
529
                wxString msg = wxString::Format(_("Could not load \"%s\", please make sure the file is valid and can be accessed.\nAny changes made in the Site Manager will not be saved."), file.GetFileName().GetFullPath().c_str());
 
530
                wxMessageBox(msg, _("Error loading xml file"), wxICON_ERROR);
 
531
 
 
532
                return false;
 
533
        }
 
534
 
 
535
        TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
 
536
        if (!pElement)
 
537
                return true;
 
538
 
 
539
        wxString lastSelection = COptions::Get()->GetOption(OPTION_SITEMANAGER_LASTSELECTED);
 
540
        if (lastSelection[0] == '0')
 
541
        {
 
542
                if (lastSelection == _T("0"))
 
543
                        pTree->SelectItem(treeId);
 
544
                else
 
545
                        lastSelection = lastSelection.Mid(1);
 
546
        }
 
547
        else
 
548
                lastSelection = _T("");
 
549
        CSiteManagerXmlHandler_Tree handler(pTree, treeId, lastSelection);
 
550
 
 
551
        bool res = Load(pElement, &handler);
 
552
 
 
553
        pTree->SortChildren(treeId);
 
554
        pTree->Expand(treeId);
 
555
        if (!pTree->GetSelection())
 
556
                pTree->SelectItem(treeId);
 
557
 
 
558
        pTree->EnsureVisible(pTree->GetSelection());
 
559
 
 
560
        return res;
 
561
}
 
562
 
 
563
bool CSiteManager::Load(TiXmlElement *pElement, CSiteManagerXmlHandler* pHandler)
 
564
{
 
565
        wxASSERT(pElement);
 
566
        wxASSERT(pHandler);
 
567
 
180
568
        for (TiXmlElement* pChild = pElement->FirstChildElement(); pChild; pChild = pChild->NextSiblingElement())
181
569
        {
182
570
                TiXmlNode* pNode = pChild->FirstChild();
183
571
                while (pNode && !pNode->ToText())
184
572
                        pNode = pNode->NextSibling();
185
 
                        
 
573
 
186
574
                if (!pNode)
187
575
                        continue;
188
 
        
 
576
 
189
577
                wxString name = ConvLocal(pNode->ToText()->Value());
190
 
                
 
578
                name.Trim(true);
 
579
                name.Trim(false);
 
580
 
191
581
                if (!strcmp(pChild->Value(), "Folder"))
192
582
                {
193
 
                        wxTreeItemId id = pTree->AppendItem(treeId, name, 0, 0);
194
 
                        pTree->SetItemImage(id, 1, wxTreeItemIcon_Expanded);
195
 
                        pTree->SetItemImage(id, 1, wxTreeItemIcon_SelectedExpanded);
196
 
                        Load(pChild, id);
 
583
                        const bool expand = GetTextAttribute(pChild, "expanded") != _T("0");
 
584
                        if (!pHandler->AddFolder(name, expand))
 
585
                                return false;
 
586
                        Load(pChild, pHandler);
 
587
                        if (!pHandler->LevelUp())
 
588
                                return false;
197
589
                }
198
590
                else if (!strcmp(pChild->Value(), "Server"))
199
591
                {
200
 
                        CServer server;
201
 
                        if (!::GetServer(pChild, server))
202
 
                                continue;
203
 
 
204
 
                        CSiteManagerItemData* data = new CSiteManagerItemData(server);
205
 
                        
206
 
                        TiXmlHandle handle(pChild);
207
 
 
208
 
                        TiXmlText* comments = handle.FirstChildElement("Comments").FirstChild().Text();
209
 
                        if (comments)
210
 
                                data->m_comments = ConvLocal(comments->Value());
211
 
                        
212
 
                        TiXmlText* localDir = handle.FirstChildElement("LocalDir").FirstChild().Text();
213
 
                        if (localDir)
214
 
                                data->m_localDir = ConvLocal(localDir->Value());
215
 
                        
216
 
                        TiXmlText* remoteDir = handle.FirstChildElement("RemoteDir").FirstChild().Text();
217
 
                        if (remoteDir)
218
 
                                data->m_remoteDir.SetSafePath(ConvLocal(remoteDir->Value()));
219
 
                        
220
 
                        pTree->AppendItem(treeId, name, 2, 2, data);
 
592
                        CSiteManagerItemData* data = ReadServerElement(pChild);
 
593
 
 
594
                        if (data)
 
595
                                pHandler->AddSite(name, data);
221
596
                }
222
597
        }
223
 
        pTree->SortChildren(treeId);
224
 
        pTree->Expand(treeId);
225
 
                
 
598
 
226
599
        return true;
227
600
}
228
601
 
 
602
CSiteManagerItemData* CSiteManager::ReadServerElement(TiXmlElement *pElement)
 
603
{
 
604
        CServer server;
 
605
        if (!::GetServer(pElement, server))
 
606
                return 0;
 
607
 
 
608
        CSiteManagerItemData* data = new CSiteManagerItemData(server);
 
609
 
 
610
        TiXmlHandle handle(pElement);
 
611
 
 
612
        TiXmlText* comments = handle.FirstChildElement("Comments").FirstChild().Text();
 
613
        if (comments)
 
614
                data->m_comments = ConvLocal(comments->Value());
 
615
 
 
616
        TiXmlText* localDir = handle.FirstChildElement("LocalDir").FirstChild().Text();
 
617
        if (localDir)
 
618
                data->m_localDir = ConvLocal(localDir->Value());
 
619
 
 
620
        TiXmlText* remoteDir = handle.FirstChildElement("RemoteDir").FirstChild().Text();
 
621
        if (remoteDir)
 
622
                data->m_remoteDir.SetSafePath(ConvLocal(remoteDir->Value()));
 
623
 
 
624
        return data;
 
625
}
 
626
 
229
627
bool CSiteManager::Save(TiXmlElement *pElement /*=0*/, wxTreeItemId treeId /*=wxTreeItemId()*/)
230
628
{
231
629
        if (!m_pSiteManagerMutex)
234
632
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
235
633
        if (!pTree)
236
634
                return false;
237
 
                
 
635
 
238
636
        if (!pElement || !treeId)
239
637
        {
240
 
                // We have to synchronize access to sitemanager.xml so that multiple processed don't write 
 
638
                // We have to synchronize access to sitemanager.xml so that multiple processed don't write
241
639
                // to the same file or one is reading while the other one writes.
242
640
                CInterProcessMutex mutex(MUTEX_SITEMANAGER);
243
641
 
266
664
                        return true;
267
665
                }
268
666
 
269
 
                bool res = Save(pElement, pTree->GetRootItem());
270
 
                
 
667
                bool res = Save(pElement, m_ownSites);
 
668
 
271
669
                wxString error;
272
670
                if (!SaveXmlFile(file, pDocument, &error))
273
671
                {
278
676
                delete pDocument->GetDocument();
279
677
                return res;
280
678
        }
281
 
        
 
679
 
282
680
        wxTreeItemId child;
283
681
        wxTreeItemIdValue cookie;
284
682
        child = pTree->GetFirstChild(treeId, cookie);
286
684
        {
287
685
                wxString name = pTree->GetItemText(child);
288
686
                char* utf8 = ConvUTF8(name);
289
 
                
 
687
 
290
688
                CSiteManagerItemData* data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(child));
291
689
                if (!data)
292
690
                {
293
691
                        TiXmlNode* pNode = pElement->InsertEndChild(TiXmlElement("Folder"));
 
692
                        const bool expanded = pTree->IsExpanded(child);
 
693
                        SetTextAttribute(pNode->ToElement(), "expanded", expanded ? _T("1") : _T("0"));
 
694
 
294
695
                        pNode->InsertEndChild(TiXmlText(utf8));
295
696
                        delete [] utf8;
296
 
                
 
697
 
297
698
                        Save(pNode->ToElement(), child);
298
699
                }
299
700
                else
324
725
                        pNode->InsertEndChild(TiXmlText(utf8));
325
726
                        delete [] utf8;
326
727
                }
327
 
                
 
728
 
328
729
                child = pTree->GetNextChild(treeId, cookie);
329
730
        }
330
 
        
 
731
 
331
732
        return false;
332
733
}
333
734
 
336
737
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
337
738
        if (!pTree)
338
739
                return;
339
 
                
 
740
 
340
741
        wxTreeItemId item = pTree->GetSelection();
341
742
        if (!item.IsOk())
342
743
                return;
343
 
        
 
744
 
344
745
        if (pTree->GetItemData(item))
345
 
                return;
346
 
                
 
746
        {
 
747
                item = pTree->GetItemParent(item);
 
748
                wxASSERT(!pTree->GetItemData(item));
 
749
        }
 
750
 
347
751
        if (!Verify())
348
752
                return;
349
 
        
 
753
 
350
754
        wxString newName = _("New folder");
351
755
        int index = 2;
352
756
        while (true)
364
768
                                found = true;
365
769
                                break;
366
770
                        }
367
 
                                                        
 
771
 
368
772
                        child = pTree->GetNextChild(item, cookie);
369
773
                }
370
774
                if (!found)
371
775
                        break;
372
 
                
 
776
 
373
777
                newName = _("New folder") + wxString::Format(_T(" %d"), index++);
374
778
        }
375
779
 
382
786
        pTree->EditLabel(newItem);
383
787
}
384
788
 
 
789
static enum ServerType GetTypeFromName(const wxString& name)
 
790
{
 
791
        for (int i = 0; i < SERVERTYPE_MAX; i++)
 
792
        {
 
793
                enum ServerType type = (enum ServerType)i;
 
794
                if (name == CServer::GetNameFromServerType(type))
 
795
                        return type;
 
796
        }
 
797
 
 
798
        return DEFAULT;
 
799
}
385
800
 
386
801
bool CSiteManager::Verify()
387
802
{
388
803
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
389
804
        if (!pTree)
390
805
                return true;
391
 
                
 
806
 
392
807
        wxTreeItemId item = pTree->GetSelection();
393
808
        if (!item.IsOk())
394
809
                return true;
405
820
                return false;
406
821
        }
407
822
 
408
 
        const wxString& protocol = XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->GetStringSelection();
409
 
        if (protocol == _("SFTP") &&
 
823
        wxString protocolName = XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->GetStringSelection();
 
824
        enum ServerProtocol protocol = CServer::GetProtocolFromName(protocolName);
 
825
        if (protocol == SFTP &&
410
826
                XRCCTRL(*this, "ID_LOGONTYPE", wxChoice)->GetStringSelection() == _("Account"))
411
827
        {
412
828
                XRCCTRL(*this, "ID_LOGONTYPE", wxChoice)->SetFocus();
415
831
        }
416
832
 
417
833
        CServer server;
418
 
        if (protocol == _("FTP"))
419
 
                server.SetProtocol(FTP);
420
 
        else if (protocol == _("SFTP"))
421
 
                server.SetProtocol(SFTP);
 
834
        if (protocol != UNKNOWN)
 
835
                server.SetProtocol(protocol);
422
836
 
423
837
        unsigned long port;
424
838
        XRCCTRL(*this, "ID_PORT", wxTextCtrl)->GetValue().ToULong(&port);
430
844
                wxMessageBox(error);
431
845
                return false;
432
846
        }
433
 
        
 
847
 
434
848
        XRCCTRL(*this, "ID_HOST", wxTextCtrl)->SetValue(server.GetHost());
435
849
        XRCCTRL(*this, "ID_PORT", wxTextCtrl)->SetValue(wxString::Format(_T("%d"), server.GetPort()));
436
850
 
437
 
        switch (server.GetProtocol())
438
 
        {
439
 
        case SFTP:
440
 
                XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(_("SFTP"));
441
 
                break;
442
 
        case FTP:
443
 
        default:
444
 
                XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(_("FTP"));
445
 
                break;
446
 
        }
 
851
        protocolName = CServer::GetProtocolName(server.GetProtocol());
 
852
        if (protocolName == _T(""))
 
853
                CServer::GetProtocolName(FTP);
 
854
        XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(protocolName);
447
855
 
448
856
        if (XRCCTRL(*this, "ID_CHARSET_CUSTOM", wxRadioButton)->GetValue())
449
857
        {
464
872
                return false;
465
873
        }
466
874
 
 
875
        // Require account for account logon type
 
876
        if (XRCCTRL(*this, "ID_LOGONTYPE", wxChoice)->GetStringSelection() == _("Account") &&
 
877
                XRCCTRL(*this, "ID_ACCOUNT", wxTextCtrl)->GetValue() == _T(""))
 
878
        {
 
879
                XRCCTRL(*this, "ID_ACCOUNT", wxTextCtrl)->SetFocus();
 
880
                wxMessageBox(_("You have to enter an account name"));
 
881
                return false;
 
882
        }
 
883
 
 
884
        const wxString remotePathRaw = XRCCTRL(*this, "ID_REMOTEDIR", wxTextCtrl)->GetValue();
 
885
        if (remotePathRaw != _T(""))
 
886
        {
 
887
                CServerPath remotePath;
 
888
                const wxString serverType = XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->GetStringSelection();
 
889
                remotePath.SetType(GetTypeFromName(serverType));
 
890
                if (!remotePath.SetPath(remotePathRaw))
 
891
                {
 
892
                        XRCCTRL(*this, "ID_REMOTEDIR", wxTextCtrl)->SetFocus();
 
893
                        wxMessageBox(_("Default remote path cannot be parsed. Make sure it is valid and is supported by the selected servertype."));
 
894
                        return false;
 
895
                }
 
896
        }
 
897
 
 
898
 
467
899
        return true;
468
900
}
469
901
 
475
907
                event.Veto();
476
908
                return;
477
909
        }
478
 
        
 
910
 
479
911
        if (event.GetItem() != pTree->GetSelection())
480
912
        {
481
913
                if (!Verify())
484
916
                        return;
485
917
                }
486
918
        }
487
 
                
 
919
 
488
920
        wxTreeItemId item = event.GetItem();
489
 
        if (!item.IsOk() || item == pTree->GetRootItem())
 
921
        if (!item.IsOk() || item == pTree->GetRootItem() || item == m_ownSites || IsPredefinedItem(item))
490
922
        {
491
923
                event.Veto();
492
924
                return;
495
927
 
496
928
void CSiteManager::OnEndLabelEdit(wxTreeEvent& event)
497
929
{
 
930
        if (event.IsEditCancelled())
 
931
                return;
 
932
 
498
933
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
499
934
        if (!pTree)
500
935
        {
501
936
                event.Veto();
502
937
                return;
503
938
        }
504
 
        
505
 
        if (event.GetItem() != pTree->GetSelection())
 
939
 
 
940
        wxTreeItemId item = event.GetItem();
 
941
        if (item != pTree->GetSelection())
506
942
        {
507
943
                if (!Verify())
508
944
                {
510
946
                        return;
511
947
                }
512
948
        }
513
 
                
514
 
        wxTreeItemId item = event.GetItem();
515
 
        if (!item.IsOk() || item == pTree->GetRootItem())
 
949
 
 
950
        if (!item.IsOk() || item == pTree->GetRootItem() || item == m_ownSites || IsPredefinedItem(item))
516
951
        {
517
952
                event.Veto();
518
953
                return;
519
954
        }
520
 
        
521
 
        wxString newName = event.GetLabel();
 
955
 
 
956
        wxString name = event.GetLabel();
 
957
 
522
958
        wxTreeItemId parent = pTree->GetItemParent(item);
523
 
                
 
959
 
 
960
        wxTreeItemId child;
 
961
        wxTreeItemIdValue cookie;
 
962
        for (wxTreeItemId child = pTree->GetFirstChild(parent, cookie); child.IsOk(); child = pTree->GetNextChild(parent, cookie))
 
963
        {
 
964
                if (child == item)
 
965
                        continue;
 
966
                if (!name.CmpNoCase(pTree->GetItemText(child)))
 
967
                {
 
968
                        wxMessageBox(_("Name already exists"), _("Cannot rename entry"), wxICON_EXCLAMATION, this);
 
969
                        event.Veto();
 
970
                        return;
 
971
                }
 
972
        }
 
973
 
524
974
        pTree->SortChildren(parent);
525
975
}
526
976
 
529
979
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
530
980
        if (!pTree)
531
981
                return;
532
 
        
533
 
        if (!Verify())
534
 
                return;
535
 
                
 
982
 
536
983
        wxTreeItemId item = pTree->GetSelection();
537
 
        if (!item.IsOk() || item == pTree->GetRootItem())
 
984
        if (!item.IsOk() || item == pTree->GetRootItem() || item == m_ownSites || IsPredefinedItem(item))
538
985
                return;
539
 
        
 
986
 
540
987
        pTree->EditLabel(item);
541
988
}
542
989
 
545
992
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
546
993
        if (!pTree)
547
994
                return;
548
 
                
 
995
 
549
996
        wxTreeItemId item = pTree->GetSelection();
550
 
        if (!item.IsOk() || item == pTree->GetRootItem())
551
 
                return;
552
 
                
 
997
        if (!item.IsOk() || item == pTree->GetRootItem() || item == m_ownSites || IsPredefinedItem(item))
 
998
                return;
 
999
 
 
1000
        CConditionalDialog dlg(this, CConditionalDialog::sitemanager_confirmdelete, CConditionalDialog::yesno);
 
1001
        dlg.SetTitle(_("Delete Site Manager entry"));
 
1002
 
 
1003
        dlg.AddText(_("Do you really want to delete selected entry?"));
 
1004
 
 
1005
        if (!dlg.Run())
 
1006
                return;
 
1007
 
 
1008
        wxTreeItemId parent = pTree->GetItemParent(item);
 
1009
        if (pTree->GetChildrenCount(parent) == 1)
 
1010
                pTree->Collapse(parent);
 
1011
 
553
1012
        pTree->Delete(item);
554
1013
}
555
1014
 
575
1034
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
576
1035
        if (!pTree)
577
1036
                return;
578
 
                
 
1037
 
579
1038
        wxTreeItemId item = pTree->GetSelection();
580
 
        if (!item.IsOk())
 
1039
        if (!item.IsOk() || IsPredefinedItem(item))
581
1040
                return;
582
 
        
 
1041
 
583
1042
        if (pTree->GetItemData(item))
584
 
                return;
585
 
                
586
 
        if (!Verify())
587
 
                return;
588
 
        
589
 
        wxString newName = _("New site");
590
 
        int index = 2;
591
 
        while (true)
592
1043
        {
593
 
                wxTreeItemId child;
594
 
                wxTreeItemIdValue cookie;
595
 
                child = pTree->GetFirstChild(item, cookie);
596
 
                bool found = false;
597
 
                while (child.IsOk())
598
 
                {
599
 
                        wxString name = pTree->GetItemText(child);
600
 
                        int cmp = name.CmpNoCase(newName);
601
 
                        if (!cmp)
602
 
                        {
603
 
                                found = true;
604
 
                                break;
605
 
                        }
606
 
                                                        
607
 
                        child = pTree->GetNextChild(item, cookie);
608
 
                }
609
 
                if (!found)
610
 
                        break;
611
 
                
612
 
                newName = _("New site") + wxString::Format(_T(" %d"), index++);
 
1044
                item = pTree->GetItemParent(item);
 
1045
                wxASSERT(!pTree->GetItemData(item));
613
1046
        }
614
1047
 
615
 
        wxTreeItemId newItem = pTree->AppendItem(item, newName, 2, 2, new CSiteManagerItemData());
616
 
        pTree->SortChildren(item);
617
 
        pTree->SelectItem(newItem);
618
 
        pTree->Expand(item);
619
 
        pTree->EditLabel(newItem);
 
1048
        if (!Verify())
 
1049
                return;
 
1050
 
 
1051
        CServer server;
 
1052
        AddNewSite(item, server);
620
1053
}
621
1054
 
622
1055
void CSiteManager::OnLogontypeSelChanged(wxCommandEvent& event)
652
1085
        if (!data)
653
1086
                return false;
654
1087
 
 
1088
        if (IsPredefinedItem(item))
 
1089
                return true;
 
1090
 
655
1091
        unsigned long port;
656
1092
        XRCCTRL(*this, "ID_PORT", wxTextCtrl)->GetValue().ToULong(&port);
657
1093
        data->m_server.SetHost(XRCCTRL(*this, "ID_HOST", wxTextCtrl)->GetValue(), port);
658
1094
 
659
 
        wxString protocol = XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->GetStringSelection();
660
 
        if (protocol == _("FTP"))
661
 
                data->m_server.SetProtocol(FTP);
662
 
        else if (protocol == _("SFTP"))
663
 
                data->m_server.SetProtocol(SFTP);
 
1095
        const wxString& protocolName = XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->GetStringSelection();
 
1096
        const enum ServerProtocol protocol = CServer::GetProtocolFromName(protocolName);
 
1097
        if (protocol != UNKNOWN)
 
1098
                data->m_server.SetProtocol(protocol);
664
1099
        else
665
1100
                data->m_server.SetProtocol(FTP);
666
1101
 
667
 
        wxString logonType = XRCCTRL(*this, "ID_LOGONTYPE", wxChoice)->GetStringSelection();
 
1102
        const wxString logonType = XRCCTRL(*this, "ID_LOGONTYPE", wxChoice)->GetStringSelection();
668
1103
        if (logonType == _("Normal"))
669
1104
                data->m_server.SetLogonType(NORMAL);
670
1105
        else if (logonType == _("Ask for password"))
679
1114
        data->m_server.SetUser(XRCCTRL(*this, "ID_USER", wxTextCtrl)->GetValue(),
680
1115
                                                   XRCCTRL(*this, "ID_PASS", wxTextCtrl)->GetValue());
681
1116
        data->m_server.SetAccount(XRCCTRL(*this, "ID_ACCOUNT", wxTextCtrl)->GetValue());
682
 
        
 
1117
 
683
1118
        data->m_comments = XRCCTRL(*this, "ID_COMMENTS", wxTextCtrl)->GetValue();
684
1119
 
685
 
        wxString serverType = XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->GetStringSelection();
686
 
        if (serverType == _("Unix"))
687
 
                data->m_server.SetType(UNIX);
688
 
        else if (serverType == _("Dos"))
689
 
                data->m_server.SetType(DOS);
690
 
        else if (serverType == _("VMS"))
691
 
                data->m_server.SetType(VMS);
692
 
        else if (serverType == _("MVS"))
693
 
                data->m_server.SetType(MVS);
694
 
        else
695
 
                data->m_server.SetType(DEFAULT);
696
 
        
 
1120
        const wxString serverType = XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->GetStringSelection();
 
1121
        data->m_server.SetType(GetTypeFromName(serverType));
 
1122
 
697
1123
        data->m_localDir = XRCCTRL(*this, "ID_LOCALDIR", wxTextCtrl)->GetValue();
698
1124
        data->m_remoteDir = CServerPath();
699
1125
        data->m_remoteDir.SetType(data->m_server.GetType());
700
1126
        data->m_remoteDir.SetPath(XRCCTRL(*this, "ID_REMOTEDIR", wxTextCtrl)->GetValue());
701
 
        data->m_server.SetTimezoneOffset(XRCCTRL(*this, "ID_TIMEZONE_HOURS", wxSpinCtrl)->GetValue() * 60 + 
702
 
                                                                         XRCCTRL(*this, "ID_TIMEZONE_MINUTES", wxSpinCtrl)->GetValue());
 
1127
        int hours, minutes;
 
1128
        hours = XRCCTRL(*this, "ID_TIMEZONE_HOURS", wxSpinCtrl)->GetValue();
 
1129
        minutes = XRCCTRL(*this, "ID_TIMEZONE_MINUTES", wxSpinCtrl)->GetValue();
 
1130
 
 
1131
        data->m_server.SetTimezoneOffset(hours * 60 + minutes);
703
1132
 
704
1133
        if (XRCCTRL(*this, "ID_TRANSFERMODE_ACTIVE", wxRadioButton)->GetValue())
705
1134
                data->m_server.SetPasvMode(MODE_ACTIVE);
725
1154
        else
726
1155
                data->m_server.SetEncodingType(ENCODING_AUTO);
727
1156
 
 
1157
        if (XRCCTRL(*this, "ID_BYPASSPROXY", wxCheckBox)->GetValue())
 
1158
                data->m_server.SetBypassProxy(true);
 
1159
        else
 
1160
                data->m_server.SetBypassProxy(false);
 
1161
 
 
1162
        data->m_server.SetName(pTree->GetItemText(item));
 
1163
 
728
1164
        return true;
729
1165
}
730
1166
 
743
1179
                return false;
744
1180
 
745
1181
        data = *pData;
746
 
        data.m_name = pTree->GetItemText(item);
747
1182
 
748
1183
        return true;
749
1184
}
799
1234
                return;
800
1235
 
801
1236
        wxTreeItemId item = pTree->GetSelection();
802
 
        
 
1237
 
 
1238
        const bool predefined = IsPredefinedItem(item);
 
1239
 
 
1240
#ifdef __WXGTK__
 
1241
        wxWindow* pFocus = FindFocus();
 
1242
#endif
 
1243
 
803
1244
        CSiteManagerItemData* data = 0;
804
1245
        if (item.IsOk())
805
1246
                data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(item));
806
1247
        if (!data)
807
1248
        {
808
1249
                // Set the control states according if it's possible to use the control
809
 
                XRCCTRL(*this, "ID_RENAME", wxWindow)->Enable(item != pTree->GetRootItem());
810
 
                XRCCTRL(*this, "ID_DELETE", wxWindow)->Enable(item != pTree->GetRootItem());
811
 
                XRCCTRL(*this, "ID_COPY", wxWindow)->Enable(item != pTree->GetRootItem());
 
1250
                const bool root_or_predefined = (item == pTree->GetRootItem() || item == m_ownSites || predefined);
 
1251
 
 
1252
                XRCCTRL(*this, "ID_RENAME", wxWindow)->Enable(!root_or_predefined);
 
1253
                XRCCTRL(*this, "ID_DELETE", wxWindow)->Enable(!root_or_predefined);
 
1254
                XRCCTRL(*this, "ID_COPY", wxWindow)->Enable(false);
812
1255
                XRCCTRL(*this, "ID_NOTEBOOK", wxWindow)->Enable(false);
813
 
                XRCCTRL(*this, "ID_NEWFOLDER", wxWindow)->Enable(true);
814
 
                XRCCTRL(*this, "ID_NEWSITE", wxWindow)->Enable(true);
 
1256
                XRCCTRL(*this, "ID_NEWFOLDER", wxWindow)->Enable(!predefined);
 
1257
                XRCCTRL(*this, "ID_NEWSITE", wxWindow)->Enable(!predefined);
815
1258
                XRCCTRL(*this, "ID_CONNECT", wxWindow)->Enable(false);
816
1259
 
817
1260
                // Empty all site information
818
1261
                XRCCTRL(*this, "ID_HOST", wxTextCtrl)->SetValue(_T(""));
819
 
                XRCCTRL(*this, "ID_PORT", wxTextCtrl)->SetValue(_T("21"));
 
1262
                XRCCTRL(*this, "ID_PORT", wxTextCtrl)->SetValue(_T(""));
820
1263
                XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(_("FTP"));
 
1264
                XRCCTRL(*this, "ID_BYPASSPROXY", wxCheckBox)->SetValue(false);
821
1265
                XRCCTRL(*this, "ID_LOGONTYPE", wxChoice)->SetStringSelection(_("Anonymous"));
822
1266
                XRCCTRL(*this, "ID_USER", wxTextCtrl)->SetValue(_T(""));
823
1267
                XRCCTRL(*this, "ID_PASS", wxTextCtrl)->SetValue(_T(""));
824
1268
                XRCCTRL(*this, "ID_ACCOUNT", wxTextCtrl)->SetValue(_T(""));
825
1269
                XRCCTRL(*this, "ID_COMMENTS", wxTextCtrl)->SetValue(_T(""));
826
 
                
827
 
                XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetStringSelection(_("Default"));
 
1270
 
 
1271
                XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetSelection(0);
828
1272
                XRCCTRL(*this, "ID_LOCALDIR", wxTextCtrl)->SetValue(_T(""));
829
1273
                XRCCTRL(*this, "ID_REMOTEDIR", wxTextCtrl)->SetValue(_T(""));
830
1274
                XRCCTRL(*this, "ID_TIMEZONE_HOURS", wxSpinCtrl)->SetValue(0);
833
1277
                XRCCTRL(*this, "ID_TRANSFERMODE_DEFAULT", wxRadioButton)->SetValue(true);
834
1278
                XRCCTRL(*this, "ID_LIMITMULTIPLE", wxCheckBox)->SetValue(false);
835
1279
                XRCCTRL(*this, "ID_MAXMULTIPLE", wxSpinCtrl)->SetValue(1);
 
1280
 
 
1281
                XRCCTRL(*this, "ID_CHARSET_AUTO", wxRadioButton)->SetValue(true);
 
1282
                XRCCTRL(*this, "ID_ENCODING", wxTextCtrl)->SetValue(_T(""));
 
1283
#ifdef __WXGTK__
 
1284
                XRCCTRL(*this, "wxID_OK", wxButton)->SetDefault();
 
1285
#endif
836
1286
        }
837
1287
        else
838
1288
        {
839
1289
                // Set the control states according if it's possible to use the control
840
 
                XRCCTRL(*this, "ID_RENAME", wxWindow)->Enable(true);
841
 
                XRCCTRL(*this, "ID_DELETE", wxWindow)->Enable(true);
 
1290
                XRCCTRL(*this, "ID_RENAME", wxWindow)->Enable(!predefined);
 
1291
                XRCCTRL(*this, "ID_DELETE", wxWindow)->Enable(!predefined);
842
1292
                XRCCTRL(*this, "ID_COPY", wxWindow)->Enable(true);
843
1293
                XRCCTRL(*this, "ID_NOTEBOOK", wxWindow)->Enable(true);
844
 
                XRCCTRL(*this, "ID_NEWFOLDER", wxWindow)->Enable(false);
845
 
                XRCCTRL(*this, "ID_NEWSITE", wxWindow)->Enable(false);
 
1294
                XRCCTRL(*this, "ID_NEWFOLDER", wxWindow)->Enable(!predefined);
 
1295
                XRCCTRL(*this, "ID_NEWSITE", wxWindow)->Enable(!predefined);
846
1296
                XRCCTRL(*this, "ID_CONNECT", wxWindow)->Enable(true);
847
1297
 
 
1298
                XRCCTRL(*this, "ID_HOST", wxWindow)->Enable(!predefined);
848
1299
                XRCCTRL(*this, "ID_HOST", wxTextCtrl)->SetValue(data->m_server.GetHost());
849
 
                int port = data->m_server.GetPort();
850
 
 
851
 
                bool showPort = true;
852
 
                switch (data->m_server.GetProtocol())
853
 
                {
854
 
                case SFTP:
855
 
                        if (port == 22)
856
 
                                showPort = false;
857
 
                        XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(_("SFTP"));
858
 
                        break;
859
 
                case FTP:
860
 
                default:
861
 
                        if (port == 21)
862
 
                                showPort = false;
863
 
                        XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(_("FTP"));
864
 
                        break;
865
 
                }
866
 
 
867
 
                if (showPort)
 
1300
                unsigned int port = data->m_server.GetPort();
 
1301
 
 
1302
                if (port != CServer::GetDefaultPort(data->m_server.GetProtocol()))
868
1303
                        XRCCTRL(*this, "ID_PORT", wxTextCtrl)->SetValue(wxString::Format(_T("%d"), port));
869
1304
                else
870
1305
                        XRCCTRL(*this, "ID_PORT", wxTextCtrl)->SetValue(_T(""));
871
 
 
872
 
 
873
 
                XRCCTRL(*this, "ID_USER", wxTextCtrl)->Enable(data->m_server.GetLogonType() != ANONYMOUS);
874
 
                XRCCTRL(*this, "ID_PASS", wxTextCtrl)->Enable(data->m_server.GetLogonType() == NORMAL || data->m_server.GetLogonType() == ACCOUNT);
875
 
                XRCCTRL(*this, "ID_ACCOUNT", wxTextCtrl)->Enable(data->m_server.GetLogonType() == ACCOUNT);
 
1306
                XRCCTRL(*this, "ID_PORT", wxWindow)->Enable(!predefined);
 
1307
 
 
1308
                const wxString& protocolName = CServer::GetProtocolName(data->m_server.GetProtocol());
 
1309
                if (protocolName != _T(""))
 
1310
                        XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(protocolName);
 
1311
                else
 
1312
                        XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(CServer::GetProtocolName(FTP));
 
1313
                XRCCTRL(*this, "ID_PROTOCOL", wxWindow)->Enable(!predefined);
 
1314
                XRCCTRL(*this, "ID_BYPASSPROXY", wxCheckBox)->SetValue(data->m_server.GetBypassProxy());
 
1315
 
 
1316
                XRCCTRL(*this, "ID_USER", wxTextCtrl)->Enable(!predefined && data->m_server.GetLogonType() != ANONYMOUS);
 
1317
                XRCCTRL(*this, "ID_PASS", wxTextCtrl)->Enable(!predefined && data->m_server.GetLogonType() == NORMAL || data->m_server.GetLogonType() == ACCOUNT);
 
1318
                XRCCTRL(*this, "ID_ACCOUNT", wxTextCtrl)->Enable(!predefined && data->m_server.GetLogonType() == ACCOUNT);
876
1319
 
877
1320
                switch (data->m_server.GetLogonType())
878
1321
                {
892
1335
                        XRCCTRL(*this, "ID_LOGONTYPE", wxChoice)->SetStringSelection(_("Anonymous"));
893
1336
                        break;
894
1337
                }
 
1338
                XRCCTRL(*this, "ID_LOGONTYPE", wxWindow)->Enable(!predefined);
895
1339
 
896
1340
                XRCCTRL(*this, "ID_USER", wxTextCtrl)->SetValue(data->m_server.GetUser());
897
1341
                XRCCTRL(*this, "ID_ACCOUNT", wxTextCtrl)->SetValue(data->m_server.GetAccount());
898
1342
                XRCCTRL(*this, "ID_PASS", wxTextCtrl)->SetValue(data->m_server.GetPass());
899
1343
                XRCCTRL(*this, "ID_COMMENTS", wxTextCtrl)->SetValue(data->m_comments);
 
1344
                XRCCTRL(*this, "ID_COMMENTS", wxWindow)->Enable(!predefined);
900
1345
 
901
 
                switch (data->m_server.GetType())
902
 
                {
903
 
                case UNIX:
904
 
                        XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetStringSelection(_("Unix"));
905
 
                        break;
906
 
                case DOS:
907
 
                        XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetStringSelection(_("Dos"));
908
 
                        break;
909
 
                case MVS:
910
 
                        XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetStringSelection(_("MVS"));
911
 
                        break;
912
 
                case VMS:
913
 
                        XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetStringSelection(_("VMS"));
914
 
                        break;
915
 
                default:
916
 
                        XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetStringSelection(_("Default"));
917
 
                        break;
918
 
                }
 
1346
                XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetSelection(data->m_server.GetType());
 
1347
                XRCCTRL(*this, "ID_SERVERTYPE", wxWindow)->Enable(!predefined);
919
1348
                XRCCTRL(*this, "ID_LOCALDIR", wxTextCtrl)->SetValue(data->m_localDir);
 
1349
                XRCCTRL(*this, "ID_LOCALDIR", wxWindow)->Enable(!predefined);
920
1350
                XRCCTRL(*this, "ID_REMOTEDIR", wxTextCtrl)->SetValue(data->m_remoteDir.GetPath());
 
1351
                XRCCTRL(*this, "ID_REMOTEDIR", wxWindow)->Enable(!predefined);
921
1352
                XRCCTRL(*this, "ID_TIMEZONE_HOURS", wxSpinCtrl)->SetValue(data->m_server.GetTimezoneOffset() / 60);
 
1353
                XRCCTRL(*this, "ID_TIMEZONE_HOURS", wxWindow)->Enable(!predefined);
922
1354
                XRCCTRL(*this, "ID_TIMEZONE_MINUTES", wxSpinCtrl)->SetValue(data->m_server.GetTimezoneOffset() % 60);
 
1355
                XRCCTRL(*this, "ID_TIMEZONE_MINUTES", wxWindow)->Enable(!predefined);
923
1356
 
924
1357
                enum PasvMode pasvMode = data->m_server.GetPasvMode();
925
1358
                if (pasvMode == MODE_ACTIVE)
928
1361
                        XRCCTRL(*this, "ID_TRANSFERMODE_PASSIVE", wxRadioButton)->SetValue(true);
929
1362
                else
930
1363
                        XRCCTRL(*this, "ID_TRANSFERMODE_DEFAULT", wxRadioButton)->SetValue(true);
 
1364
                XRCCTRL(*this, "ID_TRANSFERMODE_ACTIVE", wxWindow)->Enable(!predefined);
 
1365
                XRCCTRL(*this, "ID_TRANSFERMODE_PASSIVE", wxWindow)->Enable(!predefined);
 
1366
                XRCCTRL(*this, "ID_TRANSFERMODE_DEFAULT", wxWindow)->Enable(!predefined);
931
1367
 
932
1368
                int maxMultiple = data->m_server.MaximumMultipleConnections();
933
1369
                XRCCTRL(*this, "ID_LIMITMULTIPLE", wxCheckBox)->SetValue(maxMultiple != 0);
 
1370
                XRCCTRL(*this, "ID_LIMITMULTIPLE", wxWindow)->Enable(!predefined);
934
1371
                if (maxMultiple != 0)
935
1372
                {
936
 
                        XRCCTRL(*this, "ID_MAXMULTIPLE", wxSpinCtrl)->Enable(true);
 
1373
                        XRCCTRL(*this, "ID_MAXMULTIPLE", wxSpinCtrl)->Enable(!predefined);
937
1374
                        XRCCTRL(*this, "ID_MAXMULTIPLE", wxSpinCtrl)->SetValue(maxMultiple);
938
1375
                }
939
1376
                else
955
1392
                        XRCCTRL(*this, "ID_CHARSET_CUSTOM", wxRadioButton)->SetValue(true);
956
1393
                        break;
957
1394
                }
958
 
                XRCCTRL(*this, "ID_ENCODING", wxTextCtrl)->Enable(data->m_server.GetEncodingType() == ENCODING_CUSTOM);
 
1395
                XRCCTRL(*this, "ID_CHARSET_AUTO", wxWindow)->Enable(!predefined);
 
1396
                XRCCTRL(*this, "ID_CHARSET_UTF8", wxWindow)->Enable(!predefined);
 
1397
                XRCCTRL(*this, "ID_CHARSET_CUSTOM", wxWindow)->Enable(!predefined);
 
1398
                XRCCTRL(*this, "ID_ENCODING", wxTextCtrl)->Enable(!predefined && data->m_server.GetEncodingType() == ENCODING_CUSTOM);
959
1399
                XRCCTRL(*this, "ID_ENCODING", wxTextCtrl)->SetValue(data->m_server.GetCustomEncoding());
960
 
        }
 
1400
#ifdef __WXGTK__
 
1401
                XRCCTRL(*this, "ID_CONNECT", wxButton)->SetDefault();
 
1402
#endif
 
1403
        }
 
1404
#ifdef __WXGTK__
 
1405
        if (pFocus && !pFocus->IsEnabled())
 
1406
        {
 
1407
                for (wxWindow* pParent = pFocus->GetParent(); pParent; pParent = pParent->GetParent())
 
1408
                {
 
1409
                        if (pParent == this)
 
1410
                        {
 
1411
                                XRCCTRL(*this, "wxID_OK", wxButton)->SetFocus();
 
1412
                                break;
 
1413
                        }
 
1414
                }
 
1415
        }
 
1416
#endif
961
1417
}
962
1418
 
963
1419
void CSiteManager::OnCharsetChange(wxCommandEvent& event)
969
1425
void CSiteManager::OnProtocolSelChanged(wxCommandEvent& event)
970
1426
{
971
1427
}
 
1428
 
 
1429
void CSiteManager::OnCopySite(wxCommandEvent& event)
 
1430
{
 
1431
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
 
1432
        if (!pTree)
 
1433
                return;
 
1434
 
 
1435
        wxTreeItemId item = pTree->GetSelection();
 
1436
        if (!item.IsOk())
 
1437
                return;
 
1438
 
 
1439
        CSiteManagerItemData* data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(item));
 
1440
        if (!data)
 
1441
                return;
 
1442
 
 
1443
        if (!Verify())
 
1444
                return;
 
1445
 
 
1446
        if (!UpdateServer())
 
1447
                return;
 
1448
 
 
1449
        wxTreeItemId parent;
 
1450
        if (IsPredefinedItem(item))
 
1451
                parent = m_ownSites;
 
1452
        else
 
1453
                parent = pTree->GetItemParent(item);
 
1454
 
 
1455
        const wxString name = pTree->GetItemText(item);
 
1456
        wxString newName = wxString::Format(_("Copy of %s"), name.c_str());
 
1457
        int index = 2;
 
1458
        while (true)
 
1459
        {
 
1460
                wxTreeItemId child;
 
1461
                wxTreeItemIdValue cookie;
 
1462
                child = pTree->GetFirstChild(parent, cookie);
 
1463
                bool found = false;
 
1464
                while (child.IsOk())
 
1465
                {
 
1466
                        wxString name = pTree->GetItemText(child);
 
1467
                        int cmp = name.CmpNoCase(newName);
 
1468
                        if (!cmp)
 
1469
                        {
 
1470
                                found = true;
 
1471
                                break;
 
1472
                        }
 
1473
 
 
1474
                        child = pTree->GetNextChild(parent, cookie);
 
1475
                }
 
1476
                if (!found)
 
1477
                        break;
 
1478
 
 
1479
                newName = wxString::Format(_("Copy (%d) of %s"), index++, name.c_str());
 
1480
        }
 
1481
 
 
1482
        CSiteManagerItemData* newData = new CSiteManagerItemData();
 
1483
        *newData = *data;
 
1484
        wxTreeItemId newItem = pTree->AppendItem(parent, newName, 2, 2, newData);
 
1485
        pTree->SortChildren(parent);
 
1486
        pTree->SelectItem(newItem);
 
1487
        pTree->Expand(parent);
 
1488
        pTree->EditLabel(newItem);
 
1489
}
 
1490
 
 
1491
bool CSiteManager::LoadDefaultSites()
 
1492
{
 
1493
        const wxString& defaultsDir = wxGetApp().GetDefaultsDir();
 
1494
        if (defaultsDir == _T(""))
 
1495
                return false;
 
1496
 
 
1497
        wxFileName name(defaultsDir, _T("fzdefaults.xml"));
 
1498
        CXmlFile file(name);
 
1499
 
 
1500
        TiXmlElement* pDocument = file.Load();
 
1501
        if (!pDocument)
 
1502
                return false;
 
1503
 
 
1504
        TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
 
1505
        if (!pElement)
 
1506
                return false;
 
1507
 
 
1508
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
 
1509
        if (!pTree)
 
1510
                return false;
 
1511
 
 
1512
        int style = pTree->GetWindowStyle();
 
1513
        pTree->SetWindowStyle(style | wxTR_HIDE_ROOT);
 
1514
        wxTreeItemId root = pTree->AddRoot(_T(""), 0, 0);
 
1515
 
 
1516
        m_predefinedSites = pTree->AppendItem(root, _("Predefined Sites"), 0, 0);
 
1517
        pTree->SetItemImage(m_predefinedSites, 1, wxTreeItemIcon_Expanded);
 
1518
        pTree->SetItemImage(m_predefinedSites, 1, wxTreeItemIcon_SelectedExpanded);
 
1519
 
 
1520
        wxString lastSelection = COptions::Get()->GetOption(OPTION_SITEMANAGER_LASTSELECTED);
 
1521
        if (lastSelection[0] == '1')
 
1522
        {
 
1523
                if (lastSelection == _T("1"))
 
1524
                        pTree->SelectItem(m_predefinedSites);
 
1525
                else
 
1526
                        lastSelection = lastSelection.Mid(1);
 
1527
        }
 
1528
        else
 
1529
                lastSelection = _T("");
 
1530
        CSiteManagerXmlHandler_Tree handler(pTree, m_predefinedSites, lastSelection);
 
1531
 
 
1532
        Load(pElement, &handler);
 
1533
 
 
1534
        return true;
 
1535
}
 
1536
 
 
1537
bool CSiteManager::IsPredefinedItem(wxTreeItemId item)
 
1538
{
 
1539
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
 
1540
        wxASSERT(pTree);
 
1541
        if (!pTree)
 
1542
                return false;
 
1543
 
 
1544
        while (item)
 
1545
        {
 
1546
                if (item == m_predefinedSites)
 
1547
                        return true;
 
1548
                item = pTree->GetItemParent(item);
 
1549
        }
 
1550
 
 
1551
        return false;
 
1552
}
 
1553
 
 
1554
class CSiteManagerXmlHandler_Menu : public CSiteManagerXmlHandler
 
1555
{
 
1556
public:
 
1557
        CSiteManagerXmlHandler_Menu(wxMenu* pMenu, std::map<int, CSiteManagerItemData*> *idMap)
 
1558
                : m_pMenu(pMenu), m_idMap(idMap)
 
1559
        {
 
1560
        }
 
1561
 
 
1562
        unsigned int GetInsertIndex(wxMenu* pMenu, const wxString& name)
 
1563
        {
 
1564
                unsigned int i;
 
1565
                for (i = 0; i < pMenu->GetMenuItemCount(); i++)
 
1566
                {
 
1567
                        const wxMenuItem* const pItem = pMenu->FindItemByPosition(i);
 
1568
                        if (!pItem)
 
1569
                                continue;
 
1570
                        if (pItem->GetLabel() > name)
 
1571
                                break;
 
1572
                }
 
1573
 
 
1574
                return i;
 
1575
        }
 
1576
 
 
1577
        virtual bool AddFolder(const wxString& name, bool)
 
1578
        {
 
1579
                m_parents.push_back(m_pMenu);
 
1580
                m_childNames.push_back(name);
 
1581
 
 
1582
                m_pMenu = new wxMenu;
 
1583
 
 
1584
                return true;
 
1585
        }
 
1586
 
 
1587
        virtual bool AddSite(const wxString& name, CSiteManagerItemData* data)
 
1588
        {
 
1589
                wxString newName = name;
 
1590
                int i = GetInsertIndex(m_pMenu, newName);
 
1591
                newName.Replace(_T("&"), _T("&&"));
 
1592
                wxMenuItem* pItem = m_pMenu->Insert(i, wxID_ANY, newName);
 
1593
                (*m_idMap)[pItem->GetId()] = data;
 
1594
 
 
1595
                return true;
 
1596
        }
 
1597
 
 
1598
        // Go up a level
 
1599
        virtual bool LevelUp()
 
1600
        {
 
1601
                if (m_parents.empty() || m_childNames.empty())
 
1602
                        return false;
 
1603
 
 
1604
                wxMenu* pChild = m_pMenu;
 
1605
                m_pMenu = m_parents.back();
 
1606
                if (pChild->GetMenuItemCount())
 
1607
                {
 
1608
                        wxString name = m_childNames.back();
 
1609
                        int i = GetInsertIndex(m_pMenu, name);
 
1610
                        name.Replace(_T("&"), _T("&&"));
 
1611
 
 
1612
                        wxMenuItem* pItem = new wxMenuItem(m_pMenu, wxID_ANY, name, _T(""), wxITEM_NORMAL, pChild);
 
1613
                        m_pMenu->Insert(i, pItem);
 
1614
                }
 
1615
                else
 
1616
                        delete pChild;
 
1617
                m_childNames.pop_back();
 
1618
                m_parents.pop_back();
 
1619
 
 
1620
                return true;
 
1621
        }
 
1622
 
 
1623
protected:
 
1624
        wxMenu* m_pMenu;
 
1625
 
 
1626
        std::map<int, CSiteManagerItemData*> *m_idMap;
 
1627
 
 
1628
        std::list<wxMenu*> m_parents;
 
1629
        std::list<wxString> m_childNames;
 
1630
};
 
1631
 
 
1632
wxMenu* CSiteManager::GetSitesMenu()
 
1633
{
 
1634
        ClearIdMap();
 
1635
 
 
1636
        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
 
1637
        // to the same file or one is reading while the other one writes.
 
1638
        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
 
1639
 
 
1640
        wxMenu* predefinedSites = GetSitesMenu_Predefied(m_idMap);
 
1641
 
 
1642
        CXmlFile file(_T("sitemanager"));
 
1643
        TiXmlElement* pDocument = file.Load();
 
1644
        if (!pDocument)
 
1645
        {
 
1646
                wxString msg = wxString::Format(_("Could not load \"%s\", please make sure the file is valid and can be accessed.\nAny changes made in the Site Manager will not be saved."), file.GetFileName().GetFullPath().c_str());
 
1647
                wxMessageBox(msg, _("Error loading xml file"), wxICON_ERROR);
 
1648
 
 
1649
                if (!predefinedSites)
 
1650
                        return predefinedSites;
 
1651
 
 
1652
                wxMenu *pMenu = new wxMenu;
 
1653
                wxMenuItem* pItem = pMenu->Append(wxID_ANY, _("No sites available"));
 
1654
                pItem->Enable(false);
 
1655
                return pMenu;
 
1656
        }
 
1657
 
 
1658
        TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
 
1659
        if (!pElement)
 
1660
        {
 
1661
                if (!predefinedSites)
 
1662
                        return predefinedSites;
 
1663
 
 
1664
                wxMenu *pMenu = new wxMenu;
 
1665
                wxMenuItem* pItem = pMenu->Append(wxID_ANY, _("No sites available"));
 
1666
                pItem->Enable(false);
 
1667
                return pMenu;
 
1668
        }
 
1669
 
 
1670
        wxMenu* pMenu = new wxMenu;
 
1671
        CSiteManagerXmlHandler_Menu handler(pMenu, &m_idMap);
 
1672
 
 
1673
        bool res = Load(pElement, &handler);
 
1674
        if (!res || !pMenu->GetMenuItemCount())
 
1675
        {
 
1676
                delete pMenu;
 
1677
                pMenu = 0;
 
1678
        }
 
1679
 
 
1680
        if (pMenu)
 
1681
        {
 
1682
                if (!predefinedSites)
 
1683
                        return pMenu;
 
1684
 
 
1685
                wxMenu* pRootMenu = new wxMenu;
 
1686
                pRootMenu->AppendSubMenu(predefinedSites, _("Predefined Sites"));
 
1687
                pRootMenu->AppendSubMenu(pMenu, _("My Sites"));
 
1688
 
 
1689
                return pRootMenu;
 
1690
        }
 
1691
 
 
1692
        if (predefinedSites)
 
1693
                return predefinedSites;
 
1694
 
 
1695
        pMenu = new wxMenu;
 
1696
        wxMenuItem* pItem = pMenu->Append(wxID_ANY, _("No sites available"));
 
1697
        pItem->Enable(false);
 
1698
        return pMenu;
 
1699
}
 
1700
 
 
1701
void CSiteManager::ClearIdMap()
 
1702
{
 
1703
        for (std::map<int, CSiteManagerItemData*>::iterator iter = m_idMap.begin(); iter != m_idMap.end(); iter++)
 
1704
                delete iter->second;
 
1705
 
 
1706
        m_idMap.clear();
 
1707
}
 
1708
 
 
1709
wxMenu* CSiteManager::GetSitesMenu_Predefied(std::map<int, CSiteManagerItemData*> &idMap)
 
1710
{
 
1711
        const wxString& defaultsDir = wxGetApp().GetDefaultsDir();
 
1712
        if (defaultsDir == _T(""))
 
1713
                return 0;
 
1714
 
 
1715
        wxFileName name(defaultsDir, _T("fzdefaults.xml"));
 
1716
        CXmlFile file(name);
 
1717
 
 
1718
        TiXmlElement* pDocument = file.Load();
 
1719
        if (!pDocument)
 
1720
                return 0;
 
1721
 
 
1722
        TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
 
1723
        if (!pElement)
 
1724
                return 0;
 
1725
 
 
1726
        wxMenu* pMenu = new wxMenu;
 
1727
        CSiteManagerXmlHandler_Menu handler(pMenu, &idMap);
 
1728
 
 
1729
        if (!Load(pElement, &handler))
 
1730
        {
 
1731
                delete pMenu;
 
1732
                return 0;
 
1733
        }
 
1734
 
 
1735
        if (!pMenu->GetMenuItemCount())
 
1736
        {
 
1737
                delete pMenu;
 
1738
                return 0;
 
1739
        }
 
1740
 
 
1741
        return pMenu;
 
1742
}
 
1743
 
 
1744
CSiteManagerItemData* CSiteManager::GetSiteById(int id)
 
1745
{
 
1746
        std::map<int, CSiteManagerItemData*>::iterator iter = m_idMap.find(id);
 
1747
 
 
1748
        CSiteManagerItemData *pData;
 
1749
        if (iter != m_idMap.end())
 
1750
        {
 
1751
                pData = iter->second;
 
1752
                iter->second = 0;
 
1753
        }
 
1754
        else
 
1755
                pData = 0;
 
1756
 
 
1757
        ClearIdMap();
 
1758
 
 
1759
        return pData;
 
1760
}
 
1761
 
 
1762
void CSiteManager::OnBeginDrag(wxTreeEvent& event)
 
1763
{
 
1764
        if (!Verify())
 
1765
        {
 
1766
                event.Veto();
 
1767
                return;
 
1768
        }
 
1769
 
 
1770
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
 
1771
        if (!pTree)
 
1772
        {
 
1773
                event.Veto();
 
1774
                return;
 
1775
        }
 
1776
 
 
1777
        wxTreeItemId item = event.GetItem();
 
1778
        if (!item.IsOk())
 
1779
        {
 
1780
                event.Veto();
 
1781
                return;
 
1782
        }
 
1783
 
 
1784
        const bool predefined = IsPredefinedItem(item);
 
1785
        const bool root_or_predefined = (item == pTree->GetRootItem() || item == m_ownSites || predefined);
 
1786
 
 
1787
        CSiteManagerDataObject obj;
 
1788
 
 
1789
        wxDropSource source(this);
 
1790
        source.SetData(obj);
 
1791
 
 
1792
        m_dropSource = item;
 
1793
 
 
1794
        source.DoDragDrop(root_or_predefined ? wxDrag_CopyOnly : wxDrag_DefaultMove);
 
1795
 
 
1796
        m_dropSource = wxTreeItemId();
 
1797
}
 
1798
 
 
1799
struct itempair
 
1800
{
 
1801
        wxTreeItemId source;
 
1802
        wxTreeItemId target;
 
1803
};
 
1804
 
 
1805
bool CSiteManager::MoveItems(wxTreeItemId source, wxTreeItemId target, bool copy)
 
1806
{
 
1807
        if (source == target)
 
1808
                return false;
 
1809
 
 
1810
        if (IsPredefinedItem(target))
 
1811
                return false;
 
1812
 
 
1813
        if (IsPredefinedItem(source) && !copy)
 
1814
                return false;
 
1815
 
 
1816
    wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
 
1817
        if (pTree->GetItemData(target))
 
1818
                return false;
 
1819
 
 
1820
        wxTreeItemId item = target;
 
1821
        while (item != pTree->GetRootItem())
 
1822
        {
 
1823
                if (item == source)
 
1824
                        return false;
 
1825
                item = pTree->GetItemParent(item);
 
1826
        }
 
1827
 
 
1828
        if (!copy && pTree->GetItemParent(source) == target)
 
1829
                return false;
 
1830
 
 
1831
        wxString sourceName = pTree->GetItemText(source);
 
1832
 
 
1833
        wxTreeItemId child;
 
1834
        wxTreeItemIdValue cookie;
 
1835
        child = pTree->GetFirstChild(target, cookie);
 
1836
 
 
1837
        while (child.IsOk())
 
1838
        {
 
1839
                wxString childName = pTree->GetItemText(child);
 
1840
 
 
1841
                if (!sourceName.CmpNoCase(childName))
 
1842
                {
 
1843
                        wxMessageBox(_("An item with the same name as the dragged item already exists at the target location."), _("Failed to copy or move sites"), wxICON_INFORMATION);
 
1844
                        return false;
 
1845
                }
 
1846
 
 
1847
                child = pTree->GetNextChild(target, cookie);
 
1848
        }
 
1849
 
 
1850
        std::list<itempair> work;
 
1851
        itempair pair;
 
1852
        pair.source = source;
 
1853
        pair.target = target;
 
1854
        work.push_back(pair);
 
1855
 
 
1856
        std::list<wxTreeItemId> expand;
 
1857
 
 
1858
        while (!work.empty())
 
1859
        {
 
1860
                itempair pair = work.front();
 
1861
                work.pop_front();
 
1862
 
 
1863
                wxString name = pTree->GetItemText(pair.source);
 
1864
 
 
1865
                CSiteManagerItemData* data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(pair.source));
 
1866
 
 
1867
                wxTreeItemId newItem = pTree->AppendItem(pair.target, name, data ? 2 : 0);
 
1868
                if (!data)
 
1869
                {
 
1870
                        pTree->SetItemImage(newItem, 1, wxTreeItemIcon_Expanded);
 
1871
                        pTree->SetItemImage(newItem, 1, wxTreeItemIcon_SelectedExpanded);
 
1872
 
 
1873
                        if (pTree->IsExpanded(pair.source))
 
1874
                                expand.push_back(newItem);
 
1875
                }
 
1876
                else
 
1877
                {
 
1878
                        CSiteManagerItemData* newData = new CSiteManagerItemData;
 
1879
                        *newData = *data;
 
1880
                        pTree->SetItemData(newItem, newData);
 
1881
                }
 
1882
 
 
1883
                wxTreeItemId child;
 
1884
                wxTreeItemIdValue cookie;
 
1885
                child = pTree->GetFirstChild(pair.source, cookie);
 
1886
                while (child.IsOk())
 
1887
                {
 
1888
                        itempair newPair;
 
1889
                        newPair.source = child;
 
1890
                        newPair.target = newItem;
 
1891
                        work.push_back(newPair);
 
1892
 
 
1893
                        child = pTree->GetNextChild(pair.source, cookie);
 
1894
                }
 
1895
 
 
1896
                pTree->SortChildren(pair.target);
 
1897
        }
 
1898
 
 
1899
        if (!copy)
 
1900
        {
 
1901
                wxTreeItemId parent = pTree->GetItemParent(source);
 
1902
                if (pTree->GetChildrenCount(parent) == 1)
 
1903
                        pTree->Collapse(parent);
 
1904
 
 
1905
                pTree->Delete(source);
 
1906
        }
 
1907
 
 
1908
        for (std::list<wxTreeItemId>::iterator iter = expand.begin(); iter != expand.end(); iter++)
 
1909
                pTree->Expand(*iter);
 
1910
 
 
1911
        pTree->Expand(target);
 
1912
 
 
1913
        return true;
 
1914
}
 
1915
 
 
1916
void CSiteManager::OnChar(wxKeyEvent& event)
 
1917
{
 
1918
        if (event.GetKeyCode() != WXK_F2)
 
1919
        {
 
1920
                event.Skip();
 
1921
                return;
 
1922
        }
 
1923
 
 
1924
        wxCommandEvent cmdEvent;
 
1925
        OnRename(cmdEvent);
 
1926
}
 
1927
 
 
1928
void CSiteManager::CopyAddServer(const CServer& server)
 
1929
{
 
1930
        if (!Verify())
 
1931
                return;
 
1932
 
 
1933
        AddNewSite(m_ownSites, server);
 
1934
}
 
1935
 
 
1936
void CSiteManager::AddNewSite(wxTreeItemId parent, const CServer& server)
 
1937
{
 
1938
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
 
1939
        if (!pTree)
 
1940
                return;
 
1941
 
 
1942
        wxString newName = _("New site");
 
1943
        int index = 2;
 
1944
        while (true)
 
1945
        {
 
1946
                wxTreeItemId child;
 
1947
                wxTreeItemIdValue cookie;
 
1948
                child = pTree->GetFirstChild(parent, cookie);
 
1949
                bool found = false;
 
1950
                while (child.IsOk())
 
1951
                {
 
1952
                        wxString name = pTree->GetItemText(child);
 
1953
                        int cmp = name.CmpNoCase(newName);
 
1954
                        if (!cmp)
 
1955
                        {
 
1956
                                found = true;
 
1957
                                break;
 
1958
                        }
 
1959
 
 
1960
                        child = pTree->GetNextChild(parent, cookie);
 
1961
                }
 
1962
                if (!found)
 
1963
                        break;
 
1964
 
 
1965
                newName = _("New site") + wxString::Format(_T(" %d"), index++);
 
1966
        }
 
1967
 
 
1968
        wxTreeItemId newItem = pTree->AppendItem(parent, newName, 2, 2, new CSiteManagerItemData(server));
 
1969
        pTree->SortChildren(m_ownSites);
 
1970
        pTree->SelectItem(newItem);
 
1971
        pTree->Expand(m_ownSites);
 
1972
        pTree->EditLabel(newItem);
 
1973
}
 
1974
 
 
1975
void CSiteManager::RememberLastSelected()
 
1976
{
 
1977
        wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
 
1978
        if (!pTree)
 
1979
                return;
 
1980
 
 
1981
        wxTreeItemId item = pTree->GetSelection();
 
1982
        if (!item.IsOk())
 
1983
                return;
 
1984
 
 
1985
        wxString path;
 
1986
        while (item != pTree->GetRootItem() && item != m_ownSites && item != m_predefinedSites)
 
1987
        {
 
1988
                wxString name = pTree->GetItemText(item);
 
1989
                name.Replace(_T("\\"), _T("\\\\"));
 
1990
                name.Replace(_T("/"), _T("\\/"));
 
1991
 
 
1992
                path = name + _T("/") + path;
 
1993
 
 
1994
                item = pTree->GetItemParent(item);
 
1995
        }
 
1996
 
 
1997
        if (item == m_predefinedSites)
 
1998
                path = _T("1") + path;
 
1999
        else
 
2000
                path = _T("0") + path;
 
2001
 
 
2002
        COptions::Get()->SetOption(OPTION_SITEMANAGER_LASTSELECTED, path);
 
2003
}
 
2004
 
 
2005
bool CSiteManager::UnescapeSitePath(wxString path, std::list<wxString>& result)
 
2006
{
 
2007
        result.clear();
 
2008
 
 
2009
        wxString name;
 
2010
        const wxChar *p = path;
 
2011
 
 
2012
        // Undo escapement
 
2013
        bool lastBackslash = false;
 
2014
        while (*p)
 
2015
        {
 
2016
                const wxChar& c = *p;
 
2017
                if (c == '\\')
 
2018
                {
 
2019
                        if (lastBackslash)
 
2020
                        {
 
2021
                                name += _T("\\");
 
2022
                                lastBackslash = false;
 
2023
                        }
 
2024
                        else
 
2025
                                lastBackslash = true;
 
2026
                }
 
2027
                else if (c == '/')
 
2028
                {
 
2029
                        if (lastBackslash)
 
2030
                        {
 
2031
                                name += _T("/");
 
2032
                                lastBackslash = 0;
 
2033
                        }
 
2034
                        else
 
2035
                        {
 
2036
                                if (!name.IsEmpty())
 
2037
                                        result.push_back(name);
 
2038
                                name.clear();
 
2039
                        }
 
2040
                }
 
2041
                else
 
2042
                        name += *p;
 
2043
                p++;
 
2044
        }
 
2045
        if (lastBackslash)
 
2046
                return false;
 
2047
        if (name != _T(""))
 
2048
                result.push_back(name);
 
2049
 
 
2050
        return !result.empty();
 
2051
}
 
2052
 
 
2053
class CSiteManagerXmlHandler_ByPath : public CSiteManagerXmlHandler
 
2054
{
 
2055
public:
 
2056
        CSiteManagerXmlHandler_ByPath(const wxString& lastSelection)
 
2057
        {
 
2058
                m_theItemData = 0;
 
2059
                if (!CSiteManager::UnescapeSitePath(lastSelection, m_lastSelection))
 
2060
                        m_lastSelection.clear();
 
2061
                m_wrong_sel_depth = 0;
 
2062
        }
 
2063
 
 
2064
        virtual ~CSiteManagerXmlHandler_ByPath()
 
2065
        {
 
2066
        }
 
2067
 
 
2068
        virtual bool AddFolder(const wxString& name, bool expanded)
 
2069
        {
 
2070
                if (m_theItemData)
 
2071
                        return false;
 
2072
 
 
2073
                if (!m_wrong_sel_depth && !m_lastSelection.empty())
 
2074
                {
 
2075
                        const wxString& first = m_lastSelection.front();
 
2076
                        if (first == name)
 
2077
                                m_lastSelection.pop_front();
 
2078
                        else
 
2079
                                m_wrong_sel_depth++;
 
2080
                }
 
2081
                else
 
2082
                        m_wrong_sel_depth++;
 
2083
 
 
2084
                return true;
 
2085
        }
 
2086
 
 
2087
        virtual bool AddSite(const wxString& name, CSiteManagerItemData* data)
 
2088
        {
 
2089
                if (m_theItemData)
 
2090
                {
 
2091
                        delete data;
 
2092
                        return false;
 
2093
                }
 
2094
 
 
2095
                if (m_wrong_sel_depth || m_lastSelection.empty())
 
2096
                {
 
2097
                        delete data;
 
2098
                        return true;
 
2099
                }
 
2100
 
 
2101
                const wxString& first = m_lastSelection.front();
 
2102
                if (first != name)
 
2103
                {
 
2104
                        delete data;
 
2105
                        return true;
 
2106
                }
 
2107
 
 
2108
                m_lastSelection.clear();
 
2109
                m_theItemData = data;
 
2110
 
 
2111
                return true;
 
2112
        }
 
2113
 
 
2114
        virtual bool LevelUp()
 
2115
        {
 
2116
                if (m_wrong_sel_depth)
 
2117
                        m_wrong_sel_depth--;
 
2118
 
 
2119
                return m_theItemData == 0;
 
2120
        }
 
2121
 
 
2122
        // Our result
 
2123
        CSiteManagerItemData* m_theItemData;
 
2124
 
 
2125
protected:
 
2126
 
 
2127
        std::list<wxString> m_lastSelection;
 
2128
        int m_wrong_sel_depth;
 
2129
};
 
2130
 
 
2131
CSiteManagerItemData* CSiteManager::GetSiteByPath(wxString sitePath)
 
2132
{
 
2133
        wxChar c = sitePath[0];
 
2134
        if (c != '0' && c != '1')
 
2135
        {
 
2136
                wxMessageBox(_("Site path has to begin with 0 or 1."), _("Invalid site path"));
 
2137
                return 0;
 
2138
        }
 
2139
 
 
2140
        sitePath = sitePath.Mid(1);
 
2141
 
 
2142
        // We have to synchronize access to sitemanager.xml so that multiple processed don't write
 
2143
        // to the same file or one is reading while the other one writes.
 
2144
        CInterProcessMutex mutex(MUTEX_SITEMANAGER);
 
2145
 
 
2146
        CXmlFile file;
 
2147
        TiXmlElement* pDocument = 0;
 
2148
 
 
2149
        if (c == '0')
 
2150
                pDocument = file.Load(_T("sitemanager"));
 
2151
        else
 
2152
        {
 
2153
                const wxString& defaultsDir = wxGetApp().GetDefaultsDir();
 
2154
                if (defaultsDir == _T(""))
 
2155
                {
 
2156
                        wxMessageBox(_("Site does not exist."), _("Invalid site path"));
 
2157
                        return 0;
 
2158
                }
 
2159
                wxFileName name(defaultsDir, _T("fzdefaults.xml"));
 
2160
                pDocument = file.Load(name);
 
2161
        }
 
2162
 
 
2163
        if (!pDocument)
 
2164
        {
 
2165
                wxString msg = wxString::Format(_("Could not load \"%s\", please make sure the file is valid and can be accessed.\nAny changes made in the Site Manager will not be saved."), file.GetFileName().GetFullPath().c_str());
 
2166
                wxMessageBox(msg, _("Error loading xml file"), wxICON_ERROR);
 
2167
 
 
2168
                return 0;
 
2169
        }
 
2170
 
 
2171
        TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
 
2172
        if (!pElement)
 
2173
        {
 
2174
                wxMessageBox(_("Site does not exist."), _("Invalid site path"));
 
2175
                return 0;
 
2176
        }
 
2177
 
 
2178
 
 
2179
        CSiteManagerXmlHandler_ByPath handler(sitePath);
 
2180
 
 
2181
        Load(pElement, &handler);
 
2182
 
 
2183
        if (!handler.m_theItemData)
 
2184
        {
 
2185
                wxMessageBox(_("Site does not exist."), _("Invalid site path"));
 
2186
                return 0;
 
2187
        }
 
2188
 
 
2189
        return handler.m_theItemData;
 
2190
}