示例#1
0
    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)
示例#2
0
    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()
示例#3
0
    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
示例#4
0
    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()