#include #include "context_control.h" #include "bookmarks_dialog.h" #include "listingcomparison.h" #include "Mainfrm.h" #include "menu_bar.h" #include "Options.h" #include "QueueView.h" #include "sitemanager.h" #include "state.h" IMPLEMENT_DYNAMIC_CLASS(CMenuBar, wxMenuBar) BEGIN_EVENT_TABLE(CMenuBar, wxMenuBar) EVT_MENU(wxID_ANY, CMenuBar::OnMenuEvent) END_EVENT_TABLE() CMenuBar::CMenuBar() : CStateEventHandler(0) , m_pMainFrame() { } CMenuBar::~CMenuBar() { for (auto hidden_menu : m_hidden_items) { for (auto hidden_item : hidden_menu.second) { delete hidden_item.second; } } m_pMainFrame->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CMenuBar::OnMenuEvent), 0, this); } CMenuBar* CMenuBar::Load(CMainFrame* pMainFrame) { CMenuBar* menubar = wxDynamicCast(wxXmlResource::Get()->LoadMenuBar(_T("ID_MENUBAR")), CMenuBar); if (!menubar) return 0; menubar->m_pMainFrame = pMainFrame; #if FZ_MANUALUPDATECHECK if (COptions::Get()->GetOptionVal(OPTION_DEFAULT_DISABLEUPDATECHECK)) #endif { wxMenu *helpMenu; wxMenuItem* pUpdateItem = menubar->FindItem(XRCID("ID_CHECKFORUPDATES"), &helpMenu); if (pUpdateItem) { // Get rid of separator unsigned int count = helpMenu->GetMenuItemCount(); for (unsigned int i = 0; i < count - 1; i++) { if (helpMenu->FindItemByPosition(i) == pUpdateItem) { helpMenu->Delete(helpMenu->FindItemByPosition(i + 1)); break; } } helpMenu->Delete(pUpdateItem); } } if (COptions::Get()->GetOptionVal(OPTION_DEBUG_MENU)) { wxMenu* pMenu = wxXmlResource::Get()->LoadMenu(_T("ID_MENU_DEBUG")); if (pMenu) menubar->Append(pMenu, _("&Debug")); } menubar->UpdateBookmarkMenu(); menubar->Check(XRCID("ID_MENU_SERVER_VIEWHIDDEN"), COptions::Get()->GetOptionVal(OPTION_VIEW_HIDDEN_FILES) ? true : false); int mode = COptions::Get()->GetOptionVal(OPTION_COMPARISONMODE); if (mode != 1) menubar->Check(XRCID("ID_COMPARE_SIZE"), true); else menubar->Check(XRCID("ID_COMPARE_DATE"), true); menubar->Check(XRCID("ID_COMPARE_HIDEIDENTICAL"), COptions::Get()->GetOptionVal(OPTION_COMPARE_HIDEIDENTICAL) != 0); menubar->Check(XRCID("ID_VIEW_QUICKCONNECT"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUICKCONNECT) != 0); menubar->Check(XRCID("ID_VIEW_TOOLBAR"), COptions::Get()->GetOptionVal(OPTION_TOOLBAR_HIDDEN) == 0); menubar->Check(XRCID("ID_VIEW_MESSAGELOG"), COptions::Get()->GetOptionVal(OPTION_SHOW_MESSAGELOG) != 0); menubar->Check(XRCID("ID_VIEW_QUEUE"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUEUE) != 0); menubar->Check(XRCID("ID_VIEW_LOCALTREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_LOCAL) != 0); menubar->Check(XRCID("ID_VIEW_REMOTETREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_REMOTE) != 0); menubar->Check(XRCID("ID_MENU_VIEW_FILELISTSTATUSBAR"), COptions::Get()->GetOptionVal(OPTION_FILELIST_STATUSBAR) != 0); menubar->Check(XRCID("ID_MENU_TRANSFER_PRESERVETIMES"), COptions::Get()->GetOptionVal(OPTION_PRESERVE_TIMESTAMPS) != 0); switch (COptions::Get()->GetOptionVal(OPTION_ASCIIBINARY)) { case 1: menubar->Check(XRCID("ID_MENU_TRANSFER_TYPE_ASCII"), true); break; case 2: menubar->Check(XRCID("ID_MENU_TRANSFER_TYPE_BINARY"), true); break; default: menubar->Check(XRCID("ID_MENU_TRANSFER_TYPE_AUTO"), true); break; } menubar->UpdateSpeedLimitMenuItem(); if (COptions::Get()->GetOptionVal(OPTION_MESSAGELOG_POSITION) == 2) menubar->HideItem(XRCID("ID_VIEW_MESSAGELOG")); menubar->UpdateMenubarState(); pMainFrame->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CMenuBar::OnMenuEvent), 0, menubar); CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_REMOTE_IDLE, true); CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_SERVER, true); CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_SYNC_BROWSE, true); CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_COMPARISON, true); CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_QUEUEPROCESSING, false); CContextManager::Get()->RegisterHandler(menubar, STATECHANGE_CHANGEDCONTEXT, false); menubar->RegisterOption(OPTION_ASCIIBINARY); menubar->RegisterOption(OPTION_PRESERVE_TIMESTAMPS); menubar->RegisterOption(OPTION_TOOLBAR_HIDDEN); menubar->RegisterOption(OPTION_SHOW_MESSAGELOG); menubar->RegisterOption(OPTION_SHOW_QUEUE); menubar->RegisterOption(OPTION_SHOW_TREE_LOCAL); menubar->RegisterOption(OPTION_SHOW_TREE_REMOTE); menubar->RegisterOption(OPTION_MESSAGELOG_POSITION); menubar->RegisterOption(OPTION_COMPARISONMODE); menubar->RegisterOption(OPTION_COMPARE_HIDEIDENTICAL); menubar->RegisterOption(OPTION_SPEEDLIMIT_ENABLE); menubar->RegisterOption(OPTION_SPEEDLIMIT_INBOUND); menubar->RegisterOption(OPTION_SPEEDLIMIT_OUTBOUND); return menubar; } void CMenuBar::UpdateBookmarkMenu() { wxMenu* pMenu; if (!FindItem(XRCID("ID_BOOKMARK_ADD"), &pMenu)) return; // Delete old bookmarks for (std::map::const_iterator iter = m_bookmark_menu_id_map_global.begin(); iter != m_bookmark_menu_id_map_global.end(); ++iter) { pMenu->Delete(iter->first); } m_bookmark_menu_id_map_global.clear(); for (std::map::const_iterator iter = m_bookmark_menu_id_map_site.begin(); iter != m_bookmark_menu_id_map_site.end(); ++iter) { pMenu->Delete(iter->first); } m_bookmark_menu_id_map_site.clear(); // Delete the separators while (pMenu->GetMenuItemCount() > 2) { wxMenuItem* pSeparator = pMenu->FindItemByPosition(2); if (pSeparator) pMenu->Delete(pSeparator); } auto ids = m_bookmark_menu_ids.begin(); // Insert global bookmarks std::list global_bookmarks; if (CBookmarksDialog::GetBookmarks(global_bookmarks) && !global_bookmarks.empty()) { pMenu->AppendSeparator(); for (std::list::const_iterator iter = global_bookmarks.begin(); iter != global_bookmarks.end(); ++iter) { int id; if (ids == m_bookmark_menu_ids.end()) { id = wxNewId(); m_bookmark_menu_ids.push_back(id); } else { id = *ids; ++ids; } wxString name(*iter); name.Replace(_T("&"), _T("&&")); pMenu->Append(id, name); m_bookmark_menu_id_map_global[id] = *iter; } } // Insert site-specific bookmarks CContextControl* pContextControl = m_pMainFrame ? m_pMainFrame->GetContextControl() : 0; CContextControl::_context_controls* controls = pContextControl ? pContextControl->GetCurrentControls() : 0; if (!controls) return; if (!controls->site_bookmarks || controls->site_bookmarks->bookmarks.empty()) return; pMenu->AppendSeparator(); for (std::list::const_iterator iter = controls->site_bookmarks->bookmarks.begin(); iter != controls->site_bookmarks->bookmarks.end(); ++iter) { int id; if (ids == m_bookmark_menu_ids.end()) { id = wxNewId(); m_bookmark_menu_ids.push_back(id); } else { id = *ids; ++ids; } wxString name(*iter); name.Replace(_T("&"), _T("&&")); pMenu->Append(id, name); m_bookmark_menu_id_map_site[id] = *iter; } } void CMenuBar::ClearBookmarks() { CContextControl* pContextControl = m_pMainFrame ? m_pMainFrame->GetContextControl() : 0; CContextControl::_context_controls* controls = pContextControl ? pContextControl->GetCurrentControls() : 0; if (controls && !controls->site_bookmarks) controls->site_bookmarks = std::make_shared(); UpdateBookmarkMenu(); } void CMenuBar::OnMenuEvent(wxCommandEvent& event) { CState* pState = CContextManager::Get()->GetCurrentContext(); if (!pState) return; std::map::const_iterator iter = m_bookmark_menu_id_map_site.find(event.GetId()); if (iter != m_bookmark_menu_id_map_site.end()) { // We hit a site-specific bookmark CContextControl* pContextControl = m_pMainFrame ? m_pMainFrame->GetContextControl() : 0; CContextControl::_context_controls* controls = pContextControl ? pContextControl->GetCurrentControls() : 0; if (!controls) return; if (controls->site_bookmarks->path.empty()) return; wxString name = iter->second; name.Replace(_T("\\"), _T("\\\\")); name.Replace(_T("/"), _T("\\/")); name = controls->site_bookmarks->path + _T("/") + name; std::unique_ptr pData = CSiteManager::GetSiteByPath(name); if (!pData) return; pState->SetSyncBrowse(false); if (!pData->m_remoteDir.empty() && pState->IsRemoteIdle(true)) { const CServer* pServer = pState->GetServer(); if (!pServer || *pServer != pData->m_server) { m_pMainFrame->ConnectToSite(*pData); pData->m_localDir.clear(); // So not to set again below } else pState->ChangeRemoteDir(pData->m_remoteDir); } if (!pData->m_localDir.empty()) { bool set = pState->SetLocalDir(pData->m_localDir); if (set && pData->m_sync) { wxASSERT(!pData->m_remoteDir.empty()); pState->SetSyncBrowse(true, pData->m_remoteDir); } } return; } std::map::const_iterator iter2 = m_bookmark_menu_id_map_global.find(event.GetId()); if (iter2 != m_bookmark_menu_id_map_global.end()) { // We hit a global bookmark wxString local_dir; CServerPath remote_dir; bool sync; bool comparison; if (!CBookmarksDialog::GetBookmark(iter2->second, local_dir, remote_dir, sync, comparison)) return; pState->SetSyncBrowse(false); if (!remote_dir.empty() && pState->IsRemoteIdle(true)) { const CServer* pServer = pState->GetServer(); if (pServer) { CServerPath current_remote_path = pState->GetRemotePath(); if (!current_remote_path.empty() && current_remote_path.GetType() != remote_dir.GetType()) { wxMessageBoxEx(_("Selected global bookmark and current server use a different server type.\nUse site-specific bookmarks for this server."), _("Bookmark"), wxICON_EXCLAMATION, this); return; } pState->ChangeRemoteDir(remote_dir); } } if (!local_dir.empty()) { bool set = pState->SetLocalDir(local_dir); if (set && sync) { wxASSERT(!remote_dir.empty()); pState->SetSyncBrowse(true, remote_dir); } } if (comparison) { pState->GetComparisonManager()->CompareListings(); } return; } event.Skip(); } void CMenuBar::OnStateChange(CState* pState, enum t_statechange_notifications notification, const wxString&, const void*) { switch (notification) { case STATECHANGE_CHANGEDCONTEXT: UpdateMenubarState(); UpdateBookmarkMenu(); break; case STATECHANGE_SERVER: case STATECHANGE_REMOTE_IDLE: UpdateMenubarState(); break; case STATECHANGE_QUEUEPROCESSING: { const bool check = m_pMainFrame->GetQueue() && m_pMainFrame->GetQueue()->IsActive() != 0; Check(XRCID("ID_MENU_TRANSFER_PROCESSQUEUE"), check); } break; case STATECHANGE_SYNC_BROWSE: { bool is_sync_browse = pState && pState->GetSyncBrowse(); Check(XRCID("ID_TOOLBAR_SYNCHRONIZED_BROWSING"), is_sync_browse); } break; case STATECHANGE_COMPARISON: { bool is_comparing = pState && pState->GetComparisonManager()->IsComparing(); Check(XRCID("ID_TOOLBAR_COMPARISON"), is_comparing); } break; default: break; } } void CMenuBar::OnOptionsChanged(changed_options_t const& options) { if (options.test(OPTION_ASCIIBINARY)) { switch (COptions::Get()->GetOptionVal(OPTION_ASCIIBINARY)) { default: Check(XRCID("ID_MENU_TRANSFER_TYPE_AUTO"), true); break; case 1: Check(XRCID("ID_MENU_TRANSFER_TYPE_ASCII"), true); break; case 2: Check(XRCID("ID_MENU_TRANSFER_TYPE_BINARY"), true); break; } } if (options.test(OPTION_PRESERVE_TIMESTAMPS)) { Check(XRCID("ID_MENU_TRANSFER_PRESERVETIMES"), COptions::Get()->GetOptionVal(OPTION_PRESERVE_TIMESTAMPS) != 0); } if (options.test(OPTION_SHOW_TREE_LOCAL)) { Check(XRCID("ID_VIEW_LOCALTREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_LOCAL) != 0); } if (options.test(OPTION_SHOW_TREE_REMOTE)) { Check(XRCID("ID_VIEW_REMOTETREE"), COptions::Get()->GetOptionVal(OPTION_SHOW_TREE_REMOTE) != 0); } if (options.test(OPTION_SHOW_QUICKCONNECT)) { Check(XRCID("ID_VIEW_QUICKCONNECT"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUICKCONNECT) != 0); } if (options.test(OPTION_TOOLBAR_HIDDEN)) { Check(XRCID("ID_VIEW_TOOLBAR"), COptions::Get()->GetOptionVal(OPTION_TOOLBAR_HIDDEN) == 0); } if (options.test(OPTION_SHOW_MESSAGELOG)) { Check(XRCID("ID_VIEW_MESSAGELOG"), COptions::Get()->GetOptionVal(OPTION_SHOW_MESSAGELOG) != 0); } if (options.test(OPTION_SHOW_QUEUE)) { Check(XRCID("ID_VIEW_QUEUE"), COptions::Get()->GetOptionVal(OPTION_SHOW_QUEUE) != 0); } if (options.test(OPTION_COMPARE_HIDEIDENTICAL)) { Check(XRCID("ID_COMPARE_HIDEIDENTICAL"), COptions::Get()->GetOptionVal(OPTION_COMPARE_HIDEIDENTICAL) != 0); } if (options.test(OPTION_COMPARISONMODE)) { if (COptions::Get()->GetOptionVal(OPTION_COMPARISONMODE) != 1) Check(XRCID("ID_COMPARE_SIZE"), true); else Check(XRCID("ID_COMPARE_DATE"), true); } if (options.test(OPTION_MESSAGELOG_POSITION)) { if (COptions::Get()->GetOptionVal(OPTION_MESSAGELOG_POSITION) == 2) HideItem(XRCID("ID_VIEW_MESSAGELOG")); else { ShowItem(XRCID("ID_VIEW_MESSAGELOG")); Check(XRCID("ID_VIEW_MESSAGELOG"), COptions::Get()->GetOptionVal(OPTION_SHOW_MESSAGELOG) != 0); } } if (options.test(OPTION_SPEEDLIMIT_ENABLE) || options.test(OPTION_SPEEDLIMIT_INBOUND) || options.test(OPTION_SPEEDLIMIT_OUTBOUND)) { UpdateSpeedLimitMenuItem(); } } void CMenuBar::UpdateSpeedLimitMenuItem() { bool enable = COptions::Get()->GetOptionVal(OPTION_SPEEDLIMIT_ENABLE) != 0; int downloadLimit = COptions::Get()->GetOptionVal(OPTION_SPEEDLIMIT_INBOUND); int uploadLimit = COptions::Get()->GetOptionVal(OPTION_SPEEDLIMIT_OUTBOUND); if (!downloadLimit && !uploadLimit) enable = false; Check(XRCID("ID_MENU_TRANSFER_SPEEDLIMITS_ENABLE"), enable); } void CMenuBar::UpdateMenubarState() { CState* pState = CContextManager::Get()->GetCurrentContext(); if (!pState) return; const CServer* const pServer = pState->GetServer(); const bool idle = pState->IsRemoteIdle(); Enable(XRCID("ID_MENU_SERVER_DISCONNECT"), pServer && idle); Enable(XRCID("ID_CANCEL"), pServer && !idle); Enable(XRCID("ID_MENU_SERVER_CMD"), pServer && idle); Enable(XRCID("ID_MENU_FILE_COPYSITEMANAGER"), pServer != 0); Enable(XRCID("ID_TOOLBAR_SYNCHRONIZED_BROWSING"), pServer != 0); Enable(XRCID("ID_MENU_SERVER_SEARCH"), pServer && idle); Check(XRCID("ID_TOOLBAR_COMPARISON"), pState->GetComparisonManager()->IsComparing()); Check(XRCID("ID_TOOLBAR_SYNCHRONIZED_BROWSING"), pState->GetSyncBrowse()); bool canReconnect; if (pServer || !idle) canReconnect = false; else { CServer tmp; canReconnect = !pState->GetLastServer().GetHost().empty(); } Enable(XRCID("ID_MENU_SERVER_RECONNECT"), canReconnect); wxMenuItem* pItem = FindItem(XRCID("ID_MENU_TRANSFER_TYPE")); if (!pServer || CServer::ProtocolHasDataTypeConcept(pServer->GetProtocol())) { pItem->Enable(true); } else pItem->Enable(false); } bool CMenuBar::ShowItem(int id) { for (auto menu_iter = m_hidden_items.begin(); menu_iter != m_hidden_items.end(); ++menu_iter) { int offset = 0; for (auto iter = menu_iter->second.begin(); iter != menu_iter->second.end(); ++iter) { if (iter->second->GetId() != id) { offset++; continue; } menu_iter->first->Insert(iter->first - offset, iter->second); menu_iter->second.erase(iter); if (menu_iter->second.empty()) m_hidden_items.erase(menu_iter); return true; } } return false; } bool CMenuBar::HideItem(int id) { wxMenu* pMenu = 0; wxMenuItem* pItem = FindItem(id, &pMenu); if (!pItem || !pMenu) return false; size_t pos; pItem = pMenu->FindChildItem(id, &pos); if (!pItem) return false; pMenu->Remove(pItem); auto menu_iter = m_hidden_items.insert(std::make_pair(pMenu, std::map())).first; for (auto iter = menu_iter->second.begin(); iter != menu_iter->second.end(); ++iter) { if (iter->first > (int)pos) break; pos++; } menu_iter->second[(int)pos] = pItem; return true; }