diff options
Diffstat (limited to 'RealtimeSync/trayMenu.cpp')
-rw-r--r-- | RealtimeSync/trayMenu.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/RealtimeSync/trayMenu.cpp b/RealtimeSync/trayMenu.cpp new file mode 100644 index 00000000..5d9d2430 --- /dev/null +++ b/RealtimeSync/trayMenu.cpp @@ -0,0 +1,209 @@ +#include "trayMenu.h" +#include <wx/msgdlg.h> +#include <wx/taskbar.h> +#include <wx/app.h> +#include "resources.h" +#include <memory> +#include <wx/utils.h> +#include <wx/menu.h> +#include "watcher.h" +#include <wx/timer.h> +#include <wx/utils.h> +#include <wx/log.h> + +class RtsTrayIcon; + + +class WaitCallbackImpl : public RealtimeSync::WaitCallback +{ +public: + WaitCallbackImpl(); + + virtual void requestUiRefresh(); + + void requestAbort() + { + m_abortRequested = true; + } + + void requestResume() + { + m_resumeRequested = true; + } + +private: + std::auto_ptr<RtsTrayIcon> trayMenu; + bool m_abortRequested; + bool m_resumeRequested; +}; + + +class RtsTrayIcon : public wxTaskBarIcon +{ +public: + RtsTrayIcon(WaitCallbackImpl* callback) : + m_callback(callback) + { + wxTaskBarIcon::SetIcon(*GlobalResources::getInstance().programIcon, wxT("RealtimeSync")); + + //register double-click + Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(RtsTrayIcon::resumeToMain), NULL, this); + } + + void updateSysTray() + { + wxTheApp->Yield(); + } + +private: + enum Selection + { + CONTEXT_ABORT, + CONTEXT_RESTORE, + CONTEXT_ABOUT + }; + + virtual wxMenu* CreatePopupMenu() + { + wxMenu* contextMenu = new wxMenu; + contextMenu->Append(CONTEXT_RESTORE, _("&Restore")); + contextMenu->Append(CONTEXT_ABOUT, _("&About...")); + contextMenu->AppendSeparator(); + contextMenu->Append(CONTEXT_ABORT, _("&Exit")); + //event handling + contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(RtsTrayIcon::OnContextMenuSelection), NULL, this); + + return contextMenu; //ownership transferred to library + } + + void OnContextMenuSelection(wxCommandEvent& event) + { + const int eventId = event.GetId(); + switch (static_cast<Selection>(eventId)) + { + case CONTEXT_ABORT: + m_callback->requestAbort(); + break; + case CONTEXT_ABOUT: + { + //build information + wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__; +#if wxUSE_UNICODE + build += wxT(" - Unicode)"); +#else + build += wxT(" - ANSI)"); +#endif //wxUSE_UNICODE + + wxMessageDialog* aboutDlg = new wxMessageDialog(NULL, wxString(wxT("RealtimeSync")) + wxT("\n\n") + build, _("About"), wxOK); + aboutDlg->ShowModal(); + aboutDlg->Destroy(); + } + break; + case CONTEXT_RESTORE: + m_callback->requestResume(); + break; + } + } + + void resumeToMain(wxCommandEvent& event) + { + m_callback->requestResume(); + } + + WaitCallbackImpl* m_callback; +}; + + +bool updateUiIsAllowed() +{ + static wxLongLong lastExec = 0; + const wxLongLong newExec = wxGetLocalTimeMillis(); + + if (newExec - lastExec >= RealtimeSync::UI_UPDATE_INTERVAL) //perform ui updates not more often than necessary + { + lastExec = newExec; + return true; + } + return false; +} + + +class AbortThisProcess //exception class +{ +public: + AbortThisProcess(bool backToMain) : m_backToMain(backToMain) {} + + bool backToMainMenu() const + { + return m_backToMain; + } + +private: + bool m_backToMain; +}; + + + +WaitCallbackImpl::WaitCallbackImpl() : + m_abortRequested(false), + m_resumeRequested(false) +{ + trayMenu.reset(new RtsTrayIcon(this)); +} + + +void WaitCallbackImpl::requestUiRefresh() +{ + if (updateUiIsAllowed()) + trayMenu->updateSysTray(); + + if (m_abortRequested) + throw ::AbortThisProcess(false); + + if (m_resumeRequested) + throw ::AbortThisProcess(true); +} + + +RealtimeSync::MonitorResponse RealtimeSync::startDirectoryMonitor(const xmlAccess::XmlRealConfig& config) +{ + try + { + WaitCallbackImpl callback; + + if (config.commandline.empty()) + throw FreeFileSync::FileError(_("Commandline is empty!")); + + long lastExec = 0; + while (true) + { + wxExecute(config.commandline, wxEXEC_SYNC); //execute command + wxLog::FlushActive(); //show wxWidgets error messages (if any) + + //wait + waitForChanges(config.directories, &callback); + lastExec = wxGetLocalTime(); + + //some delay + while (wxGetLocalTime() - lastExec < static_cast<long>(config.delay)) + { + callback.requestUiRefresh(); + wxMilliSleep(RealtimeSync::UI_UPDATE_INTERVAL); + } + } + } + catch (const ::AbortThisProcess& ab) + { + if (ab.backToMainMenu()) + return RESUME; + else + return QUIT; + } + catch (const FreeFileSync::FileError& error) + { + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); + return RESUME; + } + + return RESUME; +} |