def loadFromFile(self, file_path: str) -> None:
        mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)

        item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
        if not os.path.isfile(file_path):
            Logger.log("e", "[%s] is not a file", file_path)
            return None

        parser = ConfigParser(interpolation = None, allow_no_value = True)  # Accept options without any value,

        parser.read([file_path])
        if not parser.has_option("general", "name") or not parser.has_option("general", "weight"):
            return None

        settings = []  # type: List[str]
        for section in parser.sections():
            if section == "general":
                continue

            settings.append(section)
            for option in parser[section].keys():
                settings.append(option)
        self.setSettings(settings)
        self.setId(item_id)
        self.setName(parser["general"]["name"])
        self.setWeight(int(parser["general"]["weight"]))
Esempio n. 2
0
    def loadFromFile(self, file_path: str) -> None:
        mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)

        item_id = urllib.parse.unquote_plus(
            mime_type.stripExtension(os.path.basename(file_path)))
        if not os.path.isfile(file_path):
            Logger.log("e", "[%s] is not a file", file_path)
            return None

        parser = ConfigParser(
            interpolation=None,
            allow_no_value=True)  # Accept options without any value,

        parser.read([file_path])
        if not parser.has_option("general", "name") or not parser.has_option(
                "general", "weight"):
            return None

        settings = []  # type: List[str]
        for section in parser.sections():
            if section == "general":
                continue

            settings.append(section)
            for option in parser[section].keys():
                settings.append(option)
        self.setSettings(settings)
        self.setId(item_id)
        self.setName(parser["general"]["name"])
        self.setWeight(int(parser["general"]["weight"]))
Esempio n. 3
0
    def read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]:
        """Read mesh data from file and returns a node that contains the data 
        Note that in some cases you can get an entire scene of nodes in this way (eg; 3MF)

        :return: node :type{SceneNode} or :type{list(SceneNode)} The SceneNode or SceneNodes read from file.
        """

        file_name = resolveAnySymlink(file_name)
        result = self._read(file_name)
        UM.Application.Application.getInstance().getController().getScene(
        ).addWatchedFile(file_name)

        # The mesh reader may set a MIME type itself if it knows a more specific MIME type than just going by extension.
        # If not, automatically generate one from our MIME type database, going by the file extension.
        if not isinstance(result, list):
            meshes = [result]
        else:
            meshes = result
        for mesh in meshes:
            if mesh.source_mime_type is None:
                try:
                    mesh.source_mime_type = MimeTypeDatabase.getMimeTypeForFile(
                        file_name)
                except MimeTypeNotFoundError:
                    Logger.warning(
                        f"Loaded file {file_name} has no associated MIME type."
                    )
                    # Leave MIME type at None then.

        return result
    def load(self):
        files = []
        for resource_type in self._resource_types:
            resources = Resources.getAllResourcesOfType(resource_type)

            try:
                resource_storage_path = Resources.getStoragePathForType(resource_type)
            except UnsupportedStorageTypeError:
                resource_storage_path = ""

            # Pre-process the list of files to insert relevant data
            # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack
            for path in resources:
                mime = MimeTypeDatabase.getMimeTypeForFile(path)
                container_type = self.__mime_type_map.get(mime.name)
                if not container_type:
                    Logger.log("w", "Could not determine container type for file %s, ignoring", path)
                    continue

                type_priority = 2

                if issubclass(container_type, DefinitionContainer.DefinitionContainer):
                    type_priority = 0

                if issubclass(container_type, InstanceContainer.InstanceContainer):
                    type_priority = 1

                # Since we have the mime type and resource type here, process these two properties so we do not
                # need to look up mime types etc. again.
                container_id = urllib.parse.unquote_plus(mime.stripExtension(os.path.basename(path)))
                read_only = os.path.dirname(path) != resource_storage_path

                files.append((type_priority, container_id, path, read_only, container_type))

        # Sort the list of files by type_priority so we can ensure correct loading order.
        files = sorted(files, key = lambda i: i[0])

        for _, container_id, file_path, read_only, container_type in files:
            if container_id in self._id_container_cache:
                continue

            try:
                if issubclass(container_type, DefinitionContainer.DefinitionContainer):
                    definition = self._loadCachedDefinition(container_id, file_path)
                    if definition:
                        self.addContainer(definition)
                        continue

                new_container = container_type(container_id)
                with open(file_path, encoding = "utf-8") as f:
                    new_container.deserialize(f.read())
                new_container.setReadOnly(read_only)

                if issubclass(container_type, DefinitionContainer.DefinitionContainer):
                    self._saveCachedDefinition(new_container)

                self.addContainer(new_container)
            except Exception as e:
                Logger.logException("e", "Could not deserialize container %s", container_id)
Esempio n. 5
0
    def importMaterialContainer(
            self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
        if not file_url_or_string:
            return {"status": "error", "message": "Invalid path"}

        if isinstance(file_url_or_string, QUrl):
            file_url = file_url_or_string.toLocalFile()
        else:
            file_url = file_url_or_string

        if not file_url or not os.path.exists(file_url):
            return {"status": "error", "message": "Invalid path"}

        try:
            mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url)
        except MimeTypeNotFoundError:
            return {
                "status": "error",
                "message": "Could not determine mime type of file"
            }

        container_type = self._container_registry.getContainerForMimeType(
            mime_type)
        if not container_type:
            return {
                "status":
                "error",
                "message":
                "Could not find a container to handle the specified file."
            }

        container_id = urllib.parse.unquote_plus(
            mime_type.stripExtension(os.path.basename(file_url)))
        container_id = self._container_registry.uniqueName(container_id)

        container = container_type(container_id)

        try:
            with open(file_url, "rt", encoding="utf-8") as f:
                container.deserialize(f.read())
        except PermissionError:
            return {
                "status": "error",
                "message": "Permission denied when trying to read the file"
            }
        except Exception as ex:
            return {"status": "error", "message": str(ex)}

        container.setDirty(True)

        self._container_registry.addContainer(container)

        return {
            "status":
            "success",
            "message":
            "Successfully imported container {0}".format(container.getName())
        }
 def _pathToMime(self, path: str) -> Optional[MimeType]:
     try:
         mime = MimeTypeDatabase.getMimeTypeForFile(path)
     except MimeTypeDatabase.MimeTypeNotFoundError:
         Logger.log("w", "MIME type could not be found for file: {path}, ignoring it.".format(path = path))
         return None
     if mime.name not in ContainerRegistry.mime_type_map:  # The MIME type is known, but it's not a container.
         return None
     return mime
 def _pathToMime(self, path) -> Optional[MimeType]:
     try:
         mime = MimeTypeDatabase.getMimeTypeForFile(path)
     except MimeTypeDatabase.MimeTypeNotFoundError:
         Logger.log("w", "MIME type could not be found for file: {path}, ignoring it.".format(path = path))
         return None
     if mime.name not in ContainerRegistry.mime_type_map:  # The MIME type is known, but it's not a container.
         return None
     return mime
Esempio n. 8
0
    def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
        if not container_id or not file_type or not file_url_or_string:
            return {"status": "error", "message": "Invalid arguments"}

        if isinstance(file_url_or_string, QUrl):
            file_url = file_url_or_string.toLocalFile()
        else:
            file_url = file_url_or_string

        if not file_url:
            return {"status": "error", "message": "Invalid path"}

        if file_type not in self._container_name_filters:
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url)
            except MimeTypeNotFoundError:
                return {"status": "error", "message": "Unknown File Type"}
        else:
            mime_type = self._container_name_filters[file_type]["mime"]

        containers = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().findContainers(id = container_id)
        if not containers:
            return {"status": "error", "message": "Container not found"}
        container = containers[0]

        if Platform.isOSX() and "." in file_url:
            file_url = file_url[:file_url.rfind(".")]

        for suffix in mime_type.suffixes:
            if file_url.endswith(suffix):
                break
        else:
            file_url += "." + mime_type.preferredSuffix

        if not Platform.isWindows():
            if os.path.exists(file_url):
                result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"),
                                              catalog.i18nc("@label Don't translate the XML tag <filename>!", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_url))
                if result == QMessageBox.No:
                    return {"status": "cancelled", "message": "User cancelled"}

        try:
            contents = container.serialize()
        except NotImplementedError:
            return {"status": "error", "message": "Unable to serialize container"}

        if contents is None:
            return {"status": "error", "message": "Serialization returned None. Unable to write to file"}

        try:
            with SaveFile(file_url, "w") as f:
                f.write(contents)
        except OSError:
            return {"status": "error", "message": "Unable to write to this location.", "path": file_url}

        return {"status": "success", "message": "Successfully exported container", "path": file_url}
Esempio n. 9
0
 def convertPathToId(path: str) -> str:
     mime = None
     try:
         mime = MimeTypeDatabase.getMimeTypeForFile(path)
     except MimeTypeDatabase.MimeTypeNotFoundError:
         pass
     if mime:
         return urllib.parse.unquote_plus(mime.stripExtension(os.path.basename(path)))
     else:
         return ""
Esempio n. 10
0
 def convertPathToId(path: str) -> str:
     mime = None
     try:
         mime = MimeTypeDatabase.getMimeTypeForFile(path)
     except MimeTypeDatabase.MimeTypeNotFoundError:
         pass
     if mime:
         return urllib.parse.unquote_plus(mime.stripExtension(os.path.basename(path)))
     else:
         return ""
Esempio n. 11
0
    def setBaseName(self,
                    base_name: str,
                    is_project_file: bool = False) -> None:
        self._is_user_specified_job_name = False

        # Ensure that we don't use entire path but only filename
        name = os.path.basename(base_name)

        # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its
        # extension. This cuts the extension off if necessary.
        check_name = os.path.splitext(name)[0]
        filename_parts = os.path.basename(base_name).split(".")

        # If it's a gcode, also always update the job name
        is_gcode = False
        if len(filename_parts) > 1:
            # Only check the extension(s)
            is_gcode = "gcode" in filename_parts[1:]

        # if this is a profile file, always update the job name
        # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again
        is_empty = check_name == ""
        if is_gcode or is_project_file or (
                is_empty or
            (self._base_name == "" and self._base_name != check_name)):
            # Only take the file name part, Note : file name might have 'dot' in name as well

            data = ""
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(name)
                data = mime_type.stripExtension(name)
            except MimeTypeNotFoundError:
                Logger.log("w",
                           "Unsupported Mime Type Database file extension %s",
                           name)

            if data is not None and check_name is not None:
                self._base_name = data
            else:
                self._base_name = ""

            # Strip the old "curaproject" extension from the name
            OLD_CURA_PROJECT_EXT = ".curaproject"
            if self._base_name.lower().endswith(OLD_CURA_PROJECT_EXT):
                self._base_name = self._base_name[:len(self._base_name) -
                                                  len(OLD_CURA_PROJECT_EXT)]

            # CURA-5896 Try to strip extra extensions with an infinite amount of ".curaproject.3mf".
            OLD_CURA_PROJECT_3MF_EXT = ".curaproject.3mf"
            while self._base_name.lower().endswith(OLD_CURA_PROJECT_3MF_EXT):
                self._base_name = self._base_name[:len(self._base_name) -
                                                  len(OLD_CURA_PROJECT_3MF_EXT
                                                      )]

            self._updateJobName()
Esempio n. 12
0
    def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
        if not container_id or not file_type or not file_url_or_string:
            return { "status": "error", "message": "Invalid arguments"}

        if isinstance(file_url_or_string, QUrl):
            file_url = file_url_or_string.toLocalFile()
        else:
            file_url = file_url_or_string

        if not file_url:
            return { "status": "error", "message": "Invalid path"}

        mime_type = None
        if not file_type in self._container_name_filters:
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url)
            except MimeTypeNotFoundError:
                return { "status": "error", "message": "Unknown File Type" }
        else:
            mime_type = self._container_name_filters[file_type]["mime"]

        containers = self._container_registry.findContainers(None, id = container_id)
        if not containers:
            return { "status": "error", "message": "Container not found"}
        container = containers[0]

        if Platform.isOSX() and "." in file_url:
            file_url = file_url[:file_url.rfind(".")]

        for suffix in mime_type.suffixes:
            if file_url.endswith(suffix):
                break
        else:
            file_url += "." + mime_type.preferredSuffix

        if not Platform.isWindows():
            if os.path.exists(file_url):
                result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"),
                                              catalog.i18nc("@label", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_url))
                if result == QMessageBox.No:
                    return { "status": "cancelled", "message": "User cancelled"}

        try:
            contents = container.serialize()
        except NotImplementedError:
            return { "status": "error", "message": "Unable to serialize container"}

        if contents is None:
            return {"status": "error", "message": "Serialization returned None. Unable to write to file"}

        with SaveFile(file_url, "w") as f:
            f.write(contents)

        return { "status": "success", "message": "Succesfully exported container", "path": file_url}
Esempio n. 13
0
    def importMaterialContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
        """Imports a profile from a file

        :param file_url: A URL that points to the file to import.

        :return: :type{Dict} dict with a 'status' key containing the string 'success' or 'error', and a 'message' key
            containing a message for the user
        """

        if not file_url_or_string:
            return {"status": "error", "message": "Invalid path"}

        if isinstance(file_url_or_string, QUrl):
            file_url = file_url_or_string.toLocalFile()
        else:
            file_url = file_url_or_string

        if not file_url or not os.path.exists(file_url):
            return {"status": "error", "message": "Invalid path"}

        try:
            mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url)
        except MimeTypeNotFoundError:
            return {"status": "error", "message": "Could not determine mime type of file"}

        container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
        container_type = container_registry.getContainerForMimeType(mime_type)
        if not container_type:
            return {"status": "error", "message": "Could not find a container to handle the specified file."}
        if not issubclass(container_type, InstanceContainer):
            return {"status": "error", "message": "This is not a material container, but another type of file."}

        container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url)))
        container_id = container_registry.uniqueName(container_id)

        container = container_type(container_id)

        try:
            with open(file_url, "rt", encoding = "utf-8") as f:
                container.deserialize(f.read(), file_url)
        except PermissionError:
            return {"status": "error", "message": "Permission denied when trying to read the file."}
        except ContainerFormatError:
            return {"status": "error", "Message": "The material file appears to be corrupt."}
        except Exception as ex:
            return {"status": "error", "message": str(ex)}

        container.setDirty(True)

        container_registry.addContainer(container)

        return {"status": "success", "message": "Successfully imported container {0}".format(container.getName())}
Esempio n. 14
0
    def convertPathToId(path: str) -> str:
        """Try to return Id for given path by looking at its existence in the mimetype database"""

        mime = None
        try:
            mime = MimeTypeDatabase.getMimeTypeForFile(path)
        except MimeTypeDatabase.MimeTypeNotFoundError:
            pass
        if mime:
            return urllib.parse.unquote_plus(
                mime.stripExtension(os.path.basename(path)))
        else:
            return ""
    def _pathToMime(path: str) -> Optional[MimeType]:
        """Converts a file path to the MIME type of the container it represents.

        :return: The MIME type or None if it's not a container.
        """

        try:
            mime = MimeTypeDatabase.getMimeTypeForFile(path)
        except MimeTypeDatabase.MimeTypeNotFoundError:
            Logger.log("w", "MIME type could not be found for file: {path}, ignoring it.".format(path = path))
            return None
        if mime.name not in ContainerRegistry.mime_type_map:  # The MIME type is known, but it's not a container.
            return None
        return mime
    def _populate(self):
        from cura.CuraApplication import CuraApplication
        items = []
        for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset):
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
            except MimeTypeNotFoundError:
                Logger.log("e", "Could not determine mime type of file %s", file_path)
                continue

            item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
            if not os.path.isfile(file_path):
                Logger.log("e", "[%s] is not a file", file_path)
                continue

            parser = ConfigParser(allow_no_value = True)  # accept options without any value,
            try:
                parser.read([file_path])
                if not parser.has_option("general", "name") or not parser.has_option("general", "weight"):
                    continue

                settings = []
                for section in parser.sections():
                    if section == 'general':
                        continue

                    settings.append(section)
                    for option in parser[section].keys():
                        settings.append(option)

                items.append({
                    "id": item_id,
                    "name": catalog.i18nc("@action:inmenu", parser["general"]["name"]),
                    "weight": parser["general"]["weight"],
                    "settings": settings,
                })

            except Exception:
                Logger.logException("e", "Failed to load setting preset %s", file_path)

        items.sort(key = lambda k: (int(k["weight"]), k["id"]))
        # Put "custom" at the top
        items.insert(0, {"id": "custom",
                         "name": "Custom selection",
                         "weight": -100,
                         "settings": []})

        self.setItems(items)
Esempio n. 17
0
    def _populate(self) -> None:
        from cura.CuraApplication import CuraApplication
        items = [] # type: List[Dict[str, Union[str, int, List[str]]]]
        for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset):
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
            except MimeTypeNotFoundError:
                Logger.log("e", "Could not determine mime type of file %s", file_path)
                continue

            item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
            if not os.path.isfile(file_path):
                Logger.log("e", "[%s] is not a file", file_path)
                continue

            parser = ConfigParser(allow_no_value = True)  # accept options without any value,
            try:
                parser.read([file_path])
                if not parser.has_option("general", "name") or not parser.has_option("general", "weight"):
                    continue

                settings = []  # type: List[str]
                for section in parser.sections():
                    if section == 'general':
                        continue

                    settings.append(section)
                    for option in parser[section].keys():
                        settings.append(option)

                items.append({
                    "id": item_id,
                    "name": catalog.i18nc("@action:inmenu", parser["general"]["name"]),
                    "weight": parser["general"]["weight"],
                    "settings": settings,
                })

            except Exception:
                Logger.logException("e", "Failed to load setting preset %s", file_path)

        items.sort(key = lambda k: (int(k["weight"]), k["id"]))  # type: ignore
        # Put "custom" at the top
        items.insert(0, {"id": "custom",
                         "name": "Custom selection",
                         "weight": -100,
                         "settings": []})

        self.setItems(items)
Esempio n. 18
0
    def _sendMaterials(self, materials_to_send: Set[str]) -> None:
        file_paths = Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.MaterialInstanceContainer)

        # Find all local material files and send them if needed.
        for file_path in file_paths:
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
            except MimeTypeDatabase.MimeTypeNotFoundError:
                continue

            file_name = os.path.basename(file_path)
            material_id = urllib.parse.unquote_plus(mime_type.stripExtension(file_name))
            if material_id not in materials_to_send:
                # If the material does not have to be sent we skip it.
                continue

            self._sendMaterialFile(file_path, file_name, material_id)
Esempio n. 19
0
    def setBaseName(self, base_name: str, is_project_file: bool = False) -> None:
        self._is_user_specified_job_name = False

        # Ensure that we don't use entire path but only filename
        name = os.path.basename(base_name)

        # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its
        # extension. This cuts the extension off if necessary.
        check_name = os.path.splitext(name)[0]
        filename_parts = os.path.basename(base_name).split(".")

        # If it's a gcode, also always update the job name
        is_gcode = False
        if len(filename_parts) > 1:
            # Only check the extension(s)
            is_gcode = "gcode" in filename_parts[1:]

        # if this is a profile file, always update the job name
        # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again
        is_empty = check_name == ""
        if is_gcode or is_project_file or (is_empty or (self._base_name == "" and self._base_name != check_name)):
            # Only take the file name part, Note : file name might have 'dot' in name as well

            data = ""
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(name)
                data = mime_type.stripExtension(name)
            except MimeTypeNotFoundError:
                Logger.log("w", "Unsupported Mime Type Database file extension %s", name)

            if data is not None and check_name is not None:
                self._base_name = data
            else:
                self._base_name = ""

            # Strip the old "curaproject" extension from the name
            OLD_CURA_PROJECT_EXT = ".curaproject"
            if self._base_name.lower().endswith(OLD_CURA_PROJECT_EXT):
                self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_EXT)]

            # CURA-5896 Try to strip extra extensions with an infinite amount of ".curaproject.3mf".
            OLD_CURA_PROJECT_3MF_EXT = ".curaproject.3mf"
            while self._base_name.lower().endswith(OLD_CURA_PROJECT_3MF_EXT):
                self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_3MF_EXT)]

            self._updateJobName()
Esempio n. 20
0
    def _sendMaterials(self, materials_to_send: Set[str]) -> None:
        file_paths = Resources.getAllResourcesOfType(
            CuraApplication.ResourceTypes.MaterialInstanceContainer)

        # Find all local material files and send them if needed.
        for file_path in file_paths:
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
            except MimeTypeDatabase.MimeTypeNotFoundError:
                continue

            file_name = os.path.basename(file_path)
            material_id = urllib.parse.unquote_plus(
                mime_type.stripExtension(file_name))
            if material_id not in materials_to_send:
                # If the material does not have to be sent we skip it.
                continue

            self._sendMaterialFile(file_path, file_name, material_id)
Esempio n. 21
0
    def importMaterialContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
        if not file_url_or_string:
            return {"status": "error", "message": "Invalid path"}

        if isinstance(file_url_or_string, QUrl):
            file_url = file_url_or_string.toLocalFile()
        else:
            file_url = file_url_or_string

        if not file_url or not os.path.exists(file_url):
            return {"status": "error", "message": "Invalid path"}

        try:
            mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url)
        except MimeTypeNotFoundError:
            return {"status": "error", "message": "Could not determine mime type of file"}

        container_type = self._container_registry.getContainerForMimeType(mime_type)
        if not container_type:
            return {"status": "error", "message": "Could not find a container to handle the specified file."}

        container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url)))
        container_id = self._container_registry.uniqueName(container_id)

        container = container_type(container_id)

        try:
            with open(file_url, "rt", encoding = "utf-8") as f:
                container.deserialize(f.read())
        except PermissionError:
            return {"status": "error", "message": "Permission denied when trying to read the file."}
        except ContainerFormatError:
            return {"status": "error", "Message": "The material file appears to be corrupt."}
        except Exception as ex:
            return {"status": "error", "message": str(ex)}

        container.setDirty(True)

        self._container_registry.addContainer(container)

        return {"status": "success", "message": "Successfully imported container {0}".format(container.getName())}
Esempio n. 22
0
    def setBaseName(self, base_name: str, is_project_file: bool = False):
        self._is_user_specified_job_name = False

        # Ensure that we don't use entire path but only filename
        name = os.path.basename(base_name)

        # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its
        # extension. This cuts the extension off if necessary.
        check_name = os.path.splitext(name)[0]
        filename_parts = os.path.basename(base_name).split(".")

        # If it's a gcode, also always update the job name
        is_gcode = False
        if len(filename_parts) > 1:
            # Only check the extension(s)
            is_gcode = "gcode" in filename_parts[1:]

        # if this is a profile file, always update the job name
        # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again
        is_empty = check_name == ""
        if is_gcode or is_project_file or (
                is_empty or
            (self._base_name == "" and self._base_name != check_name)):
            # Only take the file name part, Note : file name might have 'dot' in name as well

            data = ''
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(name)
                data = mime_type.stripExtension(name)
            except:
                Logger.log("w",
                           "Unsupported Mime Type Database file extension")

            if data is not None and check_name is not None:
                self._base_name = data
            else:
                self._base_name = ''

            self._updateJobName()
Esempio n. 23
0
    def _pathToIdAndMime(
            path: str) -> Tuple[Optional[str], Optional[MimeType]]:
        """ Faster combination of _pathToMime and _pathToID

            When we want to know the mime and the ID, it's better to use this function, as this prevents an extra
            mime detection from having to be made.
        """
        try:
            mime = MimeTypeDatabase.getMimeTypeForFile(path)
        except MimeTypeDatabase.MimeTypeNotFoundError:
            Logger.log(
                "w",
                "MIME type could not be found for file: {path}, ignoring it.".
                format(path=path))
            return None, None
        if mime.name not in ContainerRegistry.mime_type_map:  # The MIME type is known, but it's not a container.
            return None, None
        recovered_id = None
        if mime:
            recovered_id = urllib.parse.unquote_plus(
                mime.stripExtension(os.path.basename(path)))
        return recovered_id, mime
Esempio n. 24
0
    def load(self):
        files = []
        files_resource_type = []
        for resource_type in self._resource_types:
            resources = Resources.getAllResourcesOfType(resource_type)
            files.extend(resources)
            files_resource_type.extend([resource_type] * len(resources))

        for file_path, resource_type in zip(files, files_resource_type):
            try:
                mime = MimeTypeDatabase.getMimeTypeForFile(file_path)
                container_type = self.__mime_type_map.get(mime.name)
                container_id = mime.stripExtension(os.path.basename(file_path))

                ## Ensure that all special characters are encoded back.
                container_id = urllib.parse.unquote_plus(container_id)

                read_only = True
                try:
                    read_only = os.path.dirname(file_path) != (
                        Resources.getStoragePathForType(resource_type))
                except UnsupportedStorageTypeError:
                    pass

                if container_type is None:
                    Logger.log("w", "Unable to detect container type for %s",
                               mime.name)
                    continue

                new_container = container_type(container_id)
                with open(file_path, encoding="utf-8") as f:
                    new_container.deserialize(f.read())
                new_container.setReadOnly(read_only)
                self._containers.append(new_container)
            except Exception as e:
                Logger.logException("e", "Could not deserialize container %s",
                                    container_id)
Esempio n. 25
0
    def load(self) -> None:
        files = []
        for resource_type in self._resource_types:
            resources = Resources.getAllResourcesOfType(resource_type)

            try:
                resource_storage_path = Resources.getStoragePathForType(
                    resource_type)
            except UnsupportedStorageTypeError:
                resource_storage_path = ""

            # Pre-process the list of files to insert relevant data
            # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack
            for path in resources:
                try:
                    mime = MimeTypeDatabase.getMimeTypeForFile(path)
                except MimeTypeDatabase.MimeTypeNotFoundError:
                    # No valid mime type found for file, ignore it.
                    continue

                container_type = self.__mime_type_map.get(mime.name)
                if not container_type:
                    Logger.log(
                        "w",
                        "Could not determine container type for file %s, ignoring",
                        path)
                    continue

                type_priority = container_type.getLoadingPriority()

                # Since we have the mime type and resource type here, process these two properties so we do not
                # need to look up mime types etc. again.
                container_id = urllib.parse.unquote_plus(
                    mime.stripExtension(os.path.basename(path)))
                read_only = os.path.realpath(os.path.dirname(
                    path)) != os.path.realpath(resource_storage_path)

                files.append((type_priority, container_id, path, read_only,
                              container_type))

        # Sort the list of files by type_priority so we can ensure correct loading order.
        files = sorted(files, key=lambda i: i[0])
        resource_start_time = time.time()
        for _, container_id, file_path, read_only, container_type in files:
            if container_id in self._id_container_cache:
                Logger.log("c", "Found a container with a duplicate ID: %s",
                           container_id)
                Logger.log(
                    "c", "Existing container is %s, trying to load %s from %s",
                    self._id_container_cache[container_id], container_type,
                    file_path)
                continue

            try:
                if issubclass(container_type, DefinitionContainer):
                    definition = self._loadCachedDefinition(
                        container_id, file_path)
                    if definition:
                        self.addContainer(definition)
                        continue

                new_container = container_type(container_id)
                with open(file_path, encoding="utf-8") as f:
                    new_container.deserialize(f.read())
                new_container.setReadOnly(read_only)
                new_container.setPath(file_path)

                if issubclass(container_type, DefinitionContainer):
                    self._saveCachedDefinition(new_container)

                self.addContainer(new_container)
            except Exception as e:
                Logger.logException("e", "Could not deserialize container %s",
                                    container_id)
        Logger.log("d", "Loading data into container registry took %s seconds",
                   time.time() - resource_start_time)
Esempio n. 26
0
 def getMimeType(self) -> str:
     """Get the mime type of the selected export file type."""
     return MimeTypeDatabase.getMimeTypeForFile(self.getFileName()).name
Esempio n. 27
0
 def _stripFileToId(self, file):
     mime_type = MimeTypeDatabase.getMimeTypeForFile(file)
     file = mime_type.stripExtension(file)
     return file.replace("Cura/", "")
Esempio n. 28
0
 def _stripFileToId(self, file):
     mime_type = MimeTypeDatabase.getMimeTypeForFile(file)
     file = mime_type.stripExtension(file)
     return file.replace("Cura/", "")
Esempio n. 29
0
    def load(self) -> None:
        files = []
        old_file_expression = re.compile(r"\{sep}old\{sep}\d+\{sep}".format(sep = os.sep))

        for resource_type in self._resource_types:
            resources = Resources.getAllResourcesOfType(resource_type)

            try:
                resource_storage_path = Resources.getStoragePathForType(resource_type)
            except UnsupportedStorageTypeError:
                resource_storage_path = ""

            # Pre-process the list of files to insert relevant data
            # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack
            for path in resources:
                if old_file_expression.search(path):
                    # This is a backup file, ignore it.
                    continue

                try:
                    mime = MimeTypeDatabase.getMimeTypeForFile(path)
                except MimeTypeDatabase.MimeTypeNotFoundError:
                    # No valid mime type found for file, ignore it.
                    continue

                container_type = self.__mime_type_map.get(mime.name)
                if not container_type:
                    Logger.log("w", "Could not determine container type for file %s, ignoring", path)
                    continue

                type_priority = container_type.getLoadingPriority()

                # Since we have the mime type and resource type here, process these two properties so we do not
                # need to look up mime types etc. again.
                container_id = urllib.parse.unquote_plus(mime.stripExtension(os.path.basename(path)))
                read_only = os.path.realpath(os.path.dirname(path)) != os.path.realpath(resource_storage_path)

                files.append((type_priority, container_id, path, read_only, container_type))

        # Sort the list of files by type_priority so we can ensure correct loading order.
        files = sorted(files, key = lambda i: i[0])
        resource_start_time = time.time()
        for _, container_id, file_path, read_only, container_type in files:
            if container_id in self._id_container_cache:
                Logger.log("c", "Found a container with a duplicate ID: %s", container_id)
                Logger.log("c", "Existing container is %s, trying to load %s from %s", self._id_container_cache[container_id], container_type, file_path)
                continue

            try:
                if issubclass(container_type, DefinitionContainer):
                    definition = self._loadCachedDefinition(container_id, file_path)
                    if definition:
                        self.addContainer(definition)
                        continue

                new_container = container_type(container_id)
                with open(file_path, encoding = "utf-8") as f:
                    new_container.deserialize(f.read())
                new_container.setReadOnly(read_only)
                new_container.setPath(file_path)

                if issubclass(container_type, DefinitionContainer):
                    self._saveCachedDefinition(new_container)

                self.addContainer(new_container)
            except Exception as e:
                Logger.logException("e", "Could not deserialize container %s", container_id)
        Logger.log("d", "Loading data into container registry took %s seconds", time.time() - resource_start_time)
Esempio n. 30
0
    def load(self) -> None:
        # We disable the garbage collection while loading, as this speeds up the loading.
        # Since there is so much going on (lots of objects being created), it's better to have it wait a bit until
        # the dust settles down.
        gc.disable()
        files = []
        old_file_expression = re.compile(
            r"\{sep}old\{sep}\d+\{sep}".format(sep=os.sep))

        for resource_type in self._resource_types:
            resources = Resources.getAllResourcesOfType(resource_type)

            try:
                resource_storage_path = Resources.getStoragePathForType(
                    resource_type)
            except UnsupportedStorageTypeError:
                resource_storage_path = ""

            # Pre-process the list of files to insert relevant data
            # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack
            for path in resources:
                if old_file_expression.search(path):
                    # This is a backup file, ignore it.
                    continue

                try:
                    mime = MimeTypeDatabase.getMimeTypeForFile(path)
                except MimeTypeDatabase.MimeTypeNotFoundError:
                    # No valid mime type found for file, ignore it.
                    continue

                container_type = self.__mime_type_map.get(mime.name)
                if not container_type:
                    Logger.log(
                        "w",
                        "Could not determine container type for file %s, ignoring",
                        path)
                    continue

                type_priority = container_type.getLoadingPriority()

                # Since we have the mime type and resource type here, process these two properties so we do not
                # need to look up mime types etc. again.
                container_id = urllib.parse.unquote_plus(
                    mime.stripExtension(os.path.basename(path)))
                read_only = os.path.realpath(os.path.dirname(
                    path)) != os.path.realpath(resource_storage_path)

                files.append((type_priority, container_id, path, read_only,
                              container_type))

        # Sort the list of files by type_priority so we can ensure correct loading order.
        files = sorted(files, key=lambda i: i[0])
        resource_start_time = time.time()
        with self.lockCache():  #Because we might be writing cache files.
            for _, container_id, file_path, read_only, container_type in files:
                # Enable the rest of the application to get UI updates.
                UM.Qt.QtApplication.QtApplication.processEvents()

                if container_id in self._id_container_cache:
                    Logger.log("c",
                               "Found a container with a duplicate ID: %s",
                               container_id)
                    Logger.log(
                        "c",
                        "Existing container is %s, trying to load %s from %s",
                        self._id_container_cache[container_id], container_type,
                        file_path)
                    continue

                try:
                    if issubclass(container_type, DefinitionContainer):
                        definition = self._loadCachedDefinition(
                            container_id, file_path)
                        if definition:
                            self.addContainer(definition)
                            continue

                    new_container = container_type(container_id)
                    with open(file_path, encoding="utf-8") as f:
                        new_container.deserialize(f.read())
                    new_container.setReadOnly(read_only)
                    new_container.setPath(file_path)

                    if issubclass(container_type, DefinitionContainer):
                        self._saveCachedDefinition(new_container)

                    self.addContainer(new_container)
                except Exception as e:
                    Logger.logException("e",
                                        "Could not deserialize container %s",
                                        container_id)
            Logger.log("d",
                       "Loading data into container registry took %s seconds",
                       time.time() - resource_start_time)
            gc.enable()
Esempio n. 31
0
    def sendMissingMaterials(self, reply: QNetworkReply) -> None:
        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute
                           ) != 200:  #Got an error from the HTTP request.
            Logger.log(
                "e",
                "Couldn't request current material storage on printer. Not syncing materials."
            )
            return

        remote_materials_list = reply.readAll().data().decode("utf-8")
        try:
            remote_materials_list = json.loads(remote_materials_list)
        except json.JSONDecodeError:
            Logger.log(
                "e",
                "Current material storage on printer was a corrupted reply.")
            return
        try:
            remote_materials_by_guid = {
                material["guid"]: material
                for material in remote_materials_list
            }  #Index by GUID.
        except KeyError:
            Logger.log(
                "e",
                "Current material storage on printer was an invalid reply (missing GUIDs)."
            )
            return

        container_registry = ContainerRegistry.getInstance()
        local_materials_list = filter(
            lambda material: ("GUID" in material and "version" in material and
                              "id" in material),
            container_registry.findContainersMetadata(type="material"))
        local_materials_by_guid = {
            material["GUID"]: material
            for material in local_materials_list
            if material["id"] == material["base_file"]
        }
        for material in local_materials_list:  #For each GUID get the material with the highest version number.
            try:
                if int(material["version"]) > local_materials_by_guid[
                        material["GUID"]]["version"]:
                    local_materials_by_guid[material["GUID"]] = material
            except ValueError:
                Logger.log(
                    "e",
                    "Material {material_id} has invalid version number {number}."
                    .format(material_id=material["id"],
                            number=material["version"]))
                continue

        materials_to_send = set()  #type: Set[Dict[str, Any]]
        for guid, material in local_materials_by_guid.items():
            if guid not in remote_materials_by_guid:
                materials_to_send.add(material["id"])
                continue
            try:
                if int(material["version"]
                       ) > remote_materials_by_guid[guid]["version"]:
                    materials_to_send.add(material["id"])
                    continue
            except KeyError:
                Logger.log(
                    "e",
                    "Current material storage on printer was an invalid reply (missing version)."
                )
                return

        for file_path in Resources.getAllResourcesOfType(
                CuraApplication.ResourceTypes.MaterialInstanceContainer):
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
            except MimeTypeDatabase.MimeTypeNotFoundError:
                continue  #Not the sort of file we'd like to send then.
            _, file_name = os.path.split(file_path)
            material_id = urllib.parse.unquote_plus(
                mime_type.stripExtension(file_name))
            if material_id not in materials_to_send:
                continue

            parts = []
            with open(file_path, "rb") as f:
                parts.append(
                    self.device._createFormPart(
                        "name=\"file\"; filename=\"{file_name}\"".format(
                            file_name=file_name), f.read()))
            signature_file_path = file_path + ".sig"
            if os.path.exists(signature_file_path):
                _, signature_file_name = os.path.split(signature_file_path)
                with open(signature_file_path, "rb") as f:
                    parts.append(
                        self.device._createFormPart(
                            "name=\"signature_file\"; filename=\"{file_name}\""
                            .format(file_name=signature_file_name), f.read()))

            Logger.log(
                "d", "Syncing material {material_id} with cluster.".format(
                    material_id=material_id))
            self.device.postFormWithParts(target="materials/",
                                          parts=parts,
                                          on_finished=self.sendingFinished)