Source code for views.edit_selected_widget_delegate
# Copyright (c) 2013 Shotgun Software Inc.
#
# CONFIDENTIAL AND PROPRIETARY
#
# This work is provided "AS IS" and subject to the Shotgun Pipeline Toolkit
# Source Code License included in this distribution package. See LICENSE.
# By accessing, using, copying or modifying this work you indicate your
# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights
# not expressly granted therein are reserved by Shotgun Software Inc.
import sgtk
from sgtk.platform.qt import QtCore, QtGui
from .widget_delegate import WidgetDelegate
[docs]class EditSelectedWidgetDelegate(WidgetDelegate):
"""
Custom delegate that provides a simple mechanism where an actual widget (editor) is
presented for the selected item whilst all other items are simply drawn with a single
widget.
:ivar selection_model: The selection model of the delegate's parent view, if one
existed at the time of the delegate's initialization.
:vartype selection_model: QtGui.QItemSelectionModel
You use this class by subclassing it and implementing the methods:
- :meth:`_get_painter_widget()` - return the widget to be used to paint an index
- :meth:`_on_before_paint()` - set up the widget with the specific data ready to be painted
- :meth:`sizeHint()` - return the size of the widget to be used in the view
If you want to have an interactive widget (editor) for the selected item
then you will also need to implement:
- :meth:`_create_editor_widget()` - return a unique editor instance to be used for editing
- :meth:`_on_before_selection()` - set up the widget with the specific data ready for
interaction
.. note:: If you are using the same widget for all items then you can just implement
the :meth:`_create_widget()` method instead of the separate :meth:`_get_painter_widget()`
and :meth:`_create_editor_widget()` methods.
.. note:: In order for this class to handle selection correctly, it needs to be
attached to the view *after* the model has been attached. (This is
to ensure that it is able to obtain the view's selection model correctly.)
"""
def __init__(self, view):
"""
:param view: The parent view for this delegate
:type view: :class:`~PySide.QtGui.QWidget`
"""
WidgetDelegate.__init__(self, view)
# tracks the currently active cell
self.__current_editor_index = None
# note! Need to have a model connected to the view in order
# to have a selection model.
self.selection_model = view.selectionModel()
if self.selection_model:
self.selection_model.selectionChanged.connect(self._on_selection_changed)
########################################################################################
# implemented by deriving classes
[docs] def _on_before_selection(self, widget, model_index, style_options):
"""
This method is called just before a cell is selected. This method should
configure values on the widget (such as labels, thumbnails etc) based on the
data contained in the model index parameter which is being passed.
:param widget: The QWidget (constructed in _create_widget()) which will
be used to paint the cell.
:type parent: :class:`~PySide.QtGui.QWidget`
:param model_index: QModelIndex object representing the data of the object that is
about to be drawn.
:type model_index: :class:`~PySide.QtCore.QModelIndex`
:param style_options: object containing specifics about the
view related state of the cell.
:type style_options: :class:`~PySide.QtGui.QStyleOptionViewItem`
"""
pass
########################################################################################
# 'private' methods that are not meant to be subclassed or called by a deriving class.
def _on_selection_changed(self, selected, deselected):
"""
Signal triggered when someone changes the selection in the view.
:param selected: A list of the indexes in the model that were selected
:type selected: :class:`~PySide.QtGui.QItemSelection`
:param deselected: A list of the indexes in the model that were deselected
:type deselected: :class:`~PySide.QtGui.QItemSelection`
"""
# clean up
if self.__current_editor_index:
self.parent().closePersistentEditor(self.__current_editor_index)
self.__current_editor_index = None
selected_indexes = selected.indexes()
if len(selected_indexes) > 0:
# get the currently selected model index
model_index = selected_indexes[0]
# create an editor widget that we use for the selected item
self.__current_editor_index = model_index
# this will trigger the call to createEditor
self.parent().openPersistentEditor(model_index)
def createEditor(self, parent_widget, style_options, model_index):
"""
Subclassed implementation from QStyledItemDelegate which is
called when an "editor" is set up - the editor is set up
via the openPersistentEditor call and is created upon selection
of an item.
Normally, for performance, when we draw hundreds of grid cells,
we use the same Qwidget as a brush and simply use it to paint.
For the currently selected cell however, we need to be able to interact
with the widget (e.g. click a button for example) and therefore we need
to have a real widget for this.
:param parent_widget: The parent widget to use for the new editor widget
:type parent_widget: :class:`~PySide.QtGui.QWidget`
:param style_options: The style options to use when creating the editor
:type style_options: :class:`~PySide.QtGui.QStyleOptionViewItem`
:param model_index: The index in the data model that will be edited
using this editor
:type model_index: :class:`~PySide.QtCore.QModelIndex`
:returns: An editor widget that will be used to edit this
index
:rtype: :class:`~PySide.QtGui.QWidget`
"""
# create the editor by calling the base method:
editor_widget = WidgetDelegate.createEditor(
self, parent_widget, style_options, model_index
)
# and set it up to operate on the index:
self._on_before_selection(editor_widget, model_index, style_options)
return editor_widget
def paint(self, painter, style_options, model_index):
"""
Paint method to handle all cells that are not being currently edited.
:param painter: The painter instance to use when painting
:param style_options: The style options to use when painting
:type style_options: :class:`~PySide.QtGui.QStyleOptionViewItem`
:param model_index: The index in the data model that needs to be painted
:type model_index: :class:`~PySide.QtCore.QModelIndex`
"""
if model_index == self.__current_editor_index:
# avoid painting the index twice!
return
WidgetDelegate.paint(self, painter, style_options, model_index)