Skip to content

idle_threads

IdleItem

Python object holds information if state of idle changed.

This item is used to be independent from Qt objects.

Source code in client/ayon_timers_manager/idle_threads.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class IdleItem:
    """Python object holds information if state of idle changed.

    This item is used to be independent from Qt objects.
    """
    def __init__(self):
        self.changed = False

    def reset(self):
        self.changed = False

    def set_changed(self, changed=True):
        self.changed = changed

IdleManager

Bases: QThread

Measure user's idle time in seconds. Idle time resets on keyboard/mouse input. Is able to emit signals at specific time idle.

Source code in client/ayon_timers_manager/idle_threads.py
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class IdleManager(QtCore.QThread):
    """ Measure user's idle time in seconds.
    Idle time resets on keyboard/mouse input.
    Is able to emit signals at specific time idle.
    """
    time_signals = {}
    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.idle_item = IdleItem()

        self._is_running = False
        self._mouse_thread = None
        self._keyboard_thread = None

    def add_time_signal(self, emit_time, signal):
        """ If any module want to use IdleManager, need to use add_time_signal

        Args:
            emit_time(int): Time when signal will be emitted.
            signal(QtCore.Signal): Signal that will be emitted
                (without objects).
        """
        if emit_time not in self.time_signals:
            self.time_signals[emit_time] = []
        self.time_signals[emit_time].append(signal)

    @property
    def is_running(self):
        return self._is_running

    def _reset_time(self):
        self.idle_time = 0

    def stop(self):
        self._is_running = False

    def _on_mouse_destroy(self):
        self._mouse_thread = None

    def _on_keyboard_destroy(self):
        self._keyboard_thread = None

    def run(self):
        self.log.info('IdleManager has started')
        self._is_running = True

        thread_mouse = MouseThread(self.idle_item)
        thread_keyboard = KeyboardThread(self.idle_item)

        thread_mouse.destroyed.connect(self._on_mouse_destroy)
        thread_keyboard.destroyed.connect(self._on_keyboard_destroy)

        self._mouse_thread = thread_mouse
        self._keyboard_thread = thread_keyboard

        thread_mouse.start()
        thread_keyboard.start()

        # Main loop here is each second checked if idle item changed state
        while self._is_running:
            if self.idle_item.changed:
                self.idle_item.reset()
                self.signal_reset_timer.emit()
            else:
                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)

        self._post_run()
        self.log.info('IdleManager has stopped')

    def _post_run(self):
        # Stop threads if still exist
        if self._mouse_thread is not None:
            self._mouse_thread.signal_stop.emit()
            self._mouse_thread.terminate()
            self._mouse_thread.wait()

        if self._keyboard_thread is not None:
            self._keyboard_thread.signal_stop.emit()
            self._keyboard_thread.terminate()
            self._keyboard_thread.wait()

add_time_signal(emit_time, signal)

If any module want to use IdleManager, need to use add_time_signal

Parameters:

Name Type Description Default
emit_time int

Time when signal will be emitted.

required
signal Signal

Signal that will be emitted (without objects).

required
Source code in client/ayon_timers_manager/idle_threads.py
43
44
45
46
47
48
49
50
51
52
53
def add_time_signal(self, emit_time, signal):
    """ If any module want to use IdleManager, need to use add_time_signal

    Args:
        emit_time(int): Time when signal will be emitted.
        signal(QtCore.Signal): Signal that will be emitted
            (without objects).
    """
    if emit_time not in self.time_signals:
        self.time_signals[emit_time] = []
    self.time_signals[emit_time].append(signal)

KeyboardThread

Bases: QThread

Listens user's keyboard input

Source code in client/ayon_timers_manager/idle_threads.py
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
class KeyboardThread(QtCore.QThread):
    """Listens user's keyboard input
    """
    signal_stop = QtCore.Signal()

    def __init__(self, idle_item):
        super(KeyboardThread, self).__init__()
        self.signal_stop.connect(self.stop)
        self.k_listener = None
        self.idle_item = idle_item

    def stop(self):
        if self.k_listener is not None:
            listener = self.k_listener
            self.k_listener = None
            listener.stop()

    def on_press(self, *args, **kwargs):
        self.idle_item.set_changed()

    def run(self):
        self.k_listener = keyboard.Listener(on_press=self.on_press)
        self.k_listener.start()

MouseThread

Bases: QThread

Listens user's mouse movement.

Source code in client/ayon_timers_manager/idle_threads.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
class MouseThread(QtCore.QThread):
    """Listens user's mouse movement."""
    signal_stop = QtCore.Signal()

    def __init__(self, idle_item):
        super(MouseThread, self).__init__()
        self.signal_stop.connect(self.stop)
        self.m_listener = None
        self.idle_item = idle_item

    def stop(self):
        if self.m_listener is not None:
            self.m_listener.stop()

    def on_move(self, *args, **kwargs):
        self.idle_item.set_changed()

    def run(self):
        self.m_listener = mouse.Listener(on_move=self.on_move)
        self.m_listener.start()