mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #2024 from pypeclub/feature/timers_manager_wihtout_interface
TimersManager: Removed interface of timers manager
This commit is contained in:
commit
54a273e07f
4 changed files with 218 additions and 94 deletions
|
|
@ -11,8 +11,7 @@ from openpype.modules import OpenPypeModule
|
|||
from openpype_interfaces import (
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
IFtrackEventHandlerPaths,
|
||||
ITimersManager
|
||||
IFtrackEventHandlerPaths
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -20,8 +19,7 @@ class ClockifyModule(
|
|||
OpenPypeModule,
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
IFtrackEventHandlerPaths,
|
||||
ITimersManager
|
||||
IFtrackEventHandlerPaths
|
||||
):
|
||||
name = "clockify"
|
||||
|
||||
|
|
@ -39,6 +37,11 @@ class ClockifyModule(
|
|||
|
||||
self.clockapi = ClockifyAPI(master_parent=self)
|
||||
|
||||
# TimersManager attributes
|
||||
# - set `timers_manager_connector` only in `tray_init`
|
||||
self.timers_manager_connector = None
|
||||
self._timers_manager_module = None
|
||||
|
||||
def get_global_environments(self):
|
||||
return {
|
||||
"CLOCKIFY_WORKSPACE": self.workspace_name
|
||||
|
|
@ -61,6 +64,9 @@ class ClockifyModule(
|
|||
self.bool_timer_run = False
|
||||
self.bool_api_key_set = self.clockapi.set_api()
|
||||
|
||||
# Define itself as TimersManager connector
|
||||
self.timers_manager_connector = self
|
||||
|
||||
def tray_start(self):
|
||||
if self.bool_api_key_set is False:
|
||||
self.show_settings()
|
||||
|
|
@ -162,10 +168,6 @@ class ClockifyModule(
|
|||
self.set_menu_visibility()
|
||||
time.sleep(5)
|
||||
|
||||
def stop_timer(self):
|
||||
"""Implementation of ITimersManager."""
|
||||
self.clockapi.finish_time_entry()
|
||||
|
||||
def signed_in(self):
|
||||
if not self.timer_manager:
|
||||
return
|
||||
|
|
@ -176,8 +178,60 @@ class ClockifyModule(
|
|||
if self.timer_manager.is_running:
|
||||
self.start_timer_manager(self.timer_manager.last_task)
|
||||
|
||||
def on_message_widget_close(self):
|
||||
self.message_widget = None
|
||||
|
||||
# Definition of Tray menu
|
||||
def tray_menu(self, parent_menu):
|
||||
# Menu for Tray App
|
||||
from Qt import QtWidgets
|
||||
menu = QtWidgets.QMenu("Clockify", parent_menu)
|
||||
menu.setProperty("submenu", "on")
|
||||
|
||||
# Actions
|
||||
action_show_settings = QtWidgets.QAction("Settings", menu)
|
||||
action_stop_timer = QtWidgets.QAction("Stop timer", menu)
|
||||
|
||||
menu.addAction(action_show_settings)
|
||||
menu.addAction(action_stop_timer)
|
||||
|
||||
action_show_settings.triggered.connect(self.show_settings)
|
||||
action_stop_timer.triggered.connect(self.stop_timer)
|
||||
|
||||
self.action_stop_timer = action_stop_timer
|
||||
|
||||
self.set_menu_visibility()
|
||||
|
||||
parent_menu.addMenu(menu)
|
||||
|
||||
def show_settings(self):
|
||||
self.widget_settings.input_api_key.setText(self.clockapi.get_api_key())
|
||||
self.widget_settings.show()
|
||||
|
||||
def set_menu_visibility(self):
|
||||
self.action_stop_timer.setVisible(self.bool_timer_run)
|
||||
|
||||
# --- TimersManager connection methods ---
|
||||
def register_timers_manager(self, timer_manager_module):
|
||||
"""Store TimersManager for future use."""
|
||||
self._timers_manager_module = timer_manager_module
|
||||
|
||||
def timer_started(self, data):
|
||||
"""Tell TimersManager that timer started."""
|
||||
if self._timers_manager_module is not None:
|
||||
self._timers_manager_module.timer_started(self._module.id, data)
|
||||
|
||||
def timer_stopped(self):
|
||||
"""Tell TimersManager that timer stopped."""
|
||||
if self._timers_manager_module is not None:
|
||||
self._timers_manager_module.timer_stopped(self._module.id)
|
||||
|
||||
def stop_timer(self):
|
||||
"""Called from TimersManager to stop timer."""
|
||||
self.clockapi.finish_time_entry()
|
||||
|
||||
def start_timer(self, input_data):
|
||||
"""Implementation of ITimersManager."""
|
||||
"""Called from TimersManager to start timer."""
|
||||
# If not api key is not entered then skip
|
||||
if not self.clockapi.get_api_key():
|
||||
return
|
||||
|
|
@ -234,36 +288,3 @@ class ClockifyModule(
|
|||
self.clockapi.start_time_entry(
|
||||
description, project_id, tag_ids=tag_ids
|
||||
)
|
||||
|
||||
def on_message_widget_close(self):
|
||||
self.message_widget = None
|
||||
|
||||
# Definition of Tray menu
|
||||
def tray_menu(self, parent_menu):
|
||||
# Menu for Tray App
|
||||
from Qt import QtWidgets
|
||||
menu = QtWidgets.QMenu("Clockify", parent_menu)
|
||||
menu.setProperty("submenu", "on")
|
||||
|
||||
# Actions
|
||||
action_show_settings = QtWidgets.QAction("Settings", menu)
|
||||
action_stop_timer = QtWidgets.QAction("Stop timer", menu)
|
||||
|
||||
menu.addAction(action_show_settings)
|
||||
menu.addAction(action_stop_timer)
|
||||
|
||||
action_show_settings.triggered.connect(self.show_settings)
|
||||
action_stop_timer.triggered.connect(self.stop_timer)
|
||||
|
||||
self.action_stop_timer = action_stop_timer
|
||||
|
||||
self.set_menu_visibility()
|
||||
|
||||
parent_menu.addMenu(menu)
|
||||
|
||||
def show_settings(self):
|
||||
self.widget_settings.input_api_key.setText(self.clockapi.get_api_key())
|
||||
self.widget_settings.show()
|
||||
|
||||
def set_menu_visibility(self):
|
||||
self.action_stop_timer.setVisible(self.bool_timer_run)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ from openpype.modules import OpenPypeModule
|
|||
from openpype_interfaces import (
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
ITimersManager,
|
||||
ILaunchHookPaths,
|
||||
ISettingsChangeListener,
|
||||
IFtrackEventHandlerPaths
|
||||
|
|
@ -21,7 +20,6 @@ class FtrackModule(
|
|||
OpenPypeModule,
|
||||
ITrayModule,
|
||||
IPluginPaths,
|
||||
ITimersManager,
|
||||
ILaunchHookPaths,
|
||||
ISettingsChangeListener
|
||||
):
|
||||
|
|
@ -61,6 +59,10 @@ class FtrackModule(
|
|||
self.user_event_handlers_paths = user_event_handlers_paths
|
||||
self.tray_module = None
|
||||
|
||||
# TimersManager connection
|
||||
self.timers_manager_connector = None
|
||||
self._timers_manager_module = None
|
||||
|
||||
def get_global_environments(self):
|
||||
"""Ftrack's global environments."""
|
||||
return {
|
||||
|
|
@ -102,16 +104,6 @@ class FtrackModule(
|
|||
elif key == "user":
|
||||
self.user_event_handlers_paths.extend(value)
|
||||
|
||||
def start_timer(self, data):
|
||||
"""Implementation of ITimersManager interface."""
|
||||
if self.tray_module:
|
||||
self.tray_module.start_timer_manager(data)
|
||||
|
||||
def stop_timer(self):
|
||||
"""Implementation of ITimersManager interface."""
|
||||
if self.tray_module:
|
||||
self.tray_module.stop_timer_manager()
|
||||
|
||||
def on_system_settings_save(
|
||||
self, old_value, new_value, changes, new_value_metadata
|
||||
):
|
||||
|
|
@ -343,7 +335,10 @@ class FtrackModule(
|
|||
|
||||
def tray_init(self):
|
||||
from .tray import FtrackTrayWrapper
|
||||
|
||||
self.tray_module = FtrackTrayWrapper(self)
|
||||
# Module is it's own connector to TimersManager
|
||||
self.timers_manager_connector = self
|
||||
|
||||
def tray_menu(self, parent_menu):
|
||||
return self.tray_module.tray_menu(parent_menu)
|
||||
|
|
@ -357,3 +352,23 @@ class FtrackModule(
|
|||
def set_credentials_to_env(self, username, api_key):
|
||||
os.environ["FTRACK_API_USER"] = username or ""
|
||||
os.environ["FTRACK_API_KEY"] = api_key or ""
|
||||
|
||||
# --- TimersManager connection methods ---
|
||||
def start_timer(self, data):
|
||||
if self.tray_module:
|
||||
self.tray_module.start_timer_manager(data)
|
||||
|
||||
def stop_timer(self):
|
||||
if self.tray_module:
|
||||
self.tray_module.stop_timer_manager()
|
||||
|
||||
def register_timers_manager(self, timer_manager_module):
|
||||
self._timers_manager_module = timer_manager_module
|
||||
|
||||
def timer_started(self, data):
|
||||
if self._timers_manager_module is not None:
|
||||
self._timers_manager_module.timer_started(self.id, data)
|
||||
|
||||
def timer_stopped(self):
|
||||
if self._timers_manager_module is not None:
|
||||
self._timers_manager_module.timer_stopped(self.id)
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
from abc import abstractmethod
|
||||
from openpype.modules import OpenPypeInterface
|
||||
|
||||
|
||||
class ITimersManager(OpenPypeInterface):
|
||||
timer_manager_module = None
|
||||
|
||||
@abstractmethod
|
||||
def stop_timer(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def start_timer(self, data):
|
||||
pass
|
||||
|
||||
def timer_started(self, data):
|
||||
if not self.timer_manager_module:
|
||||
return
|
||||
|
||||
self.timer_manager_module.timer_started(self.id, data)
|
||||
|
||||
def timer_stopped(self):
|
||||
if not self.timer_manager_module:
|
||||
return
|
||||
|
||||
self.timer_manager_module.timer_stopped(self.id)
|
||||
|
|
@ -9,20 +9,90 @@ from openpype_interfaces import (
|
|||
from avalon.api import AvalonMongoDB
|
||||
|
||||
|
||||
class ExampleTimersManagerConnector:
|
||||
"""Timers manager can handle timers of multiple modules/addons.
|
||||
|
||||
Module must have object under `timers_manager_connector` attribute with
|
||||
few methods. This is example class of the object that could be stored under
|
||||
module.
|
||||
|
||||
Required methods are 'stop_timer' and 'start_timer'.
|
||||
|
||||
# TODO pass asset document instead of `hierarchy`
|
||||
Example of `data` that are passed during changing timer:
|
||||
```
|
||||
data = {
|
||||
"project_name": project_name,
|
||||
"task_name": task_name,
|
||||
"task_type": task_type,
|
||||
"hierarchy": hierarchy
|
||||
}
|
||||
```
|
||||
"""
|
||||
# Not needed at all
|
||||
def __init__(self, module):
|
||||
# Store timer manager module to be able call it's methods when needed
|
||||
self._timers_manager_module = None
|
||||
|
||||
# Store module which want to use timers manager to have access
|
||||
self._module = module
|
||||
|
||||
# Required
|
||||
def stop_timer(self):
|
||||
"""Called by timers manager when module should stop timer."""
|
||||
self._module.stop_timer()
|
||||
|
||||
# Required
|
||||
def start_timer(self, data):
|
||||
"""Method called by timers manager when should start timer."""
|
||||
self._module.start_timer(data)
|
||||
|
||||
# Optional
|
||||
def register_timers_manager(self, timer_manager_module):
|
||||
"""Method called by timers manager where it's object is passed.
|
||||
|
||||
This is moment when timers manager module can be store to be able
|
||||
call it's callbacks (e.g. timer started).
|
||||
"""
|
||||
self._timers_manager_module = timer_manager_module
|
||||
|
||||
# Custom implementation
|
||||
def timer_started(self, data):
|
||||
"""This is example of possibility to trigger callbacks on manager."""
|
||||
if self._timers_manager_module is not None:
|
||||
self._timers_manager_module.timer_started(self._module.id, data)
|
||||
|
||||
# Custom implementation
|
||||
def timer_stopped(self):
|
||||
if self._timers_manager_module is not None:
|
||||
self._timers_manager_module.timer_stopped(self._module.id)
|
||||
|
||||
|
||||
class TimersManager(OpenPypeModule, ITrayService, IIdleManager):
|
||||
""" 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).
|
||||
|
||||
To be able use this advantage module has to have attribute with name
|
||||
`timers_manager_connector` which has two methods 'stop_timer'
|
||||
and 'start_timer'. Optionally may have `register_timers_manager` where
|
||||
object of TimersManager module is passed to be able call it's callbacks.
|
||||
|
||||
See `ExampleTimersManagerConnector`.
|
||||
"""
|
||||
name = "timers_manager"
|
||||
label = "Timers Service"
|
||||
|
||||
_required_methods = (
|
||||
"stop_timer",
|
||||
"start_timer"
|
||||
)
|
||||
|
||||
def initialize(self, modules_settings):
|
||||
timers_settings = modules_settings[self.name]
|
||||
|
||||
self.enabled = timers_settings["enabled"]
|
||||
|
||||
auto_stop = timers_settings["auto_stop"]
|
||||
# When timer will stop if idle manager is running (minutes)
|
||||
full_time = int(timers_settings["full_time"] * 60)
|
||||
|
|
@ -41,7 +111,8 @@ class TimersManager(OpenPypeModule, ITrayService, IIdleManager):
|
|||
self.widget_user_idle = None
|
||||
self.signal_handler = None
|
||||
|
||||
self.modules = []
|
||||
self._connectors_by_module_id = {}
|
||||
self._modules_by_id = {}
|
||||
|
||||
def tray_init(self):
|
||||
from .widget_user_idle import WidgetUserIdle, SignalHandler
|
||||
|
|
@ -96,17 +167,35 @@ class TimersManager(OpenPypeModule, ITrayService, IIdleManager):
|
|||
self.timer_started(None, data)
|
||||
|
||||
def timer_started(self, source_id, data):
|
||||
for module in self.modules:
|
||||
if module.id != source_id:
|
||||
module.start_timer(data)
|
||||
for module_id, connector in self._connectors_by_module_id.items():
|
||||
if module_id == source_id:
|
||||
continue
|
||||
|
||||
try:
|
||||
connector.start_timer(data)
|
||||
except Exception:
|
||||
self.log.info(
|
||||
"Failed to start timer on connector {}".format(
|
||||
str(connector)
|
||||
)
|
||||
)
|
||||
|
||||
self.last_task = data
|
||||
self.is_running = True
|
||||
|
||||
def timer_stopped(self, source_id):
|
||||
for module in self.modules:
|
||||
if module.id != source_id:
|
||||
module.stop_timer()
|
||||
for module_id, connector in self._connectors_by_module_id.items():
|
||||
if module_id == source_id:
|
||||
continue
|
||||
|
||||
try:
|
||||
connector.stop_timer()
|
||||
except Exception:
|
||||
self.log.info(
|
||||
"Failed to stop timer on connector {}".format(
|
||||
str(connector)
|
||||
)
|
||||
)
|
||||
|
||||
def restart_timers(self):
|
||||
if self.last_task is not None:
|
||||
|
|
@ -120,15 +209,40 @@ class TimersManager(OpenPypeModule, ITrayService, IIdleManager):
|
|||
self.widget_user_idle.refresh_context()
|
||||
self.is_running = False
|
||||
|
||||
for module in self.modules:
|
||||
module.stop_timer()
|
||||
self.timer_stopper(None)
|
||||
|
||||
def connect_with_modules(self, enabled_modules):
|
||||
for module in enabled_modules:
|
||||
if not isinstance(module, ITimersManager):
|
||||
connector = getattr(module, "timers_manager_connector", None)
|
||||
if connector is None:
|
||||
continue
|
||||
module.timer_manager_module = self
|
||||
self.modules.append(module)
|
||||
|
||||
missing_methods = set()
|
||||
for method_name in self._required_methods:
|
||||
if not hasattr(connector, method_name):
|
||||
missing_methods.add(method_name)
|
||||
|
||||
if missing_methods:
|
||||
joined = ", ".join(
|
||||
['"{}"'.format(name for name in missing_methods)]
|
||||
)
|
||||
self.log.info((
|
||||
"Module \"{}\" has missing required methods {}."
|
||||
).format(module.name, joined))
|
||||
continue
|
||||
|
||||
self._connectors_by_module_id[module.id] = connector
|
||||
self._modules_by_id[module.id] = module
|
||||
|
||||
# Optional method
|
||||
if hasattr(connector, "register_timers_manager"):
|
||||
try:
|
||||
connector.register_timers_manager(self)
|
||||
except Exception:
|
||||
self.log.info((
|
||||
"Failed to register timers manager"
|
||||
" for connector of module \"{}\"."
|
||||
).format(module.name))
|
||||
|
||||
def callbacks_by_idle_time(self):
|
||||
"""Implementation of IIdleManager interface."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue