def _save_to_disk(self): """ Save the model to disk using QDataStream serialization. This all happens on the C++ side and is very fast. """ filename = self._cache_path # set umask to zero, store old umask old_umask = os.umask(0) try: # try to create the cache folder with as open permissions as # possible cache_dir = os.path.dirname(filename) # make sure the cache directory exists if not os.path.exists(cache_dir): try: os.makedirs(cache_dir, 0777) except OSError, e: # Race conditions are perfectly possible on some network # storage setups so make sure that we ignore any file # already exists errors, as they are not really errors! if e.errno != errno.EEXIST: # re-raise raise # write cache file fh = QtCore.QFile(filename) fh.open(QtCore.QIODevice.WriteOnly) try: out_stream = QtCore.QDataStream(fh) # write a header out_stream.writeInt64(self._FILE_MAGIC_NUMBER) out_stream.writeInt32(self._FILE_VERSION) # todo: if it turns out that there are ongoing issues with # md5 cache collisions, we could write the actual query # parameters to the header of the cache file here and compare # that against the desired query info just to be confident we # are getting a correct cache... # tell which serialization dialect to use out_stream.setVersion(QtCore.QDataStream.Qt_4_0) root = self.invisibleRootItem() self.__save_to_disk_r(out_stream, root, 0) finally: fh.close() # set mask back to previous value os.umask(old_umask) # and ensure the cache file has got open permissions os.chmod(filename, 0666)
def create_ticket(self): """ Creates a new Ticket entity in Shotgun from the contents of the dialog. """ # Create the new Ticket entity, pulling the project from the current # context, and the title, ticket body, and cc list from the UI. result = self._app.shotgun.create( "Ticket", dict( project=self._app.context.project, title=self.ui.ticket_title.text(), description=self.ui.ticket_body.toPlainText(), addressings_cc=self._cc_widget.get_value(), )) # If we have a screenshot that was recorded, we write that to disk as a # png file and then upload it to Shotgun, associating it with the Ticket # entity we just created. if self._screenshot: path = tempfile.mkstemp(suffix=".png")[1] file_obj = QtCore.QFile(path) file_obj.open(QtCore.QIODevice.WriteOnly) self._screenshot.save(file_obj, "PNG") self._app.shotgun.upload( "Ticket", result["id"], path, "attachments", ) QtGui.QMessageBox.information( self, "Ticket successfully created!", "Ticket #%s successfully submitted!" % result["id"], ) self.close()
def __load_from_disk(self): """ Load a serialized model from disk./ :returns: Number of items loaded """ num_items_loaded = 0 # open the data cache for reading fh = QtCore.QFile(self._cache_path) fh.open(QtCore.QIODevice.ReadOnly) try: in_stream = QtCore.QDataStream(fh) magic = in_stream.readInt64() if magic != self._FILE_MAGIC_NUMBER: raise Exception("Invalid file magic number!") version = in_stream.readInt32() if version != self._FILE_VERSION: raise CacheReadVersionMismatch( "Cache file version %s, expected version %s" % (version, self._FILE_VERSION) ) # tell which deserialization dialect to use in_stream.setVersion(QtCore.QDataStream.Qt_4_0) curr_parent = self.invisibleRootItem() prev_node = None curr_depth = 0 while not in_stream.atEnd(): # this is the item where the deserialized data will live item = self._SG_QUERY_MODEL_ITEM_CLASS() num_items_loaded += 1 # keep a reference to this object to make GC happy (pyside may # crash otherwise) self.__all_tree_items.append(item) item.read(in_stream) node_depth = in_stream.readInt32() # all nodes have a unique identifier stored in their metadata # the role data accessible via item.data() contains the # identifier for this item. sg_data = get_sg_data(item) if sg_data: # add the model item to our tree data dict keyed by the # unique identifier uid = sg_data.get(self._SG_DATA_UNIQUE_ID_FIELD) if uid: self.__tree_data[uid] = item # serialized items contain some sort of strange low-rez thumb # data which we cannot use. Make sure that is all cleared. item.setIcon(QtGui.QIcon()) # allow item customization prior to adding to model self._item_created(item) # serialized items do not contain a full high rez thumb, so # re-create that. First, set the default thumbnail self._populate_default_thumbnail(item) # run the finalize method so that subclasses can do any setup # they need self._finalize_item(item) if node_depth == curr_depth + 1: # this new node is a child of the previous node curr_parent = prev_node if prev_node is None: raise Exception("File integrity issues!") curr_depth = node_depth elif node_depth > curr_depth + 1: # something's wrong! raise Exception("File integrity issues!") elif node_depth < curr_depth: # we are going back up to parent level while curr_depth > node_depth: curr_depth -= 1 curr_parent = curr_parent.parent() if curr_parent is None: # we reached the root. special case curr_parent = self.invisibleRootItem() # get complete row containing all columns for the current item row = self._get_columns(item, bool(sg_data)) # and attach the node curr_parent.appendRow(row) prev_node = item finally: fh.close() return num_items_loaded
def create_ticket(self): """ Creates a new Ticket entity in Shotgun from the contents of the dialog. """ # Create the new Ticket entity, pulling the project from the current # context, and the title, ticket body, and cc list from the UI. description = self.ui.ticket_body.toPlainText() ticket_title = self.ui.ticket_title.text() if not description or not ticket_title: QtGui.QMessageBox.critical( self, 'Missing Description Ticket Tile', 'Please make sure you have included the description and the ' 'subject!', QtGui.QMessageBox.StandardButton.Abort) return ticket_body = description ticket_body += "\n\n__Engine Name__: {}\n__Engine Version__: " \ "{}\n__Context__: {}".format(self._app.engine.name, self._app.engine.version, self._app.context) error_log = self.ui.error_log.toPlainText() if error_log: ticket_body += '\n```\n{}\n```'.format(error_log) if self._app.get_setting("include_env", ""): prone_envs = self._app.get_setting("prone_envs", "") if prone_envs: prone_envs = re.split(r"[,\s]+", prone_envs) envs = {} for env in prone_envs: envs[env] = os.environ.get(env) else: envs = os.environ env_info = "\n".join([ "**{}** = {}".format(env, value) for env, value in envs.items() ]) ticket_body += "\n### Environment Variable\n{}".format(env_info) try: project_id = self._app.get_setting("project_id", "") project = {'type': 'Project', 'id': project_id} if not project_id: project = self._app.context.project result = self._app.shotgun.create( "Ticket", dict( project=project, title=ticket_title, description=ticket_body, addressings_cc=self._cc_widget.get_value(), sg_priority=str(self._ticket_priority_widget.get_value()), sg_ticket_type=str(self._ticket_type_widget.get_value()), )) except Exception as e: logger.error(e) # If we have a screenshot that was recorded, we write that to disk as a # png file and then upload it to Shotgun, associating it with the Ticket # entity we just created. if self._screenshot: path = tempfile.mkstemp(suffix=".png")[1] file_obj = QtCore.QFile(path) file_obj.open(QtCore.QIODevice.WriteOnly) self._screenshot.save(file_obj, "PNG") self._app.shotgun.upload( "Ticket", result["id"], path, "attachments", ) QtGui.QMessageBox.information( self, "Ticket successfully created!", "Ticket #%s successfully submitted!" % result["id"], ) self.close()