Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Launcher project changes #1733

Merged
merged 5 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion openpype/tools/launcher/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,59 @@
"""

import os
from Qt import QtGui
from Qt import QtGui, QtCore
from avalon.vendor import qtawesome
from openpype.api import resources

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:
Expand Down
40 changes: 20 additions & 20 deletions openpype/tools/launcher/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,15 @@


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)
Expand All @@ -51,19 +41,20 @@ def __init__(self, dbcon, parent=None):
)

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)

Expand All @@ -79,7 +70,12 @@ def _on_refresh_timeout(self):

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()
Expand All @@ -88,14 +84,18 @@ def set_project(self, project_name):
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):
Expand Down
87 changes: 25 additions & 62 deletions openpype/tools/launcher/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
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,
Expand Down Expand Up @@ -89,46 +89,37 @@ def mousePressEvent(self, event):

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)
Expand All @@ -140,15 +131,15 @@ def _on_refresh_timeout(self):

elif self.isActiveWindow():
# Refresh projects if window is active
self.model.refresh()
self.project_handler.refresh_model()


class AssetsPanel(QtWidgets.QWidget):
"""Assets page"""
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
Expand All @@ -163,7 +154,7 @@ def __init__(self, dbcon, parent=None):
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)
Expand Down Expand Up @@ -206,24 +197,19 @@ def __init__(self, dbcon, parent=None):
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)

Expand All @@ -232,19 +218,7 @@ def showEvent(self, event):
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()
Expand All @@ -253,11 +227,8 @@ def on_asset_changed(self):
"""Callback on asset selection changed

This updates the task view.

"""

print("Asset changed..")

asset_name = None
asset_silo = None

Expand Down Expand Up @@ -321,8 +292,12 @@ def __init__(self, parent=None):
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)
Expand Down Expand Up @@ -371,6 +346,8 @@ def __init__(self, parent=None):
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
Expand All @@ -383,15 +360,10 @@ def __init__(self, parent=None):
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):
Expand All @@ -415,13 +387,6 @@ def echo(self, message):
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()

Expand All @@ -441,15 +406,13 @@ def _on_action_timer(self):
# 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()

Expand Down