source: filezilla/trunk/fuentes/src/interface/menu_bar.cpp @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 3 years ago

Update new version: 3.15.02

File size: 15.7 KB
Line 
1#include <filezilla.h>
2#include "context_control.h"
3#include "bookmarks_dialog.h"
4#include "listingcomparison.h"
5#include "Mainfrm.h"
6#include "menu_bar.h"
7#include "Options.h"
8#include "QueueView.h"
9#include "sitemanager.h"
10#include "state.h"
11
12IMPLEMENT_DYNAMIC_CLASS(CMenuBar, wxMenuBar)
13
14BEGIN_EVENT_TABLE(CMenuBar, wxMenuBar)
15EVT_MENU(wxID_ANY, CMenuBar::OnMenuEvent)
16END_EVENT_TABLE()
17
18CMenuBar::CMenuBar()
19        : CStateEventHandler(0)
20        , m_pMainFrame()
21{
22}
23
24CMenuBar::~CMenuBar()
25{
26        for (auto hidden_menu : m_hidden_items) {
27                for (auto hidden_item : hidden_menu.second) {
28                        delete hidden_item.second;
29                }
30        }
31
32        m_pMainFrame->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CMenuBar::OnMenuEvent), 0, this);
33}
34
35CMenuBar* CMenuBar::Load(CMainFrame* pMainFrame)
36{
37        CMenuBar* menubar = wxDynamicCast(wxXmlResource::Get()->LoadMenuBar(_T("ID_MENUBAR")), CMenuBar);
38        if (!menubar)
39                return 0;
40
41        menubar->m_pMainFrame = pMainFrame;
42
43
44#if FZ_MANUALUPDATECHECK
45        if (COptions::Get()->GetOptionVal(OPTION_DEFAULT_DISABLEUPDATECHECK))
46#endif
47        {
48                wxMenu *helpMenu;
49
50                wxMenuItem* pUpdateItem = menubar->FindItem(XRCID("ID_CHECKFORUPDATES"), &helpMenu);
51                if (pUpdateItem)
52                {
53                        // Get rid of separator
54                        unsigned int count = helpMenu->GetMenuItemCount();
55                        for (unsigned int i = 0; i < count - 1; i++)
56                        {
57                                if (helpMenu->FindItemByPosition(i) == pUpdateItem)
58                                {
59                                        helpMenu->Delete(helpMenu->FindItemByPosition(i + 1));
60                                        break;
61                                }
62                        }
63
64                        helpMenu->Delete(pUpdateItem);
65                }
66        }
67
68        if (COptions::Get()->GetOptionVal(OPTION_DEBUG_MENU))
69        {
70                wxMenu* pMenu = wxXmlResource::Get()->LoadMenu(_T("ID_MENU_DEBUG"));
71                if (pMenu)
72                        menubar->Append(pMenu, _("&Debug"));
73        }
74
75        menubar->UpdateBookmarkMenu();
76
77        menubar->Check(XRCID("ID_MENU_SERVER_VIEWHIDDEN"), COptions::Get()->GetOptionVal(OPTION_VIEW_HIDDEN_FILES) ? true : false);
78
79        int mode = COptions::Get()->GetOptionVal(OPTION_COMPARISONMODE);
80        if (mode != 1)
81                menubar->Check(XRCID("ID_COMPARE_SIZE"), true);
82        else
83                menubar->Check(XRCID("ID_COMPARE_DATE"), true);
84
85        menubar->Check(XRCID("ID_COMPARE_HIDEIDENTICAL"), COptions::Get()->GetOptionVal(OPTION_COMPARE_HIDEIDENTICAL) != 0);
86        menubar->Check(XRCID("ID_VIEW_QUICKCONNECT"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUICKCONNECT) != 0);
87        menubar->Check(XRCID("ID_VIEW_TOOLBAR"), COptions::Get()->GetOptionVal(OPTION_TOOLBAR_HIDDEN) == 0);
88        menubar->Check(XRCID("ID_VIEW_MESSAGELOG"), COptions::Get()->GetOptionVal(OPTION_SHOW_MESSAGELOG) != 0);
89        menubar->Check(XRCID("ID_VIEW_QUEUE"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUEUE) != 0);
90        menubar->Check(XRCID("ID_VIEW_LOCALTREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_LOCAL) != 0);
91        menubar->Check(XRCID("ID_VIEW_REMOTETREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_REMOTE) != 0);
92        menubar->Check(XRCID("ID_MENU_VIEW_FILELISTSTATUSBAR"), COptions::Get()->GetOptionVal(OPTION_FILELIST_STATUSBAR) != 0);
93        menubar->Check(XRCID("ID_MENU_TRANSFER_PRESERVETIMES"), COptions::Get()->GetOptionVal(OPTION_PRESERVE_TIMESTAMPS) != 0);
94
95        switch (COptions::Get()->GetOptionVal(OPTION_ASCIIBINARY))
96        {
97        case 1:
98                menubar->Check(XRCID("ID_MENU_TRANSFER_TYPE_ASCII"), true);
99                break;
100        case 2:
101                menubar->Check(XRCID("ID_MENU_TRANSFER_TYPE_BINARY"), true);
102                break;
103        default:
104                menubar->Check(XRCID("ID_MENU_TRANSFER_TYPE_AUTO"), true);
105                break;
106        }
107
108        menubar->UpdateSpeedLimitMenuItem();
109
110        if (COptions::Get()->GetOptionVal(OPTION_MESSAGELOG_POSITION) == 2)
111                menubar->HideItem(XRCID("ID_VIEW_MESSAGELOG"));
112
113        menubar->UpdateMenubarState();
114
115        pMainFrame->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CMenuBar::OnMenuEvent), 0, menubar);
116
117        CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_REMOTE_IDLE, true);
118        CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_SERVER, true);
119        CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_SYNC_BROWSE, true);
120        CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_COMPARISON, true);
121
122        CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_QUEUEPROCESSING, false);
123        CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_CHANGEDCONTEXT, false);
124
125        menubar->RegisterOption(OPTION_ASCIIBINARY);
126        menubar->RegisterOption(OPTION_PRESERVE_TIMESTAMPS);
127
128        menubar->RegisterOption(OPTION_TOOLBAR_HIDDEN);
129        menubar->RegisterOption(OPTION_SHOW_MESSAGELOG);
130        menubar->RegisterOption(OPTION_SHOW_QUEUE);
131        menubar->RegisterOption(OPTION_SHOW_TREE_LOCAL);
132        menubar->RegisterOption(OPTION_SHOW_TREE_REMOTE);
133        menubar->RegisterOption(OPTION_MESSAGELOG_POSITION);
134        menubar->RegisterOption(OPTION_COMPARISONMODE);
135        menubar->RegisterOption(OPTION_COMPARE_HIDEIDENTICAL);
136        menubar->RegisterOption(OPTION_SPEEDLIMIT_ENABLE);
137        menubar->RegisterOption(OPTION_SPEEDLIMIT_INBOUND);
138        menubar->RegisterOption(OPTION_SPEEDLIMIT_OUTBOUND);
139
140        return menubar;
141}
142
143void CMenuBar::UpdateBookmarkMenu()
144{
145        wxMenu* pMenu;
146        if (!FindItem(XRCID("ID_BOOKMARK_ADD"), &pMenu))
147                return;
148
149        // Delete old bookmarks
150        for (std::map<int, wxString>::const_iterator iter = m_bookmark_menu_id_map_global.begin(); iter != m_bookmark_menu_id_map_global.end(); ++iter)
151        {
152                pMenu->Delete(iter->first);
153        }
154        m_bookmark_menu_id_map_global.clear();
155
156        for (std::map<int, wxString>::const_iterator iter = m_bookmark_menu_id_map_site.begin(); iter != m_bookmark_menu_id_map_site.end(); ++iter)
157        {
158                pMenu->Delete(iter->first);
159        }
160        m_bookmark_menu_id_map_site.clear();
161
162        // Delete the separators
163        while (pMenu->GetMenuItemCount() > 2)
164        {
165                wxMenuItem* pSeparator = pMenu->FindItemByPosition(2);
166                if (pSeparator)
167                        pMenu->Delete(pSeparator);
168        }
169
170        auto ids = m_bookmark_menu_ids.begin();
171
172        // Insert global bookmarks
173        std::list<wxString> global_bookmarks;
174        if (CBookmarksDialog::GetBookmarks(global_bookmarks) && !global_bookmarks.empty())
175        {
176                pMenu->AppendSeparator();
177
178                for (std::list<wxString>::const_iterator iter = global_bookmarks.begin(); iter != global_bookmarks.end(); ++iter)
179                {
180                        int id;
181                        if (ids == m_bookmark_menu_ids.end())
182                        {
183                                id = wxNewId();
184                                m_bookmark_menu_ids.push_back(id);
185                        }
186                        else
187                        {
188                                id = *ids;
189                                ++ids;
190                        }
191                        wxString name(*iter);
192                        name.Replace(_T("&"), _T("&&"));
193                        pMenu->Append(id, name);
194
195                        m_bookmark_menu_id_map_global[id] = *iter;
196                }
197        }
198
199        // Insert site-specific bookmarks
200        CContextControl* pContextControl = m_pMainFrame ? m_pMainFrame->GetContextControl() : 0;
201        CContextControl::_context_controls* controls = pContextControl ? pContextControl->GetCurrentControls() : 0;
202        if (!controls)
203                return;
204
205        if (!controls->site_bookmarks || controls->site_bookmarks->bookmarks.empty())
206                return;
207
208        pMenu->AppendSeparator();
209
210        for (std::list<wxString>::const_iterator iter = controls->site_bookmarks->bookmarks.begin(); iter != controls->site_bookmarks->bookmarks.end(); ++iter)
211        {
212                int id;
213                if (ids == m_bookmark_menu_ids.end())
214                {
215                        id = wxNewId();
216                        m_bookmark_menu_ids.push_back(id);
217                }
218                else
219                {
220                        id = *ids;
221                        ++ids;
222                }
223                wxString name(*iter);
224                name.Replace(_T("&"), _T("&&"));
225                pMenu->Append(id, name);
226
227                m_bookmark_menu_id_map_site[id] = *iter;
228        }
229}
230
231void CMenuBar::ClearBookmarks()
232{
233        CContextControl* pContextControl = m_pMainFrame ? m_pMainFrame->GetContextControl() : 0;
234        CContextControl::_context_controls* controls = pContextControl ? pContextControl->GetCurrentControls() : 0;
235
236        if (controls && !controls->site_bookmarks)
237                controls->site_bookmarks = std::make_shared<CContextControl::_context_controls::_site_bookmarks>();
238        UpdateBookmarkMenu();
239}
240
241void CMenuBar::OnMenuEvent(wxCommandEvent& event)
242{
243        CState* pState = CContextManager::Get()->GetCurrentContext();
244        if (!pState)
245                return;
246
247        std::map<int, wxString>::const_iterator iter = m_bookmark_menu_id_map_site.find(event.GetId());
248        if (iter != m_bookmark_menu_id_map_site.end()) {
249                // We hit a site-specific bookmark
250                CContextControl* pContextControl = m_pMainFrame ? m_pMainFrame->GetContextControl() : 0;
251                CContextControl::_context_controls* controls = pContextControl ? pContextControl->GetCurrentControls() : 0;
252                if (!controls)
253                        return;
254                if (controls->site_bookmarks->path.empty())
255                        return;
256
257                wxString name = iter->second;
258                name.Replace(_T("\\"), _T("\\\\"));
259                name.Replace(_T("/"), _T("\\/"));
260                name = controls->site_bookmarks->path + _T("/") + name;
261
262                std::unique_ptr<CSiteManagerItemData_Site> pData = CSiteManager::GetSiteByPath(name);
263                if (!pData)
264                        return;
265
266                pState->SetSyncBrowse(false);
267                if (!pData->m_remoteDir.empty() && pState->IsRemoteIdle(true)) {
268                        const CServer* pServer = pState->GetServer();
269                        if (!pServer || *pServer != pData->m_server) {
270                                m_pMainFrame->ConnectToSite(*pData);
271                                pData->m_localDir.clear(); // So not to set again below
272                        }
273                        else
274                                pState->ChangeRemoteDir(pData->m_remoteDir);
275                }
276                if (!pData->m_localDir.empty()) {
277                        bool set = pState->SetLocalDir(pData->m_localDir);
278
279                        if (set && pData->m_sync) {
280                                wxASSERT(!pData->m_remoteDir.empty());
281                                pState->SetSyncBrowse(true, pData->m_remoteDir);
282                        }
283                }
284
285                return;
286        }
287
288        std::map<int, wxString>::const_iterator iter2 = m_bookmark_menu_id_map_global.find(event.GetId());
289        if (iter2 != m_bookmark_menu_id_map_global.end()) {
290                // We hit a global bookmark
291                wxString local_dir;
292                CServerPath remote_dir;
293                bool sync;
294                bool comparison;
295                if (!CBookmarksDialog::GetBookmark(iter2->second, local_dir, remote_dir, sync, comparison))
296                        return;
297
298                pState->SetSyncBrowse(false);
299                if (!remote_dir.empty() && pState->IsRemoteIdle(true)) {
300                        const CServer* pServer = pState->GetServer();
301                        if (pServer) {
302                                CServerPath current_remote_path = pState->GetRemotePath();
303                                if (!current_remote_path.empty() && current_remote_path.GetType() != remote_dir.GetType()) {
304                                        wxMessageBoxEx(_("Selected global bookmark and current server use a different server type.\nUse site-specific bookmarks for this server."), _("Bookmark"), wxICON_EXCLAMATION, this);
305                                        return;
306                                }
307                                pState->ChangeRemoteDir(remote_dir);
308                        }
309                }
310                if (!local_dir.empty()) {
311                        bool set = pState->SetLocalDir(local_dir);
312
313                        if (set && sync) {
314                                wxASSERT(!remote_dir.empty());
315                                pState->SetSyncBrowse(true, remote_dir);
316                        }
317                }
318
319                if (comparison) {
320                        pState->GetComparisonManager()->CompareListings();
321                }
322
323                return;
324        }
325
326        event.Skip();
327}
328
329void CMenuBar::OnStateChange(CState* pState, enum t_statechange_notifications notification, const wxString&, const void*)
330{
331        switch (notification)
332        {
333        case STATECHANGE_CHANGEDCONTEXT:
334                UpdateMenubarState();
335                UpdateBookmarkMenu();
336                break;
337        case STATECHANGE_SERVER:
338        case STATECHANGE_REMOTE_IDLE:
339                UpdateMenubarState();
340                break;
341        case STATECHANGE_QUEUEPROCESSING:
342                {
343                        const bool check = m_pMainFrame->GetQueue() && m_pMainFrame->GetQueue()->IsActive() != 0;
344                        Check(XRCID("ID_MENU_TRANSFER_PROCESSQUEUE"), check);
345                }
346                break;
347        case STATECHANGE_SYNC_BROWSE:
348                {
349                        bool is_sync_browse = pState && pState->GetSyncBrowse();
350                        Check(XRCID("ID_TOOLBAR_SYNCHRONIZED_BROWSING"), is_sync_browse);
351                }
352                break;
353        case STATECHANGE_COMPARISON:
354                {
355                        bool is_comparing = pState && pState->GetComparisonManager()->IsComparing();
356                        Check(XRCID("ID_TOOLBAR_COMPARISON"), is_comparing);
357                }
358                break;
359        default:
360                break;
361        }
362}
363
364void CMenuBar::OnOptionsChanged(changed_options_t const& options)
365{
366        if (options.test(OPTION_ASCIIBINARY)) {
367                switch (COptions::Get()->GetOptionVal(OPTION_ASCIIBINARY))
368                {
369                default:
370                        Check(XRCID("ID_MENU_TRANSFER_TYPE_AUTO"), true);
371                        break;
372                case 1:
373                        Check(XRCID("ID_MENU_TRANSFER_TYPE_ASCII"), true);
374                        break;
375                case 2:
376                        Check(XRCID("ID_MENU_TRANSFER_TYPE_BINARY"), true);
377                        break;
378                }
379        }
380        if (options.test(OPTION_PRESERVE_TIMESTAMPS)) {
381                Check(XRCID("ID_MENU_TRANSFER_PRESERVETIMES"), COptions::Get()->GetOptionVal(OPTION_PRESERVE_TIMESTAMPS) != 0);
382        }
383        if (options.test(OPTION_SHOW_TREE_LOCAL)) {
384                Check(XRCID("ID_VIEW_LOCALTREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_LOCAL) != 0);
385        }
386        if (options.test(OPTION_SHOW_TREE_REMOTE)) {
387                Check(XRCID("ID_VIEW_REMOTETREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_REMOTE) != 0);
388        }
389        if (options.test(OPTION_SHOW_QUICKCONNECT)) {
390                Check(XRCID("ID_VIEW_QUICKCONNECT"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUICKCONNECT) != 0);
391        }
392        if (options.test(OPTION_TOOLBAR_HIDDEN)) {
393                Check(XRCID("ID_VIEW_TOOLBAR"), COptions::Get()->GetOptionVal(OPTION_TOOLBAR_HIDDEN) == 0);
394        }
395        if (options.test(OPTION_SHOW_MESSAGELOG)) {
396                Check(XRCID("ID_VIEW_MESSAGELOG"), COptions::Get()->GetOptionVal(OPTION_SHOW_MESSAGELOG) != 0);
397        }
398        if (options.test(OPTION_SHOW_QUEUE)) {
399                Check(XRCID("ID_VIEW_QUEUE"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUEUE) != 0);
400        }
401        if (options.test(OPTION_COMPARE_HIDEIDENTICAL)) {
402                Check(XRCID("ID_COMPARE_HIDEIDENTICAL"), COptions::Get()->GetOptionVal(OPTION_COMPARE_HIDEIDENTICAL) != 0);
403        }
404        if (options.test(OPTION_COMPARISONMODE)) {
405                if (COptions::Get()->GetOptionVal(OPTION_COMPARISONMODE) != 1)
406                        Check(XRCID("ID_COMPARE_SIZE"), true);
407                else
408                        Check(XRCID("ID_COMPARE_DATE"), true);
409        }
410        if (options.test(OPTION_MESSAGELOG_POSITION)) {
411                if (COptions::Get()->GetOptionVal(OPTION_MESSAGELOG_POSITION) == 2)
412                        HideItem(XRCID("ID_VIEW_MESSAGELOG"));
413                else {
414                        ShowItem(XRCID("ID_VIEW_MESSAGELOG"));
415                        Check(XRCID("ID_VIEW_MESSAGELOG"), COptions::Get()->GetOptionVal(OPTION_SHOW_MESSAGELOG) != 0);
416                }
417        }
418        if (options.test(OPTION_SPEEDLIMIT_ENABLE) || options.test(OPTION_SPEEDLIMIT_INBOUND) || options.test(OPTION_SPEEDLIMIT_OUTBOUND)) {
419                UpdateSpeedLimitMenuItem();
420        }
421}
422
423void CMenuBar::UpdateSpeedLimitMenuItem()
424{
425        bool enable = COptions::Get()->GetOptionVal(OPTION_SPEEDLIMIT_ENABLE) != 0;
426
427        int downloadLimit = COptions::Get()->GetOptionVal(OPTION_SPEEDLIMIT_INBOUND);
428        int uploadLimit = COptions::Get()->GetOptionVal(OPTION_SPEEDLIMIT_OUTBOUND);
429
430        if (!downloadLimit && !uploadLimit)
431                enable = false;
432
433        Check(XRCID("ID_MENU_TRANSFER_SPEEDLIMITS_ENABLE"), enable);
434}
435
436void CMenuBar::UpdateMenubarState()
437{
438        CState* pState = CContextManager::Get()->GetCurrentContext();
439        if (!pState)
440                return;
441
442        const CServer* const pServer = pState->GetServer();
443        const bool idle = pState->IsRemoteIdle();
444
445        Enable(XRCID("ID_MENU_SERVER_DISCONNECT"), pServer && idle);
446        Enable(XRCID("ID_CANCEL"), pServer && !idle);
447        Enable(XRCID("ID_MENU_SERVER_CMD"), pServer && idle);
448        Enable(XRCID("ID_MENU_FILE_COPYSITEMANAGER"), pServer != 0);
449        Enable(XRCID("ID_TOOLBAR_SYNCHRONIZED_BROWSING"), pServer != 0);
450        Enable(XRCID("ID_MENU_SERVER_SEARCH"), pServer && idle);
451
452        Check(XRCID("ID_TOOLBAR_COMPARISON"), pState->GetComparisonManager()->IsComparing());
453        Check(XRCID("ID_TOOLBAR_SYNCHRONIZED_BROWSING"), pState->GetSyncBrowse());
454
455        bool canReconnect;
456        if (pServer || !idle)
457                canReconnect = false;
458        else {
459                CServer tmp;
460                canReconnect = !pState->GetLastServer().GetHost().empty();
461        }
462        Enable(XRCID("ID_MENU_SERVER_RECONNECT"), canReconnect);
463
464        wxMenuItem* pItem = FindItem(XRCID("ID_MENU_TRANSFER_TYPE"));
465        if (!pServer || CServer::ProtocolHasDataTypeConcept(pServer->GetProtocol())) {
466                pItem->Enable(true);
467        }
468        else
469                pItem->Enable(false);
470}
471
472bool CMenuBar::ShowItem(int id)
473{
474        for (auto menu_iter = m_hidden_items.begin(); menu_iter != m_hidden_items.end(); ++menu_iter)
475        {
476                int offset = 0;
477
478                for (auto iter = menu_iter->second.begin(); iter != menu_iter->second.end(); ++iter)
479                {
480                        if (iter->second->GetId() != id)
481                        {
482                                offset++;
483                                continue;
484                        }
485
486                        menu_iter->first->Insert(iter->first - offset, iter->second);
487                        menu_iter->second.erase(iter);
488                        if (menu_iter->second.empty())
489                                m_hidden_items.erase(menu_iter);
490
491                        return true;
492                }
493        }
494        return false;
495}
496
497bool CMenuBar::HideItem(int id)
498{
499        wxMenu* pMenu = 0;
500        wxMenuItem* pItem = FindItem(id, &pMenu);
501        if (!pItem || !pMenu)
502                return false;
503
504        size_t pos;
505        pItem = pMenu->FindChildItem(id, &pos);
506        if (!pItem)
507                return false;
508
509        pMenu->Remove(pItem);
510
511        auto menu_iter = m_hidden_items.insert(std::make_pair(pMenu, std::map<int, wxMenuItem*>())).first;
512
513        for (auto iter = menu_iter->second.begin(); iter != menu_iter->second.end(); ++iter)
514        {
515                if (iter->first > (int)pos)
516                        break;
517
518                pos++;
519        }
520
521        menu_iter->second[(int)pos] = pItem;
522
523        return true;
524}
Note: See TracBrowser for help on using the repository browser.