From de4cb207ebaee18167c05fa78cfccb0c9c44af1b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:18:14 +0100 Subject: [PATCH] added timers manager that cares about all timers --- pype/services/timers_manager/__init__.py | 6 + .../services/timers_manager/timers_manager.py | 135 +++++++++++++++ .../timers_manager/widget_user_idle.py | 155 ++++++++++++++++++ 3 files changed, 296 insertions(+) create mode 100644 pype/services/timers_manager/__init__.py create mode 100644 pype/services/timers_manager/timers_manager.py create mode 100644 pype/services/timers_manager/widget_user_idle.py diff --git a/pype/services/timers_manager/__init__.py b/pype/services/timers_manager/__init__.py new file mode 100644 index 0000000000..a6c4535f3d --- /dev/null +++ b/pype/services/timers_manager/__init__.py @@ -0,0 +1,6 @@ +from .timers_manager import TimersManager +from .widget_user_idle import WidgetUserIdle + + +def tray_init(tray_widget, main_widget): + return TimersManager(tray_widget, main_widget) diff --git a/pype/services/timers_manager/timers_manager.py b/pype/services/timers_manager/timers_manager.py new file mode 100644 index 0000000000..e6c1c4f18a --- /dev/null +++ b/pype/services/timers_manager/timers_manager.py @@ -0,0 +1,135 @@ +from Qt import QtCore +from .widget_user_idle import WidgetUserIdle +from pypeapp.lib.config import get_presets + + +class Singleton(type): + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super( + Singleton, cls + ).__call__(*args, **kwargs) + return cls._instances[cls] + + +class TimersManager(metaclass=Singleton): + modules = [] + is_running = False + last_task = None + + def __init__(self, tray_widget, main_widget): + self.tray_widget = tray_widget + self.main_widget = main_widget + self.widget_user_idle = WidgetUserIdle(self) + self.set_signal_times() + + def set_signal_times(self): + timer_info = get_presets()['services']['timers_manager']['timer'] + full_time = int(timer_info['full_time'])*60 + message_time = int(timer_info['message_time'])*60 + self.time_show_message = full_time - message_time + self.time_stop_timer = full_time + + def add_module(self, module): + self.modules.append(module) + + def start_timers(self, data): + ''' + Dictionary "data" should contain: + - project_name(str) - Name of Project + - hierarchy(list/tuple) - list of parents(except project) + - task_type(str) + - task_name(str) + + Example: + - to run timers for task in + 'C001_BackToPast/assets/characters/villian/Lookdev BG' + - input data should contain: + data = { + 'project_name': 'C001_BackToPast', + 'hierarchy': ['assets', 'characters', 'villian'], + 'task_type': 'lookdev', + 'task_name': 'Lookdev BG' + } + ''' + self.last_task = data + for module in self.modules: + module.start_timer_manager(data) + self.is_running = True + + def restart_timers(self): + if self.last_task is not None: + self.start_timers(self.last_task) + + def stop_timers(self): + if self.is_running is False: + return + self.widget_user_idle.bool_not_stopped = False + self.widget_user_idle.refresh_context() + for module in self.modules: + module.stop_timer_manager() + self.is_running = False + + def process_modules(self, modules): + self.s_handler = SignalHandler(self) + + if 'IdleManager' in modules: + self.idle_man = modules['IdleManager'] + # Times when idle is between show widget and stop timers + for num in range(self.time_show_message-1, self.time_stop_timer): + self.idle_man.add_time_signal( + num, + self.s_handler.signal_change_label + ) + # Times when widget is already shown and user restart idle + for num in range(self.time_stop_timer - self.time_show_message): + self.idle_man.add_time_signal( + num, + self.s_handler.signal_change_label + ) + # 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.time_stop_timer, self.s_handler.signal_stop_timers + ) + + 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'): + return + + if self.idle_man.idle_time > self.time_show_message: + value = self.time_stop_timer - self.idle_man.idle_time + else: + value = 1 + ( + self.time_stop_timer - + self.time_show_message - + self.idle_man.idle_time + ) + self.widget_user_idle.change_count_widget(value) + + def show_message(self): + if self.is_running is False: + 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/services/timers_manager/widget_user_idle.py b/pype/services/timers_manager/widget_user_idle.py new file mode 100644 index 0000000000..b65ffd40ba --- /dev/null +++ b/pype/services/timers_manager/widget_user_idle.py @@ -0,0 +1,155 @@ +from pypeapp import style, Logger +from Qt import QtCore, QtGui, QtWidgets + + +class WidgetUserIdle(QtWidgets.QWidget): + + SIZE_W = 300 + SIZE_H = 160 + + def __init__(self, parent): + + 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.setWindowFlags( + QtCore.Qt.WindowCloseButtonHint | + QtCore.Qt.WindowMinimizeButtonHint + ) + + self._translate = QtCore.QCoreApplication.translate + + self.font = QtGui.QFont() + self.font.setFamily("DejaVu Sans Condensed") + self.font.setPointSize(9) + self.font.setBold(True) + self.font.setWeight(50) + self.font.setKerning(True) + + self.resize(self.SIZE_W, self.SIZE_H) + self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H)) + self.setMaximumSize(QtCore.QSize(self.SIZE_W+100, self.SIZE_H+100)) + self.setStyleSheet(style.load_stylesheet()) + + self.setLayout(self._main()) + self.refresh_context() + self.setWindowTitle('Pype - Stop timers') + + def _main(self): + self.main = QtWidgets.QVBoxLayout() + self.main.setObjectName('main') + + self.form = QtWidgets.QFormLayout() + self.form.setContentsMargins(10, 15, 10, 5) + self.form.setObjectName('form') + + msg_info = 'You didn\'t work for a long time.' + msg_question = 'Would you like to stop Timers?' + msg_stopped = ( + 'Your Timers were stopped. Do you want to start them again?' + ) + + self.lbl_info = QtWidgets.QLabel(msg_info) + self.lbl_info.setFont(self.font) + self.lbl_info.setTextFormat(QtCore.Qt.RichText) + self.lbl_info.setObjectName("lbl_info") + self.lbl_info.setWordWrap(True) + + self.lbl_question = QtWidgets.QLabel(msg_question) + self.lbl_question.setFont(self.font) + self.lbl_question.setTextFormat(QtCore.Qt.RichText) + self.lbl_question.setObjectName("lbl_question") + self.lbl_question.setWordWrap(True) + + self.lbl_stopped = QtWidgets.QLabel(msg_stopped) + self.lbl_stopped.setFont(self.font) + self.lbl_stopped.setTextFormat(QtCore.Qt.RichText) + self.lbl_stopped.setObjectName("lbl_stopped") + self.lbl_stopped.setWordWrap(True) + + self.lbl_rest_time = QtWidgets.QLabel("") + self.lbl_rest_time.setFont(self.font) + self.lbl_rest_time.setTextFormat(QtCore.Qt.RichText) + self.lbl_rest_time.setObjectName("lbl_rest_time") + self.lbl_rest_time.setWordWrap(True) + self.lbl_rest_time.setAlignment(QtCore.Qt.AlignCenter) + + self.form.addRow(self.lbl_info) + self.form.addRow(self.lbl_question) + self.form.addRow(self.lbl_stopped) + self.form.addRow(self.lbl_rest_time) + + self.group_btn = QtWidgets.QHBoxLayout() + self.group_btn.addStretch(1) + self.group_btn.setObjectName("group_btn") + + self.btn_stop = QtWidgets.QPushButton("Stop timer") + self.btn_stop.setToolTip('Stop\'s All timers') + self.btn_stop.clicked.connect(self.stop_timer) + + self.btn_continue = QtWidgets.QPushButton("Continue") + self.btn_continue.setToolTip('Timer won\'t stop') + self.btn_continue.clicked.connect(self.continue_timer) + + self.btn_close = QtWidgets.QPushButton("Close") + self.btn_close.setToolTip('Close window') + self.btn_close.clicked.connect(self.close_widget) + + self.btn_restart = QtWidgets.QPushButton("Start timers") + self.btn_restart.setToolTip('Timer will be started again') + self.btn_restart.clicked.connect(self.restart_timer) + + self.group_btn.addWidget(self.btn_continue) + self.group_btn.addWidget(self.btn_stop) + self.group_btn.addWidget(self.btn_restart) + self.group_btn.addWidget(self.btn_close) + + self.main.addLayout(self.form) + self.main.addLayout(self.group_btn) + + return self.main + + def refresh_context(self): + self.lbl_question.setVisible(self.bool_not_stopped) + self.lbl_rest_time.setVisible(self.bool_not_stopped) + self.lbl_stopped.setVisible(not self.bool_not_stopped) + + self.btn_continue.setVisible(self.bool_not_stopped) + self.btn_stop.setVisible(self.bool_not_stopped) + self.btn_restart.setVisible(not self.bool_not_stopped) + self.btn_close.setVisible(not self.bool_not_stopped) + + def change_count_widget(self, time): + str_time = str(time) + self.lbl_rest_time.setText(str_time) + + def stop_timer(self): + self.parent_widget.stop_timers() + self.close_widget() + + def restart_timer(self): + self.parent_widget.restart_timers() + self.close_widget() + + def continue_timer(self): + self.close_widget() + + def closeEvent(self, event): + event.ignore() + if self.bool_not_stopped is True: + self.continue_timer() + else: + self.close_widget() + + def close_widget(self): + self.bool_is_showed = False + self.bool_not_stopped = True + self.refresh_context() + self.hide() + + def showEvent(self, event): + self.bool_is_showed = True