summaryrefslogtreecommitdiff
path: root/RealtimeSync/tray_menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'RealtimeSync/tray_menu.cpp')
-rw-r--r--RealtimeSync/tray_menu.cpp342
1 files changed, 0 insertions, 342 deletions
diff --git a/RealtimeSync/tray_menu.cpp b/RealtimeSync/tray_menu.cpp
deleted file mode 100644
index 6e67b5ec..00000000
--- a/RealtimeSync/tray_menu.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#include "tray_menu.h"
-#include <zen/thread.h>
-#include <zen/tick_count.h>
-#include <wx/taskbar.h>
-#include <wx/icon.h> //Linux needs this
-#include <wx/app.h>
-#include <wx/menu.h>
-#include <wx/timer.h>
-#include <wx+/image_tools.h>
-#include <zen/shell_execute.h>
-#include <wx+/popup_dlg.h>
-#include <wx+/image_resources.h>
-#include "monitor.h"
-#include "../lib/resolve_path.h"
-
-using namespace rts;
-using namespace zen;
-
-
-namespace
-{
-const std::int64_t TICKS_UPDATE_INTERVAL = rts::UI_UPDATE_INTERVAL* ticksPerSec() / 1000;
-TickVal lastExec = getTicks();
-
-bool updateUiIsAllowed()
-{
- const TickVal now = getTicks(); //0 on error
- if (dist(lastExec, now) >= TICKS_UPDATE_INTERVAL) //perform ui updates not more often than necessary
- {
- lastExec = now;
- return true;
- }
- return false;
-}
-
-
-enum TrayMode
-{
- TRAY_MODE_ACTIVE,
- TRAY_MODE_WAITING,
- TRAY_MODE_ERROR,
-};
-
-
-class TrayIconObject : public wxTaskBarIcon
-{
-public:
- TrayIconObject(const wxString& jobname) :
- resumeRequested(false),
- abortRequested(false),
- showErrorMsgRequested(false),
- mode(TRAY_MODE_ACTIVE),
- iconFlashStatusLast(false),
- jobName_(jobname),
-#if defined ZEN_WIN || defined ZEN_MAC //16x16 seems to be the only size that is shown correctly on OS X
- trayBmp(getResourceImage(L"RTS_tray_16x16")) //use a 16x16 bitmap
-#elif defined ZEN_LINUX
- trayBmp(getResourceImage(L"RTS_tray_24x24")) //use a 24x24 bitmap for perfect fit
-#endif
- {
- Connect(wxEVT_TASKBAR_LEFT_DCLICK, wxEventHandler(TrayIconObject::OnDoubleClick), nullptr, this);
- setMode(mode);
- }
-
- //require polling:
- bool resumeIsRequested() const { return resumeRequested; }
- bool abortIsRequested () const { return abortRequested; }
-
- //during TRAY_MODE_ERROR those two functions are available:
- void clearShowErrorRequested() { assert(mode == TRAY_MODE_ERROR); showErrorMsgRequested = false; }
- bool getShowErrorRequested() const { assert(mode == TRAY_MODE_ERROR); return showErrorMsgRequested; }
-
- void setMode(TrayMode m)
- {
- mode = m;
- timer.Stop();
- timer.Disconnect(wxEVT_TIMER, wxEventHandler(TrayIconObject::OnErrorFlashIcon), nullptr, this);
- switch (m)
- {
- case TRAY_MODE_ACTIVE:
- setTrayIcon(trayBmp, _("Directory monitoring active"));
- break;
-
- case TRAY_MODE_WAITING:
- setTrayIcon(greyScale(trayBmp), _("Waiting until all directories are available..."));
- break;
-
- case TRAY_MODE_ERROR:
- timer.Connect(wxEVT_TIMER, wxEventHandler(TrayIconObject::OnErrorFlashIcon), nullptr, this);
- timer.Start(500); //timer interval in [ms]
- break;
- }
- }
-
-private:
- void OnErrorFlashIcon(wxEvent& event)
- {
- iconFlashStatusLast = !iconFlashStatusLast;
- setTrayIcon(iconFlashStatusLast ? trayBmp : greyScale(trayBmp), _("Error"));
- }
-
- void setTrayIcon(const wxBitmap& bmp, const wxString& statusTxt)
- {
- wxIcon realtimeIcon;
- realtimeIcon.CopyFromBitmap(bmp);
- wxString tooltip = L"RealtimeSync\n" + statusTxt;
- if (!jobName_.empty())
- tooltip += L"\n\"" + jobName_ + L"\"";
- SetIcon(realtimeIcon, tooltip);
- }
-
- enum Selection
- {
- CONTEXT_RESTORE = 1, //wxWidgets: "A MenuItem ID of zero does not work under Mac"
- CONTEXT_SHOW_ERROR,
- CONTEXT_ABORT = wxID_EXIT
- };
-
- virtual wxMenu* CreatePopupMenu()
- {
- wxMenu* contextMenu = new wxMenu;
-
- wxMenuItem* defaultItem = nullptr;
- switch (mode)
- {
- case TRAY_MODE_ACTIVE:
- case TRAY_MODE_WAITING:
- defaultItem = new wxMenuItem(contextMenu, CONTEXT_RESTORE, _("&Restore"));
- break;
- case TRAY_MODE_ERROR:
- defaultItem = new wxMenuItem(contextMenu, CONTEXT_SHOW_ERROR, _("&Show error"));
- break;
- }
-#ifdef ZEN_WIN //no wxMenuItem::SetFont() on Linux and OS X: wasn't wxWidgets supposed to be *portable* at some point in time?????
- defaultItem->SetFont(wxNORMAL_FONT->Bold());
-#endif
- contextMenu->Append(defaultItem);
-
- contextMenu->AppendSeparator();
- contextMenu->Append(CONTEXT_ABORT, _("&Exit"));
- //event handling
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(TrayIconObject::OnContextMenuSelection), nullptr, this);
-
- return contextMenu; //ownership transferred to caller
- }
-
- void OnContextMenuSelection(wxCommandEvent& event)
- {
- switch (static_cast<Selection>(event.GetId()))
- {
- case CONTEXT_ABORT:
- abortRequested = true;
- break;
-
- case CONTEXT_RESTORE:
- resumeRequested = true;
- break;
-
- case CONTEXT_SHOW_ERROR:
- showErrorMsgRequested = true;
- break;
- }
- }
-
- void OnDoubleClick(wxEvent& event)
- {
- switch (mode)
- {
- case TRAY_MODE_ACTIVE:
- case TRAY_MODE_WAITING:
- resumeRequested = true; //never throw exceptions through a C-Layer call stack (GUI)!
- break;
- case TRAY_MODE_ERROR:
- showErrorMsgRequested = true;
- break;
- }
- }
-
- bool resumeRequested;
- bool abortRequested;
- bool showErrorMsgRequested;
-
- TrayMode mode;
-
- bool iconFlashStatusLast; //flash try icon for TRAY_MODE_ERROR
- wxTimer timer; //
-
- const wxString jobName_; //RTS job name, may be empty
- const wxBitmap trayBmp;
-};
-
-
-struct AbortMonitoring //exception class
-{
- AbortMonitoring(AbortReason reasonCode) : reasonCode_(reasonCode) {}
- AbortReason reasonCode_;
-};
-
-
-//=> don't derive from wxEvtHandler or any other wxWidgets object unless instance is safely deleted (deferred) during idle event!!tray_icon.h
-class TrayIconHolder
-{
-public:
- TrayIconHolder(const wxString& jobname) :
- trayObj(new TrayIconObject(jobname)) {}
-
- ~TrayIconHolder()
- {
- //harmonize with tray_icon.cpp!!!
- trayObj->RemoveIcon();
- //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking)
- wxPendingDelete.Append(trayObj);
- }
-
- void doUiRefreshNow() //throw AbortMonitoring
- {
- wxTheApp->Yield(); //yield is UI-layer which is represented by this tray icon
-
- //advantage of polling vs callbacks: we can throw exceptions!
- if (trayObj->resumeIsRequested())
- throw AbortMonitoring(SHOW_GUI);
-
- if (trayObj->abortIsRequested())
- throw AbortMonitoring(EXIT_APP);
- }
-
- void setMode(TrayMode m) { trayObj->setMode(m); }
-
- bool getShowErrorRequested() const { return trayObj->getShowErrorRequested(); }
- void clearShowErrorRequested() { trayObj->clearShowErrorRequested(); }
-
-private:
- TrayIconObject* trayObj;
-};
-
-//##############################################################################################################
-}
-
-
-rts::AbortReason rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& config, const wxString& jobname)
-{
- std::vector<Zstring> dirNamesNonFmt = config.directories;
- vector_remove_if(dirNamesNonFmt, [](Zstring str) -> bool { trim(str); return str.empty(); }); //remove empty entries WITHOUT formatting paths yet!
-
- if (dirNamesNonFmt.empty())
- {
- showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setMainInstructions(_("A folder input field is empty.")));
- return SHOW_GUI;
- }
-
- Zstring cmdLine = config.commandline;
- trim(cmdLine);
-
- if (cmdLine.empty())
- {
- showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setMainInstructions(_("Incorrect command line:") + L" \"\""));
- return SHOW_GUI;
- }
-
- struct MonitorCallbackImpl : public MonitorCallback
- {
- MonitorCallbackImpl(const wxString& jobname,
- const Zstring& cmdLine) : trayIcon(jobname), cmdLine_(cmdLine) {}
-
- virtual void setPhase(WatchPhase mode)
- {
- switch (mode)
- {
- case MONITOR_PHASE_ACTIVE:
- trayIcon.setMode(TRAY_MODE_ACTIVE);
- break;
- case MONITOR_PHASE_WAITING:
- trayIcon.setMode(TRAY_MODE_WAITING);
- break;
- }
- }
-
- virtual void executeExternalCommand()
- {
- auto cmdLineExp = expandMacros(cmdLine_);
- try
- {
- shellExecute2(cmdLineExp, EXEC_TYPE_SYNC); //throw FileError
- }
- catch (const FileError& e)
- {
- warn_static("fix dialog hiding on OSX !!")
- showNotificationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString()));
- }
- }
-
- virtual void requestUiRefresh()
- {
- if (updateUiIsAllowed())
- trayIcon.doUiRefreshNow(); //throw AbortMonitoring
- }
-
- virtual void reportError(const std::wstring& msg)
- {
- trayIcon.setMode(TRAY_MODE_ERROR);
- trayIcon.clearShowErrorRequested();
-
- //wait for some time, then return to retry
- assert_static(15 * 1000 % UI_UPDATE_INTERVAL == 0);
- for (int i = 0; i < 15 * 1000 / UI_UPDATE_INTERVAL; ++i)
- {
- trayIcon.doUiRefreshNow(); //throw AbortMonitoring
-
- if (trayIcon.getShowErrorRequested())
- switch (showConfirmationDialog(nullptr, DialogInfoType::ERROR2, PopupDialogCfg().
- setDetailInstructions(msg), _("&Retry")))
- {
- case ConfirmationButton::DO_IT: //retry
- return;
- case ConfirmationButton::CANCEL:
- throw AbortMonitoring(SHOW_GUI);
- }
- boost::this_thread::sleep(boost::posix_time::milliseconds(UI_UPDATE_INTERVAL));
- }
- }
-
- TrayIconHolder trayIcon;
- const Zstring cmdLine_;
- } cb(jobname, cmdLine);
-
- try
- {
- monitorDirectories(dirNamesNonFmt, config.delay, cb); //cb: throw AbortMonitoring
- assert(false);
- return SHOW_GUI;
- }
- catch (const AbortMonitoring& ab)
- {
- return ab.reasonCode_;
- }
-}
bgstack15