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)
40
class CSiteManagerDataObject : public wxDataObjectSimple
43
CSiteManagerDataObject()
44
: wxDataObjectSimple(wxDataFormat(_T("FileZilla3SiteManagerObject")))
48
// GTK doesn't like data size of 0
49
virtual size_t GetDataSize() const { return 1; }
51
virtual bool GetDataHere(void *buf) const { memset(buf, 0, 1); return true; }
53
virtual bool SetData(size_t len, const void *buf) { return true; }
56
class CSiteManagerDropTarget : public wxDropTarget
59
CSiteManagerDropTarget(CSiteManager* pSiteManager)
60
: wxDropTarget(new CSiteManagerDataObject())
62
m_pSiteManager = pSiteManager;
65
virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
68
if (def == wxDragError ||
75
wxTreeItemId hit = GetHit(wxPoint(x, y));
78
if (hit == m_pSiteManager->m_dropSource)
81
const bool predefined = m_pSiteManager->IsPredefinedItem(hit);
85
wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
86
if (pTree->GetItemData(hit))
89
wxTreeItemId item = hit;
90
while (item != pTree->GetRootItem())
92
if (item == m_pSiteManager->m_dropSource)
97
item = pTree->GetItemParent(item);
100
if (def == wxDragMove && pTree->GetItemParent(m_pSiteManager->m_dropSource) == hit)
103
if (!m_pSiteManager->MoveItems(m_pSiteManager->m_dropSource, hit, def == wxDragCopy))
109
virtual bool OnDrop(wxCoord x, wxCoord y)
111
ClearDropHighlight();
113
wxTreeItemId hit = GetHit(wxPoint(x, y));
116
if (hit == m_pSiteManager->m_dropSource)
119
const bool predefined = m_pSiteManager->IsPredefinedItem(hit);
123
wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
124
if (pTree->GetItemData(hit))
127
wxTreeItemId item = hit;
128
while (item != pTree->GetRootItem())
130
if (item == m_pSiteManager->m_dropSource)
132
ClearDropHighlight();
135
item = pTree->GetItemParent(item);
141
virtual void OnLeave()
143
ClearDropHighlight();
146
virtual wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def)
148
return OnDragOver(x, y, def);
151
wxTreeItemId GetHit(const wxPoint& point)
155
wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
156
wxTreeItemId hit = pTree->HitTest(point, flags);
158
if (flags & (wxTREE_HITTEST_ABOVE | wxTREE_HITTEST_BELOW | wxTREE_HITTEST_NOWHERE | wxTREE_HITTEST_TOLEFT | wxTREE_HITTEST_TORIGHT))
159
return wxTreeItemId();
164
virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def)
166
if (def == wxDragError ||
170
ClearDropHighlight();
174
wxTreeItemId hit = GetHit(wxPoint(x, y));
177
ClearDropHighlight();
180
if (hit == m_pSiteManager->m_dropSource)
182
ClearDropHighlight();
186
const bool predefined = m_pSiteManager->IsPredefinedItem(hit);
189
ClearDropHighlight();
193
wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
194
CSiteManagerItemData* data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(hit));
197
ClearDropHighlight();
201
wxTreeItemId item = hit;
202
while (item != pTree->GetRootItem())
204
if (item == m_pSiteManager->m_dropSource)
206
ClearDropHighlight();
209
item = pTree->GetItemParent(item);
212
if (def == wxDragMove && pTree->GetItemParent(m_pSiteManager->m_dropSource) == hit)
214
ClearDropHighlight();
218
DisplayDropHighlight(hit);
223
void ClearDropHighlight()
225
if (m_dropHighlight == wxTreeItemId())
228
wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
229
pTree->SetItemDropHighlight(m_dropHighlight, false);
230
m_dropHighlight = wxTreeItemId();
233
void DisplayDropHighlight(wxTreeItemId item)
235
ClearDropHighlight();
237
wxTreeCtrl *pTree = XRCCTRL(*m_pSiteManager, "ID_SITETREE", wxTreeCtrl);
238
pTree->SetItemDropHighlight(item, true);
239
m_dropHighlight = item;
243
CSiteManager* m_pSiteManager;
244
wxTreeItemId m_dropHighlight;
32
247
CSiteManager::CSiteManager()
34
249
m_pSiteManagerMutex = 0;
250
m_pWindowStateManager = 0;
37
253
CSiteManager::~CSiteManager()
39
255
delete m_pSiteManagerMutex;
257
if (m_pWindowStateManager)
259
m_pWindowStateManager->Remember(OPTION_SITEMANAGER_POSITION);
260
delete m_pWindowStateManager;
42
bool CSiteManager::Create(wxWindow* parent)
264
bool CSiteManager::Create(wxWindow* parent, const CServer* pServer /*=0*/)
44
266
m_pSiteManagerMutex = new CInterProcessMutex(MUTEX_SITEMANAGERGLOBAL, false);
45
267
if (!m_pSiteManagerMutex->TryLock())
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);
52
274
delete m_pSiteManagerMutex;
53
275
m_pSiteManagerMutex = 0;
55
SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
58
wxGetApp().GetWrapEngine()->WrapRecursive(this, 1.33, "Site Manager");
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);
66
279
// Now create the imagelist for the site tree
67
280
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
391
RememberLastSelected();
132
393
EndModal(wxID_YES);
135
bool CSiteManager::Load(TiXmlElement *pElement /*=0*/, wxTreeItemId treeId /*=wxTreeItemId()*/)
396
class CSiteManagerXmlHandler
399
virtual ~CSiteManagerXmlHandler() {};
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;
406
virtual bool LevelUp() = 0; // *Ding*
409
class CSiteManagerXmlHandler_Tree : public CSiteManagerXmlHandler
412
CSiteManagerXmlHandler_Tree(wxTreeCtrl* pTree, wxTreeItemId root, const wxString& lastSelection)
413
: m_pTree(pTree), m_item(root)
415
if (!CSiteManager::UnescapeSitePath(lastSelection, m_lastSelection))
416
m_lastSelection.clear();
417
m_wrong_sel_depth = 0;
420
virtual ~CSiteManagerXmlHandler_Tree()
422
m_pTree->SortChildren(m_item);
423
m_pTree->Expand(m_item);
426
virtual bool AddFolder(const wxString& name, bool expanded)
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);
433
m_expand.push_back(expanded);
435
if (!m_wrong_sel_depth && !m_lastSelection.empty())
437
const wxString& first = m_lastSelection.front();
440
m_lastSelection.pop_front();
441
if (m_lastSelection.empty())
442
m_pTree->SelectItem(newItem);
453
virtual bool AddSite(const wxString& name, CSiteManagerItemData* data)
455
wxTreeItemId newItem = m_pTree->AppendItem(m_item, name, 2, 2, data);
457
if (!m_wrong_sel_depth && !m_lastSelection.empty())
459
const wxString& first = m_lastSelection.front();
462
m_lastSelection.clear();
463
m_pTree->SelectItem(newItem);
470
virtual bool LevelUp()
472
if (m_wrong_sel_depth)
475
if (!m_expand.empty())
477
const bool expand = m_expand.back();
480
m_pTree->Expand(m_item);
482
m_pTree->SortChildren(m_item);
484
wxTreeItemId parent = m_pTree->GetItemParent(m_item);
496
std::list<wxString> m_lastSelection;
497
int m_wrong_sel_depth;
499
std::list<bool> m_expand;
502
bool CSiteManager::Load()
137
504
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
141
if (!pElement || !treeId)
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);
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);
153
wxFileName file(wxGetApp().GetSettingsDir(), _T("sitemanager.xml"));
154
TiXmlElement* pDocument = GetXmlFile(file);
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);
162
pElement = pDocument->FirstChildElement("Servers");
165
delete pDocument->GetDocument();
169
bool res = Load(pElement, treeId);
171
delete pDocument->GetDocument();
173
pTree->SortChildren(treeId);
174
pTree->Expand(treeId);
175
pTree->SelectItem(treeId);
508
pTree->DeleteAllItems();
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);
514
// Load default sites
515
bool hasDefaultSites = LoadDefaultSites();
517
m_ownSites = pTree->AppendItem(pTree->GetRootItem(), _("My Sites"), 0, 0);
519
m_ownSites = pTree->AddRoot(_("My Sites"), 0, 0);
521
wxTreeItemId treeId = m_ownSites;
522
pTree->SetItemImage(treeId, 1, wxTreeItemIcon_Expanded);
523
pTree->SetItemImage(treeId, 1, wxTreeItemIcon_SelectedExpanded);
525
CXmlFile file(_T("sitemanager"));
526
TiXmlElement* pDocument = file.Load();
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);
535
TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
539
wxString lastSelection = COptions::Get()->GetOption(OPTION_SITEMANAGER_LASTSELECTED);
540
if (lastSelection[0] == '0')
542
if (lastSelection == _T("0"))
543
pTree->SelectItem(treeId);
545
lastSelection = lastSelection.Mid(1);
548
lastSelection = _T("");
549
CSiteManagerXmlHandler_Tree handler(pTree, treeId, lastSelection);
551
bool res = Load(pElement, &handler);
553
pTree->SortChildren(treeId);
554
pTree->Expand(treeId);
555
if (!pTree->GetSelection())
556
pTree->SelectItem(treeId);
558
pTree->EnsureVisible(pTree->GetSelection());
563
bool CSiteManager::Load(TiXmlElement *pElement, CSiteManagerXmlHandler* pHandler)
180
568
for (TiXmlElement* pChild = pElement->FirstChildElement(); pChild; pChild = pChild->NextSiblingElement())
182
570
TiXmlNode* pNode = pChild->FirstChild();
183
571
while (pNode && !pNode->ToText())
184
572
pNode = pNode->NextSibling();
189
577
wxString name = ConvLocal(pNode->ToText()->Value());
191
581
if (!strcmp(pChild->Value(), "Folder"))
193
wxTreeItemId id = pTree->AppendItem(treeId, name, 0, 0);
194
pTree->SetItemImage(id, 1, wxTreeItemIcon_Expanded);
195
pTree->SetItemImage(id, 1, wxTreeItemIcon_SelectedExpanded);
583
const bool expand = GetTextAttribute(pChild, "expanded") != _T("0");
584
if (!pHandler->AddFolder(name, expand))
586
Load(pChild, pHandler);
587
if (!pHandler->LevelUp())
198
590
else if (!strcmp(pChild->Value(), "Server"))
201
if (!::GetServer(pChild, server))
204
CSiteManagerItemData* data = new CSiteManagerItemData(server);
206
TiXmlHandle handle(pChild);
208
TiXmlText* comments = handle.FirstChildElement("Comments").FirstChild().Text();
210
data->m_comments = ConvLocal(comments->Value());
212
TiXmlText* localDir = handle.FirstChildElement("LocalDir").FirstChild().Text();
214
data->m_localDir = ConvLocal(localDir->Value());
216
TiXmlText* remoteDir = handle.FirstChildElement("RemoteDir").FirstChild().Text();
218
data->m_remoteDir.SetSafePath(ConvLocal(remoteDir->Value()));
220
pTree->AppendItem(treeId, name, 2, 2, data);
592
CSiteManagerItemData* data = ReadServerElement(pChild);
595
pHandler->AddSite(name, data);
223
pTree->SortChildren(treeId);
224
pTree->Expand(treeId);
602
CSiteManagerItemData* CSiteManager::ReadServerElement(TiXmlElement *pElement)
605
if (!::GetServer(pElement, server))
608
CSiteManagerItemData* data = new CSiteManagerItemData(server);
610
TiXmlHandle handle(pElement);
612
TiXmlText* comments = handle.FirstChildElement("Comments").FirstChild().Text();
614
data->m_comments = ConvLocal(comments->Value());
616
TiXmlText* localDir = handle.FirstChildElement("LocalDir").FirstChild().Text();
618
data->m_localDir = ConvLocal(localDir->Value());
620
TiXmlText* remoteDir = handle.FirstChildElement("RemoteDir").FirstChild().Text();
622
data->m_remoteDir.SetSafePath(ConvLocal(remoteDir->Value()));
229
627
bool CSiteManager::Save(TiXmlElement *pElement /*=0*/, wxTreeItemId treeId /*=wxTreeItemId()*/)
231
629
if (!m_pSiteManagerMutex)
801
1236
wxTreeItemId item = pTree->GetSelection();
1238
const bool predefined = IsPredefinedItem(item);
1241
wxWindow* pFocus = FindFocus();
803
1244
CSiteManagerItemData* data = 0;
804
1245
if (item.IsOk())
805
1246
data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(item));
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);
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);
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(""));
827
XRCCTRL(*this, "ID_SERVERTYPE", wxChoice)->SetStringSelection(_("Default"));
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);
1281
XRCCTRL(*this, "ID_CHARSET_AUTO", wxRadioButton)->SetValue(true);
1282
XRCCTRL(*this, "ID_ENCODING", wxTextCtrl)->SetValue(_T(""));
1284
XRCCTRL(*this, "wxID_OK", wxButton)->SetDefault();
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);
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();
851
bool showPort = true;
852
switch (data->m_server.GetProtocol())
857
XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(_("SFTP"));
863
XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(_("FTP"));
1300
unsigned int port = data->m_server.GetPort();
1302
if (port != CServer::GetDefaultPort(data->m_server.GetProtocol()))
868
1303
XRCCTRL(*this, "ID_PORT", wxTextCtrl)->SetValue(wxString::Format(_T("%d"), port));
870
1305
XRCCTRL(*this, "ID_PORT", wxTextCtrl)->SetValue(_T(""));
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);
1308
const wxString& protocolName = CServer::GetProtocolName(data->m_server.GetProtocol());
1309
if (protocolName != _T(""))
1310
XRCCTRL(*this, "ID_PROTOCOL", wxChoice)->SetStringSelection(protocolName);
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());
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);
877
1320
switch (data->m_server.GetLogonType())
969
1425
void CSiteManager::OnProtocolSelChanged(wxCommandEvent& event)
1429
void CSiteManager::OnCopySite(wxCommandEvent& event)
1431
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
1435
wxTreeItemId item = pTree->GetSelection();
1439
CSiteManagerItemData* data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(item));
1446
if (!UpdateServer())
1449
wxTreeItemId parent;
1450
if (IsPredefinedItem(item))
1451
parent = m_ownSites;
1453
parent = pTree->GetItemParent(item);
1455
const wxString name = pTree->GetItemText(item);
1456
wxString newName = wxString::Format(_("Copy of %s"), name.c_str());
1461
wxTreeItemIdValue cookie;
1462
child = pTree->GetFirstChild(parent, cookie);
1464
while (child.IsOk())
1466
wxString name = pTree->GetItemText(child);
1467
int cmp = name.CmpNoCase(newName);
1474
child = pTree->GetNextChild(parent, cookie);
1479
newName = wxString::Format(_("Copy (%d) of %s"), index++, name.c_str());
1482
CSiteManagerItemData* newData = new CSiteManagerItemData();
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);
1491
bool CSiteManager::LoadDefaultSites()
1493
const wxString& defaultsDir = wxGetApp().GetDefaultsDir();
1494
if (defaultsDir == _T(""))
1497
wxFileName name(defaultsDir, _T("fzdefaults.xml"));
1498
CXmlFile file(name);
1500
TiXmlElement* pDocument = file.Load();
1504
TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
1508
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
1512
int style = pTree->GetWindowStyle();
1513
pTree->SetWindowStyle(style | wxTR_HIDE_ROOT);
1514
wxTreeItemId root = pTree->AddRoot(_T(""), 0, 0);
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);
1520
wxString lastSelection = COptions::Get()->GetOption(OPTION_SITEMANAGER_LASTSELECTED);
1521
if (lastSelection[0] == '1')
1523
if (lastSelection == _T("1"))
1524
pTree->SelectItem(m_predefinedSites);
1526
lastSelection = lastSelection.Mid(1);
1529
lastSelection = _T("");
1530
CSiteManagerXmlHandler_Tree handler(pTree, m_predefinedSites, lastSelection);
1532
Load(pElement, &handler);
1537
bool CSiteManager::IsPredefinedItem(wxTreeItemId item)
1539
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
1546
if (item == m_predefinedSites)
1548
item = pTree->GetItemParent(item);
1554
class CSiteManagerXmlHandler_Menu : public CSiteManagerXmlHandler
1557
CSiteManagerXmlHandler_Menu(wxMenu* pMenu, std::map<int, CSiteManagerItemData*> *idMap)
1558
: m_pMenu(pMenu), m_idMap(idMap)
1562
unsigned int GetInsertIndex(wxMenu* pMenu, const wxString& name)
1565
for (i = 0; i < pMenu->GetMenuItemCount(); i++)
1567
const wxMenuItem* const pItem = pMenu->FindItemByPosition(i);
1570
if (pItem->GetLabel() > name)
1577
virtual bool AddFolder(const wxString& name, bool)
1579
m_parents.push_back(m_pMenu);
1580
m_childNames.push_back(name);
1582
m_pMenu = new wxMenu;
1587
virtual bool AddSite(const wxString& name, CSiteManagerItemData* data)
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;
1599
virtual bool LevelUp()
1601
if (m_parents.empty() || m_childNames.empty())
1604
wxMenu* pChild = m_pMenu;
1605
m_pMenu = m_parents.back();
1606
if (pChild->GetMenuItemCount())
1608
wxString name = m_childNames.back();
1609
int i = GetInsertIndex(m_pMenu, name);
1610
name.Replace(_T("&"), _T("&&"));
1612
wxMenuItem* pItem = new wxMenuItem(m_pMenu, wxID_ANY, name, _T(""), wxITEM_NORMAL, pChild);
1613
m_pMenu->Insert(i, pItem);
1617
m_childNames.pop_back();
1618
m_parents.pop_back();
1626
std::map<int, CSiteManagerItemData*> *m_idMap;
1628
std::list<wxMenu*> m_parents;
1629
std::list<wxString> m_childNames;
1632
wxMenu* CSiteManager::GetSitesMenu()
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);
1640
wxMenu* predefinedSites = GetSitesMenu_Predefied(m_idMap);
1642
CXmlFile file(_T("sitemanager"));
1643
TiXmlElement* pDocument = file.Load();
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);
1649
if (!predefinedSites)
1650
return predefinedSites;
1652
wxMenu *pMenu = new wxMenu;
1653
wxMenuItem* pItem = pMenu->Append(wxID_ANY, _("No sites available"));
1654
pItem->Enable(false);
1658
TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
1661
if (!predefinedSites)
1662
return predefinedSites;
1664
wxMenu *pMenu = new wxMenu;
1665
wxMenuItem* pItem = pMenu->Append(wxID_ANY, _("No sites available"));
1666
pItem->Enable(false);
1670
wxMenu* pMenu = new wxMenu;
1671
CSiteManagerXmlHandler_Menu handler(pMenu, &m_idMap);
1673
bool res = Load(pElement, &handler);
1674
if (!res || !pMenu->GetMenuItemCount())
1682
if (!predefinedSites)
1685
wxMenu* pRootMenu = new wxMenu;
1686
pRootMenu->AppendSubMenu(predefinedSites, _("Predefined Sites"));
1687
pRootMenu->AppendSubMenu(pMenu, _("My Sites"));
1692
if (predefinedSites)
1693
return predefinedSites;
1696
wxMenuItem* pItem = pMenu->Append(wxID_ANY, _("No sites available"));
1697
pItem->Enable(false);
1701
void CSiteManager::ClearIdMap()
1703
for (std::map<int, CSiteManagerItemData*>::iterator iter = m_idMap.begin(); iter != m_idMap.end(); iter++)
1704
delete iter->second;
1709
wxMenu* CSiteManager::GetSitesMenu_Predefied(std::map<int, CSiteManagerItemData*> &idMap)
1711
const wxString& defaultsDir = wxGetApp().GetDefaultsDir();
1712
if (defaultsDir == _T(""))
1715
wxFileName name(defaultsDir, _T("fzdefaults.xml"));
1716
CXmlFile file(name);
1718
TiXmlElement* pDocument = file.Load();
1722
TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
1726
wxMenu* pMenu = new wxMenu;
1727
CSiteManagerXmlHandler_Menu handler(pMenu, &idMap);
1729
if (!Load(pElement, &handler))
1735
if (!pMenu->GetMenuItemCount())
1744
CSiteManagerItemData* CSiteManager::GetSiteById(int id)
1746
std::map<int, CSiteManagerItemData*>::iterator iter = m_idMap.find(id);
1748
CSiteManagerItemData *pData;
1749
if (iter != m_idMap.end())
1751
pData = iter->second;
1762
void CSiteManager::OnBeginDrag(wxTreeEvent& event)
1770
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
1777
wxTreeItemId item = event.GetItem();
1784
const bool predefined = IsPredefinedItem(item);
1785
const bool root_or_predefined = (item == pTree->GetRootItem() || item == m_ownSites || predefined);
1787
CSiteManagerDataObject obj;
1789
wxDropSource source(this);
1790
source.SetData(obj);
1792
m_dropSource = item;
1794
source.DoDragDrop(root_or_predefined ? wxDrag_CopyOnly : wxDrag_DefaultMove);
1796
m_dropSource = wxTreeItemId();
1801
wxTreeItemId source;
1802
wxTreeItemId target;
1805
bool CSiteManager::MoveItems(wxTreeItemId source, wxTreeItemId target, bool copy)
1807
if (source == target)
1810
if (IsPredefinedItem(target))
1813
if (IsPredefinedItem(source) && !copy)
1816
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
1817
if (pTree->GetItemData(target))
1820
wxTreeItemId item = target;
1821
while (item != pTree->GetRootItem())
1825
item = pTree->GetItemParent(item);
1828
if (!copy && pTree->GetItemParent(source) == target)
1831
wxString sourceName = pTree->GetItemText(source);
1834
wxTreeItemIdValue cookie;
1835
child = pTree->GetFirstChild(target, cookie);
1837
while (child.IsOk())
1839
wxString childName = pTree->GetItemText(child);
1841
if (!sourceName.CmpNoCase(childName))
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);
1847
child = pTree->GetNextChild(target, cookie);
1850
std::list<itempair> work;
1852
pair.source = source;
1853
pair.target = target;
1854
work.push_back(pair);
1856
std::list<wxTreeItemId> expand;
1858
while (!work.empty())
1860
itempair pair = work.front();
1863
wxString name = pTree->GetItemText(pair.source);
1865
CSiteManagerItemData* data = reinterpret_cast<CSiteManagerItemData* >(pTree->GetItemData(pair.source));
1867
wxTreeItemId newItem = pTree->AppendItem(pair.target, name, data ? 2 : 0);
1870
pTree->SetItemImage(newItem, 1, wxTreeItemIcon_Expanded);
1871
pTree->SetItemImage(newItem, 1, wxTreeItemIcon_SelectedExpanded);
1873
if (pTree->IsExpanded(pair.source))
1874
expand.push_back(newItem);
1878
CSiteManagerItemData* newData = new CSiteManagerItemData;
1880
pTree->SetItemData(newItem, newData);
1884
wxTreeItemIdValue cookie;
1885
child = pTree->GetFirstChild(pair.source, cookie);
1886
while (child.IsOk())
1889
newPair.source = child;
1890
newPair.target = newItem;
1891
work.push_back(newPair);
1893
child = pTree->GetNextChild(pair.source, cookie);
1896
pTree->SortChildren(pair.target);
1901
wxTreeItemId parent = pTree->GetItemParent(source);
1902
if (pTree->GetChildrenCount(parent) == 1)
1903
pTree->Collapse(parent);
1905
pTree->Delete(source);
1908
for (std::list<wxTreeItemId>::iterator iter = expand.begin(); iter != expand.end(); iter++)
1909
pTree->Expand(*iter);
1911
pTree->Expand(target);
1916
void CSiteManager::OnChar(wxKeyEvent& event)
1918
if (event.GetKeyCode() != WXK_F2)
1924
wxCommandEvent cmdEvent;
1928
void CSiteManager::CopyAddServer(const CServer& server)
1933
AddNewSite(m_ownSites, server);
1936
void CSiteManager::AddNewSite(wxTreeItemId parent, const CServer& server)
1938
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
1942
wxString newName = _("New site");
1947
wxTreeItemIdValue cookie;
1948
child = pTree->GetFirstChild(parent, cookie);
1950
while (child.IsOk())
1952
wxString name = pTree->GetItemText(child);
1953
int cmp = name.CmpNoCase(newName);
1960
child = pTree->GetNextChild(parent, cookie);
1965
newName = _("New site") + wxString::Format(_T(" %d"), index++);
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);
1975
void CSiteManager::RememberLastSelected()
1977
wxTreeCtrl *pTree = XRCCTRL(*this, "ID_SITETREE", wxTreeCtrl);
1981
wxTreeItemId item = pTree->GetSelection();
1986
while (item != pTree->GetRootItem() && item != m_ownSites && item != m_predefinedSites)
1988
wxString name = pTree->GetItemText(item);
1989
name.Replace(_T("\\"), _T("\\\\"));
1990
name.Replace(_T("/"), _T("\\/"));
1992
path = name + _T("/") + path;
1994
item = pTree->GetItemParent(item);
1997
if (item == m_predefinedSites)
1998
path = _T("1") + path;
2000
path = _T("0") + path;
2002
COptions::Get()->SetOption(OPTION_SITEMANAGER_LASTSELECTED, path);
2005
bool CSiteManager::UnescapeSitePath(wxString path, std::list<wxString>& result)
2010
const wxChar *p = path;
2013
bool lastBackslash = false;
2016
const wxChar& c = *p;
2022
lastBackslash = false;
2025
lastBackslash = true;
2036
if (!name.IsEmpty())
2037
result.push_back(name);
2048
result.push_back(name);
2050
return !result.empty();
2053
class CSiteManagerXmlHandler_ByPath : public CSiteManagerXmlHandler
2056
CSiteManagerXmlHandler_ByPath(const wxString& lastSelection)
2059
if (!CSiteManager::UnescapeSitePath(lastSelection, m_lastSelection))
2060
m_lastSelection.clear();
2061
m_wrong_sel_depth = 0;
2064
virtual ~CSiteManagerXmlHandler_ByPath()
2068
virtual bool AddFolder(const wxString& name, bool expanded)
2073
if (!m_wrong_sel_depth && !m_lastSelection.empty())
2075
const wxString& first = m_lastSelection.front();
2077
m_lastSelection.pop_front();
2079
m_wrong_sel_depth++;
2082
m_wrong_sel_depth++;
2087
virtual bool AddSite(const wxString& name, CSiteManagerItemData* data)
2095
if (m_wrong_sel_depth || m_lastSelection.empty())
2101
const wxString& first = m_lastSelection.front();
2108
m_lastSelection.clear();
2109
m_theItemData = data;
2114
virtual bool LevelUp()
2116
if (m_wrong_sel_depth)
2117
m_wrong_sel_depth--;
2119
return m_theItemData == 0;
2123
CSiteManagerItemData* m_theItemData;
2127
std::list<wxString> m_lastSelection;
2128
int m_wrong_sel_depth;
2131
CSiteManagerItemData* CSiteManager::GetSiteByPath(wxString sitePath)
2133
wxChar c = sitePath[0];
2134
if (c != '0' && c != '1')
2136
wxMessageBox(_("Site path has to begin with 0 or 1."), _("Invalid site path"));
2140
sitePath = sitePath.Mid(1);
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);
2147
TiXmlElement* pDocument = 0;
2150
pDocument = file.Load(_T("sitemanager"));
2153
const wxString& defaultsDir = wxGetApp().GetDefaultsDir();
2154
if (defaultsDir == _T(""))
2156
wxMessageBox(_("Site does not exist."), _("Invalid site path"));
2159
wxFileName name(defaultsDir, _T("fzdefaults.xml"));
2160
pDocument = file.Load(name);
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);
2171
TiXmlElement* pElement = pDocument->FirstChildElement("Servers");
2174
wxMessageBox(_("Site does not exist."), _("Invalid site path"));
2179
CSiteManagerXmlHandler_ByPath handler(sitePath);
2181
Load(pElement, &handler);
2183
if (!handler.m_theItemData)
2185
wxMessageBox(_("Site does not exist."), _("Invalid site path"));
2189
return handler.m_theItemData;