From 0bf9624c79f37ae9adff72eda3135ded6f419f14 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 3 Jun 2021 14:59:32 +0200 Subject: [PATCH 1/4] modules can add doubleclick callbacks for tray --- openpype/modules/base.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/openpype/modules/base.py b/openpype/modules/base.py index 441a9731b7..21f7a0c76a 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -172,6 +172,10 @@ class ITrayModule: if self._tray_manager: self._tray_manager.show_tray_message(title, message, icon, msecs) + def add_doubleclick_callback(self, callback): + if hasattr(self.manager, "add_doubleclick_callback"): + self.manager.add_doubleclick_callback(self, callback) + class ITrayAction(ITrayModule): """Implementation of Tray action. @@ -184,6 +188,9 @@ class ITrayAction(ITrayModule): necessary. """ + admin_action = False + _admin_submenu = None + @property @abstractmethod def label(self): @@ -677,7 +684,7 @@ class TrayModulesManager(ModulesManager): ) def __init__(self): - self.log = PypeLogger().get_logger(self.__class__.__name__) + self.log = PypeLogger.get_logger(self.__class__.__name__) self.modules = [] self.modules_by_id = {} @@ -685,6 +692,28 @@ class TrayModulesManager(ModulesManager): self._report = {} self.tray_manager = None + self.doubleclick_callbacks = {} + self.doubleclick_callback = None + + def add_doubleclick_callback(self, module, callback): + """Register doubleclick callbacks on tray icon. + + Currently there is no way how to determine which is launched. Name of + callback can be defined with `doubleclick_callback` attribute. + + Missing feature how to define default callback. + """ + callback_name = "_".join([module.name, callback.__name__]) + if callback_name not in self.doubleclick_callbacks: + self.doubleclick_callbacks[callback_name] = callback + if self.doubleclick_callback is None: + self.doubleclick_callback = callback_name + return + + self.log.warning(( + "Callback with name \"{}\" is already registered." + ).format(callback_name)) + def initialize(self, tray_manager, tray_menu): self.tray_manager = tray_manager self.initialize_modules() From bd46be2b0e0aa8f588957c14744fce4f3eecce5d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 3 Jun 2021 14:59:41 +0200 Subject: [PATCH 2/4] launcher add doubleclick callback --- openpype/modules/launcher_action.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/modules/launcher_action.py b/openpype/modules/launcher_action.py index 5ed8585b6a..0059ff021b 100644 --- a/openpype/modules/launcher_action.py +++ b/openpype/modules/launcher_action.py @@ -15,6 +15,8 @@ class LauncherAction(PypeModule, ITrayAction): def tray_init(self): self.create_window() + self.add_doubleclick_callback(self.show_launcher) + def tray_start(self): return From c319365042a66f03fbcf42880aaed60aa838c5f3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 3 Jun 2021 15:00:11 +0200 Subject: [PATCH 3/4] TrayManager have ability to access and trigger doublick callback --- openpype/tools/tray/pype_tray.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openpype/tools/tray/pype_tray.py b/openpype/tools/tray/pype_tray.py index 2c739e3e39..7b1b7ab0b8 100644 --- a/openpype/tools/tray/pype_tray.py +++ b/openpype/tools/tray/pype_tray.py @@ -44,6 +44,18 @@ class TrayManager: self._main_thread_callbacks = collections.deque() self._execution_in_progress = None + @property + def doubleclick_callback(self): + """Doubleclick callback for Tray icon.""" + callback_name = self.modules_manager.doubleclick_callback + return self.modules_manager.doubleclick_callbacks.get(callback_name) + + def execute_doubleclick(self): + """Execute double click callback in main thread.""" + callback = self.doubleclick_callback + if callback: + self.execute_in_main_thread(callback) + def execute_in_main_thread(self, callback): self._main_thread_callbacks.append(callback) From dd0f9f11d9e327c0708103c415077d5b2b964ac5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 3 Jun 2021 15:00:37 +0200 Subject: [PATCH 4/4] TrayIcon can catch doubleclick on windows and linux --- openpype/tools/tray/pype_tray.py | 44 +++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/openpype/tools/tray/pype_tray.py b/openpype/tools/tray/pype_tray.py index 7b1b7ab0b8..b78897a48c 100644 --- a/openpype/tools/tray/pype_tray.py +++ b/openpype/tools/tray/pype_tray.py @@ -190,6 +190,8 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): :type parent: QtWidgets.QMainWindow """ + doubleclick_time_ms = 100 + def __init__(self, parent): icon = QtGui.QIcon(resources.pype_icon_filepath()) @@ -208,20 +210,50 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): self.tray_man = TrayManager(self, self.parent) self.tray_man.initialize_modules() - # Catch activate event for left click if not on MacOS - # - MacOS has this ability by design so menu would be doubled - if platform.system().lower() != "darwin": - self.activated.connect(self.on_systray_activated) # Add menu to Context of SystemTrayIcon self.setContextMenu(self.menu) atexit.register(self.exit) + # Catch activate event for left click if not on MacOS + # - MacOS has this ability by design and is harder to modify this + # behavior + if platform.system().lower() == "darwin": + return + + self.activated.connect(self.on_systray_activated) + + click_timer = QtCore.QTimer() + click_timer.setInterval(self.doubleclick_time_ms) + click_timer.timeout.connect(self._click_timer_timeout) + + self._click_timer = click_timer + self._doubleclick = False + + def _click_timer_timeout(self): + self._click_timer.stop() + doubleclick = self._doubleclick + # Reset bool value + self._doubleclick = False + if doubleclick: + self.tray_man.execute_doubleclick() + else: + self._show_context_menu() + + def _show_context_menu(self): + pos = QtGui.QCursor().pos() + self.contextMenu().popup(pos) + def on_systray_activated(self, reason): # show contextMenu if left click if reason == QtWidgets.QSystemTrayIcon.Trigger: - position = QtGui.QCursor().pos() - self.contextMenu().popup(position) + if self.tray_man.doubleclick_callback: + self._click_timer.start() + else: + self._show_context_menu() + + elif reason == QtWidgets.QSystemTrayIcon.DoubleClick: + self._doubleclick = True def exit(self): """ Exit whole application.