Merge pull request #1733 from pypeclub/bugfix/launcher_project_changes

Launcher project changes
This commit is contained in:
Jakub Trllo 2021-06-22 11:51:59 +02:00 committed by GitHub
commit b8863ff568
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 83 deletions

View file

@ -15,7 +15,7 @@ provides a bridge between the file-based project inventory and configuration.
"""
import os
from Qt import QtGui
from Qt import QtGui, QtCore
from avalon.vendor import qtawesome
from openpype.api import resources
@ -23,6 +23,51 @@ ICON_CACHE = {}
NOT_FOUND = type("NotFound", (object, ), {})
class ProjectHandler(QtCore.QObject):
"""Handler of project model and current project in Launcher tool.
Helps to organize two separate widgets handling current project selection.
It is easier to trigger project change callbacks from one place than from
multiple differect places without proper handling or sequence changes.
Args:
dbcon(AvalonMongoDB): Mongo connection with Session.
model(ProjectModel): Object of projects model which is shared across
all widgets using projects. Arg dbcon should be used as source for
the model.
"""
# Project list will be refreshed each 10000 msecs
# - this is not part of helper implementation but should be used by widgets
# that may require reshing of projects
refresh_interval = 10000
# Signal emmited when project has changed
project_changed = QtCore.Signal(str)
def __init__(self, dbcon, model):
super(ProjectHandler, self).__init__()
# Store project model for usage
self.model = model
# Store dbcon
self.dbcon = dbcon
self.current_project = dbcon.Session.get("AVALON_PROJECT")
def set_project(self, project_name):
# Change current project of this handler
self.current_project = project_name
# Change session project to take effect for other widgets using the
# dbcon object.
self.dbcon.Session["AVALON_PROJECT"] = project_name
# Trigger change signal when everything is updated to new project
self.project_changed.emit(project_name)
def refresh_model(self):
self.model.refresh()
def get_action_icon(action):
icon_name = action.icon
if not icon_name:

View file

@ -20,25 +20,15 @@ from .constants import (
class ProjectBar(QtWidgets.QWidget):
project_changed = QtCore.Signal(int)
# Project list will be refreshed each 10000 msecs
refresh_interval = 10000
def __init__(self, dbcon, parent=None):
def __init__(self, project_handler, parent=None):
super(ProjectBar, self).__init__(parent)
self.dbcon = dbcon
model = ProjectModel(dbcon)
model.hide_invisible = True
project_combobox = QtWidgets.QComboBox(self)
# Change delegate so stylysheets are applied
project_delegate = QtWidgets.QStyledItemDelegate(project_combobox)
project_combobox.setItemDelegate(project_delegate)
project_combobox.setModel(model)
project_combobox.setModel(project_handler.model)
project_combobox.setRootModelIndex(QtCore.QModelIndex())
layout = QtWidgets.QHBoxLayout(self)
@ -51,19 +41,20 @@ class ProjectBar(QtWidgets.QWidget):
)
refresh_timer = QtCore.QTimer()
refresh_timer.setInterval(self.refresh_interval)
refresh_timer.setInterval(project_handler.refresh_interval)
self.model = model
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.project_changed)
self.project_combobox.currentIndexChanged.connect(self.on_index_change)
project_handler.project_changed.connect(self._on_project_change)
# Set current project by default if it's set.
project_name = self.dbcon.Session.get("AVALON_PROJECT")
project_name = project_handler.current_project
if project_name:
self.set_project(project_name)
@ -79,7 +70,12 @@ class ProjectBar(QtWidgets.QWidget):
elif self.isActiveWindow():
# Refresh projects if window is active
self.model.refresh()
self.project_handler.refresh_model()
def _on_project_change(self, project_name):
if self.get_current_project() == project_name:
return
self.set_project(project_name)
def get_current_project(self):
return self.project_combobox.currentText()
@ -88,14 +84,18 @@ class ProjectBar(QtWidgets.QWidget):
index = self.project_combobox.findText(project_name)
if index < 0:
# Try refresh combobox model
self.refresh()
self.project_handler.refresh_model()
index = self.project_combobox.findText(project_name)
if index >= 0:
self.project_combobox.setCurrentIndex(index)
def refresh(self):
self.model.refresh()
def on_index_change(self, idx):
if not self.isVisible():
return
project_name = self.get_current_project()
self.project_handler.set_project(project_name)
class ActionBar(QtWidgets.QWidget):

View file

@ -12,7 +12,7 @@ from avalon.tools import lib as tools_lib
from avalon.tools.widgets import AssetWidget
from avalon.vendor import qtawesome
from .models import ProjectModel
from .lib import get_action_label
from .lib import get_action_label, ProjectHandler
from .widgets import (
ProjectBar,
ActionBar,
@ -89,46 +89,37 @@ class ProjectIconView(QtWidgets.QListView):
class ProjectsPanel(QtWidgets.QWidget):
"""Projects Page"""
project_clicked = QtCore.Signal(str)
# Refresh projects each 10000 msecs
refresh_interval = 10000
def __init__(self, dbcon, parent=None):
def __init__(self, project_handler, parent=None):
super(ProjectsPanel, self).__init__(parent=parent)
layout = QtWidgets.QVBoxLayout(self)
self.dbcon = dbcon
self.dbcon.install()
view = ProjectIconView(parent=self)
view.setSelectionMode(QtWidgets.QListView.NoSelection)
flick = FlickCharm(parent=self)
flick.activateOn(view)
model = ProjectModel(self.dbcon)
model.hide_invisible = True
view.setModel(model)
view.setModel(project_handler.model)
layout.addWidget(view)
refresh_timer = QtCore.QTimer()
refresh_timer.setInterval(self.refresh_interval)
refresh_timer.setInterval(project_handler.refresh_interval)
refresh_timer.timeout.connect(self._on_refresh_timeout)
view.clicked.connect(self.on_clicked)
self.model = model
self.view = view
self.refresh_timer = refresh_timer
self.project_handler = project_handler
def on_clicked(self, index):
if index.isValid():
project_name = index.data(QtCore.Qt.DisplayRole)
self.project_clicked.emit(project_name)
self.project_handler.set_project(project_name)
def showEvent(self, event):
self.model.refresh()
self.project_handler.refresh_model()
if not self.refresh_timer.isActive():
self.refresh_timer.start()
super(ProjectsPanel, self).showEvent(event)
@ -140,7 +131,7 @@ class ProjectsPanel(QtWidgets.QWidget):
elif self.isActiveWindow():
# Refresh projects if window is active
self.model.refresh()
self.project_handler.refresh_model()
class AssetsPanel(QtWidgets.QWidget):
@ -148,7 +139,7 @@ class AssetsPanel(QtWidgets.QWidget):
back_clicked = QtCore.Signal()
session_changed = QtCore.Signal()
def __init__(self, dbcon, parent=None):
def __init__(self, project_handler, dbcon, parent=None):
super(AssetsPanel, self).__init__(parent=parent)
self.dbcon = dbcon
@ -163,7 +154,7 @@ class AssetsPanel(QtWidgets.QWidget):
btn_back = QtWidgets.QPushButton(project_bar_widget)
btn_back.setIcon(btn_back_icon)
project_bar = ProjectBar(self.dbcon, project_bar_widget)
project_bar = ProjectBar(project_handler, project_bar_widget)
layout.addWidget(btn_back)
layout.addWidget(project_bar)
@ -206,24 +197,19 @@ class AssetsPanel(QtWidgets.QWidget):
layout.addWidget(body)
# signals
project_bar.project_changed.connect(self.on_project_changed)
project_handler.project_changed.connect(self.on_project_changed)
assets_widget.selection_changed.connect(self.on_asset_changed)
assets_widget.refreshed.connect(self.on_asset_changed)
tasks_widget.task_changed.connect(self.on_task_change)
btn_back.clicked.connect(self.back_clicked)
self.project_handler = project_handler
self.project_bar = project_bar
self.assets_widget = assets_widget
self.tasks_widget = tasks_widget
self._btn_back = btn_back
# Force initial refresh for the assets since we might not be
# trigging a Project switch if we click the project that was set
# prior to launching the Launcher
# todo: remove this behavior when AVALON_PROJECT is not required
assets_widget.refresh()
def showEvent(self, event):
super(AssetsPanel, self).showEvent(event)
@ -232,19 +218,7 @@ class AssetsPanel(QtWidgets.QWidget):
btn_size = self.project_bar.height()
self._btn_back.setFixedSize(QtCore.QSize(btn_size, btn_size))
def set_project(self, project):
before = self.project_bar.get_current_project()
if before == project:
self.assets_widget.refresh()
return
self.project_bar.set_project(project)
self.on_project_changed()
def on_project_changed(self):
project_name = self.project_bar.get_current_project()
self.dbcon.Session["AVALON_PROJECT"] = project_name
self.session_changed.emit()
self.assets_widget.refresh()
@ -253,11 +227,8 @@ class AssetsPanel(QtWidgets.QWidget):
"""Callback on asset selection changed
This updates the task view.
"""
print("Asset changed..")
asset_name = None
asset_silo = None
@ -321,8 +292,12 @@ class LauncherWindow(QtWidgets.QDialog):
self.windowFlags() | QtCore.Qt.WindowMinimizeButtonHint
)
project_panel = ProjectsPanel(self.dbcon)
asset_panel = AssetsPanel(self.dbcon)
project_model = ProjectModel(self.dbcon)
project_model.hide_invisible = True
project_handler = ProjectHandler(self.dbcon, project_model)
project_panel = ProjectsPanel(project_handler)
asset_panel = AssetsPanel(project_handler, self.dbcon)
page_slider = SlidePageWidget()
page_slider.addWidget(project_panel)
@ -371,6 +346,8 @@ class LauncherWindow(QtWidgets.QDialog):
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
self.project_panel = project_panel
self.asset_panel = asset_panel
@ -383,15 +360,10 @@ class LauncherWindow(QtWidgets.QDialog):
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_panel.project_clicked.connect(self.on_project_clicked)
project_handler.project_changed.connect(self.on_project_change)
asset_panel.back_clicked.connect(self.on_back_clicked)
asset_panel.session_changed.connect(self.on_session_changed)
# todo: Simplify this callback connection
asset_panel.project_bar.project_changed.connect(
self.on_project_changed
)
self.resize(520, 740)
def showEvent(self, event):
@ -415,13 +387,6 @@ class LauncherWindow(QtWidgets.QDialog):
QtCore.QTimer.singleShot(5000, lambda: self.message_label.setText(""))
self.log.debug(message)
def on_project_changed(self):
project_name = self.asset_panel.project_bar.get_current_project()
self.dbcon.Session["AVALON_PROJECT"] = project_name
# Update the Action plug-ins available for the current project
self.discover_actions()
def on_session_changed(self):
self.filter_actions()
@ -441,15 +406,13 @@ class LauncherWindow(QtWidgets.QDialog):
# Refresh projects if window is active
self.discover_actions()
def on_project_clicked(self, project_name):
self.dbcon.Session["AVALON_PROJECT"] = project_name
# Refresh projects
self.asset_panel.set_project(project_name)
def on_project_change(self, project_name):
# Update the Action plug-ins available for the current project
self.set_page(1)
self.discover_actions()
def on_back_clicked(self):
self.dbcon.Session["AVALON_PROJECT"] = None
self.project_handler.set_project(None)
self.set_page(0)
self.discover_actions()