mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
AYON Launcher tool: Fix refresh btn (#5685)
* rename 'refresh' to 'set_context' in 'TasksModel' * implemented 'refresh' for folders and tasks widgets * propagate refresh to all widgets * don't use 'clear' of 'QStandardItemModel' * change lifetime of folders cache to a minute * added 'refresh_actions' method to launcher to skip clear cache of folders * shorten line * sorting is not case sensitive
This commit is contained in:
parent
12f4128901
commit
2ea8d6530f
9 changed files with 124 additions and 42 deletions
|
|
@ -295,3 +295,13 @@ class AbstractLauncherFrontEnd(AbstractLauncherCommon):
|
|||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def refresh_actions(self):
|
||||
"""Refresh actions and all related data.
|
||||
|
||||
Triggers 'controller.refresh.actions.started' event at the beginning
|
||||
and 'controller.refresh.actions.finished' at the end.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -145,5 +145,17 @@ class BaseLauncherController(
|
|||
|
||||
self._emit_event("controller.refresh.finished")
|
||||
|
||||
def refresh_actions(self):
|
||||
self._emit_event("controller.refresh.actions.started")
|
||||
|
||||
# Refresh project settings (used for actions discovery)
|
||||
self._project_settings = {}
|
||||
# Refresh projects - they define applications
|
||||
self._projects_model.reset()
|
||||
# Refresh actions
|
||||
self._actions_model.refresh()
|
||||
|
||||
self._emit_event("controller.refresh.actions.finished")
|
||||
|
||||
def _emit_event(self, topic, data=None):
|
||||
self.emit_event(topic, data, "controller")
|
||||
|
|
|
|||
|
|
@ -46,10 +46,6 @@ class ActionsQtModel(QtGui.QStandardItemModel):
|
|||
def __init__(self, controller):
|
||||
super(ActionsQtModel, self).__init__()
|
||||
|
||||
controller.register_event_callback(
|
||||
"controller.refresh.finished",
|
||||
self._on_controller_refresh_finished,
|
||||
)
|
||||
controller.register_event_callback(
|
||||
"selection.project.changed",
|
||||
self._on_selection_project_changed,
|
||||
|
|
@ -170,13 +166,6 @@ class ActionsQtModel(QtGui.QStandardItemModel):
|
|||
self._action_items_by_id = action_items_by_id
|
||||
self.refreshed.emit()
|
||||
|
||||
def _on_controller_refresh_finished(self):
|
||||
context = self._controller.get_selected_context()
|
||||
self._selected_project_name = context["project_name"]
|
||||
self._selected_folder_id = context["folder_id"]
|
||||
self._selected_task_id = context["task_id"]
|
||||
self.refresh()
|
||||
|
||||
def _on_selection_project_changed(self, event):
|
||||
self._selected_project_name = event["project_name"]
|
||||
self._selected_folder_id = None
|
||||
|
|
@ -361,6 +350,9 @@ class ActionsWidget(QtWidgets.QWidget):
|
|||
|
||||
self._set_row_height(1)
|
||||
|
||||
def refresh(self):
|
||||
self._model.refresh()
|
||||
|
||||
def _set_row_height(self, rows):
|
||||
self.setMinimumHeight(rows * 75)
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,10 @@ class HierarchyPage(QtWidgets.QWidget):
|
|||
if visible and project_name:
|
||||
self._projects_combobox.set_selection(project_name)
|
||||
|
||||
def refresh(self):
|
||||
self._folders_widget.refresh()
|
||||
self._tasks_widget.refresh()
|
||||
|
||||
def _on_back_clicked(self):
|
||||
self._controller.set_selected_project(None)
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ class ProjectIconView(QtWidgets.QListView):
|
|||
|
||||
class ProjectsWidget(QtWidgets.QWidget):
|
||||
"""Projects Page"""
|
||||
|
||||
refreshed = QtCore.Signal()
|
||||
|
||||
def __init__(self, controller, parent=None):
|
||||
super(ProjectsWidget, self).__init__(parent=parent)
|
||||
|
||||
|
|
@ -104,6 +107,7 @@ class ProjectsWidget(QtWidgets.QWidget):
|
|||
main_layout.addWidget(projects_view, 1)
|
||||
|
||||
projects_view.clicked.connect(self._on_view_clicked)
|
||||
projects_model.refreshed.connect(self.refreshed)
|
||||
projects_filter_text.textChanged.connect(
|
||||
self._on_project_filter_change)
|
||||
refresh_btn.clicked.connect(self._on_refresh_clicked)
|
||||
|
|
@ -119,6 +123,15 @@ class ProjectsWidget(QtWidgets.QWidget):
|
|||
self._projects_model = projects_model
|
||||
self._projects_proxy_model = projects_proxy_model
|
||||
|
||||
def has_content(self):
|
||||
"""Model has at least one project.
|
||||
|
||||
Returns:
|
||||
bool: True if there is any content in the model.
|
||||
"""
|
||||
|
||||
return self._projects_model.has_content()
|
||||
|
||||
def _on_view_clicked(self, index):
|
||||
if index.isValid():
|
||||
project_name = index.data(QtCore.Qt.DisplayRole)
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ class LauncherWindow(QtWidgets.QWidget):
|
|||
message_timer.setInterval(self.message_interval)
|
||||
message_timer.setSingleShot(True)
|
||||
|
||||
refresh_timer = QtCore.QTimer()
|
||||
refresh_timer.setInterval(self.refresh_interval)
|
||||
actions_refresh_timer = QtCore.QTimer()
|
||||
actions_refresh_timer.setInterval(self.refresh_interval)
|
||||
|
||||
page_slide_anim = QtCore.QVariantAnimation(self)
|
||||
page_slide_anim.setDuration(self.page_side_anim_interval)
|
||||
|
|
@ -108,8 +108,10 @@ class LauncherWindow(QtWidgets.QWidget):
|
|||
page_slide_anim.setEndValue(1.0)
|
||||
page_slide_anim.setEasingCurve(QtCore.QEasingCurve.OutQuad)
|
||||
|
||||
projects_page.refreshed.connect(self._on_projects_refresh)
|
||||
message_timer.timeout.connect(self._on_message_timeout)
|
||||
refresh_timer.timeout.connect(self._on_refresh_timeout)
|
||||
actions_refresh_timer.timeout.connect(
|
||||
self._on_actions_refresh_timeout)
|
||||
page_slide_anim.valueChanged.connect(
|
||||
self._on_page_slide_value_changed)
|
||||
page_slide_anim.finished.connect(self._on_page_slide_finished)
|
||||
|
|
@ -132,6 +134,7 @@ class LauncherWindow(QtWidgets.QWidget):
|
|||
self._is_on_projects_page = True
|
||||
self._window_is_active = False
|
||||
self._refresh_on_activate = False
|
||||
self._selected_project_name = None
|
||||
|
||||
self._pages_widget = pages_widget
|
||||
self._pages_layout = pages_layout
|
||||
|
|
@ -143,7 +146,7 @@ class LauncherWindow(QtWidgets.QWidget):
|
|||
# self._action_history = action_history
|
||||
|
||||
self._message_timer = message_timer
|
||||
self._refresh_timer = refresh_timer
|
||||
self._actions_refresh_timer = actions_refresh_timer
|
||||
self._page_slide_anim = page_slide_anim
|
||||
|
||||
hierarchy_page.setVisible(not self._is_on_projects_page)
|
||||
|
|
@ -152,14 +155,14 @@ class LauncherWindow(QtWidgets.QWidget):
|
|||
def showEvent(self, event):
|
||||
super(LauncherWindow, self).showEvent(event)
|
||||
self._window_is_active = True
|
||||
if not self._refresh_timer.isActive():
|
||||
self._refresh_timer.start()
|
||||
if not self._actions_refresh_timer.isActive():
|
||||
self._actions_refresh_timer.start()
|
||||
self._controller.refresh()
|
||||
|
||||
def closeEvent(self, event):
|
||||
super(LauncherWindow, self).closeEvent(event)
|
||||
self._window_is_active = False
|
||||
self._refresh_timer.stop()
|
||||
self._actions_refresh_timer.stop()
|
||||
|
||||
def changeEvent(self, event):
|
||||
if event.type() in (
|
||||
|
|
@ -170,15 +173,15 @@ class LauncherWindow(QtWidgets.QWidget):
|
|||
self._window_is_active = is_active
|
||||
if is_active and self._refresh_on_activate:
|
||||
self._refresh_on_activate = False
|
||||
self._on_refresh_timeout()
|
||||
self._refresh_timer.start()
|
||||
self._on_actions_refresh_timeout()
|
||||
self._actions_refresh_timer.start()
|
||||
|
||||
super(LauncherWindow, self).changeEvent(event)
|
||||
|
||||
def _on_refresh_timeout(self):
|
||||
def _on_actions_refresh_timeout(self):
|
||||
# Stop timer if widget is not visible
|
||||
if self._window_is_active:
|
||||
self._controller.refresh()
|
||||
self._controller.refresh_actions()
|
||||
else:
|
||||
self._refresh_on_activate = True
|
||||
|
||||
|
|
@ -191,12 +194,26 @@ class LauncherWindow(QtWidgets.QWidget):
|
|||
|
||||
def _on_project_selection_change(self, event):
|
||||
project_name = event["project_name"]
|
||||
self._selected_project_name = project_name
|
||||
if not project_name:
|
||||
self._go_to_projects_page()
|
||||
|
||||
elif self._is_on_projects_page:
|
||||
self._go_to_hierarchy_page(project_name)
|
||||
|
||||
def _on_projects_refresh(self):
|
||||
# There is nothing to do, we're on projects page
|
||||
if self._is_on_projects_page:
|
||||
return
|
||||
|
||||
# No projects were found -> go back to projects page
|
||||
if not self._projects_page.has_content():
|
||||
self._go_to_projects_page()
|
||||
return
|
||||
|
||||
self._hierarchy_page.refresh()
|
||||
self._actions_widget.refresh()
|
||||
|
||||
def _on_action_trigger_started(self, event):
|
||||
self._echo("Running action: {}".format(event["full_label"]))
|
||||
|
||||
|
|
|
|||
|
|
@ -199,13 +199,18 @@ class HierarchyModel(object):
|
|||
Hierarchy items are folders and tasks. Folders can have as parent another
|
||||
folder or project. Tasks can have as parent only folder.
|
||||
"""
|
||||
lifetime = 60 # A minute
|
||||
|
||||
def __init__(self, controller):
|
||||
self._folders_items = NestedCacheItem(levels=1, default_factory=dict)
|
||||
self._folders_by_id = NestedCacheItem(levels=2, default_factory=dict)
|
||||
self._folders_items = NestedCacheItem(
|
||||
levels=1, default_factory=dict, lifetime=self.lifetime)
|
||||
self._folders_by_id = NestedCacheItem(
|
||||
levels=2, default_factory=dict, lifetime=self.lifetime)
|
||||
|
||||
self._task_items = NestedCacheItem(levels=2, default_factory=dict)
|
||||
self._tasks_by_id = NestedCacheItem(levels=2, default_factory=dict)
|
||||
self._task_items = NestedCacheItem(
|
||||
levels=2, default_factory=dict, lifetime=self.lifetime)
|
||||
self._tasks_by_id = NestedCacheItem(
|
||||
levels=2, default_factory=dict, lifetime=self.lifetime)
|
||||
|
||||
self._folders_refreshing = set()
|
||||
self._tasks_refreshing = set()
|
||||
|
|
|
|||
|
|
@ -56,11 +56,21 @@ class FoldersModel(QtGui.QStandardItemModel):
|
|||
|
||||
return self._has_content
|
||||
|
||||
def clear(self):
|
||||
def refresh(self):
|
||||
"""Refresh folders for last selected project.
|
||||
|
||||
Force to update folders model from controller. This may or may not
|
||||
trigger query from server, that's based on controller's cache.
|
||||
"""
|
||||
|
||||
self.set_project_name(self._last_project_name)
|
||||
|
||||
def _clear_items(self):
|
||||
self._items_by_id = {}
|
||||
self._parent_id_by_id = {}
|
||||
self._has_content = False
|
||||
super(FoldersModel, self).clear()
|
||||
root_item = self.invisibleRootItem()
|
||||
root_item.removeRows(0, root_item.rowCount())
|
||||
|
||||
def get_index_by_id(self, item_id):
|
||||
"""Get index by folder id.
|
||||
|
|
@ -90,7 +100,7 @@ class FoldersModel(QtGui.QStandardItemModel):
|
|||
self._is_refreshing = True
|
||||
|
||||
if self._last_project_name != project_name:
|
||||
self.clear()
|
||||
self._clear_items()
|
||||
self._last_project_name = project_name
|
||||
|
||||
thread = self._refresh_threads.get(project_name)
|
||||
|
|
@ -135,7 +145,7 @@ class FoldersModel(QtGui.QStandardItemModel):
|
|||
def _fill_items(self, folder_items_by_id):
|
||||
if not folder_items_by_id:
|
||||
if folder_items_by_id is not None:
|
||||
self.clear()
|
||||
self._clear_items()
|
||||
self._is_refreshing = False
|
||||
self.refreshed.emit()
|
||||
return
|
||||
|
|
@ -247,6 +257,7 @@ class FoldersWidget(QtWidgets.QWidget):
|
|||
folders_model = FoldersModel(controller)
|
||||
folders_proxy_model = RecursiveSortFilterProxyModel()
|
||||
folders_proxy_model.setSourceModel(folders_model)
|
||||
folders_proxy_model.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
|
||||
folders_view.setModel(folders_proxy_model)
|
||||
|
||||
|
|
@ -293,6 +304,14 @@ class FoldersWidget(QtWidgets.QWidget):
|
|||
|
||||
self._folders_proxy_model.setFilterFixedString(name)
|
||||
|
||||
def refresh(self):
|
||||
"""Refresh folders model.
|
||||
|
||||
Force to update folders model from controller.
|
||||
"""
|
||||
|
||||
self._folders_model.refresh()
|
||||
|
||||
def _on_project_selection_change(self, event):
|
||||
project_name = event["project_name"]
|
||||
self._set_project_name(project_name)
|
||||
|
|
@ -300,9 +319,6 @@ class FoldersWidget(QtWidgets.QWidget):
|
|||
def _set_project_name(self, project_name):
|
||||
self._folders_model.set_project_name(project_name)
|
||||
|
||||
def _clear(self):
|
||||
self._folders_model.clear()
|
||||
|
||||
def _on_folders_refresh_finished(self, event):
|
||||
if event["sender"] != SENDER_NAME:
|
||||
self._set_project_name(event["project_name"])
|
||||
|
|
|
|||
|
|
@ -44,14 +44,20 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
# Initial state
|
||||
self._add_invalid_selection_item()
|
||||
|
||||
def clear(self):
|
||||
def _clear_items(self):
|
||||
self._items_by_name = {}
|
||||
self._has_content = False
|
||||
self._remove_invalid_items()
|
||||
super(TasksModel, self).clear()
|
||||
root_item = self.invisibleRootItem()
|
||||
root_item.removeRows(0, root_item.rowCount())
|
||||
|
||||
def refresh(self, project_name, folder_id):
|
||||
"""Refresh tasks for folder.
|
||||
def refresh(self):
|
||||
"""Refresh tasks for last project and folder."""
|
||||
|
||||
self._refresh(self._last_project_name, self._last_folder_id)
|
||||
|
||||
def set_context(self, project_name, folder_id):
|
||||
"""Set context for which should be tasks showed.
|
||||
|
||||
Args:
|
||||
project_name (Union[str]): Name of project.
|
||||
|
|
@ -121,7 +127,7 @@ class TasksModel(QtGui.QStandardItemModel):
|
|||
return self._empty_tasks_item
|
||||
|
||||
def _add_invalid_item(self, item):
|
||||
self.clear()
|
||||
self._clear_items()
|
||||
root_item = self.invisibleRootItem()
|
||||
root_item.appendRow(item)
|
||||
|
||||
|
|
@ -299,6 +305,7 @@ class TasksWidget(QtWidgets.QWidget):
|
|||
tasks_model = TasksModel(controller)
|
||||
tasks_proxy_model = QtCore.QSortFilterProxyModel()
|
||||
tasks_proxy_model.setSourceModel(tasks_model)
|
||||
tasks_proxy_model.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
|
||||
tasks_view.setModel(tasks_proxy_model)
|
||||
|
||||
|
|
@ -334,8 +341,14 @@ class TasksWidget(QtWidgets.QWidget):
|
|||
self._handle_expected_selection = handle_expected_selection
|
||||
self._expected_selection_data = None
|
||||
|
||||
def _clear(self):
|
||||
self._tasks_model.clear()
|
||||
def refresh(self):
|
||||
"""Refresh folders for last selected project.
|
||||
|
||||
Force to update folders model from controller. This may or may not
|
||||
trigger query from server, that's based on controller's cache.
|
||||
"""
|
||||
|
||||
self._tasks_model.refresh()
|
||||
|
||||
def _on_tasks_refresh_finished(self, event):
|
||||
"""Tasks were refreshed in controller.
|
||||
|
|
@ -353,13 +366,13 @@ class TasksWidget(QtWidgets.QWidget):
|
|||
or event["folder_id"] != self._selected_folder_id
|
||||
):
|
||||
return
|
||||
self._tasks_model.refresh(
|
||||
self._tasks_model.set_context(
|
||||
event["project_name"], self._selected_folder_id
|
||||
)
|
||||
|
||||
def _folder_selection_changed(self, event):
|
||||
self._selected_folder_id = event["folder_id"]
|
||||
self._tasks_model.refresh(
|
||||
self._tasks_model.set_context(
|
||||
event["project_name"], self._selected_folder_id
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue