mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 13:24:54 +01:00
Merge pull request #5867 from ynput/bugfix/launcher-refresh-issues
This commit is contained in:
commit
18070ed7a1
7 changed files with 86 additions and 60 deletions
|
|
@ -3,7 +3,7 @@ from qtpy import QtWidgets, QtCore
|
|||
from openpype.tools.flickcharm import FlickCharm
|
||||
from openpype.tools.utils import PlaceholderLineEdit, RefreshButton
|
||||
from openpype.tools.ayon_utils.widgets import (
|
||||
ProjectsModel,
|
||||
ProjectsQtModel,
|
||||
ProjectSortFilterProxy,
|
||||
)
|
||||
from openpype.tools.ayon_utils.models import PROJECTS_MODEL_SENDER
|
||||
|
|
@ -95,7 +95,7 @@ class ProjectsWidget(QtWidgets.QWidget):
|
|||
projects_view.setSelectionMode(QtWidgets.QListView.NoSelection)
|
||||
flick = FlickCharm(parent=self)
|
||||
flick.activateOn(projects_view)
|
||||
projects_model = ProjectsModel(controller)
|
||||
projects_model = ProjectsQtModel(controller)
|
||||
projects_proxy_model = ProjectSortFilterProxy()
|
||||
projects_proxy_model.setSourceModel(projects_model)
|
||||
|
||||
|
|
@ -133,9 +133,14 @@ class ProjectsWidget(QtWidgets.QWidget):
|
|||
return self._projects_model.has_content()
|
||||
|
||||
def _on_view_clicked(self, index):
|
||||
if index.isValid():
|
||||
project_name = index.data(QtCore.Qt.DisplayRole)
|
||||
self._controller.set_selected_project(project_name)
|
||||
if not index.isValid():
|
||||
return
|
||||
model = index.model()
|
||||
flags = model.flags(index)
|
||||
if not flags & QtCore.Qt.ItemIsEnabled:
|
||||
return
|
||||
project_name = index.data(QtCore.Qt.DisplayRole)
|
||||
self._controller.set_selected_project(project_name)
|
||||
|
||||
def _on_project_filter_change(self, text):
|
||||
self._projects_proxy_model.setFilterFixedString(text)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from openpype.tools.utils import (
|
|||
from openpype.style import get_objected_colors
|
||||
|
||||
from openpype.tools.ayon_utils.widgets import (
|
||||
FoldersModel,
|
||||
FoldersQtModel,
|
||||
FOLDERS_MODEL_SENDER_NAME,
|
||||
)
|
||||
from openpype.tools.ayon_utils.widgets.folders_widget import FOLDER_ID_ROLE
|
||||
|
|
@ -182,7 +182,7 @@ class UnderlinesFolderDelegate(QtWidgets.QItemDelegate):
|
|||
painter.restore()
|
||||
|
||||
|
||||
class LoaderFoldersModel(FoldersModel):
|
||||
class LoaderFoldersModel(FoldersQtModel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LoaderFoldersModel, self).__init__(*args, **kwargs)
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ def _get_project_items_from_entitiy(projects):
|
|||
|
||||
class ProjectsModel(object):
|
||||
def __init__(self, controller):
|
||||
self._projects_cache = CacheItem(default_factory=dict)
|
||||
self._projects_cache = CacheItem(default_factory=list)
|
||||
self._project_items_by_name = {}
|
||||
self._projects_by_name = {}
|
||||
|
||||
|
|
@ -103,8 +103,18 @@ class ProjectsModel(object):
|
|||
self._refresh_projects_cache()
|
||||
|
||||
def get_project_items(self, sender):
|
||||
"""
|
||||
|
||||
Args:
|
||||
sender (str): Name of sender who asked for items.
|
||||
|
||||
Returns:
|
||||
Union[list[ProjectItem], None]: List of project items, or None
|
||||
if model is refreshing.
|
||||
"""
|
||||
|
||||
if not self._projects_cache.is_valid:
|
||||
self._refresh_projects_cache(sender)
|
||||
return self._refresh_projects_cache(sender)
|
||||
return self._projects_cache.get_data()
|
||||
|
||||
def get_project_entity(self, project_name):
|
||||
|
|
@ -136,11 +146,12 @@ class ProjectsModel(object):
|
|||
|
||||
def _refresh_projects_cache(self, sender=None):
|
||||
if self._is_refreshing:
|
||||
return
|
||||
return None
|
||||
|
||||
with self._project_refresh_event_manager(sender):
|
||||
project_items = self._query_projects()
|
||||
self._projects_cache.update_data(project_items)
|
||||
return self._projects_cache.get_data()
|
||||
|
||||
def _query_projects(self):
|
||||
projects = ayon_api.get_projects(fields=["name", "active", "library"])
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
from .projects_widget import (
|
||||
# ProjectsWidget,
|
||||
ProjectsCombobox,
|
||||
ProjectsModel,
|
||||
ProjectsQtModel,
|
||||
ProjectSortFilterProxy,
|
||||
)
|
||||
|
||||
from .folders_widget import (
|
||||
FoldersWidget,
|
||||
FoldersModel,
|
||||
FoldersQtModel,
|
||||
FOLDERS_MODEL_SENDER_NAME,
|
||||
)
|
||||
|
||||
from .tasks_widget import (
|
||||
TasksWidget,
|
||||
TasksModel,
|
||||
TasksQtModel,
|
||||
TASKS_MODEL_SENDER_NAME,
|
||||
)
|
||||
from .utils import (
|
||||
|
|
@ -25,15 +25,15 @@ from .utils import (
|
|||
__all__ = (
|
||||
# "ProjectsWidget",
|
||||
"ProjectsCombobox",
|
||||
"ProjectsModel",
|
||||
"ProjectsQtModel",
|
||||
"ProjectSortFilterProxy",
|
||||
|
||||
"FoldersWidget",
|
||||
"FoldersModel",
|
||||
"FoldersQtModel",
|
||||
"FOLDERS_MODEL_SENDER_NAME",
|
||||
|
||||
"TasksWidget",
|
||||
"TasksModel",
|
||||
"TasksQtModel",
|
||||
"TASKS_MODEL_SENDER_NAME",
|
||||
|
||||
"get_qt_icon",
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ FOLDER_PATH_ROLE = QtCore.Qt.UserRole + 3
|
|||
FOLDER_TYPE_ROLE = QtCore.Qt.UserRole + 4
|
||||
|
||||
|
||||
class FoldersModel(QtGui.QStandardItemModel):
|
||||
class FoldersQtModel(QtGui.QStandardItemModel):
|
||||
"""Folders model which cares about refresh of folders.
|
||||
|
||||
Args:
|
||||
|
|
@ -26,7 +26,7 @@ class FoldersModel(QtGui.QStandardItemModel):
|
|||
refreshed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller):
|
||||
super(FoldersModel, self).__init__()
|
||||
super(FoldersQtModel, self).__init__()
|
||||
|
||||
self._controller = controller
|
||||
self._items_by_id = {}
|
||||
|
|
@ -104,8 +104,8 @@ class FoldersModel(QtGui.QStandardItemModel):
|
|||
|
||||
if not project_name:
|
||||
self._last_project_name = project_name
|
||||
self._current_refresh_thread = None
|
||||
self._fill_items({})
|
||||
self._current_refresh_thread = None
|
||||
return
|
||||
|
||||
self._is_refreshing = True
|
||||
|
|
@ -152,6 +152,7 @@ class FoldersModel(QtGui.QStandardItemModel):
|
|||
return
|
||||
|
||||
self._fill_items(thread.get_result())
|
||||
self._current_refresh_thread = None
|
||||
|
||||
def _fill_item_data(self, item, folder_item):
|
||||
"""
|
||||
|
|
@ -281,7 +282,7 @@ class FoldersWidget(QtWidgets.QWidget):
|
|||
folders_view = TreeView(self)
|
||||
folders_view.setHeaderHidden(True)
|
||||
|
||||
folders_model = FoldersModel(controller)
|
||||
folders_model = FoldersQtModel(controller)
|
||||
folders_proxy_model = RecursiveSortFilterProxyModel()
|
||||
folders_proxy_model.setSourceModel(folders_model)
|
||||
folders_proxy_model.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ PROJECT_IS_CURRENT_ROLE = QtCore.Qt.UserRole + 4
|
|||
LIBRARY_PROJECT_SEPARATOR_ROLE = QtCore.Qt.UserRole + 5
|
||||
|
||||
|
||||
class ProjectsModel(QtGui.QStandardItemModel):
|
||||
class ProjectsQtModel(QtGui.QStandardItemModel):
|
||||
refreshed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller):
|
||||
super(ProjectsModel, self).__init__()
|
||||
super(ProjectsQtModel, self).__init__()
|
||||
self._controller = controller
|
||||
|
||||
self._project_items = {}
|
||||
|
|
@ -35,12 +35,11 @@ class ProjectsModel(QtGui.QStandardItemModel):
|
|||
|
||||
self._selected_project = None
|
||||
|
||||
self._is_refreshing = False
|
||||
self._refresh_thread = None
|
||||
|
||||
@property
|
||||
def is_refreshing(self):
|
||||
return self._is_refreshing
|
||||
return self._refresh_thread is not None
|
||||
|
||||
def refresh(self):
|
||||
self._refresh()
|
||||
|
|
@ -169,28 +168,33 @@ class ProjectsModel(QtGui.QStandardItemModel):
|
|||
return self._select_item
|
||||
|
||||
def _refresh(self):
|
||||
if self._is_refreshing:
|
||||
if self._refresh_thread is not None:
|
||||
return
|
||||
self._is_refreshing = True
|
||||
|
||||
refresh_thread = RefreshThread(
|
||||
"projects", self._query_project_items
|
||||
)
|
||||
refresh_thread.refresh_finished.connect(self._refresh_finished)
|
||||
refresh_thread.start()
|
||||
|
||||
self._refresh_thread = refresh_thread
|
||||
refresh_thread.start()
|
||||
|
||||
def _query_project_items(self):
|
||||
return self._controller.get_project_items()
|
||||
return self._controller.get_project_items(
|
||||
sender=PROJECTS_MODEL_SENDER
|
||||
)
|
||||
|
||||
def _refresh_finished(self):
|
||||
# TODO check if failed
|
||||
result = self._refresh_thread.get_result()
|
||||
if result is not None:
|
||||
self._fill_items(result)
|
||||
|
||||
self._refresh_thread = None
|
||||
|
||||
self._fill_items(result)
|
||||
|
||||
self._is_refreshing = False
|
||||
self.refreshed.emit()
|
||||
if result is None:
|
||||
self._refresh()
|
||||
else:
|
||||
self.refreshed.emit()
|
||||
|
||||
def _fill_items(self, project_items):
|
||||
new_project_names = {
|
||||
|
|
@ -403,7 +407,7 @@ class ProjectsCombobox(QtWidgets.QWidget):
|
|||
projects_combobox = QtWidgets.QComboBox(self)
|
||||
combobox_delegate = QtWidgets.QStyledItemDelegate(projects_combobox)
|
||||
projects_combobox.setItemDelegate(combobox_delegate)
|
||||
projects_model = ProjectsModel(controller)
|
||||
projects_model = ProjectsQtModel(controller)
|
||||
projects_proxy_model = ProjectSortFilterProxy()
|
||||
projects_proxy_model.setSourceModel(projects_model)
|
||||
projects_combobox.setModel(projects_proxy_model)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ ITEM_NAME_ROLE = QtCore.Qt.UserRole + 3
|
|||
TASK_TYPE_ROLE = QtCore.Qt.UserRole + 4
|
||||
|
||||
|
||||
class TasksModel(QtGui.QStandardItemModel):
|
||||
class TasksQtModel(QtGui.QStandardItemModel):
|
||||
"""Tasks model which cares about refresh of tasks by folder id.
|
||||
|
||||
Args:
|
||||
|
|
@ -22,7 +22,7 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
refreshed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller):
|
||||
super(TasksModel, self).__init__()
|
||||
super(TasksQtModel, self).__init__()
|
||||
|
||||
self._controller = controller
|
||||
|
||||
|
|
@ -185,28 +185,7 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
thread.refresh_finished.connect(self._on_refresh_thread)
|
||||
thread.start()
|
||||
|
||||
def _on_refresh_thread(self, thread_id):
|
||||
"""Callback when refresh thread is finished.
|
||||
|
||||
Technically can be running multiple refresh threads at the same time,
|
||||
to avoid using values from wrong thread, we check if thread id is
|
||||
current refresh thread id.
|
||||
|
||||
Tasks are stored by name, so if a folder has same task name as
|
||||
previously selected folder it keeps the selection.
|
||||
|
||||
Args:
|
||||
thread_id (str): Thread id.
|
||||
"""
|
||||
|
||||
# Make sure to remove thread from '_refresh_threads' dict
|
||||
thread = self._refresh_threads.pop(thread_id)
|
||||
if (
|
||||
self._current_refresh_thread is None
|
||||
or thread_id != self._current_refresh_thread.id
|
||||
):
|
||||
return
|
||||
|
||||
def _fill_data_from_thread(self, thread):
|
||||
task_items = thread.get_result()
|
||||
# Task items are refreshed
|
||||
if task_items is None:
|
||||
|
|
@ -247,7 +226,33 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
if new_items:
|
||||
root_item.appendRows(new_items)
|
||||
|
||||
def _on_refresh_thread(self, thread_id):
|
||||
"""Callback when refresh thread is finished.
|
||||
|
||||
Technically can be running multiple refresh threads at the same time,
|
||||
to avoid using values from wrong thread, we check if thread id is
|
||||
current refresh thread id.
|
||||
|
||||
Tasks are stored by name, so if a folder has same task name as
|
||||
previously selected folder it keeps the selection.
|
||||
|
||||
Args:
|
||||
thread_id (str): Thread id.
|
||||
"""
|
||||
|
||||
# Make sure to remove thread from '_refresh_threads' dict
|
||||
thread = self._refresh_threads.pop(thread_id)
|
||||
if (
|
||||
self._current_refresh_thread is None
|
||||
or thread_id != self._current_refresh_thread.id
|
||||
):
|
||||
return
|
||||
|
||||
self._fill_data_from_thread(thread)
|
||||
|
||||
root_item = self.invisibleRootItem()
|
||||
self._has_content = root_item.rowCount() > 0
|
||||
self._current_refresh_thread = None
|
||||
self._is_refreshing = False
|
||||
self.refreshed.emit()
|
||||
|
||||
|
|
@ -280,7 +285,7 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
if section == 0:
|
||||
return "Tasks"
|
||||
|
||||
return super(TasksModel, self).headerData(
|
||||
return super(TasksQtModel, self).headerData(
|
||||
section, orientation, role
|
||||
)
|
||||
|
||||
|
|
@ -305,7 +310,7 @@ class TasksWidget(QtWidgets.QWidget):
|
|||
tasks_view = DeselectableTreeView(self)
|
||||
tasks_view.setIndentation(0)
|
||||
|
||||
tasks_model = TasksModel(controller)
|
||||
tasks_model = TasksQtModel(controller)
|
||||
tasks_proxy_model = QtCore.QSortFilterProxyModel()
|
||||
tasks_proxy_model.setSourceModel(tasks_model)
|
||||
tasks_proxy_model.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue