Merge pull request #1634 from pypeclub/feature/tray_doubleclick

This commit is contained in:
Milan Kolar 2021-06-03 16:29:47 +02:00 committed by GitHub
commit f0a01aac73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 7 deletions

View file

@ -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.
@ -701,7 +705,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 = {}
@ -709,6 +713,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()

View file

@ -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

View file

@ -48,6 +48,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)
@ -185,6 +197,8 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
:type parent: QtWidgets.QMainWindow
"""
doubleclick_time_ms = 100
def __init__(self, parent):
icon = QtGui.QIcon(resources.pype_icon_filepath())
@ -203,20 +217,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.