diff --git a/openpype/tools/launcher/constants.py b/openpype/tools/launcher/constants.py index e6dbbb6e192..7f394cb5ace 100644 --- a/openpype/tools/launcher/constants.py +++ b/openpype/tools/launcher/constants.py @@ -8,5 +8,5 @@ ANIMATION_START_ROLE = QtCore.Qt.UserRole + 4 ANIMATION_STATE_ROLE = QtCore.Qt.UserRole + 5 - -ANIMATION_LEN = 10 +# Animation length in seconds +ANIMATION_LEN = 7 diff --git a/openpype/tools/launcher/lib.py b/openpype/tools/launcher/lib.py index 65d40cd0df6..d6374f49d20 100644 --- a/openpype/tools/launcher/lib.py +++ b/openpype/tools/launcher/lib.py @@ -44,9 +44,12 @@ class ProjectHandler(QtCore.QObject): # Signal emmited when project has changed project_changed = QtCore.Signal(str) + projects_refreshed = QtCore.Signal() + timer_timeout = QtCore.Signal() def __init__(self, dbcon, model): super(ProjectHandler, self).__init__() + self._active = False # Store project model for usage self.model = model # Store dbcon @@ -54,6 +57,28 @@ def __init__(self, dbcon, model): self.current_project = dbcon.Session.get("AVALON_PROJECT") + refresh_timer = QtCore.QTimer() + refresh_timer.setInterval(self.refresh_interval) + refresh_timer.timeout.connect(self._on_timeout) + + self.refresh_timer = refresh_timer + + def _on_timeout(self): + if self._active: + self.timer_timeout.emit() + self.refresh_model() + + def set_active(self, active): + self._active = active + + def start_timer(self, trigger=False): + self.refresh_timer.start() + if trigger: + self._on_timeout() + + def stop_timer(self): + self.refresh_timer.stop() + def set_project(self, project_name): # Change current project of this handler self.current_project = project_name @@ -66,6 +91,7 @@ def set_project(self, project_name): def refresh_model(self): self.model.refresh() + self.projects_refreshed.emit() def get_action_icon(action): diff --git a/openpype/tools/launcher/models.py b/openpype/tools/launcher/models.py index 846a07e081e..4988829c116 100644 --- a/openpype/tools/launcher/models.py +++ b/openpype/tools/launcher/models.py @@ -122,7 +122,6 @@ def __init__(self, dbcon, parent=None): self.application_manager = ApplicationManager() - self._groups = {} self.default_icon = qtawesome.icon("fa.cube", color="white") # Cache of available actions self._registered_actions = list() @@ -138,14 +137,18 @@ def discover(self): actions.extend(app_actions) self._registered_actions = actions - self.items_by_id.clear() + + self.filter_actions() def get_application_actions(self): actions = [] if not self.dbcon.Session.get("AVALON_PROJECT"): return actions - project_doc = self.dbcon.find_one({"type": "project"}) + project_doc = self.dbcon.find_one( + {"type": "project"}, + {"config.apps": True} + ) if not project_doc: return actions @@ -182,16 +185,12 @@ def get_icon(self, action, skip_default=False): return icon def filter_actions(self): + self.items_by_id.clear() # Validate actions based on compatibility self.clear() - self.items_by_id.clear() - self._groups.clear() - actions = self.filter_compatible_actions(self._registered_actions) - self.beginResetModel() - single_actions = [] varianted_actions = collections.defaultdict(list) grouped_actions = collections.defaultdict(list) @@ -274,12 +273,17 @@ def filter_actions(self): items_by_order[order].append(item) + self.beginResetModel() + + items = [] for order in sorted(items_by_order.keys()): for item in items_by_order[order]: item_id = str(uuid.uuid4()) item.setData(item_id, ACTION_ID_ROLE) self.items_by_id[item_id] = item - self.appendRow(item) + items.append(item) + + self.invisibleRootItem().appendRows(items) self.endResetModel() diff --git a/openpype/tools/launcher/widgets.py b/openpype/tools/launcher/widgets.py index 048210115ca..35c7d98be16 100644 --- a/openpype/tools/launcher/widgets.py +++ b/openpype/tools/launcher/widgets.py @@ -40,16 +40,11 @@ def __init__(self, project_handler, parent=None): QtWidgets.QSizePolicy.Maximum ) - refresh_timer = QtCore.QTimer() - refresh_timer.setInterval(project_handler.refresh_interval) - self.project_handler = project_handler self.project_delegate = project_delegate self.project_combobox = project_combobox - self.refresh_timer = refresh_timer # Signals - refresh_timer.timeout.connect(self._on_refresh_timeout) self.project_combobox.currentIndexChanged.connect(self.on_index_change) project_handler.project_changed.connect(self._on_project_change) @@ -58,20 +53,6 @@ def __init__(self, project_handler, parent=None): if project_name: self.set_project(project_name) - def showEvent(self, event): - if not self.refresh_timer.isActive(): - self.refresh_timer.start() - super(ProjectBar, self).showEvent(event) - - def _on_refresh_timeout(self): - if not self.isVisible(): - # Stop timer if widget is not visible - self.refresh_timer.stop() - - elif self.isActiveWindow(): - # Refresh projects if window is active - self.project_handler.refresh_model() - def _on_project_change(self, project_name): if self.get_current_project() == project_name: return @@ -103,9 +84,10 @@ class ActionBar(QtWidgets.QWidget): action_clicked = QtCore.Signal(object) - def __init__(self, dbcon, parent=None): + def __init__(self, project_handler, dbcon, parent=None): super(ActionBar, self).__init__(parent) + self.project_handler = project_handler self.dbcon = dbcon layout = QtWidgets.QHBoxLayout(self) @@ -152,17 +134,25 @@ def __init__(self, dbcon, parent=None): self.set_row_height(1) + project_handler.projects_refreshed.connect(self._on_projects_refresh) view.clicked.connect(self.on_clicked) def discover_actions(self): + if self._animation_timer.isActive(): + self._animation_timer.stop() self.model.discover() def filter_actions(self): + if self._animation_timer.isActive(): + self._animation_timer.stop() self.model.filter_actions() def set_row_height(self, rows): self.setMinimumHeight(rows * 75) + def _on_projects_refresh(self): + self.discover_actions() + def _on_animation(self): time_now = time.time() for action_id in tuple(self._animated_items): @@ -182,6 +172,8 @@ def _on_animation(self): self.update() def _start_animation(self, index): + # Offset refresh timout + self.project_handler.start_timer() action_id = index.data(ACTION_ID_ROLE) item = self.model.items_by_id.get(action_id) if item: @@ -202,6 +194,9 @@ def on_clicked(self, index): self.action_clicked.emit(action) return + # Offset refresh timout + self.project_handler.start_timer() + actions = index.data(ACTION_ROLE) menu = QtWidgets.QMenu(self) diff --git a/openpype/tools/launcher/window.py b/openpype/tools/launcher/window.py index 979aab42cf5..bd37a9b89c0 100644 --- a/openpype/tools/launcher/window.py +++ b/openpype/tools/launcher/window.py @@ -103,14 +103,9 @@ def __init__(self, project_handler, parent=None): layout.addWidget(view) - refresh_timer = QtCore.QTimer() - refresh_timer.setInterval(project_handler.refresh_interval) - - refresh_timer.timeout.connect(self._on_refresh_timeout) view.clicked.connect(self.on_clicked) self.view = view - self.refresh_timer = refresh_timer self.project_handler = project_handler def on_clicked(self, index): @@ -118,21 +113,6 @@ def on_clicked(self, index): project_name = index.data(QtCore.Qt.DisplayRole) self.project_handler.set_project(project_name) - def showEvent(self, event): - self.project_handler.refresh_model() - if not self.refresh_timer.isActive(): - self.refresh_timer.start() - super(ProjectsPanel, self).showEvent(event) - - def _on_refresh_timeout(self): - if not self.isVisible(): - # Stop timer if widget is not visible - self.refresh_timer.stop() - - elif self.isActiveWindow(): - # Refresh projects if window is active - self.project_handler.refresh_model() - class AssetsPanel(QtWidgets.QWidget): """Assets page""" @@ -268,8 +248,6 @@ def on_task_change(self): class LauncherWindow(QtWidgets.QDialog): """Launcher interface""" - # Refresh actions each 10000msecs - actions_refresh_timeout = 10000 def __init__(self, parent=None): super(LauncherWindow, self).__init__(parent) @@ -304,7 +282,7 @@ def __init__(self, parent=None): page_slider.addWidget(asset_panel) # actions - actions_bar = ActionBar(self.dbcon, self) + actions_bar = ActionBar(project_handler, self.dbcon, self) # statusbar statusbar = QtWidgets.QWidget() @@ -342,10 +320,6 @@ def __init__(self, parent=None): layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) - actions_refresh_timer = QtCore.QTimer() - actions_refresh_timer.setInterval(self.actions_refresh_timeout) - - self.actions_refresh_timer = actions_refresh_timer self.project_handler = project_handler self.message_label = message_label @@ -357,22 +331,31 @@ def __init__(self, parent=None): self._page = 0 # signals - actions_refresh_timer.timeout.connect(self._on_action_timer) actions_bar.action_clicked.connect(self.on_action_clicked) action_history.trigger_history.connect(self.on_history_action) project_handler.project_changed.connect(self.on_project_change) + project_handler.timer_timeout.connect(self._on_refresh_timeout) asset_panel.back_clicked.connect(self.on_back_clicked) asset_panel.session_changed.connect(self.on_session_changed) self.resize(520, 740) def showEvent(self, event): - if not self.actions_refresh_timer.isActive(): - self.actions_refresh_timer.start() - self.discover_actions() + self.project_handler.set_active(True) + self.project_handler.start_timer(True) super(LauncherWindow, self).showEvent(event) + def _on_refresh_timeout(self): + # Stop timer if widget is not visible + if not self.isVisible(): + self.project_handler.stop_timer() + + def changeEvent(self, event): + if event.type() == QtCore.QEvent.ActivationChange: + self.project_handler.set_active(self.isActiveWindow()) + super(LauncherWindow, self).changeEvent(event) + def set_page(self, page): current = self.page_slider.currentIndex() if current == page and self._page == page: @@ -392,20 +375,10 @@ def on_session_changed(self): def discover_actions(self): self.actions_bar.discover_actions() - self.filter_actions() def filter_actions(self): self.actions_bar.filter_actions() - def _on_action_timer(self): - if not self.isVisible(): - # Stop timer if widget is not visible - self.actions_refresh_timer.stop() - - elif self.isActiveWindow(): - # Refresh projects if window is active - self.discover_actions() - def on_project_change(self, project_name): # Update the Action plug-ins available for the current project self.set_page(1)