From ac6238c9385efee5af259c7ff6c54e43a08af4d0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 1 Feb 2022 11:39:43 +0100 Subject: [PATCH] fetch project versions in thread to not stuck UI --- openpype/tools/settings/settings/widgets.py | 63 ++++++++++++++++----- openpype/tools/utils/__init__.py | 4 +- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index 4bab67dba5..85610f7c19 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -1,5 +1,6 @@ import os import copy +import uuid from Qt import QtWidgets, QtCore, QtGui from avalon.vendor import qtawesome from avalon.mongodb import ( @@ -12,7 +13,10 @@ from openpype.tools.utils.widgets import ImageButton from openpype.tools.utils.lib import paint_image_with_color from openpype.widgets.nice_checkbox import NiceCheckbox -from openpype.tools.utils import PlaceholderLineEdit +from openpype.tools.utils import ( + PlaceholderLineEdit, + DynamicQThread +) from openpype.settings.lib import find_closest_version_for_projects from openpype.lib import get_openpype_version from .images import ( @@ -765,6 +769,8 @@ class SettingsNiceCheckbox(NiceCheckbox): class ProjectModel(QtGui.QStandardItemModel): + _update_versions = QtCore.Signal() + def __init__(self, only_active, *args, **kwargs): super(ProjectModel, self).__init__(*args, **kwargs) @@ -775,6 +781,7 @@ class ProjectModel(QtGui.QStandardItemModel): self._only_active = only_active self._default_item = None self._items_by_name = {} + self._versions_by_project = {} colors = get_objected_colors() font_color = colors["font"].get_qcolor() @@ -782,6 +789,33 @@ class ProjectModel(QtGui.QStandardItemModel): self._version_font_color = font_color self._current_version = get_openpype_version() + self._version_refresh_threads = [] + self._version_refresh_id = None + + self._update_versions.connect(self._on_update_versions_signal) + + def _on_update_versions_signal(self): + for project_name, version in self._versions_by_project.items(): + if project_name is None: + item = self._default_item + else: + item = self._items_by_name.get(project_name) + + if item and version != self._current_version: + item.setData(version, PROJECT_VERSION_ROLE) + + def _fetch_settings_versions(self): + """Used versions per project are loaded in thread to not stuck UI.""" + version_refresh_id = self._version_refresh_id + all_project_names = list(self._items_by_name.keys()) + all_project_names.append(None) + closest_by_project_name = find_closest_version_for_projects( + all_project_names + ) + if self._version_refresh_id == version_refresh_id: + self._versions_by_project = closest_by_project_name + self._update_versions.emit() + def flags(self, index): if index.column() == 1: index = self.index(index.row(), 0, index.parent()) @@ -791,6 +825,9 @@ class ProjectModel(QtGui.QStandardItemModel): self.dbcon = dbcon def refresh(self): + # Change id of versions refresh + self._version_refresh_id = uuid.uuid4() + new_items = [] if self._default_item is None: item = QtGui.QStandardItem(DEFAULT_PROJECT_LABEL) @@ -828,20 +865,6 @@ class ProjectModel(QtGui.QStandardItemModel): font.setItalic(True) item.setFont(font) - # TODO this could be threaded - all_project_names = list(project_names) - all_project_names.append(None) - closes_by_project_name = find_closest_version_for_projects( - all_project_names - ) - for project_name, version in closes_by_project_name.items(): - if project_name is None: - item = self._default_item - else: - item = self._items_by_name.get(project_name) - - if item and version != self._current_version: - item.setData(version, PROJECT_VERSION_ROLE) root_item = self.invisibleRootItem() for project_name in tuple(self._items_by_name.keys()): if project_name not in project_names: @@ -851,6 +874,16 @@ class ProjectModel(QtGui.QStandardItemModel): if new_items: root_item.appendRows(new_items) + # Fetch versions per project in thread + thread = DynamicQThread(self._fetch_settings_versions) + self._version_refresh_threads.append(thread) + thread.start() + + # Cleanup done threads + for thread in tuple(self._version_refresh_threads): + if thread.isFinished(): + self._version_refresh_threads.remove(thread) + def data(self, index, role=QtCore.Qt.DisplayRole): if index.column() == 1: if role == QtCore.Qt.TextAlignmentRole: diff --git a/openpype/tools/utils/__init__.py b/openpype/tools/utils/__init__.py index 2f13eeb9db..dbe6b27a39 100644 --- a/openpype/tools/utils/__init__.py +++ b/openpype/tools/utils/__init__.py @@ -10,7 +10,8 @@ from .lib import ( WrappedCallbackItem, paint_image_with_color, get_warning_pixmap, - set_style_property + set_style_property, + DynamicQThread, ) @@ -26,4 +27,5 @@ __all__ = ( "paint_image_with_color", "get_warning_pixmap", "set_style_property", + "DynamicQThread", )