From e7f284050b8b8b1297c9b0acf23f1dbd3cacd164 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:41:09 +0200 Subject: [PATCH 1/8] IdleManager is not QThread but threading.Thread --- pype/modules/idle_manager/idle_manager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/modules/idle_manager/idle_manager.py b/pype/modules/idle_manager/idle_manager.py index cfcdfef78f..80776a0541 100644 --- a/pype/modules/idle_manager/idle_manager.py +++ b/pype/modules/idle_manager/idle_manager.py @@ -1,11 +1,12 @@ import time import collections from Qt import QtCore +import threading from pynput import mouse, keyboard from pype.api import Logger -class IdleManager(QtCore.QThread): +class IdleManager(threading.Thread): """ Measure user's idle time in seconds. Idle time resets on keyboard/mouse input. Is able to emit signals at specific time idle. From b28c7f36fb03011a757f06aac91c44d92d9011c9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:42:23 +0200 Subject: [PATCH 2/8] there are not registered Qt signals ut callbacks --- pype/modules/idle_manager/idle_manager.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pype/modules/idle_manager/idle_manager.py b/pype/modules/idle_manager/idle_manager.py index 80776a0541..66f63fbace 100644 --- a/pype/modules/idle_manager/idle_manager.py +++ b/pype/modules/idle_manager/idle_manager.py @@ -11,14 +11,13 @@ class IdleManager(threading.Thread): Idle time resets on keyboard/mouse input. Is able to emit signals at specific time idle. """ - time_signals = collections.defaultdict(list) + time_callbacks = collections.defaultdict(list) idle_time = 0 signal_reset_timer = QtCore.Signal() def __init__(self): super(IdleManager, self).__init__() self.log = Logger().get_logger(self.__class__.__name__) - self.signal_reset_timer.connect(self._reset_time) self.qaction = None self.failed_icon = None self._is_running = False @@ -33,18 +32,18 @@ class IdleManager(threading.Thread): def tray_exit(self): self.stop() try: - self.time_signals = {} + self.time_callbacks = {} except Exception: pass - def add_time_signal(self, emit_time, signal): - """ If any module want to use IdleManager, need to use add_time_signal - :param emit_time: time when signal will be emitted - :type emit_time: int - :param signal: signal that will be emitted (without objects) - :type signal: QtCore.Signal + def add_time_callback(self, emit_time, callback): + """If any module want to use IdleManager, need to use this method. + + Args: + emit_time(int): Time when callback will be triggered. + callback(func): Callback that will be triggered. """ - self.time_signals[emit_time].append(signal) + self.time_callbacks[emit_time].append(callback) @property def is_running(self): From 3660ca7c10071d1244f6e41ff0d303ba4a2fb195 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:43:48 +0200 Subject: [PATCH 3/8] mouse and keyboard threads are not QThreads --- pype/modules/idle_manager/idle_manager.py | 63 +++++++---------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/pype/modules/idle_manager/idle_manager.py b/pype/modules/idle_manager/idle_manager.py index 66f63fbace..f952434546 100644 --- a/pype/modules/idle_manager/idle_manager.py +++ b/pype/modules/idle_manager/idle_manager.py @@ -58,9 +58,9 @@ class IdleManager(threading.Thread): def run(self): self.log.info('IdleManager has started') self._is_running = True - thread_mouse = MouseThread(self.signal_reset_timer) + thread_mouse = MouseThread(self._reset_time) thread_mouse.start() - thread_keyboard = KeyboardThread(self.signal_reset_timer) + thread_keyboard = KeyboardThread(self._reset_time) thread_keyboard.start() try: while self.is_running: @@ -79,16 +79,14 @@ class IdleManager(threading.Thread): # Threads don't have their attrs when Qt application already finished try: - thread_mouse.signal_stop.emit() - thread_mouse.terminate() - thread_mouse.wait() + thread_mouse.stop() + thread_mouse.join() except AttributeError: pass try: - thread_keyboard.signal_stop.emit() - thread_keyboard.terminate() - thread_keyboard.wait() + thread_keyboard.stop() + thread_keyboard.join() except AttributeError: pass @@ -96,49 +94,24 @@ class IdleManager(threading.Thread): self.log.info('IdleManager has stopped') -class MouseThread(QtCore.QThread): - """Listens user's mouse movement - """ - signal_stop = QtCore.Signal() +class MouseThread(mouse.Listener): + """Listens user's mouse movement.""" - def __init__(self, signal): - super(MouseThread, self).__init__() - self.signal_stop.connect(self.stop) - self.m_listener = None - - self.signal_reset_timer = signal - - def stop(self): - if self.m_listener is not None: - self.m_listener.stop() + def __init__(self, callback): + super(MouseThread, self).__init__(on_move=self.on_move) + self.callback = callback def on_move(self, posx, posy): - self.signal_reset_timer.emit() - - def run(self): - self.m_listener = mouse.Listener(on_move=self.on_move) - self.m_listener.start() + self.callback() -class KeyboardThread(QtCore.QThread): - """Listens user's keyboard input - """ - signal_stop = QtCore.Signal() +class KeyboardThread(keyboard.Listener): + """Listens user's keyboard input.""" - def __init__(self, signal): - super(KeyboardThread, self).__init__() - self.signal_stop.connect(self.stop) - self.k_listener = None + def __init__(self, callback): + super(KeyboardThread, self).__init__(on_press=self.on_press) - self.signal_reset_timer = signal - - def stop(self): - if self.k_listener is not None: - self.k_listener.stop() + self.callback = callback def on_press(self, key): - self.signal_reset_timer.emit() - - def run(self): - self.k_listener = keyboard.Listener(on_press=self.on_press) - self.k_listener.start() + self.callback() From b15af67bdb96d6bc5bf14828f42503e1a5fe2c90 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:44:49 +0200 Subject: [PATCH 4/8] removed rest of Qt from idle manager --- pype/modules/idle_manager/idle_manager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pype/modules/idle_manager/idle_manager.py b/pype/modules/idle_manager/idle_manager.py index f952434546..15618d6076 100644 --- a/pype/modules/idle_manager/idle_manager.py +++ b/pype/modules/idle_manager/idle_manager.py @@ -1,6 +1,5 @@ import time import collections -from Qt import QtCore import threading from pynput import mouse, keyboard from pype.api import Logger @@ -13,7 +12,6 @@ class IdleManager(threading.Thread): """ time_callbacks = collections.defaultdict(list) idle_time = 0 - signal_reset_timer = QtCore.Signal() def __init__(self): super(IdleManager, self).__init__() From adb9749d63ef5c208e2f57aecd0022359b47d6ac Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:45:09 +0200 Subject: [PATCH 5/8] callback are executed in threads which are joined when done --- pype/modules/idle_manager/idle_manager.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pype/modules/idle_manager/idle_manager.py b/pype/modules/idle_manager/idle_manager.py index 15618d6076..3a9f9154a9 100644 --- a/pype/modules/idle_manager/idle_manager.py +++ b/pype/modules/idle_manager/idle_manager.py @@ -19,6 +19,7 @@ class IdleManager(threading.Thread): self.qaction = None self.failed_icon = None self._is_running = False + self.threads = [] def set_qaction(self, qaction, failed_icon): self.qaction = qaction @@ -62,11 +63,20 @@ class IdleManager(threading.Thread): thread_keyboard.start() try: while self.is_running: + if self.idle_time in self.time_callbacks: + for callback in self.time_callbacks[self.idle_time]: + thread = threading.Thread(target=callback) + thread.start() + self.threads.append(thread) + + for thread in tuple(self.threads): + if not thread.isAlive(): + thread.join() + self.threads.remove(thread) + self.idle_time += 1 - if self.idle_time in self.time_signals: - for signal in self.time_signals[self.idle_time]: - signal.emit() time.sleep(1) + except Exception: self.log.warning( 'Idle Manager service has failed', exc_info=True From 66190c01854d1b5cdce204b7b6e1dc7c8210f8bd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:45:52 +0200 Subject: [PATCH 6/8] SignalHandler moved from timers_manager to widget part --- pype/modules/timers_manager/timers_manager.py | 14 +------------- pype/modules/timers_manager/widget_user_idle.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pype/modules/timers_manager/timers_manager.py b/pype/modules/timers_manager/timers_manager.py index cec730d007..55bec8d963 100644 --- a/pype/modules/timers_manager/timers_manager.py +++ b/pype/modules/timers_manager/timers_manager.py @@ -1,5 +1,4 @@ -from Qt import QtCore -from .widget_user_idle import WidgetUserIdle +from .widget_user_idle import WidgetUserIdle, SignalHandler from pype.api import Logger, config @@ -174,14 +173,3 @@ class TimersManager(metaclass=Singleton): return if self.widget_user_idle.bool_is_showed is False: self.widget_user_idle.show() - - -class SignalHandler(QtCore.QObject): - signal_show_message = QtCore.Signal() - signal_change_label = QtCore.Signal() - signal_stop_timers = QtCore.Signal() - def __init__(self, cls): - super().__init__() - self.signal_show_message.connect(cls.show_message) - self.signal_change_label.connect(cls.change_label) - self.signal_stop_timers.connect(cls.stop_timers) diff --git a/pype/modules/timers_manager/widget_user_idle.py b/pype/modules/timers_manager/widget_user_idle.py index 697c0a04d9..f6f3c49357 100644 --- a/pype/modules/timers_manager/widget_user_idle.py +++ b/pype/modules/timers_manager/widget_user_idle.py @@ -154,3 +154,15 @@ class WidgetUserIdle(QtWidgets.QWidget): def showEvent(self, event): self.bool_is_showed = True + + +class SignalHandler(QtCore.QObject): + signal_show_message = QtCore.Signal() + signal_change_label = QtCore.Signal() + signal_stop_timers = QtCore.Signal() + + def __init__(self, cls): + super().__init__() + self.signal_show_message.connect(cls.show_message) + self.signal_change_label.connect(cls.change_label) + self.signal_stop_timers.connect(cls.stop_timers) From 14d8d3c6a88951957eaa29a39e3989533177d087 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:46:26 +0200 Subject: [PATCH 7/8] simplified user widget in timers manager --- pype/modules/timers_manager/widget_user_idle.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pype/modules/timers_manager/widget_user_idle.py b/pype/modules/timers_manager/widget_user_idle.py index f6f3c49357..22455846fd 100644 --- a/pype/modules/timers_manager/widget_user_idle.py +++ b/pype/modules/timers_manager/widget_user_idle.py @@ -1,4 +1,3 @@ -from pype.api import Logger from avalon import style from Qt import QtCore, QtGui, QtWidgets @@ -8,18 +7,18 @@ class WidgetUserIdle(QtWidgets.QWidget): SIZE_W = 300 SIZE_H = 160 - def __init__(self, parent): + def __init__(self, module, tray_widget): super(WidgetUserIdle, self).__init__() self.bool_is_showed = False self.bool_not_stopped = True - self.parent_widget = parent - self.setWindowIcon(parent.tray_widget.icon) + self.module = module + self.setWindowIcon(tray_widget.icon) self.setWindowFlags( - QtCore.Qt.WindowCloseButtonHint | - QtCore.Qt.WindowMinimizeButtonHint + QtCore.Qt.WindowCloseButtonHint + | QtCore.Qt.WindowMinimizeButtonHint ) self._translate = QtCore.QCoreApplication.translate @@ -129,11 +128,11 @@ class WidgetUserIdle(QtWidgets.QWidget): self.lbl_rest_time.setText(str_time) def stop_timer(self): - self.parent_widget.stop_timers() + self.module.stop_timers() self.close_widget() def restart_timer(self): - self.parent_widget.restart_timers() + self.module.restart_timers() self.close_widget() def continue_timer(self): From 31a0bfef1805f89add37c015f9a99791fd19384e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 1 Jul 2020 17:46:57 +0200 Subject: [PATCH 8/8] timers manager does not register signals but callbacks in idle manager --- pype/modules/timers_manager/timers_manager.py | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/pype/modules/timers_manager/timers_manager.py b/pype/modules/timers_manager/timers_manager.py index 55bec8d963..8df7952baf 100644 --- a/pype/modules/timers_manager/timers_manager.py +++ b/pype/modules/timers_manager/timers_manager.py @@ -30,7 +30,10 @@ class TimersManager(metaclass=Singleton): self.log = Logger().get_logger(self.__class__.__name__) self.tray_widget = tray_widget self.main_widget = main_widget - self.widget_user_idle = WidgetUserIdle(self) + + self.idle_man = None + self.signal_handler = None + self.widget_user_idle = WidgetUserIdle(self, tray_widget) def set_signal_times(self): try: @@ -113,49 +116,59 @@ class TimersManager(metaclass=Singleton): :param modules: All imported modules from TrayManager :type modules: dict """ - self.s_handler = SignalHandler(self) if 'IdleManager' in modules: + self.signal_handler = SignalHandler(self) if self.set_signal_times() is True: self.register_to_idle_manager(modules['IdleManager']) + def time_callback(self, int_def): + if not self.signal_handler: + return + + if int_def == 0: + self.signal_handler.signal_show_message.emit() + elif int_def == 1: + self.signal_handler.signal_change_label.emit() + elif int_def == 2: + self.signal_handler.signal_stop_timers.emit() + def register_to_idle_manager(self, man_obj): self.idle_man = man_obj + + # Time when message is shown + self.idle_man.add_time_callback( + self.time_show_message, + lambda: self.time_callback(0) + ) + # Times when idle is between show widget and stop timers show_to_stop_range = range( - self.time_show_message-1, self.time_stop_timer + self.time_show_message - 1, self.time_stop_timer ) for num in show_to_stop_range: - self.idle_man.add_time_signal( - num, - self.s_handler.signal_change_label + self.idle_man.add_time_callback( + num, lambda: self.time_callback(1) ) # Times when widget is already shown and user restart idle shown_and_moved_range = range( self.time_stop_timer - self.time_show_message ) for num in shown_and_moved_range: - self.idle_man.add_time_signal( - num, - self.s_handler.signal_change_label + self.idle_man.add_time_callback( + num, lambda: self.time_callback(1) ) - # Time when message is shown - self.idle_man.add_time_signal( - self.time_show_message, - self.s_handler.signal_show_message - ) + # Time when timers are stopped - self.idle_man.add_time_signal( + self.idle_man.add_time_callback( self.time_stop_timer, - self.s_handler.signal_stop_timers + lambda: self.time_callback(2) ) def change_label(self): if self.is_running is False: return - if self.widget_user_idle.bool_is_showed is False: - return - if not hasattr(self, 'idle_man'): + if not self.idle_man or self.widget_user_idle.bool_is_showed is False: return if self.idle_man.idle_time > self.time_show_message: