Skip to content
Open
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
232 changes: 137 additions & 95 deletions python/tk_multi_loader/dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def __init__(self, action_manager, parent=None):
"""
QtGui.QWidget.__init__(self, parent)
self._action_manager = action_manager
self._bundle = sgtk.platform.current_bundle()

# The loader app can be invoked from other applications with a custom
# action manager as a File Open-like dialog. For these managers, we won't
Expand Down Expand Up @@ -923,8 +924,8 @@ def _on_show_subitems_toggled(self):
help_screen.show_help_screen(self.window(), app, help_pix)

# tell publish UI to update itself
item = self._get_selected_entity()
self._load_publishes_for_entity_item(item)
item = self._get_selected_entities()[0]
self._load_publishes_for_entity_items([item])

def _on_thumb_size_slider_change(self, value):
"""
Expand Down Expand Up @@ -1046,29 +1047,29 @@ def _on_reload_action(self):
########################################################################################
# entity listing tree view and presets toolbar

def _get_selected_entity(self):
def _get_selected_entities(self):
"""
Returns the item currently selected in the tree view, None
Returns the items currently selected in the tree view, None
if no selection has been made.
"""

selected_item = None
selected_items = [None]
selection_model = self._entity_presets[self._current_entity_preset].view.selectionModel()
if selection_model.hasSelection():

current_idx = selection_model.selection().indexes()[0]
if selection_model.hasSelection():
selection = selection_model.selection().indexes()

model = current_idx.model()
selected_items = []
for current_idx in selection:
model = current_idx.model()

if not isinstance(model, (SgHierarchyModel, SgEntityModel)):
# proxy model!
current_idx = model.mapToSource(current_idx)
if not isinstance(model, (SgHierarchyModel, SgEntityModel)):
# proxy model!
current_idx = model.mapToSource(current_idx)

# now we have arrived at our model derived from StandardItemModel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add these comments back in.

# so let's retrieve the standarditem object associated with the index
selected_item = current_idx.model().itemFromIndex(current_idx)
selected_item = current_idx.model().itemFromIndex(current_idx)
selected_items.append(selected_item)

return selected_item
return selected_items

def _select_tab(self, tab_caption, track_in_history):
"""
Expand Down Expand Up @@ -1122,7 +1123,7 @@ def _select_item_in_entity_tree(self, tab_caption, item):
# to selected is in vertically centered in the widget

# get the currently selected item in our tab
selected_item = self._get_selected_entity()
selected_item = self._get_selected_entities()[0]

if selected_item and selected_item.index() == item.index():
# the item is already selected!
Expand Down Expand Up @@ -1208,6 +1209,12 @@ def _load_entity_presets(self):

sg_entity_type = setting_dict["entity_type"]

# Check to see if we are showing a tags view.
if sg_entity_type == 'Tag':
type_tag = True
else:
type_tag = False

# get optional publish_filter setting
# note: actual value in the yaml settings can be None,
# that's why we cannot use setting_dict.get("publish_filters", [])
Expand Down Expand Up @@ -1242,6 +1249,12 @@ def _load_entity_presets(self):
view.setHeaderHidden(True)
view.setModel(proxy_model)

# Enable multiselection on tag list entities (or in this case extended selection so selections are sticky)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the part of the comment in parens is a little confusing. can you clarify?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, multiselect requires shift or ctrl to be pressed. Extended selection doesn't; the selection remains sticky and you can click to toggle items on and off which I thought was a more appropriate UI behaviour for tag filters.

if type_tag:
view.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
else:
view.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)

# Keep a handle to all the new Qt objects, otherwise the GC may not work.
self._dynamic_widgets.extend([model, proxy_model, tab, layout, view])

Expand Down Expand Up @@ -1496,10 +1509,10 @@ def _hierarchy_refreshed(self):
Slot triggered when the hierarchy model has been refreshed. This allows to show all the
folder items in the right-hand side for the current selection.
"""
selected_item = self._get_selected_entity()
selected_item = self._get_selected_entities()[0]

# tell publish UI to update itself
self._load_publishes_for_entity_item(selected_item)
self._load_publishes_for_entity_items([selected_item])

def _node_activated(self, incremental_paths, view, proxy_model):
"""
Expand Down Expand Up @@ -1608,6 +1621,7 @@ def _switch_profile_tab(self, new_index, track_in_history):
:param track_in_history: Hint to this method that the actions should be tracked in the
history.
"""

# qt returns unicode/qstring here so force to str
curr_tab_name = shotgun_model.sanitize_qt(self.ui.entity_preset_tabs.tabText(new_index))

Expand All @@ -1631,7 +1645,7 @@ def _switch_profile_tab(self, new_index, track_in_history):

if track_in_history:
# figure out what is selected
selected_item = self._get_selected_entity()
selected_item = self._get_selected_entities()[0]

# update breadcrumbs
self._populate_entity_breadcrumbs(selected_item)
Expand All @@ -1643,40 +1657,52 @@ def _switch_profile_tab(self, new_index, track_in_history):
self._setup_details_panel([])

# tell the publish view to change
self._load_publishes_for_entity_item(selected_item)
self._load_publishes_for_entity_items([selected_item])

def _on_treeview_item_selected(self):
"""
Slot triggered when someone changes the selection in a treeview.
"""
selected_items = self._get_selected_entities()

selected_item = self._get_selected_entity()
model = self._entity_presets[self._current_entity_preset].model

# update breadcrumbs
self._populate_entity_breadcrumbs(selected_item)
# If nothing is selected, refresh the view.
if len(selected_items) == 0:
if isinstance(model, SgEntityModel):
model.async_refresh()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a comment on why this is necessary

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be wrong it's been a while since I looked at this, but if you don't refresh the view when nothing is selected, then you'll be left with a filtered list of published_files, where you actually want the list to reset to fully unfiltered.

else:
# when an item in the treeview is selected, the child
# nodes are displayed in the main view, so make sure
# they are loaded.

# when an item in the treeview is selected, the child
# nodes are displayed in the main view, so make sure
# they are loaded.
model = self._entity_presets[self._current_entity_preset].model
if selected_item and model.canFetchMore(selected_item.index()):
model.fetchMore(selected_item.index())
multi_selection_filters = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't seemed to be used after it is populated.

for selected_item in selected_items:
# update breadcrumbs
self._populate_entity_breadcrumbs(selected_item)

# notify history
self._add_history_record(self._current_entity_preset, selected_item)
selected_item_filters = model.get_filters(selected_item)
for f in selected_item_filters:
if f not in multi_selection_filters:
multi_selection_filters.append(f)

# tell details panel to clear itself
self._setup_details_panel([])
if selected_item and model.canFetchMore(selected_item.index()):
model.fetchMore(selected_item.index())

# tell publish UI to update itself
self._load_publishes_for_entity_item(selected_item)
# notify history
self._add_history_record(self._current_entity_preset, selected_item)

# tell details panel to clear itself
self._setup_details_panel([])

def _load_publishes_for_entity_item(self, item):
# tell publish UI to update itself
self._load_publishes_for_entity_items(selected_items)

def _load_publishes_for_entity_items(self, items):
"""
Given an item from the treeview, or None if no item
is selected, prepare the publish area UI.
"""

# clear selection. If we don't clear the model at this point,
# the selection model will attempt to pair up with the model is
# data is being loaded in, resulting in many many events
Expand All @@ -1686,67 +1712,69 @@ def _load_publishes_for_entity_item(self, item):
child_folders = []
proxy_model = self._entity_presets[self._current_entity_preset].proxy_model

if item is None:
# nothing is selected, bring in all the top level
# objects in the current tab
num_children = proxy_model.rowCount()

for x in range(num_children):
# get the (proxy model) index for the child
child_idx_proxy = proxy_model.index(x, 0)
# switch to shotgun model index
child_idx = proxy_model.mapToSource(child_idx_proxy)
# resolve the index into an actual standarditem object
i = self._entity_presets[self._current_entity_preset].model.itemFromIndex(child_idx)
child_folders.append(i)
for item in items:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like the changes below are strictly the result of adding this line and shifting everything. can you confirm? i don't trust my eyes. 😄

if item is None:
# nothing is selected, bring in all the top level
# objects in the current tab
num_children = proxy_model.rowCount()

for x in range(num_children):
# get the (proxy model) index for the child
child_idx_proxy = proxy_model.index(x, 0)
# switch to shotgun model index
child_idx = proxy_model.mapToSource(child_idx_proxy)
# resolve the index into an actual standarditem object
i = self._entity_presets[self._current_entity_preset].model.itemFromIndex(child_idx)
child_folders.append(i)

else:
# we got a specific item to process!

# now get the proxy model level item instead - this way we can take search into
# account as we show the folder listings.
root_model_idx = item.index()
root_model_idx_proxy = proxy_model.mapFromSource(root_model_idx)
num_children = proxy_model.rowCount(root_model_idx_proxy)

# get all the folder children - these need to be displayed
# by the model as folders

for x in range(num_children):
# get the (proxy model) index for the child
child_idx_proxy = root_model_idx_proxy.child(x, 0)
# switch to shotgun model index
child_idx = proxy_model.mapToSource(child_idx_proxy)
# resolve the index into an actual standarditem object
i = self._entity_presets[self._current_entity_preset].model.itemFromIndex(child_idx)
child_folders.append(i)

# Is the show child folders checked?
# The hierarchy model cannot handle "Show items in subfolders" mode.
show_sub_items = self.ui.show_sub_items.isChecked() and \
not isinstance(self._entity_presets[self._current_entity_preset].model, SgHierarchyModel)

if show_sub_items:
# indicate this with a special background color
self.ui.publish_view.setStyleSheet("#publish_view { background-color: rgba(44, 147, 226, 20%); }")
if len(child_folders) > 0:
# delegates are rendered in a special way
# if we are on a non-leaf node in the tree (e.g there are subfolders)
self._publish_thumb_delegate.set_sub_items_mode(True)
self._publish_list_delegate.set_sub_items_mode(True)
else:
# we are at leaf level and the subitems check box is checked
# render the cells
# we got a specific item to process!

# now get the proxy model level item instead - this way we can take search into
# account as we show the folder listings.
root_model_idx = item.index()
root_model_idx_proxy = proxy_model.mapFromSource(root_model_idx)
num_children = proxy_model.rowCount(root_model_idx_proxy)

# get all the folder children - these need to be displayed
# by the model as folders

for x in range(num_children):
# get the (proxy model) index for the child
child_idx_proxy = root_model_idx_proxy.child(x, 0)
# switch to shotgun model index
child_idx = proxy_model.mapToSource(child_idx_proxy)
# resolve the index into an actual standarditem object
i = self._entity_presets[self._current_entity_preset].model.itemFromIndex(child_idx)
child_folders.append(i)

# Is the show child folders checked?
# The hierarchy model cannot handle "Show items in subfolders" mode.
show_sub_items = self.ui.show_sub_items.isChecked() and \
not isinstance(self._entity_presets[self._current_entity_preset].model, SgHierarchyModel)

if show_sub_items:
# indicate this with a special background color
self.ui.publish_view.setStyleSheet("#publish_view { background-color: rgba(44, 147, 226, 20%); }")
if len(child_folders) > 0:
# delegates are rendered in a special way
# if we are on a non-leaf node in the tree (e.g there are subfolders)
self._publish_thumb_delegate.set_sub_items_mode(True)
self._publish_list_delegate.set_sub_items_mode(True)
else:
# we are at leaf level and the subitems check box is checked
# render the cells
self._publish_thumb_delegate.set_sub_items_mode(False)
self._publish_list_delegate.set_sub_items_mode(False)
else:
self.ui.publish_view.setStyleSheet("")
self._publish_thumb_delegate.set_sub_items_mode(False)
self._publish_list_delegate.set_sub_items_mode(False)
else:
self.ui.publish_view.setStyleSheet("")
self._publish_thumb_delegate.set_sub_items_mode(False)
self._publish_list_delegate.set_sub_items_mode(False)

# now finally load up the data in the publish model
publish_filters = self._entity_presets[self._current_entity_preset].publish_filters
self._publish_model.load_data(item, child_folders, show_sub_items, publish_filters)
# now finally load up the data in the publish model
publish_filters = self._entity_presets[self._current_entity_preset].publish_filters

self._publish_model.load_data(items, child_folders, show_sub_items, publish_filters)

def _populate_entity_breadcrumbs(self, selected_item):
"""
Expand All @@ -1755,7 +1783,6 @@ def _populate_entity_breadcrumbs(self, selected_item):
:param selected_item: Item currently selected in the tree view or
`None` when no selection has been made.
"""

crumbs = []

if selected_item:
Expand Down Expand Up @@ -1819,6 +1846,21 @@ def _populate_entity_breadcrumbs(self, selected_item):

self.ui.entity_breadcrumbs.setText("<big>%s</big>" % breadcrumbs)

def _log_debug(self, msg):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these necessary? They don't seem to be used by the new code.

"""
Convenience wrapper around debug logging

:param msg: debug message
"""
self._bundle.log_debug("[%s] %s" % (self.__class__.__name__, msg))

def _log_info(self, msg):
"""
Convenience wrapper around debug logging

:param msg: debug message
"""
self._bundle.log_info("[%s] %s" % (self.__class__.__name__, msg))

################################################################################################
# Helper stuff
Expand Down
Loading