Shotgun Model¶
Introduction¶
The shotgun data model helps you build responsive, data rich applications quickly and leverage Qt’s built-in model/view framework

The Shotgun Model is a custom Qt Model specialized for Shotgun Queries. It uses a disk based cache and runs queries asynchronously to Shotgun in the background for performance. In a nut shell, you derive your own model class from it, set up a query, and then hook up your model to a Qt View which will draw the data. The class contains several callbacks and allows for extensive customization, yet tries to shadow and encapsulate a lot of the details.

Why should I use the Shotgun Model?¶
Using the Shotgun Model means switching to Model/View based programming. While there is perhaps slightly more overhead to get started with this, there are many benefits. The Shotgun Model (and the corresponding delegates and Shotgun View components) is an attempt to bridge this gap and make it quick and painless to get started with Qt Model/View programming.
Qt provides a strong and mature Model/View hierarchy which is robust and easy to work with. If you are not familiar with it, please check the following links:
- Tutorial: http://qt-project.org/doc/qt-4.8/modelview.html
- Technical details: http://qt-project.org/doc/qt-4.8/model-view-programming.html
The benefits with this approach will become evident as you scale your UIs and their complexity. Developing code and tools where the data and the UI is combined will work in simple scenarios but for data rich applications this approach becomes hard to maintain, difficult to reuse and typically scales poorly as the dataset complexity grows. By leveraging Qts built-in functionality, you get access to a mature and well documented toolbox that makes it quick to develop tools:
- A Shotgun model instance represents a single shotgun query. With two lines of code you can connect the resultset of such a query with a standard Qt list, tree or table.
- The Shotgun model is cached, meaning that all data is fetched in the background in a worker thread. This means that the data in your UI will load up instantly and you never have to wait for shotgun. If the query result is different than the cached result, the view will be updated on the fly as the data arrives.
- With Qt you have access to SelectionModels, making it easy to create consistent selection behavior, even across multiple views. With full keyboard support.
- With Qt proxy models you can easily create interactive searching and filtering on the client side.
- Views and models are optimized and will perform nicely even if you have thousands of items loaded.
- Through the shotgun view module, you can easily control the Qt delegates system, making it easy to draw custom UIs for each cell in your view.
Shotgun Model Hello World¶
A hello world style example would look something like this, assuming this code is inside a toolkit app:
# Import the shotgun_model module from the shotgun utils framework
shotgun_model = tank.platform.import_framework("tk-framework-shotgunutils", "shotgun_model")
# Set up alias
ShotgunModel = shotgun_model.ShotgunModel
# Create a standard Qt Tree View
view = QtGui.QTreeView(parent_widget)
# Set up our data backend
model = shotgun_model.SimpleShotgunModel(parent_widget)
# Tell the view to pull data from the model
view.setModel(model)
# load all assets from Shotgun
model.load_data(entity_type="Asset")
The above code will create a standard Qt tree view of all assets in Shotgun.
Beyond Hello World¶
The simple setup outlined above could be extended in the following ways:
- If you need more control of how the data is being retrieved, consider instead creating
your own class and derive from
ShotgunModel
. This makes it possible to customize the shotgun data as it arrives from Shotgun, control the hierarchy grouping and many other things. - If you want to retrieve results from your view, connect signals to the view’s selection model.
- If you want to cull out items from the model, for example only to show items matching a particular
search criteria, use a Proxy Model (typically
QSortFilterProxyModel
). - If you want to control the way items are displayed in the view, consider using the Shotgun delegates
module which is part of the Qt widgets framework. For more information, see
WidgetDelegate
Progress Spinner¶
The model emits several signals at various points in its refresh cycle. If you want a spinner
to pop up to indicate that data is being loaded, simply add a ShotgunModelOverlayWidget
between your view and model, like this:
overlay_widget = tank.platform.import_framework("tk-framework-qtwidgets", "overlay_widget")
# once you have created a view and a model, set up an overlay object to
# track the model's activity. Whenver the model is loading data,
# the overlay will show a spinner.
overlay = overlay_widget.ShotgunModelOverlayWidget(model, view)
If you want to refine how the overlay behaves, simply subclass the class above. This can be useful if you for example want to display a ‘no items found’ message whenever a shotgun query returns zero items.
Data Items¶
The Shotgun Model derives from QStandardItemModel
which is a base model which managed the storage
of model data inside a collection of QStandardItem
objects. Each of these objects have a number of
standard property and so called roles, holding various pieces of data such as icons, colors etc.
The Shotgun Model introduces two new standard roles which can be used by both subclassing and calling
code:
ShotgunModel.SG_DATA_ROLE
holds the shotgun data associated with an object. In a tree view, only leaf nodes have this data defined - other nodes have it set to None. For leaf nodes, it is a standard shotgun dictionary containing all the items that were returned by the Shotgun query.ShotgunModel.SG_ASSOCIATED_FIELD_ROLE
holds the associated field value for a node. This is contained in a dictionary with the keys name and value. For example, for a leaf node this is typically something like{"name": "code", "value": "AAA_123"}
. For an intermediate node, it may be something such as{"name": "sg_sequence", "value": {"id": 123, "name": "AAA", "type": "Sequence"} }
.
SimpleShotgunModel¶
Convenience wrapper around the Shotgun model for quick and easy access. Use this when you want
to prototype data modeling or if your are looking for a simple flat data set reflecting a
shotgun query. All you need to do is to instantiate the class (typically once, in your constructor)
and then call SimpleShotgunModel.load_data()
to
specify which shotgun query to load up in the model. Subsequently call
load_data()
whenever you
wish to change the Shotgun query associated with the model.
This class derives from ShotgunModel
so all the
customization methods available in the
normal ShotgunModel can also be subclassed from this class.
ShotgunEntityModel¶
Another convenience wrapper around the ShotgunModel
. This model is useful when you
want to represent a tree view of Sequences, Shots or Assets. By default, the model will
associate standard dark-style Shotgun entity type icons to items in the list.
ShotgunModel¶
A Qt Model representing a Shotgun query.
This class implements a standard QAbstractItemModel
specialized to hold the contents
of a particular Shotgun query. It is cached and refreshes its data asynchronously.
The model can either be a flat list or a tree. This is controlled by a grouping parameter which works just like the Shotgun grouping. For example, if you pull in assets grouped by asset type, you get a tree of data with intermediate data types for the asset types. The leaf nodes in this case would be assets.