From 3128a8aad8ac0887112efc9f6ab881d1cff4db1a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 13 Mar 2019 11:14:49 +0100 Subject: [PATCH 01/16] avalon_apps added to pype just to separate them from pype-setup --- pype/avalon_apps/__init__.py | 7 ++++ pype/avalon_apps/avalon_app.py | 69 ++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 pype/avalon_apps/__init__.py create mode 100644 pype/avalon_apps/avalon_app.py diff --git a/pype/avalon_apps/__init__.py b/pype/avalon_apps/__init__.py new file mode 100644 index 0000000000..a578d03ccc --- /dev/null +++ b/pype/avalon_apps/__init__.py @@ -0,0 +1,7 @@ +from .avalon_app import AvalonApps + + +def tray_init(tray_widget, main_widget): + av_apps = AvalonApps(main_widget, tray_widget) + av_apps.tray_menu(tray_widget.menu) + return av_apps diff --git a/pype/avalon_apps/avalon_app.py b/pype/avalon_apps/avalon_app.py new file mode 100644 index 0000000000..303f5c9f03 --- /dev/null +++ b/pype/avalon_apps/avalon_app.py @@ -0,0 +1,69 @@ +import os +import argparse +from Qt import QtGui, QtWidgets +from avalon.tools import libraryloader +from pypeapp.api import Logger +from avalon import io +from launcher import launcher_widget, lib as launcher_lib + + +class AvalonApps: + def __init__(self, main_parent=None, parent=None): + self.log = Logger().get_logger(__name__) + self.main_parent = main_parent + self.parent = parent + self.app_launcher = None + + # Definition of Tray menu + def tray_menu(self, parent_menu=None): + # Actions + if parent_menu is None: + if self.parent is None: + self.log.warning('Parent menu is not set') + return + elif self.parent.hasattr('menu'): + parent_menu = self.parent.menu + else: + self.log.warning('Parent menu is not set') + return + + avalon_launcher_icon = launcher_lib.resource("icon", "main.png") + aShowLauncher = QtWidgets.QAction( + QtGui.QIcon(avalon_launcher_icon), "&Launcher", parent_menu + ) + + aLibraryLoader = QtWidgets.QAction("&Library", parent_menu) + + parent_menu.addAction(aShowLauncher) + parent_menu.addAction(aLibraryLoader) + + aShowLauncher.triggered.connect(self.show_launcher) + aLibraryLoader.triggered.connect(self.show_library_loader) + + return + + def show_launcher(self): + # if app_launcher don't exist create it/otherwise only show main window + if self.app_launcher is None: + parser = argparse.ArgumentParser() + parser.add_argument("--demo", action="store_true") + parser.add_argument( + "--root", default=os.environ["AVALON_PROJECTS"] + ) + kwargs = parser.parse_args() + + root = kwargs.root + root = os.path.realpath(root) + io.install() + APP_PATH = launcher_lib.resource("qml", "main.qml") + self.app_launcher = launcher_widget.Launcher(root, APP_PATH) + + self.app_launcher.window.show() + + def show_library_loader(self): + libraryloader.show( + parent=self.main_parent, + icon=self.parent.icon, + show_projects=True, + show_libraries=True + ) From c01f5946acc7fd8c1369e4992bbd19441dd4c77e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 13 Mar 2019 11:15:03 +0100 Subject: [PATCH 02/16] added tray_init to ftrack module --- pype/ftrack/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pype/ftrack/__init__.py b/pype/ftrack/__init__.py index bf18979e91..dd1be1796f 100644 --- a/pype/ftrack/__init__.py +++ b/pype/ftrack/__init__.py @@ -1,2 +1,9 @@ from .lib import * from .ftrack_server import * +from .ftrack_run import FtrackRunner + + +def tray_init(tray_widget, main_widget): + ftrack = FtrackRunner(main_widget, tray_widget) + main_widget.menu.addMenu(ftrack.trayMenu(tray_widget.menu)) + ftrack.validate() From ed0dc701302e4145bba018a723dd693399f0af3d Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 18 Mar 2019 14:56:55 +0100 Subject: [PATCH 03/16] enhanced tray_init in ftrack and avalon apps --- pype/avalon_apps/__init__.py | 3 ++- pype/avalon_apps/avalon_app.py | 14 ++++---------- pype/ftrack/__init__.py | 6 ++++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pype/avalon_apps/__init__.py b/pype/avalon_apps/__init__.py index a578d03ccc..1d7c3c8a81 100644 --- a/pype/avalon_apps/__init__.py +++ b/pype/avalon_apps/__init__.py @@ -1,7 +1,8 @@ from .avalon_app import AvalonApps -def tray_init(tray_widget, main_widget): +def tray_init(tray_widget, main_widget, parent_menu): av_apps = AvalonApps(main_widget, tray_widget) av_apps.tray_menu(tray_widget.menu) + return av_apps diff --git a/pype/avalon_apps/avalon_app.py b/pype/avalon_apps/avalon_app.py index 303f5c9f03..072d7fbb3f 100644 --- a/pype/avalon_apps/avalon_app.py +++ b/pype/avalon_apps/avalon_app.py @@ -27,20 +27,15 @@ class AvalonApps: self.log.warning('Parent menu is not set') return - avalon_launcher_icon = launcher_lib.resource("icon", "main.png") - aShowLauncher = QtWidgets.QAction( - QtGui.QIcon(avalon_launcher_icon), "&Launcher", parent_menu - ) - + icon = QtGui.QIcon(launcher_lib.resource("icon", "main.png")) + aShowLauncher = QtWidgets.QAction(icon, "&Launcher", parent_menu) aLibraryLoader = QtWidgets.QAction("&Library", parent_menu) - parent_menu.addAction(aShowLauncher) - parent_menu.addAction(aLibraryLoader) - aShowLauncher.triggered.connect(self.show_launcher) aLibraryLoader.triggered.connect(self.show_library_loader) - return + parent_menu.addAction(aShowLauncher) + parent_menu.addAction(aLibraryLoader) def show_launcher(self): # if app_launcher don't exist create it/otherwise only show main window @@ -57,7 +52,6 @@ class AvalonApps: io.install() APP_PATH = launcher_lib.resource("qml", "main.qml") self.app_launcher = launcher_widget.Launcher(root, APP_PATH) - self.app_launcher.window.show() def show_library_loader(self): diff --git a/pype/ftrack/__init__.py b/pype/ftrack/__init__.py index dd1be1796f..cdaacca68c 100644 --- a/pype/ftrack/__init__.py +++ b/pype/ftrack/__init__.py @@ -3,7 +3,9 @@ from .ftrack_server import * from .ftrack_run import FtrackRunner -def tray_init(tray_widget, main_widget): +def tray_init(tray_widget, main_widget, parent_menu): ftrack = FtrackRunner(main_widget, tray_widget) - main_widget.menu.addMenu(ftrack.trayMenu(tray_widget.menu)) + main_widget.menu.addMenu(ftrack.trayMenu(parent_menu)) ftrack.validate() + + return ftrack From d85a3d9f6764849535b612144f1471b9b2460730 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:13:04 +0100 Subject: [PATCH 04/16] added idle manager as service that checks users idle time --- pype/services/__init__.py | 0 pype/services/idle_manager/__init__.py | 7 ++ pype/services/idle_manager/idle_manager.py | 97 ++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 pype/services/__init__.py create mode 100644 pype/services/idle_manager/__init__.py create mode 100644 pype/services/idle_manager/idle_manager.py diff --git a/pype/services/__init__.py b/pype/services/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pype/services/idle_manager/__init__.py b/pype/services/idle_manager/__init__.py new file mode 100644 index 0000000000..7c07d3ebee --- /dev/null +++ b/pype/services/idle_manager/__init__.py @@ -0,0 +1,7 @@ +from .idle_manager import IdleManager + + +def tray_init(tray_widget, main_widget): + manager = IdleManager() + manager.start() + return manager diff --git a/pype/services/idle_manager/idle_manager.py b/pype/services/idle_manager/idle_manager.py new file mode 100644 index 0000000000..cc6e177916 --- /dev/null +++ b/pype/services/idle_manager/idle_manager.py @@ -0,0 +1,97 @@ +import time +from Qt import QtCore, QtGui, QtWidgets +from pype.vendor.pynput import mouse, keyboard +from pypeapp import Logger + + +class IdleManager(QtCore.QThread): + 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._is_running = False + + def add_time_signal(self, emit_time, signal): + 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 run(self): + self.log.info('IdleManager has started') + self._is_running = True + thread_mouse = MouseThread(self.signal_reset_timer) + thread_mouse.start() + thread_keyboard = KeyboardThread(self.signal_reset_timer) + thread_keyboard.start() + while self._is_running: + 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) + + thread_mouse.signal_stop.emit() + thread_mouse.terminate() + thread_mouse.wait() + thread_keyboard.signal_stop.emit() + thread_keyboard.terminate() + thread_keyboard.wait() + self.log.info('IdleManager has stopped') + + +class MouseThread(QtCore.QThread): + signal_stop = QtCore.Signal() + + 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 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() + + +class KeyboardThread(QtCore.QThread): + signal_stop = QtCore.Signal() + + def __init__(self, signal): + super(KeyboardThread, self).__init__() + self.signal_stop.connect(self.stop) + self.k_listener = None + + self.signal_reset_timer = signal + + def stop(self): + if self.k_listener is not None: + self.k_listener.stop() + + 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() From de4cb207ebaee18167c05fa78cfccb0c9c44af1b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:18:14 +0100 Subject: [PATCH 05/16] 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 From b6bcd8d07672600960cd9cbc786ff8bb76abec57 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:21:00 +0100 Subject: [PATCH 06/16] ftrack module tray_menu modified so menu is added to tray context --- pype/ftrack/ftrack_run.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pype/ftrack/ftrack_run.py b/pype/ftrack/ftrack_run.py index a722f8d3fe..9362db297f 100644 --- a/pype/ftrack/ftrack_run.py +++ b/pype/ftrack/ftrack_run.py @@ -123,9 +123,9 @@ class FtrackRunner: log.error("During Killing action server: {0}".format(e)) # Definition of Tray menu - def trayMenu(self, parent): + def tray_menu(self, parent_menu): # Menu for Tray App - self.menu = QtWidgets.QMenu('Ftrack', parent) + self.menu = QtWidgets.QMenu('Ftrack', parent_menu) self.menu.setProperty('submenu', 'on') self.menu.setStyleSheet(style.load_stylesheet()) @@ -162,7 +162,9 @@ class FtrackRunner: self.bool_logged = False self.set_menu_visibility() - return self.menu + parent_menu.addMenu(self.menu) + + self.validate() # Definition of visibility of each menu actions def set_menu_visibility(self): From fc87f65b222bfde41112c7f05e33d8ca0a168ab7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:24:59 +0100 Subject: [PATCH 07/16] removed unused code in ftrack module --- pype/ftrack/ftrack_run.py | 346 -------------------------------------- 1 file changed, 346 deletions(-) diff --git a/pype/ftrack/ftrack_run.py b/pype/ftrack/ftrack_run.py index 9362db297f..5719262ba6 100644 --- a/pype/ftrack/ftrack_run.py +++ b/pype/ftrack/ftrack_run.py @@ -210,76 +210,23 @@ class FtrackRunner: except Exception as e: log.error("During Killing Timer event server: {0}".format(e)) - def start_countdown_thread(self): - if self.thread_timer_coundown is None: - self.thread_timer_coundown = CountdownThread(self) - self.thread_timer_coundown.signal_show_question.connect( - self.show_widget_timer - ) - self.thread_timer_coundown.signal_send_time.connect( - self.change_count_widget - ) - self.thread_timer_coundown.signal_stop_timer.connect( - self.timer_stop - ) - self.thread_timer_coundown.start() - def stop_countdown_thread(self): - if self.thread_timer_coundown is not None: - self.thread_timer_coundown.runs = False - self.thread_timer_coundown.terminate() - self.thread_timer_coundown.wait() - self.thread_timer_coundown = None - - def show_widget_timer(self): - self.widget_timer.show() - self.widget_timer.setWindowState(QtCore.Qt.WindowMinimized) - self.widget_timer.setWindowState(QtCore.Qt.WindowActive) - # self.widget_timer.activateWindow() - - def change_count_widget(self, time): - str_time = str(time).replace(".0", "") - self.widget_timer.lbl_rest_time.setText(str_time) - - def timer_started(self): - self.start_countdown_thread() - - def timer_stopped(self): - self.stop_countdown_thread() - - def timer_stop(self): if self.thread_timer is not None: - self.widget_timer.main_context = False - self.widget_timer.refresh_context() - self.thread_timer.signal_stop_timer.emit() - if self.thread_timer_coundown is not None: - self.stop_countdown_thread() - def timer_restart(self): if self.thread_timer is not None: - self.thread_timer.signal_restart_timer.emit() - self.timer_started() - def timer_continue(self): - if self.thread_timer_coundown is not None: - self.thread_timer_coundown.signal_continue_timer.emit() class FtrackEventsThread(QtCore.QThread): # Senders signal_timer_started = QtCore.Signal() signal_timer_stopped = QtCore.Signal() - # Listeners - signal_stop_timer = QtCore.Signal() - signal_restart_timer = QtCore.Signal() def __init__(self, parent): super(FtrackEventsThread, self).__init__() cred = credentials._get_credentials() self.username = cred['username'] - self.signal_stop_timer.connect(self.ftrack_stop_timer) - self.signal_restart_timer.connect(self.ftrack_restart_timer) self.user = None self.last_task = None @@ -298,7 +245,6 @@ class FtrackEventsThread(QtCore.QThread): timer = self.timer_session.query(timer_query).first() if timer is not None: self.last_task = timer['context'] - self.signal_timer_started.emit() self.timer_session.event_hub.wait() @@ -321,7 +267,6 @@ class FtrackEventsThread(QtCore.QThread): self.last_task = timer['context'] if old is None: - self.signal_timer_started.emit() elif new is None: self.signal_timer_stopped.emit() @@ -332,295 +277,4 @@ class FtrackEventsThread(QtCore.QThread): except Exception as e: log.debug("Timer stop had issues: {}".format(e)) - def ftrack_restart_timer(self): - try: - if (self.last_task is not None) and (self.user is not None): - self.user.start_timer(self.last_task) - self.timer_session.commit() - except Exception as e: - log.debug("Timer stop had issues: {}".format(e)) - - -class CountdownThread(QtCore.QThread): - # Senders - signal_show_question = QtCore.Signal() - signal_send_time = QtCore.Signal(object) - signal_stop_timer = QtCore.Signal() - signal_stop_countdown = QtCore.Signal() - # Listeners - signal_reset_timer = QtCore.Signal() - signal_continue_timer = QtCore.Signal() - - def __init__(self, parent): - super(CountdownThread, self).__init__() - - self.runs = True - self.over_line = False - config_data = self.load_timer_values() - self.count_length = config_data['full_time']*60 - self.border_line = config_data['message_time']*60 + 1 - self.reset_count() - self.signal_reset_timer.connect(self.reset_count) - self.signal_continue_timer.connect(self.continue_timer) - - def continue_timer(self): - self.over_line = False - self.reset_count() - - def reset_count(self): - if self.over_line is True: - self.actual = self.border_line - else: - self.actual = self.count_length - - def stop(self): - self.runs = False - - def run(self): - thread_mouse = MouseThread(self) - thread_mouse.start() - thread_keyboard = KeyboardThread(self) - thread_keyboard.start() - while self.runs: - if self.actual == self.border_line: - self.signal_show_question.emit() - self.over_line = True - - if self.actual <= self.border_line: - self.signal_send_time.emit(self.actual) - - time.sleep(1) - self.actual -= 1 - - if self.actual == 0: - self.runs = False - self.signal_stop_timer.emit() - - thread_mouse.signal_stop.emit() - thread_mouse.terminate() - thread_mouse.wait() - thread_keyboard.signal_stop.emit() - thread_keyboard.terminate() - thread_keyboard.wait() - - def load_timer_values(self): - templates = os.environ['PYPE_STUDIO_TEMPLATES'] - path_items = [templates, 'presets', 'ftrack', 'ftrack_config.json'] - filepath = os.path.sep.join(path_items) - data = dict() - try: - with open(filepath) as data_file: - json_dict = json.load(data_file) - data = json_dict['timer'] - except Exception as e: - msg = ( - 'Loading "Ftrack Config file" Failed.' - ' Please check log for more information.' - ' Times are set to default.' - ) - log.warning("{} - {}".format(msg, str(e))) - - data = self.validate_timer_values(data) - - return data - - def validate_timer_values(self, data): - # default values - if 'full_time' not in data: - data['full_time'] = 15 - if 'message_time' not in data: - data['message_time'] = 0.5 - - # minimum values - if data['full_time'] < 2: - data['full_time'] = 2 - # message time is earlier that full time - if data['message_time'] > data['full_time']: - data['message_time'] = data['full_time'] - 0.5 - return data - - -class MouseThread(QtCore.QThread): - signal_stop = QtCore.Signal() - - def __init__(self, parent): - super(MouseThread, self).__init__() - self.parent = parent - self.signal_stop.connect(self.stop) - self.m_listener = None - - def stop(self): - if self.m_listener is not None: - self.m_listener.stop() - - def on_move(self, posx, posy): - self.parent.signal_reset_timer.emit() - - def run(self): - self.m_listener = mouse.Listener(on_move=self.on_move) - self.m_listener.start() - - -class KeyboardThread(QtCore.QThread): - signal_stop = QtCore.Signal() - - def __init__(self, parent): - super(KeyboardThread, self).__init__() - self.parent = parent - self.signal_stop.connect(self.stop) - self.k_listener = None - - def stop(self): - if self.k_listener is not None: - self.k_listener.stop() - - def on_press(self, key): - self.parent.signal_reset_timer.emit() - - def run(self): - self.k_listener = keyboard.Listener(on_press=self.on_press) - self.k_listener.start() - - -class StopTimer(QtWidgets.QWidget): - - SIZE_W = 300 - SIZE_H = 160 - - def __init__(self, parent=None): - - super(StopTimer, self).__init__() - - self.main_context = True - self.parent = parent - self.setWindowIcon(self.parent.parent.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 Ftrack timer') - - 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 Ftrack timer?' - msg_stopped = ( - 'Your Ftrack timer was stopped. Do you want to start 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 Ftrack timer') - self.btn_stop.clicked.connect(self.stop_timer) - - self.btn_continue = QtWidgets.QPushButton("Continue") - self.btn_continue.setToolTip('Timer will continue') - 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 timer") - 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.main_context) - self.lbl_rest_time.setVisible(self.main_context) - self.lbl_stopped.setVisible(not self.main_context) - - self.btn_continue.setVisible(self.main_context) - self.btn_stop.setVisible(self.main_context) - self.btn_restart.setVisible(not self.main_context) - self.btn_close.setVisible(not self.main_context) - - def stop_timer(self): - self.parent.timer_stop() - self.close_widget() - - def restart_timer(self): - self.parent.timer_restart() - self.close_widget() - - def continue_timer(self): - self.parent.timer_continue() - self.close_widget() - - def closeEvent(self, event): - event.ignore() - if self.main_context is True: - self.continue_timer() - else: - self.close_widget() - - def close_widget(self): - self.main_context = True - self.refresh_context() - self.hide() From c85b9bc3b7d10a08610aa2d11efcae314fa42bfc Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:30:13 +0100 Subject: [PATCH 08/16] ftrack events_thread cares about timer --- pype/ftrack/ftrack_run.py | 47 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/pype/ftrack/ftrack_run.py b/pype/ftrack/ftrack_run.py index 5719262ba6..2bf9da2dbe 100644 --- a/pype/ftrack/ftrack_run.py +++ b/pype/ftrack/ftrack_run.py @@ -220,7 +220,7 @@ class FtrackRunner: class FtrackEventsThread(QtCore.QThread): # Senders - signal_timer_started = QtCore.Signal() + signal_timer_started = QtCore.Signal(object) signal_timer_stopped = QtCore.Signal() def __init__(self, parent): @@ -245,9 +245,30 @@ class FtrackEventsThread(QtCore.QThread): timer = self.timer_session.query(timer_query).first() if timer is not None: self.last_task = timer['context'] + self.signal_timer_started.emit( + self.get_data_from_task(self.last_task) + ) self.timer_session.event_hub.wait() + def get_data_from_task(self, task_entity): + data = {} + data['task_name'] = task_entity['name'] + data['task_type'] = task_entity['type']['name'] + data['project_name'] = task_entity['project']['full_name'] + data['hierarchy'] = self.get_parents(task_entity['parent']) + + return data + + def get_parents(self, entity): + output = [] + if entity.entity_type.lower() == 'project': + return output + output.extend(self.get_parents(entity['parent'])) + output.append(entity['name']) + + return output + def event_handler(self, event): try: if event['data']['entities'][0]['objectTypeId'] != 'timer': @@ -267,6 +288,9 @@ class FtrackEventsThread(QtCore.QThread): self.last_task = timer['context'] if old is None: + self.signal_timer_started.emit( + self.get_data_from_task(self.last_task) + ) elif new is None: self.signal_timer_stopped.emit() @@ -274,7 +298,28 @@ class FtrackEventsThread(QtCore.QThread): try: self.user.stop_timer() self.timer_session.commit() + self.signal_timer_stopped.emit() except Exception as e: log.debug("Timer stop had issues: {}".format(e)) + def ftrack_start_timer(self, input_data): + if self.user is None: + return + if ( + input_data['task_name'] == self.last_task['name'] and + input_data['hierarchy'][-1] == self.last_task['parent']['name'] + ): + return + task_query = ( + 'Task where name is "{task_name}"' + ' and parent.name is "{entity_name}"' + ' and project.full_name is "{project_name}"' + ).format(**input_data) + + task = self.timer_session.query(task_query).one() + self.last_task = task + self.user.start_timer(task) + self.timer_session.commit() + self.signal_timer_started.emit( + self.get_data_from_task(self.last_task) ) From 39a236f5b88ef99987fb871983e48f4f71d0362b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:31:04 +0100 Subject: [PATCH 09/16] ftrack module has stop and start timer methods for timers manager --- pype/ftrack/ftrack_run.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pype/ftrack/ftrack_run.py b/pype/ftrack/ftrack_run.py index 2bf9da2dbe..8f2d450bad 100644 --- a/pype/ftrack/ftrack_run.py +++ b/pype/ftrack/ftrack_run.py @@ -25,13 +25,9 @@ class FtrackRunner: self.parent = parent self.widget_login = login_dialog.Login_Dialog_ui(self) - self.widget_timer = StopTimer(self) self.action_server = FtrackServer('action') self.thread_action_server = None self.thread_timer = None - self.thread_timer_coundown = None - - # self.signal_start_timer.connect(self.timerStart) self.bool_logged = False self.bool_action_server = False @@ -211,11 +207,21 @@ class FtrackRunner: log.error("During Killing Timer event server: {0}".format(e)) + def start_timer_manager(self, data): if self.thread_timer is not None: + self.thread_timer.ftrack_start_timer(data) + def stop_timer_manager(self): if self.thread_timer is not None: + self.thread_timer.ftrack_stop_timer() + def timer_started(self, data): + if hasattr(self, 'timer_manager'): + self.timer_manager.start_timers(data) + def timer_stopped(self): + if hasattr(self, 'timer_manager'): + self.timer_manager.stop_timers() class FtrackEventsThread(QtCore.QThread): From d29752c5aaccd90249490f18d6a7c889e129fca7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:33:07 +0100 Subject: [PATCH 10/16] added process_modules to ftrack module which looks for TimersManager --- pype/ftrack/ftrack_run.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pype/ftrack/ftrack_run.py b/pype/ftrack/ftrack_run.py index 8f2d450bad..d795edb08b 100644 --- a/pype/ftrack/ftrack_run.py +++ b/pype/ftrack/ftrack_run.py @@ -206,6 +206,10 @@ class FtrackRunner: except Exception as e: log.error("During Killing Timer event server: {0}".format(e)) + def process_modules(self, modules): + if 'TimersManager' in modules: + self.timer_manager = modules['TimersManager'] + self.timer_manager.add_module(self) def start_timer_manager(self, data): if self.thread_timer is not None: From 30abd7ff5c24bcadd61c755fd663bbc05df26cb7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:35:46 +0100 Subject: [PATCH 11/16] fixed imports to 2.0 in pype/ftrack --- pype/api.py | 2 +- .../actions/action_application_loader.py | 4 ++-- pype/ftrack/actions/action_asset_delete.py | 2 +- .../actions/action_client_review_sort.py | 2 +- pype/ftrack/actions/action_component_open.py | 2 +- .../actions/action_create_cust_attrs.py | 24 ++++--------------- pype/ftrack/actions/action_create_folders.py | 2 +- pype/ftrack/actions/action_delete_asset.py | 2 +- .../actions/action_delete_asset_byname.py | 2 +- .../actions/action_delete_unpublished.py | 2 +- pype/ftrack/actions/action_djvview.py | 4 ++-- pype/ftrack/actions/action_job_killer.py | 4 +--- pype/ftrack/actions/action_set_version.py | 2 +- .../actions/action_sync_to_avalon_local.py | 2 +- pype/ftrack/actions/action_test.py | 2 +- pype/ftrack/actions/action_thumbToChildern.py | 2 +- pype/ftrack/actions/action_thumbToParent.py | 2 +- pype/ftrack/actions/event_collect_entities.py | 2 +- pype/ftrack/credentials.py | 1 - pype/ftrack/ftrack_run.py | 16 ++++--------- pype/ftrack/ftrack_server/event_server.py | 4 ++-- pype/ftrack/ftrack_server/event_server_cli.py | 4 ++-- pype/ftrack/ftrack_server/ftrack_server.py | 6 ++--- pype/ftrack/lib/avalon_sync.py | 4 ++-- pype/ftrack/lib/ftrack_base_handler.py | 4 ++-- pype/ftrack/login_dialog.py | 4 ++-- pype/ftrack/login_tools.py | 2 +- pype/templates.py | 5 ++-- 28 files changed, 46 insertions(+), 68 deletions(-) diff --git a/pype/api.py b/pype/api.py index 747ad425f8..5230a41405 100644 --- a/pype/api.py +++ b/pype/api.py @@ -15,7 +15,7 @@ from .action import ( RepairContextAction ) -from app.api import Logger +from pypeapp.api import Logger from . import ( Anatomy, diff --git a/pype/ftrack/actions/action_application_loader.py b/pype/ftrack/actions/action_application_loader.py index 3202c19d40..9cca5ea047 100644 --- a/pype/ftrack/actions/action_application_loader.py +++ b/pype/ftrack/actions/action_application_loader.py @@ -2,10 +2,10 @@ import toml import time from pype.ftrack import AppAction from avalon import lib -from app.api import Logger +from pypeapp.api import Logger from pype import lib as pypelib -log = Logger.getLogger(__name__) +log = Logger().get_logger(__name__) def registerApp(app, session): diff --git a/pype/ftrack/actions/action_asset_delete.py b/pype/ftrack/actions/action_asset_delete.py index c47c8ac4ac..684b3862a8 100644 --- a/pype/ftrack/actions/action_asset_delete.py +++ b/pype/ftrack/actions/action_asset_delete.py @@ -1,7 +1,7 @@ import sys import argparse import logging -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/action_client_review_sort.py b/pype/ftrack/actions/action_client_review_sort.py index 1e2f37ec74..b06a928007 100644 --- a/pype/ftrack/actions/action_client_review_sort.py +++ b/pype/ftrack/actions/action_client_review_sort.py @@ -2,7 +2,7 @@ import sys import argparse import logging -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/action_component_open.py b/pype/ftrack/actions/action_component_open.py index 579d8ebe85..c40a04b2fd 100644 --- a/pype/ftrack/actions/action_component_open.py +++ b/pype/ftrack/actions/action_component_open.py @@ -3,7 +3,7 @@ import argparse import logging import subprocess import os -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/action_create_cust_attrs.py b/pype/ftrack/actions/action_create_cust_attrs.py index fb57221ccd..09749cf2c5 100644 --- a/pype/ftrack/actions/action_create_cust_attrs.py +++ b/pype/ftrack/actions/action_create_cust_attrs.py @@ -2,10 +2,11 @@ import os import sys import argparse import json -import ftrack_api import arrow import logging +from pype.vendor import ftrack_api from pype.ftrack import BaseAction, get_ca_mongoid +from pypeapp.lib.config import get_presets """ This action creates/updates custom attributes. @@ -122,11 +123,6 @@ class CustomAttributes(BaseAction): def __init__(self, session): super().__init__(session) - templates = os.environ['PYPE_STUDIO_TEMPLATES'] - path_items = [ - templates, 'presets', 'ftrack', 'ftrack_custom_attributes.json' - ] - self.filepath = os.path.sep.join(path_items) self.types = {} self.object_type_ids = {} self.groups = {} @@ -230,22 +226,12 @@ class CustomAttributes(BaseAction): self.process_attribute(data) def custom_attributes_from_file(self, session, event): - try: - with open(self.filepath) as data_file: - json_dict = json.load(data_file) - except Exception as e: - msg = ( - 'Loading "Custom attribute file" Failed.' - ' Please check log for more information' - ) - self.log.warning("{} - {}".format(msg, str(e))) - self.show_message(event, msg) - return + presets = get_presets()['ftrack']['ftrack_custom_attributes'] - for cust_attr_name in json_dict: + for cust_attr_name in presets: try: data = {} - cust_attr = json_dict[cust_attr_name] + cust_attr = presets[cust_attr_name] # Get key, label, type data.update(self.get_required(cust_attr)) # Get hierachical/ entity_type/ object_id diff --git a/pype/ftrack/actions/action_create_folders.py b/pype/ftrack/actions/action_create_folders.py index 7ce5526164..cc4023342d 100644 --- a/pype/ftrack/actions/action_create_folders.py +++ b/pype/ftrack/actions/action_create_folders.py @@ -4,7 +4,7 @@ import argparse import sys import errno -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction import json from pype import api as pype diff --git a/pype/ftrack/actions/action_delete_asset.py b/pype/ftrack/actions/action_delete_asset.py index 7a4c15e9fb..838a77570f 100644 --- a/pype/ftrack/actions/action_delete_asset.py +++ b/pype/ftrack/actions/action_delete_asset.py @@ -2,7 +2,7 @@ import sys import logging from bson.objectid import ObjectId import argparse -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction from avalon.tools.libraryloader.io_nonsingleton import DbConnector diff --git a/pype/ftrack/actions/action_delete_asset_byname.py b/pype/ftrack/actions/action_delete_asset_byname.py index ee6f875ad3..9da60ce763 100644 --- a/pype/ftrack/actions/action_delete_asset_byname.py +++ b/pype/ftrack/actions/action_delete_asset_byname.py @@ -1,7 +1,7 @@ import sys import logging import argparse -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction from avalon.tools.libraryloader.io_nonsingleton import DbConnector diff --git a/pype/ftrack/actions/action_delete_unpublished.py b/pype/ftrack/actions/action_delete_unpublished.py index 018a70b423..377e118ffb 100644 --- a/pype/ftrack/actions/action_delete_unpublished.py +++ b/pype/ftrack/actions/action_delete_unpublished.py @@ -1,7 +1,7 @@ import sys import argparse import logging -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/action_djvview.py b/pype/ftrack/actions/action_djvview.py index d8e6996db4..4e027b740b 100644 --- a/pype/ftrack/actions/action_djvview.py +++ b/pype/ftrack/actions/action_djvview.py @@ -5,12 +5,12 @@ import json import logging import subprocess from operator import itemgetter -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseHandler from app.api import Logger from pype import lib -log = Logger.getLogger(__name__) +log = Logger().get_logger(__name__) class DJVViewAction(BaseHandler): diff --git a/pype/ftrack/actions/action_job_killer.py b/pype/ftrack/actions/action_job_killer.py index d8d0e81cb1..008b36b1c1 100644 --- a/pype/ftrack/actions/action_job_killer.py +++ b/pype/ftrack/actions/action_job_killer.py @@ -1,10 +1,8 @@ -# :coding: utf-8 -# :copyright: Copyright (c) 2017 ftrack import sys import argparse import logging -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/action_set_version.py b/pype/ftrack/actions/action_set_version.py index 3954733041..f6e745b3ec 100644 --- a/pype/ftrack/actions/action_set_version.py +++ b/pype/ftrack/actions/action_set_version.py @@ -1,7 +1,7 @@ import sys import argparse import logging -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/action_sync_to_avalon_local.py b/pype/ftrack/actions/action_sync_to_avalon_local.py index 68c55be652..d3fb140cc4 100644 --- a/pype/ftrack/actions/action_sync_to_avalon_local.py +++ b/pype/ftrack/actions/action_sync_to_avalon_local.py @@ -4,7 +4,7 @@ import argparse import logging import json -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction, lib as ftracklib diff --git a/pype/ftrack/actions/action_test.py b/pype/ftrack/actions/action_test.py index ad97cba487..36adb99074 100644 --- a/pype/ftrack/actions/action_test.py +++ b/pype/ftrack/actions/action_test.py @@ -6,7 +6,7 @@ import os import json import re -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction from avalon import io, inventory, schema diff --git a/pype/ftrack/actions/action_thumbToChildern.py b/pype/ftrack/actions/action_thumbToChildern.py index 2ff6faec48..5b63ec264f 100644 --- a/pype/ftrack/actions/action_thumbToChildern.py +++ b/pype/ftrack/actions/action_thumbToChildern.py @@ -3,7 +3,7 @@ import argparse import logging import json -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/action_thumbToParent.py b/pype/ftrack/actions/action_thumbToParent.py index 98124aca70..eb5623328e 100644 --- a/pype/ftrack/actions/action_thumbToParent.py +++ b/pype/ftrack/actions/action_thumbToParent.py @@ -2,7 +2,7 @@ import sys import argparse import logging import json -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseAction diff --git a/pype/ftrack/actions/event_collect_entities.py b/pype/ftrack/actions/event_collect_entities.py index d5a34b0153..71f2d26ff3 100644 --- a/pype/ftrack/actions/event_collect_entities.py +++ b/pype/ftrack/actions/event_collect_entities.py @@ -1,4 +1,4 @@ -import ftrack_api +from pype.vendor import ftrack_api from pype.ftrack import BaseEvent diff --git a/pype/ftrack/credentials.py b/pype/ftrack/credentials.py index 89353ea984..30d503c534 100644 --- a/pype/ftrack/credentials.py +++ b/pype/ftrack/credentials.py @@ -77,7 +77,6 @@ def _check_credentials(username=None, apiKey=None): session = ftrack_api.Session() session.close() except Exception as e: - print(e) return False return True diff --git a/pype/ftrack/ftrack_run.py b/pype/ftrack/ftrack_run.py index d795edb08b..e45a0cc8b7 100644 --- a/pype/ftrack/ftrack_run.py +++ b/pype/ftrack/ftrack_run.py @@ -2,22 +2,16 @@ import os import json import threading import time -import ftrack_api -from app import style -from app.vendor.Qt import QtCore, QtGui, QtWidgets +from Qt import QtCore, QtGui, QtWidgets -from pype.ftrack import credentials, login_dialog as login_dialog - -from pype.vendor.pynput import mouse, keyboard -from . import FtrackServer +from pype.vendor import ftrack_api +from pypeapp import style +from pype.ftrack import FtrackServer, credentials, login_dialog as login_dialog from pype import api as pype -# load data from templates -pype.load_data_from_templates() - -log = pype.Logger.getLogger(__name__, "ftrack") +log = pype.Logger().get_logger(FtrackModule.__name__, "ftrack") class FtrackRunner: diff --git a/pype/ftrack/ftrack_server/event_server.py b/pype/ftrack/ftrack_server/event_server.py index e824d1d899..2b3acad076 100644 --- a/pype/ftrack/ftrack_server/event_server.py +++ b/pype/ftrack/ftrack_server/event_server.py @@ -1,10 +1,10 @@ import sys from pype.ftrack import credentials, login_dialog as login_dialog from pype.ftrack.ftrack_server import FtrackServer -from app.vendor.Qt import QtWidgets +from Qt import QtWidgets from pype import api -log = api.Logger.getLogger(__name__, "ftrack-event-server") +log = api.Logger().get_logger(__name__, "ftrack-event-server") class EventServer: diff --git a/pype/ftrack/ftrack_server/event_server_cli.py b/pype/ftrack/ftrack_server/event_server_cli.py index a466bf5723..2e9519df26 100644 --- a/pype/ftrack/ftrack_server/event_server_cli.py +++ b/pype/ftrack/ftrack_server/event_server_cli.py @@ -1,9 +1,9 @@ import sys from pype.ftrack import credentials from pype.ftrack.ftrack_server import FtrackServer -from app import api +from pypeapp import api -log = api.Logger.getLogger(__name__, "ftrack-event-server-cli") +log = api.Logger().get_logger(__name__, "ftrack-event-server-cli") possible_yes = ['y', 'yes'] possible_no = ['n', 'no'] diff --git a/pype/ftrack/ftrack_server/ftrack_server.py b/pype/ftrack/ftrack_server/ftrack_server.py index 91caff216e..27207edc48 100644 --- a/pype/ftrack/ftrack_server/ftrack_server.py +++ b/pype/ftrack/ftrack_server/ftrack_server.py @@ -2,12 +2,12 @@ import os import sys import types import importlib -import ftrack_api +from pype.vendor import ftrack_api import time import logging -from app.api import Logger +from pypeapp.api import Logger -log = Logger.getLogger(__name__) +log = Logger().get_logger(__name__) """ # Required - Needed for connection to Ftrack diff --git a/pype/ftrack/lib/avalon_sync.py b/pype/ftrack/lib/avalon_sync.py index 6c3c9a0be4..56fe5f1ed2 100644 --- a/pype/ftrack/lib/avalon_sync.py +++ b/pype/ftrack/lib/avalon_sync.py @@ -8,11 +8,11 @@ import avalon import avalon.api from avalon import schema from avalon.vendor import toml, jsonschema -from app.api import Logger +from pypeapp.api import Logger ValidationError = jsonschema.ValidationError -log = Logger.getLogger(__name__) +log = Logger().get_logger(__name__) def get_ca_mongoid(): diff --git a/pype/ftrack/lib/ftrack_base_handler.py b/pype/ftrack/lib/ftrack_base_handler.py index a823394bb9..6d56fcb010 100644 --- a/pype/ftrack/lib/ftrack_base_handler.py +++ b/pype/ftrack/lib/ftrack_base_handler.py @@ -1,7 +1,7 @@ -import ftrack_api import functools import time from pype import api as pype +from pype.vendor import ftrack_api class MissingPermision(Exception): @@ -27,7 +27,7 @@ class BaseHandler(object): def __init__(self, session): '''Expects a ftrack_api.Session instance''' self._session = session - self.log = pype.Logger.getLogger(self.__class__.__name__) + self.log = pype.Logger().get_logger(self.__class__.__name__) # Using decorator self.register = self.register_decorator(self.register) diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index 2828afe539..04ebd59ae4 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -1,7 +1,7 @@ import os import requests -from app.vendor.Qt import QtCore, QtGui, QtWidgets -from app import style +from Qt import QtCore, QtGui, QtWidgets +from pypeapp import style from . import credentials, login_tools diff --git a/pype/ftrack/login_tools.py b/pype/ftrack/login_tools.py index 592ec152ee..b259f2d2ed 100644 --- a/pype/ftrack/login_tools.py +++ b/pype/ftrack/login_tools.py @@ -5,7 +5,7 @@ import webbrowser import functools import pype import inspect -from app.vendor.Qt import QtCore +from Qt import QtCore class LoginServerHandler(BaseHTTPRequestHandler): diff --git a/pype/templates.py b/pype/templates.py index c5578a983c..92dad30e7e 100644 --- a/pype/templates.py +++ b/pype/templates.py @@ -3,8 +3,9 @@ import re from avalon import io from avalon import api as avalon from . import lib -from app.api import (Templates, Logger, format) -log = Logger.getLogger(__name__, +# from pypeapp.api import (Templates, Logger, format) +from pypeapp.api import Logger +log = Logger().get_logger(__name__, os.getenv("AVALON_APP", "pype-config")) SESSION = None From 2bd3019a32c51217ca917b1a58ac4578f3494006 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:36:26 +0100 Subject: [PATCH 12/16] ftrack runner renamed to ftrack module --- pype/ftrack/{ftrack_run.py => ftrack_module.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename pype/ftrack/{ftrack_run.py => ftrack_module.py} (99%) diff --git a/pype/ftrack/ftrack_run.py b/pype/ftrack/ftrack_module.py similarity index 99% rename from pype/ftrack/ftrack_run.py rename to pype/ftrack/ftrack_module.py index e45a0cc8b7..cd29f88286 100644 --- a/pype/ftrack/ftrack_run.py +++ b/pype/ftrack/ftrack_module.py @@ -14,7 +14,7 @@ from pype import api as pype log = pype.Logger().get_logger(FtrackModule.__name__, "ftrack") -class FtrackRunner: +class FtrackModule: def __init__(self, main_parent=None, parent=None): self.parent = parent From 2ea5c8b5683e9c3caf5fc3ddc2481ce4f99282e1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:36:54 +0100 Subject: [PATCH 13/16] tray init modified --- pype/avalon_apps/__init__.py | 7 ++----- pype/ftrack/__init__.py | 10 +++------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/pype/avalon_apps/__init__.py b/pype/avalon_apps/__init__.py index 1d7c3c8a81..845f94a330 100644 --- a/pype/avalon_apps/__init__.py +++ b/pype/avalon_apps/__init__.py @@ -1,8 +1,5 @@ from .avalon_app import AvalonApps -def tray_init(tray_widget, main_widget, parent_menu): - av_apps = AvalonApps(main_widget, tray_widget) - av_apps.tray_menu(tray_widget.menu) - - return av_apps +def tray_init(tray_widget, main_widget): + return AvalonApps(main_widget, tray_widget) diff --git a/pype/ftrack/__init__.py b/pype/ftrack/__init__.py index cdaacca68c..922de28e16 100644 --- a/pype/ftrack/__init__.py +++ b/pype/ftrack/__init__.py @@ -1,11 +1,7 @@ from .lib import * from .ftrack_server import * -from .ftrack_run import FtrackRunner +from .ftrack_module import FtrackModule -def tray_init(tray_widget, main_widget, parent_menu): - ftrack = FtrackRunner(main_widget, tray_widget) - main_widget.menu.addMenu(ftrack.trayMenu(parent_menu)) - ftrack.validate() - - return ftrack +def tray_init(tray_widget, main_widget): + return FtrackModule(main_widget, tray_widget) From 67aa4e7d081fab6c092b1e9d0d39d38375e27a0e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 20 Mar 2019 09:44:27 +0100 Subject: [PATCH 14/16] changed log name in ftrack module --- pype/ftrack/ftrack_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/ftrack/ftrack_module.py b/pype/ftrack/ftrack_module.py index cd29f88286..a68bc2ac26 100644 --- a/pype/ftrack/ftrack_module.py +++ b/pype/ftrack/ftrack_module.py @@ -11,7 +11,7 @@ from pype.ftrack import FtrackServer, credentials, login_dialog as login_dialog from pype import api as pype -log = pype.Logger().get_logger(FtrackModule.__name__, "ftrack") +log = pype.Logger().get_logger("FtrackModule", "ftrack") class FtrackModule: From fc01a4240bef74ead01734b38eca60f77f89f22d Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 22 Mar 2019 19:31:19 +0100 Subject: [PATCH 15/16] timers manager tries to load presets before add to idle manager --- .../services/timers_manager/timers_manager.py | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/pype/services/timers_manager/timers_manager.py b/pype/services/timers_manager/timers_manager.py index e6c1c4f18a..5d324ef453 100644 --- a/pype/services/timers_manager/timers_manager.py +++ b/pype/services/timers_manager/timers_manager.py @@ -1,6 +1,7 @@ from Qt import QtCore from .widget_user_idle import WidgetUserIdle from pypeapp.lib.config import get_presets +from pypeapp import Logger class Singleton(type): @@ -20,17 +21,22 @@ class TimersManager(metaclass=Singleton): last_task = None def __init__(self, tray_widget, main_widget): + 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.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 + try: + 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 + return True + except Exception: + self.log.warning('Was not able to load presets for TimersManager') + return False def add_module(self, module): self.modules.append(module) @@ -76,28 +82,39 @@ class TimersManager(metaclass=Singleton): 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 + if self.set_signal_times() is True: + self.register_to_idle_manager(modules['IdleManager']) + + def register_to_idle_manager(self, man_obj): + self.idle_man = man_obj + # Times when idle is between show widget and stop timers + show_to_stop_range = range( + self.time_show_message-1, self.time_stop_timer + ) + for num in show_to_stop_range: self.idle_man.add_time_signal( - self.time_show_message, - self.s_handler.signal_show_message + num, + self.s_handler.signal_change_label ) - # Time when timers are stopped + # 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( - self.time_stop_timer, self.s_handler.signal_stop_timers + 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: From b61cceccee28d1c9ab44615d501e55dd237379a8 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 22 Mar 2019 19:32:01 +0100 Subject: [PATCH 16/16] added basic docstrings --- pype/avalon_apps/avalon_app.py | 2 +- pype/ftrack/ftrack_module.py | 1 - pype/services/idle_manager/idle_manager.py | 14 +++++++++++ .../services/timers_manager/timers_manager.py | 25 ++++++++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/pype/avalon_apps/avalon_app.py b/pype/avalon_apps/avalon_app.py index 072d7fbb3f..efad3f3ce0 100644 --- a/pype/avalon_apps/avalon_app.py +++ b/pype/avalon_apps/avalon_app.py @@ -29,7 +29,7 @@ class AvalonApps: icon = QtGui.QIcon(launcher_lib.resource("icon", "main.png")) aShowLauncher = QtWidgets.QAction(icon, "&Launcher", parent_menu) - aLibraryLoader = QtWidgets.QAction("&Library", parent_menu) + aLibraryLoader = QtWidgets.QAction("Library", parent_menu) aShowLauncher.triggered.connect(self.show_launcher) aLibraryLoader.triggered.connect(self.show_library_loader) diff --git a/pype/ftrack/ftrack_module.py b/pype/ftrack/ftrack_module.py index a68bc2ac26..127b39d2fc 100644 --- a/pype/ftrack/ftrack_module.py +++ b/pype/ftrack/ftrack_module.py @@ -117,7 +117,6 @@ class FtrackModule: # Menu for Tray App self.menu = QtWidgets.QMenu('Ftrack', parent_menu) self.menu.setProperty('submenu', 'on') - self.menu.setStyleSheet(style.load_stylesheet()) # Actions - server self.smActionS = self.menu.addMenu("Action server") diff --git a/pype/services/idle_manager/idle_manager.py b/pype/services/idle_manager/idle_manager.py index cc6e177916..e8ba246121 100644 --- a/pype/services/idle_manager/idle_manager.py +++ b/pype/services/idle_manager/idle_manager.py @@ -5,6 +5,10 @@ from pypeapp import Logger 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() @@ -16,6 +20,12 @@ class IdleManager(QtCore.QThread): self._is_running = False 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 + """ if emit_time not in self.time_signals: self.time_signals[emit_time] = [] self.time_signals[emit_time].append(signal) @@ -54,6 +64,8 @@ class IdleManager(QtCore.QThread): class MouseThread(QtCore.QThread): + """Listens user's mouse movement + """ signal_stop = QtCore.Signal() def __init__(self, signal): @@ -76,6 +88,8 @@ class MouseThread(QtCore.QThread): class KeyboardThread(QtCore.QThread): + """Listens user's keyboard input + """ signal_stop = QtCore.Signal() def __init__(self, signal): diff --git a/pype/services/timers_manager/timers_manager.py b/pype/services/timers_manager/timers_manager.py index 5d324ef453..6f10a0ec68 100644 --- a/pype/services/timers_manager/timers_manager.py +++ b/pype/services/timers_manager/timers_manager.py @@ -5,6 +5,8 @@ from pypeapp import Logger class Singleton(type): + """ Signleton implementation + """ _instances = {} def __call__(cls, *args, **kwargs): @@ -16,6 +18,12 @@ class Singleton(type): class TimersManager(metaclass=Singleton): + """ Handles about Timers. + + Should be able to start/stop all timers at once. + If IdleManager is imported then is able to handle about stop timers + when user idles for a long time (set in presets). + """ modules = [] is_running = False last_task = None @@ -39,11 +47,20 @@ class TimersManager(metaclass=Singleton): return False def add_module(self, module): + """ Adds module to context + + Module must have implemented methods: + - ``start_timer_manager(data)`` + - ``stop_timer_manager()`` + """ self.modules.append(module) def start_timers(self, data): ''' - Dictionary "data" should contain: + :param data: basic information needed to start any timer + :type data: dict + ..note:: + Dictionary "data" should contain: - project_name(str) - Name of Project - hierarchy(list/tuple) - list of parents(except project) - task_type(str) @@ -53,6 +70,7 @@ class TimersManager(metaclass=Singleton): - to run timers for task in 'C001_BackToPast/assets/characters/villian/Lookdev BG' - input data should contain: + .. code-block:: Python data = { 'project_name': 'C001_BackToPast', 'hierarchy': ['assets', 'characters', 'villian'], @@ -79,6 +97,11 @@ class TimersManager(metaclass=Singleton): self.is_running = False def process_modules(self, modules): + """ Gives ability to connect with imported modules from TrayManager. + + :param modules: All imported modules from TrayManager + :type modules: dict + """ self.s_handler = SignalHandler(self) if 'IdleManager' in modules: