diff --git a/client/ayon_core/tools/tray/pype_tray.py b/client/ayon_core/tools/tray/pype_tray.py index cf42fb3c59..bba1856def 100644 --- a/client/ayon_core/tools/tray/pype_tray.py +++ b/client/ayon_core/tools/tray/pype_tray.py @@ -14,22 +14,17 @@ from ayon_core.lib import ( run_detached_process, ) from ayon_core.lib.openpype_version import ( - op_version_control_available, get_expected_version, - get_installed_version, - is_current_version_studio_latest, - is_current_version_higher_than_expected, is_running_from_build, - get_openpype_version, - is_running_staging, - is_staging_enabled, ) -from ayon_core.modules import TrayModulesManager +from ayon_core.addon import ( + ITrayAction, + ITrayService, + TrayAddonsManager, +) from ayon_core.settings import get_system_settings from ayon_core.tools.utils import ( WrappedCallbackItem, - paint_image_with_color, - get_warning_pixmap, get_openpype_qt_app, ) @@ -73,250 +68,6 @@ class PixmapLabel(QtWidgets.QLabel): super(PixmapLabel, self).resizeEvent(event) -class VersionUpdateDialog(QtWidgets.QDialog): - restart_requested = QtCore.Signal() - ignore_requested = QtCore.Signal() - - _min_width = 400 - _min_height = 130 - - def __init__(self, parent=None): - super(VersionUpdateDialog, self).__init__(parent) - - icon = QtGui.QIcon(resources.get_openpype_icon_filepath()) - self.setWindowIcon(icon) - self.setWindowFlags( - self.windowFlags() - | QtCore.Qt.WindowStaysOnTopHint - ) - - self.setMinimumWidth(self._min_width) - self.setMinimumHeight(self._min_height) - - top_widget = QtWidgets.QWidget(self) - - gift_pixmap = self._get_gift_pixmap() - gift_icon_label = PixmapLabel(gift_pixmap, top_widget) - - label_widget = QtWidgets.QLabel(top_widget) - label_widget.setWordWrap(True) - - top_layout = QtWidgets.QHBoxLayout(top_widget) - top_layout.setSpacing(10) - top_layout.addWidget(gift_icon_label, 0, QtCore.Qt.AlignCenter) - top_layout.addWidget(label_widget, 1) - - ignore_btn = QtWidgets.QPushButton(self) - restart_btn = QtWidgets.QPushButton(self) - restart_btn.setObjectName("TrayRestartButton") - - btns_layout = QtWidgets.QHBoxLayout() - btns_layout.addStretch(1) - btns_layout.addWidget(ignore_btn, 0) - btns_layout.addWidget(restart_btn, 0) - - layout = QtWidgets.QVBoxLayout(self) - layout.addWidget(top_widget, 0) - layout.addStretch(1) - layout.addLayout(btns_layout, 0) - - ignore_btn.clicked.connect(self._on_ignore) - restart_btn.clicked.connect(self._on_reset) - - self._label_widget = label_widget - self._gift_icon_label = gift_icon_label - self._ignore_btn = ignore_btn - self._restart_btn = restart_btn - - self._restart_accepted = False - self._current_is_higher = False - - self.setStyleSheet(style.load_stylesheet()) - - def _get_gift_pixmap(self): - image_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "images", - "gifts.png" - ) - src_image = QtGui.QImage(image_path) - color_value = style.get_objected_colors("font") - - return paint_image_with_color( - src_image, - color_value.get_qcolor() - ) - - def showEvent(self, event): - super(VersionUpdateDialog, self).showEvent(event) - self._restart_accepted = False - - def closeEvent(self, event): - super(VersionUpdateDialog, self).closeEvent(event) - if self._restart_accepted or self._current_is_higher: - return - # Trigger ignore requested only if restart was not clicked and current - # version is lower - self.ignore_requested.emit() - - def update_versions( - self, current_version, expected_version, current_is_higher - ): - if not current_is_higher: - title = "OpenPype update is needed" - label_message = ( - "Running OpenPype version is {}." - " Your production has been updated to version {}." - ).format(str(current_version), str(expected_version)) - ignore_label = "Later" - restart_label = "Restart && Update" - else: - title = "OpenPype version is higher" - label_message = ( - "Running OpenPype version is {}." - " Your production uses version {}." - ).format(str(current_version), str(expected_version)) - ignore_label = "Ignore" - restart_label = "Restart && Change" - - self.setWindowTitle(title) - - self._current_is_higher = current_is_higher - - self._gift_icon_label.setVisible(not current_is_higher) - - self._label_widget.setText(label_message) - self._ignore_btn.setText(ignore_label) - self._restart_btn.setText(restart_label) - - def _on_ignore(self): - self.reject() - - def _on_reset(self): - self._restart_accepted = True - self.restart_requested.emit() - self.accept() - - -class ProductionStagingDialog(QtWidgets.QDialog): - """Tell user that he has enabled staging but is in production version. - - This is showed only when staging is enabled with '--use-staging' and it's - version is the same as production's version. - """ - - def __init__(self, parent=None): - super(ProductionStagingDialog, self).__init__(parent) - - icon = QtGui.QIcon(resources.get_openpype_icon_filepath()) - self.setWindowIcon(icon) - self.setWindowTitle("Production and Staging versions are the same") - self.setWindowFlags( - self.windowFlags() - | QtCore.Qt.WindowStaysOnTopHint - ) - - top_widget = QtWidgets.QWidget(self) - - staging_pixmap = QtGui.QPixmap( - resources.get_openpype_staging_icon_filepath() - ) - staging_icon_label = PixmapLabel(staging_pixmap, top_widget) - message = ( - "Because production and staging versions are the same" - " your changes and work will affect both." - ) - content_label = QtWidgets.QLabel(message, self) - content_label.setWordWrap(True) - - top_layout = QtWidgets.QHBoxLayout(top_widget) - top_layout.setContentsMargins(0, 0, 0, 0) - top_layout.setSpacing(10) - top_layout.addWidget( - staging_icon_label, 0, - QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter - ) - top_layout.addWidget(content_label, 1) - - footer_widget = QtWidgets.QWidget(self) - ok_btn = QtWidgets.QPushButton("I understand", footer_widget) - - footer_layout = QtWidgets.QHBoxLayout(footer_widget) - footer_layout.setContentsMargins(0, 0, 0, 0) - footer_layout.addStretch(1) - footer_layout.addWidget(ok_btn) - - main_layout = QtWidgets.QVBoxLayout(self) - main_layout.addWidget(top_widget, 0) - main_layout.addStretch(1) - main_layout.addWidget(footer_widget, 0) - - self.setStyleSheet(style.load_stylesheet()) - self.resize(400, 140) - - ok_btn.clicked.connect(self._on_ok_clicked) - - def _on_ok_clicked(self): - self.close() - - -class BuildVersionDialog(QtWidgets.QDialog): - """Build/Installation version is too low for current OpenPype version. - - This dialog tells to user that it's build OpenPype is too old. - """ - def __init__(self, parent=None): - super(BuildVersionDialog, self).__init__(parent) - - icon = QtGui.QIcon(resources.get_openpype_icon_filepath()) - self.setWindowIcon(icon) - self.setWindowTitle("Outdated OpenPype installation") - self.setWindowFlags( - self.windowFlags() - | QtCore.Qt.WindowStaysOnTopHint - ) - - top_widget = QtWidgets.QWidget(self) - - warning_pixmap = get_warning_pixmap() - warning_icon_label = PixmapLabel(warning_pixmap, top_widget) - - message = ( - "Your installation of OpenPype does not match minimum" - " requirements.

Please update OpenPype installation" - " to newer version." - ) - content_label = QtWidgets.QLabel(message, self) - - top_layout = QtWidgets.QHBoxLayout(top_widget) - top_layout.setContentsMargins(0, 0, 0, 0) - top_layout.addWidget( - warning_icon_label, 0, - QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter - ) - top_layout.addWidget(content_label, 1) - - footer_widget = QtWidgets.QWidget(self) - ok_btn = QtWidgets.QPushButton("I understand", footer_widget) - - footer_layout = QtWidgets.QHBoxLayout(footer_widget) - footer_layout.setContentsMargins(0, 0, 0, 0) - footer_layout.addStretch(1) - footer_layout.addWidget(ok_btn) - - main_layout = QtWidgets.QVBoxLayout(self) - main_layout.addWidget(top_widget, 0) - main_layout.addStretch(1) - main_layout.addWidget(footer_widget, 0) - - self.setStyleSheet(style.load_stylesheet()) - - ok_btn.clicked.connect(self._on_ok_clicked) - - def _on_ok_clicked(self): - self.close() - - class TrayManager: """Cares about context of application. @@ -340,13 +91,10 @@ class TrayManager: version_check_interval = 5 self._version_check_interval = version_check_interval * 60 * 1000 - self.modules_manager = TrayModulesManager() + self._addons_manager = TrayAddonsManager() self.errors = [] - self._version_check_timer = None - self._version_dialog = None - self.main_thread_timer = None self._main_thread_callbacks = collections.deque() self._execution_in_progress = None @@ -354,8 +102,8 @@ class TrayManager: @property def doubleclick_callback(self): """Double-click callback for Tray icon.""" - callback_name = self.modules_manager.doubleclick_callback - return self.modules_manager.doubleclick_callbacks.get(callback_name) + callback_name = self._addons_manager.doubleclick_callback + return self._addons_manager.doubleclick_callbacks.get(callback_name) def execute_doubleclick(self): """Execute double click callback in main thread.""" @@ -363,79 +111,9 @@ class TrayManager: if callback: self.execute_in_main_thread(callback) - def _on_version_check_timer(self): - # Check if is running from build and stop future validations if yes - if not is_running_from_build() or not op_version_control_available(): - self._version_check_timer.stop() - return - - self.validate_openpype_version() - - def validate_openpype_version(self): - using_requested = is_current_version_studio_latest() - # TODO Handle situations when version can't be detected - if using_requested is None: - using_requested = True - - self._restart_action.setVisible(not using_requested) - if using_requested: - if ( - self._version_dialog is not None - and self._version_dialog.isVisible() - ): - self._version_dialog.close() - return - - installed_version = get_installed_version() - expected_version = get_expected_version() - - # Request new build if is needed - if ( - # Backwards compatibility - not hasattr(expected_version, "is_compatible") - or not expected_version.is_compatible(installed_version) - ): - if ( - self._version_dialog is not None - and self._version_dialog.isVisible() - ): - self._version_dialog.close() - - dialog = BuildVersionDialog() - dialog.exec_() - return - - if self._version_dialog is None: - self._version_dialog = VersionUpdateDialog() - self._version_dialog.restart_requested.connect( - self._restart_and_install - ) - self._version_dialog.ignore_requested.connect( - self._outdated_version_ignored - ) - - current_version = get_openpype_version() - current_is_higher = is_current_version_higher_than_expected() - - self._version_dialog.update_versions( - current_version, expected_version, current_is_higher - ) - self._version_dialog.show() - self._version_dialog.raise_() - self._version_dialog.activateWindow() - def _restart_and_install(self): self.restart(use_expected_version=True) - def _outdated_version_ignored(self): - self.show_tray_message( - "OpenPype version is outdated", - ( - "Please update your OpenPype as soon as possible." - " To update, restart OpenPype Tray application." - ) - ) - def execute_in_main_thread(self, callback, *args, **kwargs): if isinstance(callback, WrappedCallbackItem): item = callback @@ -458,13 +136,9 @@ class TrayManager: self._execution_in_progress = False def initialize_modules(self): - """Add modules to tray.""" - from ayon_core.modules import ( - ITrayAction, - ITrayService - ) + """Add addons to tray.""" - self.modules_manager.initialize(self, self.tray_widget.menu) + self._addons_manager.initialize(self, self.tray_widget.menu) admin_submenu = ITrayAction.admin_submenu(self.tray_widget.menu) self.tray_widget.menu.addMenu(admin_submenu) @@ -484,10 +158,10 @@ class TrayManager: self.tray_widget.menu.addAction(exit_action) # Tell each module which modules were imported - self.modules_manager.start_modules() + self._addons_manager.start_addons() # Print time report - self.modules_manager.print_report() + self._addons_manager.print_report() # create timer loop to check callback functions main_thread_timer = QtCore.QTimer() @@ -497,27 +171,11 @@ class TrayManager: self.main_thread_timer = main_thread_timer - version_check_timer = QtCore.QTimer() - if self._version_check_interval > 0: - version_check_timer.timeout.connect(self._on_version_check_timer) - version_check_timer.setInterval(self._version_check_interval) - version_check_timer.start() - self._version_check_timer = version_check_timer - self.execute_in_main_thread(self._startup_validations) def _startup_validations(self): """Run possible startup validations.""" - # Trigger version validation on start - self._version_check_timer.timeout.emit() - - if not op_version_control_available(): - dialog = BuildVersionDialog() - dialog.exec_() - - elif is_staging_enabled() and not is_running_staging(): - dialog = ProductionStagingDialog() - dialog.exec_() + pass def show_tray_message(self, title, message, icon=None, msecs=None): """Show tray message. @@ -638,7 +296,7 @@ class TrayManager: self.tray_widget.exit() def on_exit(self): - self.modules_manager.on_exit() + self._addons_manager.on_exit() def _on_version_action(self): if self.pype_info_widget is None: @@ -812,10 +470,10 @@ def main(): starter = PypeTrayStarter(app) # TODO remove when pype.exe will have an icon - if os.name == "nt": + if not is_running_from_build() and os.name == "nt": import ctypes ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( - u"pype_tray" + u"ayon_tray" ) sys.exit(app.exec_())