mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
creator dialog has context widget and creator's attributes
This commit is contained in:
parent
9c6a57aa58
commit
f0b7f72325
5 changed files with 201 additions and 369 deletions
|
|
@ -15,6 +15,9 @@ from openpype.pipeline.create import (
|
|||
)
|
||||
|
||||
from .widgets import IconValuePixmapLabel
|
||||
from .assets_widget import CreateDialogAssetsWidget
|
||||
from .tasks_widget import CreateDialogTasksWidget
|
||||
from .precreate_widget import AttributesWidget
|
||||
from ..constants import (
|
||||
VARIANT_TOOLTIP,
|
||||
CREATOR_IDENTIFIER_ROLE,
|
||||
|
|
@ -202,7 +205,34 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
self._name_pattern = name_pattern
|
||||
self._compiled_name_pattern = re.compile(name_pattern)
|
||||
|
||||
context_widget = QtWidgets.QWidget(self)
|
||||
|
||||
assets_widget = CreateDialogAssetsWidget(controller, context_widget)
|
||||
tasks_widget = CreateDialogTasksWidget(controller, context_widget)
|
||||
|
||||
context_layout = QtWidgets.QVBoxLayout(context_widget)
|
||||
context_layout.setContentsMargins(0, 0, 0, 0)
|
||||
context_layout.setSpacing(0)
|
||||
context_layout.addWidget(assets_widget, 2)
|
||||
context_layout.addWidget(tasks_widget, 1)
|
||||
|
||||
pre_create_scroll_area = QtWidgets.QScrollArea(self)
|
||||
pre_create_contet_widget = QtWidgets.QWidget(pre_create_scroll_area)
|
||||
pre_create_scroll_area.setWidget(pre_create_contet_widget)
|
||||
pre_create_scroll_area.setWidgetResizable(True)
|
||||
|
||||
pre_create_contet_layout = QtWidgets.QVBoxLayout(
|
||||
pre_create_contet_widget
|
||||
)
|
||||
pre_create_attributes_widget = AttributesWidget(
|
||||
pre_create_contet_widget
|
||||
)
|
||||
pre_create_contet_layout.addWidget(pre_create_attributes_widget, 0)
|
||||
pre_create_contet_layout.addStretch(1)
|
||||
|
||||
creator_description_widget = CreatorDescriptionWidget(self)
|
||||
# TODO add HELP button
|
||||
creator_description_widget.setVisible(False)
|
||||
|
||||
creators_view = QtWidgets.QListView(self)
|
||||
creators_model = QtGui.QStandardItemModel()
|
||||
|
|
@ -235,6 +265,14 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
form_layout.addRow("Name:", variant_layout)
|
||||
form_layout.addRow("Subset:", subset_name_input)
|
||||
|
||||
mid_widget = QtWidgets.QWidget(self)
|
||||
mid_layout = QtWidgets.QVBoxLayout(mid_widget)
|
||||
mid_layout.setContentsMargins(0, 0, 0, 0)
|
||||
mid_layout.addWidget(QtWidgets.QLabel("Choose family:", self))
|
||||
mid_layout.addWidget(creators_view, 1)
|
||||
mid_layout.addLayout(form_layout, 0)
|
||||
mid_layout.addWidget(create_btn, 0)
|
||||
|
||||
left_layout = QtWidgets.QVBoxLayout()
|
||||
left_layout.addWidget(QtWidgets.QLabel("Choose family:", self))
|
||||
left_layout.addWidget(creators_view, 1)
|
||||
|
|
@ -242,20 +280,36 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
left_layout.addWidget(create_btn, 0)
|
||||
|
||||
layout = QtWidgets.QHBoxLayout(self)
|
||||
layout.addLayout(left_layout, 0)
|
||||
layout.addSpacing(5)
|
||||
layout.addWidget(creator_description_widget, 1)
|
||||
layout.setSpacing(10)
|
||||
layout.addWidget(context_widget, 1)
|
||||
layout.addWidget(mid_widget, 1)
|
||||
layout.addWidget(pre_create_scroll_area, 1)
|
||||
|
||||
prereq_timer = QtCore.QTimer()
|
||||
prereq_timer.setInterval(50)
|
||||
prereq_timer.setSingleShot(True)
|
||||
|
||||
prereq_timer.timeout.connect(self._on_prereq_timer)
|
||||
|
||||
create_btn.clicked.connect(self._on_create)
|
||||
variant_input.returnPressed.connect(self._on_create)
|
||||
variant_input.textChanged.connect(self._on_variant_change)
|
||||
creators_view.selectionModel().currentChanged.connect(
|
||||
self._on_item_change
|
||||
self._on_creator_item_change
|
||||
)
|
||||
variant_hints_menu.triggered.connect(self._on_variant_action)
|
||||
assets_widget.selection_changed.connect(self._on_asset_change)
|
||||
assets_widget.current_context_required.connect(
|
||||
self._on_current_session_context_request
|
||||
)
|
||||
tasks_widget.task_changed.connect(self._on_task_change)
|
||||
|
||||
controller.add_plugins_refresh_callback(self._on_plugins_refresh)
|
||||
|
||||
self._pre_create_attributes_widget = pre_create_attributes_widget
|
||||
self._context_widget = context_widget
|
||||
self._assets_widget = assets_widget
|
||||
self._tasks_widget = tasks_widget
|
||||
self.creator_description_widget = creator_description_widget
|
||||
|
||||
self.subset_name_input = subset_name_input
|
||||
|
|
@ -269,12 +323,54 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
self.creators_view = creators_view
|
||||
self.create_btn = create_btn
|
||||
|
||||
self._prereq_timer = prereq_timer
|
||||
|
||||
def _context_change_is_enabled(self):
|
||||
return self._context_widget.isEnabled()
|
||||
|
||||
def _get_asset_name(self):
|
||||
asset_name = None
|
||||
if self._context_change_is_enabled():
|
||||
asset_name = self._assets_widget.get_selected_asset_name()
|
||||
|
||||
if asset_name is None:
|
||||
asset_name = self._asset_name
|
||||
return asset_name
|
||||
|
||||
def _get_task_name(self):
|
||||
task_name = None
|
||||
if self._context_change_is_enabled():
|
||||
# Don't use selection of task if asset is not set
|
||||
asset_name = self._assets_widget.get_selected_asset_name()
|
||||
if asset_name:
|
||||
task_name = self._tasks_widget.get_selected_task_name()
|
||||
|
||||
if not task_name:
|
||||
task_name = self._task_name
|
||||
return task_name
|
||||
|
||||
@property
|
||||
def dbcon(self):
|
||||
return self.controller.dbcon
|
||||
|
||||
def _set_context_enabled(self, enabled):
|
||||
self._assets_widget.set_enabled(enabled)
|
||||
self._tasks_widget.set_enabled(enabled)
|
||||
self._context_widget.setEnabled(enabled)
|
||||
|
||||
def refresh(self):
|
||||
self._prereq_available = True
|
||||
# Get context before refresh to keep selection of asset and
|
||||
# task widgets
|
||||
asset_name = self._get_asset_name()
|
||||
task_name = self._get_task_name()
|
||||
|
||||
self._prereq_available = False
|
||||
|
||||
# Disable context widget so refresh of asset will use context asset
|
||||
# name
|
||||
self._set_context_enabled(False)
|
||||
|
||||
self._assets_widget.refresh()
|
||||
|
||||
# Refresh data before update of creators
|
||||
self._refresh_asset()
|
||||
|
|
@ -282,21 +378,36 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
# data
|
||||
self._refresh_creators()
|
||||
|
||||
self._assets_widget.set_current_asset_name(self._asset_name)
|
||||
self._assets_widget.select_asset_by_name(asset_name)
|
||||
self._tasks_widget.set_asset_name(asset_name)
|
||||
self._tasks_widget.select_task_name(task_name)
|
||||
|
||||
self._invalidate_prereq()
|
||||
|
||||
def _invalidate_prereq(self):
|
||||
self._prereq_timer.start()
|
||||
|
||||
def _on_prereq_timer(self):
|
||||
prereq_available = True
|
||||
if self.creators_model.rowCount() < 1:
|
||||
prereq_available = False
|
||||
|
||||
if self._asset_doc is None:
|
||||
# QUESTION how to handle invalid asset?
|
||||
self.subset_name_input.setText("< Asset is not set >")
|
||||
self._prereq_available = False
|
||||
prereq_available = False
|
||||
|
||||
if self.creators_model.rowCount() < 1:
|
||||
self._prereq_available = False
|
||||
if prereq_available != self._prereq_available:
|
||||
self._prereq_available = prereq_available
|
||||
|
||||
self.create_btn.setEnabled(self._prereq_available)
|
||||
self.creators_view.setEnabled(self._prereq_available)
|
||||
self.variant_input.setEnabled(self._prereq_available)
|
||||
self.variant_hints_btn.setEnabled(self._prereq_available)
|
||||
self.create_btn.setEnabled(prereq_available)
|
||||
self.creators_view.setEnabled(prereq_available)
|
||||
self.variant_input.setEnabled(prereq_available)
|
||||
self.variant_hints_btn.setEnabled(prereq_available)
|
||||
self._on_variant_change()
|
||||
|
||||
def _refresh_asset(self):
|
||||
asset_name = self._asset_name
|
||||
asset_name = self._get_asset_name()
|
||||
|
||||
# Skip if asset did not change
|
||||
if self._asset_doc and self._asset_doc["name"] == asset_name:
|
||||
|
|
@ -324,6 +435,9 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
)
|
||||
self._subset_names = set(subset_docs.distinct("name"))
|
||||
|
||||
if not asset_doc:
|
||||
self.subset_name_input.setText("< Asset is not set >")
|
||||
|
||||
def _refresh_creators(self):
|
||||
# Refresh creators and add their families to list
|
||||
existing_items = {}
|
||||
|
|
@ -366,25 +480,62 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
if not indexes:
|
||||
index = self.creators_model.index(0, 0)
|
||||
self.creators_view.setCurrentIndex(index)
|
||||
else:
|
||||
index = indexes[0]
|
||||
|
||||
identifier = index.data(CREATOR_IDENTIFIER_ROLE)
|
||||
|
||||
self._set_creator(identifier)
|
||||
|
||||
def _on_plugins_refresh(self):
|
||||
# Trigger refresh only if is visible
|
||||
if self.isVisible():
|
||||
self.refresh()
|
||||
|
||||
def _on_item_change(self, new_index, _old_index):
|
||||
def _on_asset_change(self):
|
||||
self._refresh_asset()
|
||||
|
||||
asset_name = self._assets_widget.get_selected_asset_name()
|
||||
self._tasks_widget.set_asset_name(asset_name)
|
||||
if self._context_change_is_enabled():
|
||||
self._invalidate_prereq()
|
||||
|
||||
def _on_task_change(self):
|
||||
if self._context_change_is_enabled():
|
||||
self._invalidate_prereq()
|
||||
|
||||
def _on_current_session_context_request(self):
|
||||
self._assets_widget.set_current_session_asset()
|
||||
if self._task_name:
|
||||
self._tasks_widget.select_task_name(self._task_name)
|
||||
|
||||
def _on_creator_item_change(self, new_index, _old_index):
|
||||
identifier = None
|
||||
if new_index.isValid():
|
||||
identifier = new_index.data(CREATOR_IDENTIFIER_ROLE)
|
||||
self._set_creator(identifier)
|
||||
|
||||
def _set_creator(self, identifier):
|
||||
creator = self.controller.manual_creators.get(identifier)
|
||||
|
||||
self.creator_description_widget.set_plugin(creator)
|
||||
|
||||
self._selected_creator = creator
|
||||
if not creator:
|
||||
self._pre_create_attributes_widget.set_attr_defs([])
|
||||
self._set_context_enabled(False)
|
||||
return
|
||||
|
||||
if (
|
||||
creator.create_allow_context_change
|
||||
!= self._context_change_is_enabled()
|
||||
):
|
||||
self._set_context_enabled(creator.create_allow_context_change)
|
||||
self._refresh_asset()
|
||||
|
||||
attr_defs = creator.get_pre_create_attr_defs()
|
||||
self._pre_create_attributes_widget.set_attr_defs(attr_defs)
|
||||
|
||||
default_variants = creator.get_default_variants()
|
||||
if not default_variants:
|
||||
default_variants = ["Main"]
|
||||
|
|
@ -410,12 +561,19 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
if self.variant_input.text() != value:
|
||||
self.variant_input.setText(value)
|
||||
|
||||
def _on_variant_change(self, variant_value):
|
||||
if not self._prereq_available or not self._selected_creator:
|
||||
def _on_variant_change(self, variant_value=None):
|
||||
if not self._prereq_available:
|
||||
return
|
||||
|
||||
# This should probably never happen?
|
||||
if not self._selected_creator:
|
||||
if self.subset_name_input.text():
|
||||
self.subset_name_input.setText("")
|
||||
return
|
||||
|
||||
if variant_value is None:
|
||||
variant_value = self.variant_input.text()
|
||||
|
||||
match = self._compiled_name_pattern.match(variant_value)
|
||||
valid = bool(match)
|
||||
self.create_btn.setEnabled(valid)
|
||||
|
|
@ -425,7 +583,7 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
return
|
||||
|
||||
project_name = self.controller.project_name
|
||||
task_name = self._task_name
|
||||
task_name = self._get_task_name()
|
||||
|
||||
asset_doc = copy.deepcopy(self._asset_doc)
|
||||
# Calculate subset name with Creator plugin
|
||||
|
|
@ -522,9 +680,9 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
family = index.data(FAMILY_ROLE)
|
||||
subset_name = self.subset_name_input.text()
|
||||
variant = self.variant_input.text()
|
||||
asset_name = self._asset_name
|
||||
task_name = self._task_name
|
||||
options = {}
|
||||
asset_name = self._get_asset_name()
|
||||
task_name = self._get_task_name()
|
||||
pre_create_data = self._pre_create_attributes_widget.current_value()
|
||||
# Where to define these data?
|
||||
# - what data show be stored?
|
||||
instance_data = {
|
||||
|
|
@ -537,7 +695,7 @@ class CreateDialog(QtWidgets.QDialog):
|
|||
error_info = None
|
||||
try:
|
||||
self.controller.create(
|
||||
creator_identifier, subset_name, instance_data, options
|
||||
creator_identifier, subset_name, instance_data, pre_create_data
|
||||
)
|
||||
|
||||
except CreatorError as exc:
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
|
|
@ -1,201 +0,0 @@
|
|||
import re
|
||||
import collections
|
||||
|
||||
from Qt import QtCore, QtGui
|
||||
|
||||
|
||||
class AssetsHierarchyModel(QtGui.QStandardItemModel):
|
||||
"""Assets hiearrchy model.
|
||||
|
||||
For selecting asset for which should beinstance created.
|
||||
|
||||
Uses controller to load asset hierarchy. All asset documents are stored by
|
||||
their parents.
|
||||
"""
|
||||
def __init__(self, controller):
|
||||
super(AssetsHierarchyModel, self).__init__()
|
||||
self._controller = controller
|
||||
|
||||
self._items_by_name = {}
|
||||
|
||||
def reset(self):
|
||||
self.clear()
|
||||
|
||||
self._items_by_name = {}
|
||||
assets_by_parent_id = self._controller.get_asset_hierarchy()
|
||||
|
||||
items_by_name = {}
|
||||
_queue = collections.deque()
|
||||
_queue.append((self.invisibleRootItem(), None))
|
||||
while _queue:
|
||||
parent_item, parent_id = _queue.popleft()
|
||||
children = assets_by_parent_id.get(parent_id)
|
||||
if not children:
|
||||
continue
|
||||
|
||||
children_by_name = {
|
||||
child["name"]: child
|
||||
for child in children
|
||||
}
|
||||
items = []
|
||||
for name in sorted(children_by_name.keys()):
|
||||
child = children_by_name[name]
|
||||
item = QtGui.QStandardItem(name)
|
||||
items_by_name[name] = item
|
||||
items.append(item)
|
||||
_queue.append((item, child["_id"]))
|
||||
|
||||
parent_item.appendRows(items)
|
||||
|
||||
self._items_by_name = items_by_name
|
||||
|
||||
def name_is_valid(self, item_name):
|
||||
return item_name in self._items_by_name
|
||||
|
||||
def get_index_by_name(self, item_name):
|
||||
item = self._items_by_name.get(item_name)
|
||||
if item:
|
||||
return item.index()
|
||||
return QtCore.QModelIndex()
|
||||
|
||||
|
||||
class TasksModel(QtGui.QStandardItemModel):
|
||||
"""Tasks model.
|
||||
|
||||
Task model must have set context of asset documents.
|
||||
|
||||
Items in model are based on 0-infinite asset documents. Always contain
|
||||
an interserction of context asset tasks. When no assets are in context
|
||||
them model is empty if 2 or more are in context assets that don't have
|
||||
tasks with same names then model is empty too.
|
||||
|
||||
Args:
|
||||
controller (PublisherController): Controller which handles creation and
|
||||
publishing.
|
||||
"""
|
||||
def __init__(self, controller):
|
||||
super(TasksModel, self).__init__()
|
||||
self._controller = controller
|
||||
self._items_by_name = {}
|
||||
self._asset_names = []
|
||||
self._task_names_by_asset_name = {}
|
||||
|
||||
def set_asset_names(self, asset_names):
|
||||
"""Set assets context."""
|
||||
self._asset_names = asset_names
|
||||
self.reset()
|
||||
|
||||
@staticmethod
|
||||
def get_intersection_of_tasks(task_names_by_asset_name):
|
||||
"""Calculate intersection of task names from passed data.
|
||||
|
||||
Example:
|
||||
```
|
||||
# Passed `task_names_by_asset_name`
|
||||
{
|
||||
"asset_1": ["compositing", "animation"],
|
||||
"asset_2": ["compositing", "editorial"]
|
||||
}
|
||||
```
|
||||
Result:
|
||||
```
|
||||
# Set
|
||||
{"compositing"}
|
||||
```
|
||||
|
||||
Args:
|
||||
task_names_by_asset_name (dict): Task names in iterable by parent.
|
||||
"""
|
||||
tasks = None
|
||||
for task_names in task_names_by_asset_name.values():
|
||||
if tasks is None:
|
||||
tasks = set(task_names)
|
||||
else:
|
||||
tasks &= set(task_names)
|
||||
|
||||
if not tasks:
|
||||
break
|
||||
return tasks or set()
|
||||
|
||||
def is_task_name_valid(self, asset_name, task_name):
|
||||
"""Is task name available for asset.
|
||||
|
||||
Args:
|
||||
asset_name (str): Name of asset where should look for task.
|
||||
task_name (str): Name of task which should be available in asset's
|
||||
tasks.
|
||||
"""
|
||||
task_names = self._task_names_by_asset_name.get(asset_name)
|
||||
if task_names and task_name in task_names:
|
||||
return True
|
||||
return False
|
||||
|
||||
def reset(self):
|
||||
"""Update model by current context."""
|
||||
if not self._asset_names:
|
||||
self._items_by_name = {}
|
||||
self._task_names_by_asset_name = {}
|
||||
self.clear()
|
||||
return
|
||||
|
||||
task_names_by_asset_name = (
|
||||
self._controller.get_task_names_by_asset_names(self._asset_names)
|
||||
)
|
||||
self._task_names_by_asset_name = task_names_by_asset_name
|
||||
|
||||
new_task_names = self.get_intersection_of_tasks(
|
||||
task_names_by_asset_name
|
||||
)
|
||||
old_task_names = set(self._items_by_name.keys())
|
||||
if new_task_names == old_task_names:
|
||||
return
|
||||
|
||||
root_item = self.invisibleRootItem()
|
||||
for task_name in old_task_names:
|
||||
if task_name not in new_task_names:
|
||||
item = self._items_by_name.pop(task_name)
|
||||
root_item.removeRow(item.row())
|
||||
|
||||
new_items = []
|
||||
for task_name in new_task_names:
|
||||
if task_name in self._items_by_name:
|
||||
continue
|
||||
|
||||
item = QtGui.QStandardItem(task_name)
|
||||
self._items_by_name[task_name] = item
|
||||
new_items.append(item)
|
||||
root_item.appendRows(new_items)
|
||||
|
||||
|
||||
class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel):
|
||||
"""Recursive proxy model.
|
||||
|
||||
Item is not filtered if any children match the filter.
|
||||
|
||||
Use case: Filtering by string - parent won't be filtered if does not match
|
||||
the filter string but first checks if any children does.
|
||||
"""
|
||||
def filterAcceptsRow(self, row, parent_index):
|
||||
regex = self.filterRegExp()
|
||||
if not regex.isEmpty():
|
||||
model = self.sourceModel()
|
||||
source_index = model.index(
|
||||
row, self.filterKeyColumn(), parent_index
|
||||
)
|
||||
if source_index.isValid():
|
||||
pattern = regex.pattern()
|
||||
|
||||
# Check current index itself
|
||||
value = model.data(source_index, self.filterRole())
|
||||
if re.search(pattern, value, re.IGNORECASE):
|
||||
return True
|
||||
|
||||
rows = model.rowCount(source_index)
|
||||
for idx in range(rows):
|
||||
if self.filterAcceptsRow(idx, source_index):
|
||||
return True
|
||||
return False
|
||||
|
||||
return super(RecursiveSortFilterProxyModel, self).filterAcceptsRow(
|
||||
row, parent_index
|
||||
)
|
||||
|
|
@ -10,11 +10,6 @@ from avalon.vendor import qtawesome
|
|||
from openpype.widgets.attribute_defs import create_widget_for_attr_def
|
||||
from openpype.tools import resources
|
||||
from openpype.tools.flickcharm import FlickCharm
|
||||
from .models import (
|
||||
AssetsHierarchyModel,
|
||||
TasksModel,
|
||||
RecursiveSortFilterProxyModel,
|
||||
)
|
||||
from openpype.tools.utils import (
|
||||
PlaceholderLineEdit,
|
||||
IconButton,
|
||||
|
|
@ -22,6 +17,8 @@ from openpype.tools.utils import (
|
|||
BaseClickableFrame
|
||||
)
|
||||
from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS
|
||||
from .assets_widget import AssetsDialog
|
||||
from .tasks_widget import TasksModel
|
||||
from .icons import (
|
||||
get_pixmap,
|
||||
get_icon_path
|
||||
|
|
@ -307,143 +304,6 @@ class AbstractInstanceView(QtWidgets.QWidget):
|
|||
).format(self.__class__.__name__))
|
||||
|
||||
|
||||
class AssetsDialog(QtWidgets.QDialog):
|
||||
"""Dialog to select asset for a context of instance."""
|
||||
def __init__(self, controller, parent):
|
||||
super(AssetsDialog, self).__init__(parent)
|
||||
self.setWindowTitle("Select asset")
|
||||
|
||||
model = AssetsHierarchyModel(controller)
|
||||
proxy_model = RecursiveSortFilterProxyModel()
|
||||
proxy_model.setSourceModel(model)
|
||||
proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
|
||||
filter_input = PlaceholderLineEdit(self)
|
||||
filter_input.setPlaceholderText("Filter assets..")
|
||||
|
||||
asset_view = QtWidgets.QTreeView(self)
|
||||
asset_view.setModel(proxy_model)
|
||||
asset_view.setHeaderHidden(True)
|
||||
asset_view.setFrameShape(QtWidgets.QFrame.NoFrame)
|
||||
asset_view.setEditTriggers(QtWidgets.QTreeView.NoEditTriggers)
|
||||
asset_view.setAlternatingRowColors(True)
|
||||
asset_view.setSelectionBehavior(QtWidgets.QTreeView.SelectRows)
|
||||
asset_view.setAllColumnsShowFocus(True)
|
||||
|
||||
ok_btn = QtWidgets.QPushButton("OK", self)
|
||||
cancel_btn = QtWidgets.QPushButton("Cancel", self)
|
||||
|
||||
btns_layout = QtWidgets.QHBoxLayout()
|
||||
btns_layout.addStretch(1)
|
||||
btns_layout.addWidget(ok_btn)
|
||||
btns_layout.addWidget(cancel_btn)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self)
|
||||
layout.addWidget(filter_input, 0)
|
||||
layout.addWidget(asset_view, 1)
|
||||
layout.addLayout(btns_layout, 0)
|
||||
|
||||
filter_input.textChanged.connect(self._on_filter_change)
|
||||
ok_btn.clicked.connect(self._on_ok_clicked)
|
||||
cancel_btn.clicked.connect(self._on_cancel_clicked)
|
||||
|
||||
self._filter_input = filter_input
|
||||
self._ok_btn = ok_btn
|
||||
self._cancel_btn = cancel_btn
|
||||
|
||||
self._model = model
|
||||
self._proxy_model = proxy_model
|
||||
|
||||
self._asset_view = asset_view
|
||||
|
||||
self._selected_asset = None
|
||||
# Soft refresh is enabled
|
||||
# - reset will happen at all cost if soft reset is enabled
|
||||
# - adds ability to call reset on multiple places without repeating
|
||||
self._soft_reset_enabled = True
|
||||
|
||||
def showEvent(self, event):
|
||||
"""Refresh asset model on show."""
|
||||
super(AssetsDialog, self).showEvent(event)
|
||||
# Refresh on show
|
||||
self.reset(False)
|
||||
|
||||
def reset(self, force=True):
|
||||
"""Reset asset model."""
|
||||
if not force and not self._soft_reset_enabled:
|
||||
return
|
||||
|
||||
if self._soft_reset_enabled:
|
||||
self._soft_reset_enabled = False
|
||||
|
||||
self._model.reset()
|
||||
|
||||
def name_is_valid(self, name):
|
||||
"""Is asset name valid.
|
||||
|
||||
Args:
|
||||
name(str): Asset name that should be checked.
|
||||
"""
|
||||
# Make sure we're reset
|
||||
self.reset(False)
|
||||
# Valid the name by model
|
||||
return self._model.name_is_valid(name)
|
||||
|
||||
def _on_filter_change(self, text):
|
||||
"""Trigger change of filter of assets."""
|
||||
self._proxy_model.setFilterFixedString(text)
|
||||
|
||||
def _on_cancel_clicked(self):
|
||||
self.done(0)
|
||||
|
||||
def _on_ok_clicked(self):
|
||||
index = self._asset_view.currentIndex()
|
||||
asset_name = None
|
||||
if index.isValid():
|
||||
asset_name = index.data(QtCore.Qt.DisplayRole)
|
||||
self._selected_asset = asset_name
|
||||
self.done(1)
|
||||
|
||||
def set_selected_assets(self, asset_names):
|
||||
"""Change preselected asset before showing the dialog.
|
||||
|
||||
This also resets model and clean filter.
|
||||
"""
|
||||
self.reset(False)
|
||||
self._asset_view.collapseAll()
|
||||
self._filter_input.setText("")
|
||||
|
||||
indexes = []
|
||||
for asset_name in asset_names:
|
||||
index = self._model.get_index_by_name(asset_name)
|
||||
if index.isValid():
|
||||
indexes.append(index)
|
||||
|
||||
if not indexes:
|
||||
return
|
||||
|
||||
index_deque = collections.deque()
|
||||
for index in indexes:
|
||||
index_deque.append(index)
|
||||
|
||||
all_indexes = []
|
||||
while index_deque:
|
||||
index = index_deque.popleft()
|
||||
all_indexes.append(index)
|
||||
|
||||
parent_index = index.parent()
|
||||
if parent_index.isValid():
|
||||
index_deque.append(parent_index)
|
||||
|
||||
for index in all_indexes:
|
||||
proxy_index = self._proxy_model.mapFromSource(index)
|
||||
self._asset_view.expand(proxy_index)
|
||||
|
||||
def get_selected_asset(self):
|
||||
"""Get selected asset name."""
|
||||
return self._selected_asset
|
||||
|
||||
|
||||
class ClickableLineEdit(QtWidgets.QLineEdit):
|
||||
"""QLineEdit capturing left mouse click.
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
default_width = 1000
|
||||
default_height = 600
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, parent=None, reset_on_show=None):
|
||||
super(PublisherWindow, self).__init__(parent)
|
||||
|
||||
self.setWindowTitle("OpenPype publisher")
|
||||
|
|
@ -41,6 +41,9 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
icon = QtGui.QIcon(resources.get_openpype_icon_filepath())
|
||||
self.setWindowIcon(icon)
|
||||
|
||||
if reset_on_show is None:
|
||||
reset_on_show = True
|
||||
|
||||
if parent is None:
|
||||
on_top_flag = QtCore.Qt.WindowStaysOnTopHint
|
||||
else:
|
||||
|
|
@ -55,6 +58,7 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
| on_top_flag
|
||||
)
|
||||
|
||||
self._reset_on_show = reset_on_show
|
||||
self._first_show = True
|
||||
self._refreshing_instances = False
|
||||
|
||||
|
|
@ -117,12 +121,16 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
subset_view_btns_layout.addWidget(change_view_btn)
|
||||
|
||||
# Layout of view and buttons
|
||||
subset_view_layout = QtWidgets.QVBoxLayout()
|
||||
# - widget 'subset_view_widget' is necessary
|
||||
# - only layout won't be resized automatically to minimum size hint
|
||||
# on child resize request!
|
||||
subset_view_widget = QtWidgets.QWidget(subset_views_widget)
|
||||
subset_view_layout = QtWidgets.QVBoxLayout(subset_view_widget)
|
||||
subset_view_layout.setContentsMargins(0, 0, 0, 0)
|
||||
subset_view_layout.addLayout(subset_views_layout, 1)
|
||||
subset_view_layout.addLayout(subset_view_btns_layout, 0)
|
||||
|
||||
subset_views_widget.set_center_widget(subset_view_layout)
|
||||
subset_views_widget.set_center_widget(subset_view_widget)
|
||||
|
||||
# Whole subset layout with attributes and details
|
||||
subset_content_widget = QtWidgets.QWidget(subset_frame)
|
||||
|
|
@ -249,7 +257,8 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
self._first_show = False
|
||||
self.resize(self.default_width, self.default_height)
|
||||
self.setStyleSheet(style.load_stylesheet())
|
||||
self.reset()
|
||||
if self._reset_on_show:
|
||||
self.reset()
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.controller.save_changes()
|
||||
|
|
@ -382,6 +391,12 @@ class PublisherWindow(QtWidgets.QDialog):
|
|||
context_title = self.controller.get_context_title()
|
||||
self.set_context_label(context_title)
|
||||
|
||||
# Give a change to process Resize Request
|
||||
QtWidgets.QApplication.processEvents()
|
||||
# Trigger update geometry of
|
||||
widget = self.subset_views_layout.currentWidget()
|
||||
widget.updateGeometry()
|
||||
|
||||
def _on_subset_change(self, *_args):
|
||||
# Ignore changes if in middle of refreshing
|
||||
if self._refreshing_instances:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue