Skip to content
Manne Öhrström edited this page Jul 9, 2015 · 58 revisions

The Shotgun Utils Framework contains a collection of helpers and tools to make it easy and painless to build consistent looking applications. It contains several modules which can each be used independently:

  • A Shotgun Data Model deriving from QStandardItemModel which makes it easy to build responsive, data rich applications quickly.
  • A settings system handles per-user preferences and makes it easy to work with the QSettings class from within your app code.
  • An asynchronous shotgun data receiver which makes it easy to work with background queries and thumbnail retrieval

In the following documentation sections, each module is presented in detail with API reference and code examples.

Shotgun Model

The shotgun data model helps you build responsive, data rich applications quickly and leverage QT's build 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 nutshell, 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.

For convenience, three different classes are provided, allowing you to choose the right level of encapsulation.

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:

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 behaviour, 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 treeview 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 ShotgunOverlayModel. 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 Qtwidgets framework.

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, colours 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"} }.

Datetime objects and the Shotgun API

Because of issues with serialization, please note that datetime objects returned by the Shotgun API are automatically converted to unix timestamps by the model. A unix timestamp is the number of seconds since 1 Jan 1971, in the UTC time zone.

When you are pulling data from the shotgun model and want to convert this unix timestamp to a local timezone object, which is what you would get from the Shotgun API, use the following code:

import datetime
from tank_vendor import shotgun_api3
local_datetime = datetime.datetime.fromtimestamp(unix_time, shotgun_api3.sg_timezone.LocalTimezone())

Furthermore, if you want to turn that into a nicely formatted string:

time_str = local_datetime.strftime('%Y-%m-%d %H:%M')

Class SimpleShotgunModel API Reference

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 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.

SimpleShotgunModel Constructor

Class constructor. The simple shotgun model contains a progress spinner which will appear whenever the object is doesn't have any data to display. This progress spinner will be placed on top of the parent object specified in the parent constructor parameter.

SimpleShotgunModel(parent)

Constructor Parameters

  • QWidget parent - QWidget which this model will be parented under. This widget will also be used to paint a spinner and display error messages.

load_data()

Loads shotgun data into the model, using the cache if possible. The model is not nested and the first field that is specified via the fields parameter (code by default) will be used as the default name for all model items.

model_obj.load_data(entity_type, filters=None, fields=None)

Parameters & Return Value

  • str entity_type - Shotgun Entity Type to load data for.
  • list filters - Shotgun API find-style filter list. If no list is specified, all records for the given entity type will be retrieved.
  • list fields - List of Shotgun fields to retrieve. If not specified, the 'code' field will be retrieved.

Class ShotgunOverlayModel API Reference

Convenience wrapper around the ShotgunModel class which adds spinner and error reporting overlay functionality. Where the ShotgunModel is a classic model class which purely deals with data, this class connects with a QWidget in order to provide progress feedback whenever necessary. Internally, it holds an instance of the ShotgunOverlayWidget widget (which is part of the QtWidgets framework) and will show this whenever there is no data to display in the view. This means that it is straight forward to create shotgun views with a spinner on top indicating when data is being loaded and where any errors are automatically reported to the user.

Signal progress_spinner_start

progress_spinner_start()

Signal that gets emitted whenever the model deems it appropriate to indicate that data is being loaded. Note that this signal is not emitted every time data is loaded from Shotgun, but only when there is no cached data available to display. This signal can be useful if an implementation wants to set up a custom overlay system instead of or in addition to the built in one that is provided via the set_overlay_parent() method.

ShotgunOverlayModel Constructor

Constructor. This will create a model which can later be used to load and manage Shotgun data.

ShotgunOverlayModel(parent, overlay_widget, download_thumbs=True, schema_generation=0, bg_load_thumbs=False)

Constructor Parameters

  • QObject parent - Parent object.
  • QWidget overlay_widget - Widget on which the spinner/info overlay should be positioned.
  • bool download_thumbs - Boolean to indicate if this model should attempt to download and process thumbnails for the downloaded data.
  • int schema_generation - Schema generation index. If you are changing the format of the data you are retrieving from Shotgun, and therefore want to invalidate any cache files that may already exist in the system, you can increment this integer.
  • bool bg_load_thumbs - Background loading of thumbs. If set to True, the model will not only asynchronously download thumbs from Shotgun, but also load them in from disk. This is usually recommended behaviour as it takes a significant load off the main UI thread. If set to False, the model will execute the client callback _populate_thumbnail(), if set to True, the model will execute the client callback _populate_thumbnail_image().

_show_overlay_spinner()

Shows the associated overlay spinner.

model_obj._show_overlay_spinner()

_hide_overlay_info()

Hides any overlay that is currently shown, except for error messages.

model_obj._hide_overlay_info()

_show_overlay_pixmap()

Show an overlay status message in the form of a pixmap. This is for example useful if a particular query doesn't return any results. If an error message is already being shown, the pixmap will not replace the error message.

model_obj._hide_overlay_info(pixmap)

Parameters & Return Value

  • QPixmap pixmap - QPixmap object containing graphic to show

_show_overlay_info_message()

Show an overlay status message. If an error is already displayed, this info message will not be shown.

model_obj._show_overlay_info_message(msg)

Parameters & Return Value

  • str msg - message to display
  • Returns: True if the message was shown, False if not.

_show_overlay_error_message()

Show an overlay error message.

model_obj._show_overlay_error_message(msg)

Parameters & Return Value

  • str msg - message to display

Class ShotgunModel API Reference

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.

In order to use this class, you normally subclass it and implement certain key data methods for setting up queries, customizing etc. Then you connect your class to a QView of some sort which will display the result. If you need to do manipulations such as sorting or filtering on the data, connect a QProxyModel between your class and the view.

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.

Signal query_changed

query_changed()

Signal which gets emitted whenever the model's sg query is changed. when the query changes, the contents of the model is cleared and the loading of new data is initiated.

Signal cache_loaded

cache_loaded()

Signal which gets emitted whenever the model loads cache data. this typically follows shortly after a query changed signal, if cache data is available.

Signal data_refreshing

data_refreshing()

Signal which gets emitted whenever the model starts to refresh its shotgun data. This is emitted from _refresh_data() at the beginning of a refresh operaton. Useful signal if you want to present a loading indicator of some kind.

Signal data_refreshed

data_refreshed(bool)

Signal which gets emitted whenever the model has been updated with fresh shotgun data. The boolean indicates that a change in the model data has taken place as part of this process. If the refresh fails for some reason, this signal may not be emitted.

The synchronous data refresh cycle starts with a call to _refresh_data() and normally ends with either a data_refreshed or a data_refresh_fail being emitted. The exception being that if you call _load_data() or clear the model in some other way, the signals may never be emitted.

Signal data_refresh_fail

data_refresh_fail(str)

Signal which gets emitted in the case the refresh fails for some reason, typically due to the absence of an Internet connection. This signal could for example be used to drive a "retry" button of some kind. The str parameter carries an error message with details about why the refresh wasn't successful.

ShotgunModel Constructor

Constructor. This will create a model which can later be used to load and manage Shotgun data.

ShotgunOverlayModel(parent, download_thumbs=True, schema_generation=0, bg_load_thumbs=False)

Constructor Parameters

  • QObject parent - Parent object.
  • bool download_thumbs - Boolean to indicate if this model should attempt to download and process thumbnails for the downloaded data.
  • int schema_generation - Schema generation index. If you are changing the format of the data you are retrieving from Shotgun, and therefore want to invalidate any cache files that may already exist in the system, you can increment this integer.
  • bool bg_load_thumbs - Background loading of thumbs. If set to True, the model will not only asynchronously download thumbs from Shotgun, but also load them in from disk. This is usually recommended behaviour as it takes a significant load off the main UI thread. If set to False, the model will execute the client callback _populate_thumbnail(), if set to True, the model will execute the client callback _populate_thumbnail_image().

set_shotgun_connection()

Specify the shotgun api instance this model should use to communicate with Shotgun. If not specified, each model instance will instantiate its own connection, via toolkit. The behavior where each model has its own connection is generally recommended for thread safety reasons since the Shotgun API isn't natively thread-safe.

sg_model_obj.set_shotgun_connection( sg )

Parameters & Return Value

  • Shotgun sg - Shotgun API instance.

destroy()

Call this method prior to destroying this object. This will ensure all worker threads etc are stopped. The method does not return a value but it is blocking and may be slow to execute.

sg_model_obj.destroy()

hard_refresh()

Clears any caches on disk, then refreshes the data.

sg_model_obj.hard_refresh()

item_from_entity()

Tried to locate an item contained in the model matching the given entity type and entity id. Returns a QStandardItem if found, returns none if not found.

sg_model_obj.item_from_entity( entity_type, entity_id )

Parameters & Return Value

  • string entity_type - Shotgun entity type to look for.
  • int entity_id - Shotgun entity id to look for.
  • Returns: QStandardItem or None if no object could be found.

get_filters()

Returns a list of Shotgun filters representing the given item. This is useful if you are trying to determine how intermediate leaf nodes partition leaf node data.

sg_model_obj.get_filters( item )

For example, if you have created a hierarchical model for a Shot listing: [sg_sequence, sg_status, code], the Shotgun model will group the data by sequence, then by status. Finally, the leaf nodes will be the shot names. If you execute the get_filters() method on a sequence level tree node, it may return

[ ['sg_sequence', 'is', {'type': 'Sequence', 'id': 123, 'name': 'foo'}] ]

If you execute the get_filters() on a status node in the tree, it may return

[ ['sg_sequence', 'is', {'type': 'Sequence', 'id': 123, 'name': 'foo'}],
    ['sg_status', 'is', 'ip'] ]

Parameters & Return Value

  • QStandardItem item - One of the QStandardItem model items that is associated with this model.
  • Returns: standard shotgun filter list to represent that item.

get_entity_type()

Returns the Shotgun Entity type associated with this model.

sg_model_obj.get_entity_type()
  • Returns: Shotgun entity type string (e.g. 'Shot', 'Asset' etc).

Protected methods not meant to be subclassed

These methods are typically called from within the subclass, but they are not meant to be subclassed themselves. If you do decide to subclass them, carefully ensure that you call the base class implementation for correct behaviour.

_load_data()

This is the main method to use to configure the model. You basically pass a specific find query to the model and it will start tracking this particular set of filter and hierarchy parameters. Any existing data in contained in the model will be cleared. This method will not call the Shotgun API. If cached data is available, this will be immediately loaded (this operation is very fast even for substantial amounts of data). If you want to refresh the data contained in the model (which you typically want to!), call the _refresh_data() method.

sg_model_obj._load_data( entity_type, filters, hierarchy, fields, fields, order=None, seed=None )

Parameters

  • str entity_type - Shotgun entity type to download
  • str filters - List of Shotgun filters. Standard Shotgun syntax.
  • str hierarchy - List of grouping fields. These should be names of Shotgun fields. If you for example want to create a list of items, the value ["code"] will be suitable. This will generate a data model which is flat and where each item's default name is the Shotgun name field. If you want to generate a tree where assets are broken down by asset type, you could instead specify ["sg_asset_type", "code"].
  • str fields - Fields to retrieve from Shotgun (in addition to the ones specified in the hierarchy parameter). Standard Shotgun API syntax. If you specify None for this parameter, Shotgun will not be called when the _refresh_data() method is being executed.
  • str order - Order clause for the Shotgun data. Standard Shotgun API syntax. Note that this is an advanced parameter which is meant to be used in subclassing only. The model itself will be ordered by its default display name, and if any other type of ordering is desirable, use for example a QProxyModel to handle this. However, knowing in which order results will arrive from Shotgun can be beneficial if you are doing grouping, deferred loading and aggregation of data as part of your subclassed implementation, typically via the _before_data_processing() method.
  • str seed - Advanced parameter. With each shotgun query being cached on disk, the model generates a cache seed which it is using to store data on disk. Since the cache data on disk is a reflection of a particular shotgun query, this seed is typically generated from the various query and field parameters passed to this method. However, in some cases when you are doing advanced subclassing, for example when you are culling out data based on some external state, the model state does not solely depend on the shotgun query parameters. It may also depend on some external factors. In this case, the cache seed should also be influenced by those parameters and you can pass an external string via this parameter which will be added to the seed.
  • Returns: True if a cached load was successful and the model was populated, False if not.

_refresh_data()

Rebuilds the data in the model to ensure it is up to date. This call is asynchronous and will return instantly. The update will be applied whenever the data from Shotgun is returned. If the model is empty (no cached data), a spinner is shown. If cached data is available, the update happens silently in the background. If data has been added, this will be injected into the existing structure. In this case, the rest of the model is intact, meaning that also selections and other view related states are unaffected. If data has been modified or deleted, a full rebuild is issued, meaning that all existing items from the model are removed. This does affect view related states such as selection.

sg_model_obj._refresh_data()

_request_thumbnail_download()

Request that a thumbnail is downloaded for an item. If a thumbnail is successfully retrieved, either from disk (cached) or via shotgun, the methods _populate_thumbnail() or _populate_thumbnail_image() will be called. If you want to control exactly how your shotgun thumbnail is to appear in the UI, you can subclass this method. For example, you can subclass this method and perform image composition prior to the image being added to the item object.

Note: This is an advanced method which you can use if you want to load thumbnail data other than the standard 'image' field. If that's what you need, simply make sure that you set the download_thumbs parameter to true when you create the model and standard thumbnails will be automatically downloaded. This method is either used for linked thumb fields or if you want to download thumbnails for external model data that doesn't come from Shotgun.

sg_model_obj._request_thumbnail_download( item, field, url, entity_type, entity_id )

Parameters & Return Value

  • QStandardItem item - StandardItem to request download for.
  • str field - Shotgun field where the thumbnail is stored. This is typically 'image' but can also for example be 'sg_sequence.Sequence.image'.
  • str url - Thumbnail url as returned by Shotgun
  • str entity_type - Shotgun entity type
  • int entity_id - Shotgun entity id

Protected methods to be implemented by subclasses

These methods are not required to be implemented by deriving classes, but in case you need to do advanced customization, the below methods provide a lot of flexibility.

_populate_item()

Whenever an item is constructed, this method is called. It allows subclasses to intercept the construction of a QStandardItem and add additional metadata or make other changes that may be useful. Nothing needs to be returned. This method is called before the item is added into the model tree. At the point when the item is added into the tree, various signals will fire, informing views and proxy models that a new item has been added. This methods allows a subclassing object to add custom data prior to this.

Note that when an item is fetched from the cache, this method is not called, it will only be called when shotgun data initially arrives from a Shotgun API query.

This is typically subclassed if you retrieve additional fields alongside the standard "name" field and you want to put those into various custom data roles. These custom fields on the item can later on be picked up by custom (delegate) rendering code in the view.

sg_model_obj._populate_item( item, sg_data )

Parameters & Return Value

  • QStandardItem item - QStandardItem that is about to be added to the model. This has been primed with the standard settings that the ShotgunModel handles.
  • dict sg_data - Shotgun data dictionary that was received from Shotgun given the fields and other settings specified in _load_data().

_populate_default_thumbnail()

Called whenever an item is constructed and needs to be associated with a default thumbnail. In the current implementation, thumbnails are not cached in the same way as the rest of the model data, meaning that this method is executed each time an item is constructed, regardless of if it came from an asynchronous shotgun query or a cache fetch.

The purpose of this method is that you can subclass it if you want to ensure that items have an associated thumbnail directly when they are first created.

Later on in the data load cycle, if the model was instantiated with the download_thumbs parameter set to True, the standard Shotgun image field thumbnail will be automatically downloaded for all items (or picked up from local cache if possible). When these real thumbnails arrive, the _populate_thumbnail() or _populate_thumbnail_image() method will be called.

sg_model_obj._populate_default_thumbnail( item )

Parameters & Return Value

  • QStandardItem item - QStandardItem that is about to be added to the model. This has been primed with the standard settings that the ShotgunModel handles.

_finalize_item()

Called whenever an item is fully constructed, either because a shotgun query returned it or because it was loaded as part of a cache load from disk.

sg_model_obj._finalize_item( item )

Parameters & Return Value

  • QStandardItem item - QStandardItem that is about to be added to the model. This has been primed with the standard settings that the ShotgunModel handles.

_populate_thumbnail() / _populate_thumbnail_image()

Called whenever the real thumbnail for an item exists on disk. If the model was constructed with bg_load_thums set to False, _populate_thumbnail() is called. If bg_load_thumbs was set to True, _populate_thumbnail_image() is called instead.

The following execution sequence typically happens:

  • QStandardItem is created, either through a cache load from disk or from a payload coming from the Shogun API.
  • After the item has been set up with its associated Shotgun data, _populate_default_thumbnail() is called, allowing client code to set up a default thumbnail that will be shown while potential real thumbnail data is being loaded.
  • The model will now start looking for the real thumbail.
    • If the thumbnail is already cached on disk, _populate_thumbnail() or _populate_thumbnail_image() is called very soon.
    • If there isn't a thumbnail associated, _populate_thumbnail() or _populate_thumbnail_image() will not be called.
    • If there isn't a thumbnail cached, the model will asynchronously download the thumbnail from Shotgun and then (after some time) call _populate_thumbnail() or _populate_thumbnail_image().

This method will be called for standard thumbnails if the model has been instantiated with the download_thumbs flag set to be true. It will be called for items which are associated with shotgun entities (in a tree data layout, this is typically leaf nodes). It will also be called once the data requested via _request_thumbnail_download() arrives.

This method makes it possible to control how the thumbnail is applied and associated with the item. The default implementation will simply set the thumbnail to be icon of the item, but this can be altered by subclassing this method.

sg_model_obj._populate_thumbnail( item, field, path )
sg_model_obj._populate_thumbnail_image( item, field, image, path )

Parameters & Return Value

  • QStandardItem item - QStandardItem which is associated with the given thumbnail
  • string field - The Shotgun field which the thumbnail is associated with.
  • QImage image - Image object containing the image data for the thumbnail stored in path.
  • string path - A path on disk to the thumbnail. This is a file in jpeg format.

_before_data_processing()

Called just after data has been retrieved from Shotgun but before any processing takes place. This makes it possible for deriving classes to perform summaries, calculations and other manipulations of the data before it is passed on to the model class.

sg_model_obj._before_data_processing( sg_data_list )

Parameters & Return Value

  • list sg_data_list - list of shotgun dictionaries, as retunrned by the find() call.
  • Returns: Should return a list of shotgun dictionaries, on the same form as the input.

_load_external_data()

Called whenever the model needs to be rebuilt from scratch. This is called prior to any shotgun data is added to the model. This makes it possible for deriving classes to add custom data to the model in a very flexible fashion. Such data will not be cached by the ShotgunModel framework.

sg_model_obj._load_external_data()

Parameters & Return Value

  • Returns: A list of QStandardItem objects.

Settings module

The settings module makes it easy to store things like user preferences, app related state etc. For example, if you want your app to remember the state of a checkbox across sessions, you can use the settings module to store this value. Adding persisting settings to an app can quickly drastically improve the user experience at a very low cost.

This settings module wraps around QSettings. This means that the settings data will be stored on your local machine and that they are for the current user only. If you need to share a preference or setting between multiple users, this module is most likely not the right one to use.

Settings can have different scope. This indicates how the setting should be shared between instances of apps, shotgun setups etc. Please note that the setting is still per-user and per-machine, so if it is scoped to be "global", it means that it will be shared across all different apps, engines, configurations, projects and shotgun sites for the current user on their local machine.

  • SCOPE_GLOBAL - No restriction.
  • SCOPE_SITE - Settings are per Shotgun site.
  • SCOPE_PROJECT - Settings are per Shotgun project.
  • SCOPE_CONFIG - Settings are per Shotgun Pipeline Configuration.
  • SCOPE_INSTANCE - Settings are per app or engine instance. For example, if your app contains a set of filters, and you want these to be remembered across sessions, you would typically use this scope. Each instance of the app will remember its own filters, so when you run it in the asset environment, one set of filters are remembered, when you run it in the shot environment, another set of filters etc.
  • SCOPE_ENGINE - One setting per engine. This makes it possible to store one set of preferences for apps running in Photoshop, Maya, Nuke etc. This makes it possible to for example store a setting that remembers if a "welcome screen" for your app has been displayed - so that it is only displayed once in Maya, once in Nuke etc.

The following code illustrates typical use of the settings module:

# example of how the settings module can be used within your app code
# import the module - note that this is using the special
# import_framework code so it won't work outside an app
settings = sgtk.platform.import_framework("tk-framework-shotgunutils", "settings")

# typically in the constructor of your main dialog or in the app, create a settings object:
self._settings_manager = settings.UserSettings(sgtk.platform.current_bundle())

# the settings system will handle serialization and management of data types
# so you can pass simple types such as strings, ints and lists and dicts of these.
#
# retrieve a settings value and default to a value if no settings was found
scale_val = self._settings_manager.retrieve("thumb_size_scale", 140)

# or store the same value
self._settings_manager.store("thumb_size_scale", 140)

# by default, things are scoped with `SCOPE_GLOBAL`. 
# If you want to specify another scope, add a scope parameter.

# Fetch a prefeence with a specific scope
ui_launched = self._settings_manager.retrieve("ui_launched", False, self._settings_manager.SCOPE_ENGINE)

# And store a preference with a specific scope
self._settings_manager.store("ui_launched", True, self._settings_manager.SCOPE_ENGINE)

Shotgun Data Retriever

The Shotgun data retriever makes it easy to pull in shotgun data and thumbnails in a background thread. It also manages caching of thumbnails on disk so that they don't need to be retrieved over and over again.

You start the worker thread, then you can submit a series of requests which will be handled by the data object. Each time data arrives, a signal is emitted with the details of the data. Each object will by default have its own Shotgun API connection. Requests are prioritised so according to their priority. For example, find() queries will always take precedence over shotgun thumbnail downloads.

# import the module - note that this is using the special
# import_framework code so it won't work outside an app
sg_data = sgtk.platform.import_framework("tk-framework-shotgunutils", "shotgun_data") 

class ExampleWidget(QtGui.QWidget):

    def __init__(self):

        QtGui.QWidget.__init__(self)
                
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        
        # set up data retriever
        self.__sg_data = sg_data.ShotgunDataRetriever(self)
        self.__sg_data.work_completed.connect( self.__on_worker_signal)
        self.__sg_data.work_failure.connect( self.__on_worker_failure)

        # and start its thread!
        self.__sg_data_retriever.start()

        # do an async request
        self._find_uid = self.__sg_data.execute_find("Shot", [], ["code"])


    def closeEvent(self, event):
        """
        Executed when the widget dialog is closed.
        """
        # gracefully stop our data retriever. This call
        # will block util the currently processing request has completed.
        self.__sg_data_retriever.stop()

        # okay to close dialog
        event.accept()

    def __on_worker_failure(self, uid, msg):
        """
        Asynchronous callback - the worker thread errored.
        """        
        print "Error: %s" % msg        
     
    def __on_worker_signal(self, uid, request_type, data):
        """
        Signaled whenever the worker completes something.
        """
        print "Data arrived: %s" % data 

API Reference for ShotgunDataRetriever

Asynchronous data retrieve class which can be used to retrieve data and thumbnails from Shotgun and from disk thumbnail cache. The class manages a queue where you can add various requests. Requests are queued up using for example the execute_find() and request_thumbnail() methods.

Requests are executed in the following priority order:

  • First any thumbnails that are already cached on disk are handled.
  • Next, shotgun find() queries are handled.
  • Lastly thumbnail downloads are handled.

The thread will emit work_completed and work_failure signals when tasks are completed (or fail). The clear() method will clear the current queue. The currently processing item will finish processing and may send out signals even after a clear. Make sure you call the stop() method prior to destruction in order for the system to gracefully shut down.

Signal work_completed

work_completed(uid, request_type, data_dict)

Signal that is emitted every time a requested task has completed.

  • uid is a unique id which matches the unique id returned by the corresponding request call.

  • request_type is a string denoting the type of request this event is associated with. It can be either find or thumbnail.

  • data_dict is a dictionary containing the payload of the request. It will be different depending on what type of request it is. For find() requests, the data_dict will be on the form {"sg": data }, where data is the data returned by the Shotgun API. For thumbnail requests, the data dict will be on the form {"thumb_path": path}, where path is a path to a location on disk where the thumbnail can be accessed.

Signal work_failure

work_completed(uid, error_message)

Signal that is emitted every time a requested task has failed.

  • uid is a unique id which matches the unique id returned by the corresponding request call.

  • error_message is a string which contains information about the failure.

ShotgunDataRetriever Constructor

Constructor. This will create a new thread instance. Once instantiated, you need to start the thread by executing start().

ShotgunDataRetriever(parent=None)

Constructor Parameters

  • QObject parent - Parent object.

set_shotgun_connection()

Specify the shotgun api instance this model should use to communicate with Shotgun. If not specified, each instance will instantiate its own connection, via toolkit. The behavior where each instance has its own connection is generally recommended for thread safety reasons since the Shotgun API isn't natively threadsafe.

We strongly recommend that the API instance passed in here is not used in any other threads since this may lead to undefined behaviour.

sg_data_obj.set_shotgun_connection( sg )

Parameters & Return Value

  • Shotgun sg - Shotgun API instance.

clear()

Clears the queue. Any currently processing item will complete without interruption, and signals will be sent out for these items.

sg_data_obj.destroy()

stop()

Gracefully stop the receiver.

Once stop() has been called, the object needs to be discarded. This is a blocking call. It will synchronounsly wait until any potential currently processing item has completed.

sg_data_obj.stop()

execute_find/create/update/delete

Add a Shotgun API crud query to the queue.

The query will be queued up and once processed, either a work_completed or work_failure signal will be emitted.

sg_data_obj.execute_find(*args, **kwargs)
sg_data_obj.execute_create(*args, **kwargs)
sg_data_obj.execute_update(*args, **kwargs)
sg_data_obj.execute_delete(*args, **kwargs)

Parameters & Return Value

  • *args / **kwargs - The method accepts the same parameters as the find/create/update/delete methods in the Shotgun API.
  • Returns: A unique identifier string representing this request. This identifier is also part of the payload sent via the work_completed and work_failure signals, making it possible to match them up.

get_schema()

Adds a shotgun schema request of a method to the queue. The Shotgun API methods schema_read() and schema_entity_read() will be executed.

The query will be queued up and once processed, either a work_completed or work_failure signal will be emitted.

sg_data_obj.get_schema(project_id=None)

Parameters & Return Value

  • project_id - If specified, the schema listing returned will be constrained by the schema settings for the given project.
  • Returns: A unique identifier string representing this request. This identifier is also part of the payload sent via the work_completed and work_failure signals, making it possible to match them up.

execute_method()

Adds the generic execution of a method to the queue.

The specified method will be called on the form method(sg, data), where sg is a shotgun API instance and data is a dictionary with specific data that the method needs.

The query will be queued up and once processed, either a work_completed or work_failure signal will be emitted.

sg_data_obj.execute_method(method, data)

Parameters & Return Value

  • method - Method to execute

  • dict data - Data to pass to the executing method.

  • Returns: A unique identifier string representing this request. This identifier is also part of the payload sent via the work_completed and work_failure signals, making it possible to match them up.

request_thumbnail()

Adds a Shotgun thumbnail request to the queue.

If a cached version of the thumbnail exists, this will be returned. If not, the Shotgun will be downloaded from Shotgun.

sg_data_obj.request_thumbnail(url, entity_type, entity_id, field)

Parameters & Return Value

  • str url - The thumbnail url string that is associated with this thumbnail. This is the field value as returned by a Shotgun query.

  • str entity_type - Shotgun entity type with which the thumb is associated.

  • int entity_id - Shotgun entity id with which the thumb is associated.

  • str field - Thumbnail field. Normally image but could also for example be a deep link field such as sg_sequence.Sequence.image.

  • Returns: A unique identifier string representing this request. This identifier is also part of the payload sent via the work_completed and work_failure signals, making it possible to match them up.

download_thumbnail()

Static method which synchronously downloads a thumbnail given a Shotgun thumbnail url.

ShotgunDataRetriever.request_thumbnail(url, bundle)

Convenience and compatibility method for quick and easy synchrnous thumbnail download. This will retrieve a shotgun thumbnail given a url - if it already exists in the cache, a path to it will be returned instantly. If not, it will be downloaded from Shotgun, placed in the standard cache location on disk and its path will be returned.

This is a helper method meant to make it easy to port over synchronous legacy code - for a better solution, we recommend using the thumbnail retrieval that runs in a background thread.

Bcause Shotgun thumbnail urls have an expiry time, make sure to only pass urls to this method that have been very recently retrieved via a Shotgun find call.

Parameters & Return Value

  • str url - The thumbnail url string that is associated with this thumbnail. This is the field value as returned by a Shotgun query.
  • Bundle bundle - App, Framework or Engine object requesting the download.
  • Returns: A path to the thumbnail on disk.
Clone this wiki locally