def ensure_data_is_loaded(self, index=None): """ Recursively processes the model and ensures that all data has been loaded into the model. Beginning with v5, the Shotgun model defer loads its data into the model for optimal performance. Normally, this is not an issue - the data is typically requested prior to a user expanding a tree node in a view. In some cases, however, it is necessary to pre-fetch parts of the tree. One example of this is if you want to perform filtering via a :class:`~PySide.QtGui.QSortFilterProxyModel`. Please note that for large data sets, this operation may be slow. .. versionadded:: 5.0.0 :param index: Model index for which to recursively load data. If set to None, the entire tree will be loaded. :type index: :class:`~PySide.QtCore.QModelIndex` """ if index is None: # load everything index = self.invisibleRootItem().index() if self.canFetchMore(index): self.fetchMore(index) for child_index in range(self.rowCount(index)): child_model_index = self.index(child_index, 0, parent=index) self.ensure_data_is_loaded(child_model_index)
def compare_shotgun_data(a, b): """ Compares two shotgun data structures. Both inputs are assumed to contain utf-8 encoded data. :returns: True if a is same as b, false otherwise """ if isinstance(a, dict): # input is a dictionary if isinstance(a, dict) and isinstance(b, dict) and len(a) == len(b): # dicts are symmetrical. Compare items recursively. for a_key in a.keys(): if not compare_shotgun_data(a.get(a_key), b.get(a_key)): return False else: # dicts are misaligned return False elif isinstance(a, list): # input is a list if isinstance(a, list) and isinstance(b, list) and len(a) == len(b): # lists are symmetrical. Compare items recursively. for idx in range(len(a)): if not compare_shotgun_data(a[idx], b[idx]): return False else: # list items are misaligned return False # handle thumbnail fields as a special case # thumbnail urls are (typically, there seem to be several standards!) # on the form: # https://sg-media-usor-01.s3.amazonaws.com/xxx/yyy/ # filename.ext?lots_of_authentication_headers # # the query string changes all the times, so when we check if an item # is out of date, omit it. elif ( isinstance(a, str) and isinstance(b, str) and a.startswith("http") and b.startswith("http") and ("amazonaws" in a or "AccessKeyId" in a) ): # attempt to parse values are urls and eliminate the querystring # compare hostname + path only url_obj_a = six.moves.urllib.parse.urlparse(a) url_obj_b = six.moves.urllib.parse.urlparse(b) compare_str_a = "%s/%s" % (url_obj_a.netloc, url_obj_a.path) compare_str_b = "%s/%s" % (url_obj_b.netloc, url_obj_b.path) if compare_str_a != compare_str_b: # url has changed return False elif a != b: # compare all other values using simple equality return False return True
def __do_depth_first_tree_deletion(self, node): """ Depth first iteration and deletion of all child nodes :param node: :class:`~PySide.QtGui.QStandardItem` tree node """ # depth first traversal for index in range(node.rowCount()): child_node = node.child(index) self.__do_depth_first_tree_deletion(child_node) # delete the child leaves for index in range(node.rowCount(), 0, -1): # notes about range syntax: # index will count from rowCount down to 1 # to get zero based indices, subtract 1 node.removeRow(index - 1)
def __remove_unique_id_r(self, item): """ Removes the unique id (if one exists) from the self.__items_by_uid dictionary for this item and all its children :param :class:`~PySide.QtGui.QStandardItem` item: Model item to process """ # process children for row_index in range(item.rowCount()): child_item = item.child(row_index) self.__remove_unique_id_r(child_item) # now process self unique_id = item.data(self._SG_ITEM_UNIQUE_ID) if unique_id and unique_id in self.__items_by_uid: del self.__items_by_uid[unique_id]
def __chunks(sg_batch_data, chunk_size): for i in range(0, len(sg_batch_data), chunk_size): yield sg_batch_data[i:i + chunk_size]