def container_registry(application):
    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-definitioncontainer",
            comment = "Uranium Definition Container",
            suffixes = ["def.json"]
        )
    )

    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-instancecontainer",
            comment = "Uranium Instance Container",
            suffixes = [ "inst.cfg" ]
        )
    )

    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-containerstack",
            comment = "Uranium Container Stack",
            suffixes = [ "stack.cfg" ]
        )
    )

    Resources.addSearchPath(os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..", "Settings")))
    ContainerRegistry._ContainerRegistry__instance = None # Reset the private instance variable every time
    PluginRegistry.getInstance().removeType("settings_container")

    ContainerRegistry.getInstance().load()

    return ContainerRegistry.getInstance()
Example #2
0
    def __init__(self, width, height):
        super().__init__("selection", width, height, -999)

        self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "selection.shader"))
        self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader"))
        self._gl = OpenGL.getInstance().getBindingsObject()
        self._scene = Application.getInstance().getController().getScene()

        self._renderer = Application.getInstance().getRenderer()

        self._selection_map = {}
        self._toolhandle_selection_map = {
            self._dropAlpha(ToolHandle.DisabledSelectionColor): ToolHandle.NoAxis,
            self._dropAlpha(ToolHandle.XAxisSelectionColor): ToolHandle.XAxis,
            self._dropAlpha(ToolHandle.YAxisSelectionColor): ToolHandle.YAxis,
            self._dropAlpha(ToolHandle.ZAxisSelectionColor): ToolHandle.ZAxis,
            self._dropAlpha(ToolHandle.AllAxisSelectionColor): ToolHandle.AllAxis,
            ToolHandle.DisabledSelectionColor: ToolHandle.NoAxis,
            ToolHandle.XAxisSelectionColor: ToolHandle.XAxis,
            ToolHandle.YAxisSelectionColor: ToolHandle.YAxis,
            ToolHandle.ZAxisSelectionColor: ToolHandle.ZAxis,
            ToolHandle.AllAxisSelectionColor: ToolHandle.AllAxis
        }

        self._output = None
Example #3
0
    def __init__(self):
        Resources.addResourcePath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura"))
        if not hasattr(sys, "frozen"):
            Resources.addResourcePath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))

        super().__init__(name = "cura", version = "master")

        self.setRequiredPlugins([
            "CuraEngineBackend",
            "MeshView",
            "LayerView",
            "STLReader",
            "SelectionTool",
            "CameraTool",
            "GCodeWriter",
            "LocalFileStorage"
        ])
        self._physics = None
        self._volume = None
        self._platform = None
        self._output_devices = {}
        self._print_information = None
        self._i18n_catalog = None

        self.activeMachineChanged.connect(self._onActiveMachineChanged)

        Preferences.getInstance().addPreference("cura/active_machine", "")
        Preferences.getInstance().addPreference("cura/active_mode", "simple")
Example #4
0
    def registerObjects(self, engine):
        engine.rootContext().setContextProperty("Printer", self)
        engine.rootContext().setContextProperty("CuraApplication", self)
        self._print_information = PrintInformation.PrintInformation()
        engine.rootContext().setContextProperty("PrintInformation", self._print_information)
        self._cura_actions = CuraActions.CuraActions(self)
        engine.rootContext().setContextProperty("CuraActions", self._cura_actions)

        qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")

        qmlRegisterType(cura.Settings.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")

        qmlRegisterType(cura.Settings.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
        qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler")

        qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager)

        qmlRegisterSingletonType(QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions")

        engine.rootContext().setContextProperty("ExtruderManager", cura.Settings.ExtruderManager.getInstance())

        for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles):
            type_name = os.path.splitext(os.path.basename(path))[0]
            if type_name in ("Cura", "Actions"):
                continue

            qmlRegisterType(QUrl.fromLocalFile(path), "Cura", 1, 0, type_name)
Example #5
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._enabled_shader:
            self._enabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader"))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue("u_diffuseColor1", [0.48, 0.48, 0.48, 1.0])
            self._disabled_shader.setUniformValue("u_diffuseColor2", [0.68, 0.68, 0.68, 1.0])
            self._disabled_shader.setUniformValue("u_width", 50.0)

        if Application.getInstance().getGlobalContainerStack():
            if Preferences.getInstance().getValue("view/show_overhang"):
                angle = Application.getInstance().getGlobalContainerStack().getProperty("support_angle", "value")
                if angle is not None:
                    self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle)))
                else:
                    self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang.
            else:
                self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0)))

        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    # TODO: Find a better way to handle this
                    #if node.getBoundingBoxMesh():
                    #    renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines)

                    uniforms = {}
                    if self._extruders_model.rowCount() > 0:
                        # Get color to render this mesh in from ExtrudersModel
                        extruder_index = 0
                        extruder_id = node.callDecoration("getActiveExtruder")
                        if extruder_id:
                            extruder_index = max(0, self._extruders_model.find("id", extruder_id))

                        extruder_color = self._extruders_model.getItem(extruder_index)["colour"]
                        try:
                            # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
                            # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
                            uniforms["diffuse_color"] = [
                                int(extruder_color[1:3], 16) / 255,
                                int(extruder_color[3:5], 16) / 255,
                                int(extruder_color[5:7], 16) / 255,
                                1.0
                            ]
                        except ValueError:
                            pass

                    if hasattr(node, "_outside_buildarea"):
                        if node._outside_buildarea:
                            renderer.queueNode(node, shader = self._disabled_shader)
                        else:
                            renderer.queueNode(node, shader = self._enabled_shader, uniforms = uniforms)
                    else:
                        renderer.queueNode(node, material = self._enabled_shader, uniforms = uniforms)
                if node.callDecoration("isGroup"):
                    renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = Renderer.RenderLines)
Example #6
0
    def _onInstanceNameChanged(self, instance, old_name):
        file_name = urllib.parse.quote_plus(old_name)
        try:
            path = Resources.getStoragePath(Resources.MachineInstances, file_name + ".cfg")
            os.remove(path)
            path = Resources.getStoragePath(Resources.MachineInstanceProfiles, file_name + ".curaprofile")
            os.remove(path)
        except FileNotFoundError:
            pass

        #Update machine instance name for all profiles attached to this machine instance
        for profile in self._profiles:
            if profile.isReadOnly() or profile.getMachineInstanceName() != old_name:
                continue

            file_name = urllib.parse.quote_plus(profile.getName()) + ".cfg"
            try:
                path = Resources.getStoragePath(Resources.Profiles, file_name)
                os.remove(path)
            except FileNotFoundError:
                pass

            profile.setMachineInstanceName(instance.getName())

        self.machineInstanceNameChanged.emit(instance)
Example #7
0
    def restore(self) -> bool:
        if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None):
            # We can restore without the minimum required information.
            Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.")
            self._showMessage(
                self.catalog.i18nc("@info:backup_failed",
                                   "Tried to restore a Cura backup without having proper data or meta data."))
            return False

        current_version = self._application.getVersion()
        version_to_restore = self.meta_data.get("cura_release", "master")

        if current_version < version_to_restore:
            # Cannot restore version newer than current because settings might have changed.
            Logger.log("d", "Tried to restore a Cura backup of version {version_to_restore} with cura version {current_version}".format(version_to_restore = version_to_restore, current_version = current_version))
            self._showMessage(
                self.catalog.i18nc("@info:backup_failed",
                                   "Tried to restore a Cura backup that is higher than the current version."))
            return False

        version_data_dir = Resources.getDataStoragePath()
        archive = ZipFile(io.BytesIO(self.zip_file), "r")
        extracted = self._extractArchive(archive, version_data_dir)

        # Under Linux, preferences are stored elsewhere, so we copy the file to there.
        if Platform.isLinux():
            preferences_file_name = self._application.getApplicationName()
            preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name))
            backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name))
            Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file)
            shutil.move(backup_preferences_file, preferences_file)

        return extracted
    def _getUpgradeTasks(self) -> Iterator[UpgradeTask]:
        storage_path_prefixes = set()
        storage_path_prefixes.add(Resources.getConfigStoragePath())
        storage_path_prefixes.add(Resources.getDataStoragePath())

        # Make sure the types and paths are ordered so we always get the same results.
        self._storage_paths = collections.OrderedDict(sorted(self._storage_paths.items()))
        for key in self._storage_paths:
            self._storage_paths[key] = collections.OrderedDict(sorted(self._storage_paths[key].items()))

        # Use pattern: /^(pattern_a|pattern_b|pattern_c|...)$/
        combined_regex_ignored_files = "^(" + "|".join(self._ignored_files) + ")"
        for old_configuration_type, version_storage_paths_dict in self._storage_paths.items():
            for src_version, storage_paths in version_storage_paths_dict.items():
                for prefix in storage_path_prefixes:
                    for storage_path in storage_paths:
                        path = os.path.join(prefix, storage_path)
                        for configuration_file in self._getFilesInDirectory(path):
                            # Get file version. Only add this upgrade task if the current file version matches with
                            # the defined version that scans through this folder.
                            if re.match(combined_regex_ignored_files, configuration_file):
                                continue
                            try:
                                with open(os.path.join(path, configuration_file), "r", encoding = "utf-8") as f:
                                    file_version = self._get_version_functions[old_configuration_type](f.read())
                                    if file_version != src_version:
                                        continue
                            except:
                                Logger.log("w", "Failed to get file version: %s, skip it", configuration_file)
                                continue

                            Logger.log("i", "Create upgrade task for configuration file [%s] with type [%s] and source version [%s]",
                                       configuration_file, old_configuration_type, file_version)
                            yield UpgradeTask(storage_path = path, file_name = configuration_file,
                                              configuration_type = old_configuration_type)
Example #9
0
    def _updateTimeQualitySettings(self):
        if not self._current_settings or not self._enabled:
            return

        if not self._low_quality_settings:
            self._low_quality_settings = MachineSettings()
            self._low_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + ".json"))
            self._low_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, "profiles", "low_quality.conf"))

        if not self._high_quality_settings:
            self._high_quality_settings = MachineSettings()
            self._high_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + ".json"))
            self._high_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, "profiles", "high_quality.conf"))

        for key, options in self._interpolation_settings.items():
            minimum_value = None
            if options["minimum"] == "low":
                minimum_value = self._low_quality_settings.getSettingValueByKey(key)
            elif options["minimum"] == "high":
                minimum_value = self._high_quality_settings.getSettingValueByKey(key)
            else:
                continue

            maximum_value = None
            if options["maximum"] == "low":
                maximum_value = self._low_quality_settings.getSettingValueByKey(key)
            elif options["maximum"] == "high":
                maximum_value = self._high_quality_settings.getSettingValueByKey(key)
            else:
                continue

            setting_value = round(minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100), options["precision"])
            self._current_settings.setSettingValueByKey(key, setting_value)
Example #10
0
    def loadProfiles(self):
        storage_path = Resources.getStoragePathForType(Resources.Profiles)

        dirs = Resources.getAllPathsForType(Resources.Profiles)
        for dir in dirs:
            if not os.path.isdir(dir):
                continue

            read_only = dir != storage_path

            for file_name in os.listdir(dir):
                path = os.path.join(dir, file_name)

                if os.path.isdir(path):
                    continue

                profile = Profile(self, read_only)
                try:
                    profile.loadFromFile(path)
                except Exception as e:
                    Logger.log("e", "An exception occurred loading Profile %s: %s", path, str(e))
                    continue

                if not self.findProfile(profile.getName()):
                    self._profiles.append(profile)
                    profile.nameChanged.connect(self._onProfileNameChanged)

        profile = self.findProfile(Preferences.getInstance().getValue("machines/active_profile"))
        if profile:
            self.setActiveProfile(profile)

        self.profilesChanged.emit()
Example #11
0
    def registerObjects(self, engine):
        engine.rootContext().setContextProperty("Printer", self)
        engine.rootContext().setContextProperty("CuraApplication", self)
        self._print_information = PrintInformation.PrintInformation()
        engine.rootContext().setContextProperty("PrintInformation", self._print_information)
        self._cura_actions = CuraActions.CuraActions(self)
        engine.rootContext().setContextProperty("CuraActions", self._cura_actions)

        qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")

        qmlRegisterType(cura.Settings.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")

        qmlRegisterType(cura.Settings.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
        qmlRegisterSingletonType(cura.Settings.ProfilesModel, "Cura", 1, 0, "ProfilesModel", cura.Settings.ProfilesModel.createProfilesModel)
        qmlRegisterType(cura.Settings.QualityAndUserProfilesModel, "Cura", 1, 0, "QualityAndUserProfilesModel")
        qmlRegisterType(cura.Settings.UserProfilesModel, "Cura", 1, 0, "UserProfilesModel")
        qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler")
        qmlRegisterType(cura.Settings.QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel")
        qmlRegisterType(cura.Settings.MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")

        qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager)

        # As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work.
        actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")))
        qmlRegisterSingletonType(actions_url, "Cura", 1, 0, "Actions")

        engine.rootContext().setContextProperty("ExtruderManager", cura.Settings.ExtruderManager.getInstance())

        for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles):
            type_name = os.path.splitext(os.path.basename(path))[0]
            if type_name in ("Cura", "Actions"):
                continue

            qmlRegisterType(QUrl.fromLocalFile(path), "Cura", 1, 0, type_name)
Example #12
0
def container_registry(application):
    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-definitioncontainer",
            comment = "Uranium Definition Container",
            suffixes = ["def.json"]
        )
    )

    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-instancecontainer",
            comment = "Uranium Instance Container",
            suffixes = [ "inst.cfg" ]
        )
    )

    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-containerstack",
            comment = "Uranium Container Stack",
            suffixes = [ "stack.cfg" ]
        )
    )

    Resources.addSearchPath(os.path.dirname(os.path.abspath(__file__)))
    ContainerRegistry._ContainerRegistry__instance = None # Reset the private instance variable every time

    ContainerRegistry.setApplication(application)

    UM.Settings.ContainerStack.setContainerRegistry(ContainerRegistry.getInstance())
    UM.Settings.InstanceContainer.setContainerRegistry(ContainerRegistry.getInstance())
    return ContainerRegistry.getInstance()
Example #13
0
    def loadQtTranslation(self, file, language = "default"):
        #TODO Add support for specifying a language from preferences
        path = None
        if language == "default":
            # If we have a language set in the environment, try and use that.
            lang = os.getenv("LANGUAGE")
            if lang:
                try:
                    path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm")
                except FileNotFoundError:
                    path = None

            # If looking up the language from the enviroment fails, try and use Qt's system locale instead.
            if not path:
                locale = QLocale.system()

                # First, try and find a directory for any of the provided languages
                for lang in locale.uiLanguages():
                    try:
                        path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm")
                        language = lang
                    except FileNotFoundError:
                        pass
                    else:
                        break

                # If that fails, see if we can extract a language "class" from the
                # preferred language. This will turn "en-GB" into "en" for example.
                if not path:
                    lang = locale.uiLanguages()[0]
                    lang = lang[0:lang.find("-")]
                    try:
                        path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm")
                        language = lang
                    except FileNotFoundError:
                        pass
        else:
            path = Resources.getPath(Resources.i18nLocation, language, "LC_MESSAGES", file + ".qm")

        # If all else fails, fall back to english.
        if not path:
            Logger.log("w", "Could not find any translations matching {0} for file {1}, falling back to english".format(language, file))
            try:
                path = Resources.getPath(Resources.i18nLocation, "en", "LC_MESSAGES", file + ".qm")
            except FileNotFoundError:
                Logger.log("w", "Could not find English translations for file {0}. Switching to developer english.".format(file))
                return

        translator = QTranslator()
        if not translator.load(path):
            Logger.log("e", "Unable to load translations %s", file)
            return

        # Store a reference to the translator.
        # This prevents the translator from being destroyed before Qt has a chance to use it.
        self._translators[file] = translator

        # Finally, install the translator so Qt can use it.
        self.installTranslator(translator)
Example #14
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()
        renderer.setRenderSelection(False)

        if not self._material:
            self._material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag"))
            self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0])

            self._selection_material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag"))
            self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128))

        for node in DepthFirstIterator(scene.getRoot()):
            # We do not want to render ConvexHullNode as it conflicts with the bottom layers.
            # However, it is somewhat relevant when the node is selected, so do render it then.
            if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()):
                continue

            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    if Selection.isSelected(node):
                        renderer.queueNode(node, material = self._selection_material, transparent = True)
                    layer_data = node.callDecoration("getLayerData")
                    if not layer_data:
                        continue

                    # Render all layers below a certain number as line mesh instead of vertices.
                    if self._current_layer_num - self._solid_layers > -1:
                        start = 0
                        end = 0
                        element_counts = layer_data.getElementCounts()
                        for layer, counts in element_counts.items():
                            if layer + self._solid_layers > self._current_layer_num:
                                break
                            end += counts

                        # This uses glDrawRangeElements internally to only draw a certain range of lines.
                        renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end)

                    # We currently recreate the current "solid" layers every time a
                    if not self._current_layer_mesh:
                        self._current_layer_mesh = MeshData()
                        for i in range(self._solid_layers):
                            layer = self._current_layer_num - i
                            if layer < 0:
                                continue

                            layer_mesh = layer_data.getLayer(layer).createMesh()
                            if not layer_mesh or layer_mesh.getVertices() is None:
                                continue

                            self._current_layer_mesh.addVertices(layer_mesh.getVertices())

                            # Scale layer color by a brightness factor based on the current layer number
                            # This will result in a range of 0.5 - 1.0 to multiply colors by.
                            brightness = (2.0 - (i / self._solid_layers)) / 2.0
                            self._current_layer_mesh.addColors(layer_mesh.getColors() * brightness)

                    renderer.queueNode(node, mesh = self._current_layer_mesh, material = self._material)
    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)
 def _actionTriggered(self, _, action_id):
     if action_id == "reset":
         result = QMessageBox.question(None, i18n_catalog.i18nc("@title:window", "Reset to factory"),
                                       i18n_catalog.i18nc("@label",
                                                     "Reset will remove all your current printers and profiles! Are you sure you want to reset?"))
         if result == QMessageBox.Yes:
             Resources.factoryReset()
             sys.exit(1)
Example #17
0
    def run(self):
        self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene..."))

        controller = self.getController()

        controller.setActiveView("SolidView")
        controller.setCameraTool("CameraTool")
        controller.setSelectionTool("SelectionTool")

        t = controller.getTool("TranslateTool")
        if t:
            t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.YAxis,ToolHandle.ZAxis])

        Selection.selectionChanged.connect(self.onSelectionChanged)

        root = controller.getScene().getRoot()
        self._platform = Scene_Platform(root)

        self._volume = BuildVolume.BuildVolume(root)

        self.getRenderer().setBackgroundColor(QColor(245, 245, 245))

        self._physics = PlatformPhysics.PlatformPhysics(controller, self._volume)

        camera = Camera("3d", root)
        camera.setPosition(Vector(-80, 250, 700))
        camera.setPerspective(True)
        camera.lookAt(Vector(0, 0, 0))
        controller.getScene().setActiveCamera("3d")

        self.getController().getTool("CameraTool").setOrigin(Vector(0, 100, 0))

        self._camera_animation = CameraAnimation.CameraAnimation()
        self._camera_animation.setCameraTool(self.getController().getTool("CameraTool"))

        self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading interface..."))

        # Initialise extruder so as to listen to global container stack changes before the first global container stack is set.
        cura.Settings.ExtruderManager.getInstance()
        qmlRegisterSingletonType(cura.Settings.MachineManager, "Cura", 1, 0, "MachineManager",
                                 cura.Settings.MachineManager.createMachineManager)

        qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
        self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
        self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles))
        self.initializeEngine()

        if self._engine.rootObjects:
            self.closeSplash()

            for file in self.getCommandLineOption("file", []):
                self._openFile(file)
            for file_name in self._open_file_queue: #Open all the files that were queued up while plug-ins were loading.
                self._openFile(file_name)

            self._started = True

            self.exec_()
Example #18
0
    def saveAll(self) -> None:
        for instance in self.findInstanceContainers():
            if not instance.isDirty():
                continue

            try:
                data = instance.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException("e", "An exception occurred trying to serialize container %s", instance.getId())
                continue

            mime_type = self.getMimeTypeForContainer(type(instance))
            if mime_type is not None:
                file_name = urllib.parse.quote_plus(instance.getId()) + "." + mime_type.preferredSuffix
                path = Resources.getStoragePath(Resources.InstanceContainers, file_name)
                with SaveFile(path, "wt") as f:
                    f.write(data)

        for stack in self.findContainerStacks():
            if not stack.isDirty():
                continue

            try:
                data = stack.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException("e", "An exception occurred trying to serialize container %s", stack.getId())
                continue

            mime_type = self.getMimeTypeForContainer(type(stack))
            if mime_type is not None:
                file_name = urllib.parse.quote_plus(stack.getId()) + "." + mime_type.preferredSuffix
                path = Resources.getStoragePath(Resources.ContainerStacks, file_name)
                with SaveFile(path, "wt") as f:
                    f.write(data)

        for definition in self.findDefinitionContainers():
            try:
                data = definition.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException("e", "An exception occurred trying to serialize container %s", definition.getId())
                continue

            mime_type = self.getMimeTypeForContainer(type(definition))
            if mime_type is not None:
                file_name = urllib.parse.quote_plus(definition.getId()) + "." + mime_type.preferredSuffix
                path = Resources.getStoragePath(Resources.DefinitionContainers, file_name)
                with SaveFile(path, "wt") as f:
                    f.write(data)
Example #19
0
    def saveMachineInstances(self):
        if self._active_machine:
            Preferences.getInstance().setValue("machines/active_instance", self._active_machine.getName())

        for instance in self._machine_instances:
            file_name = urllib.parse.quote_plus(instance.getName()) + ".cfg"
            instance.saveToFile(Resources.getStoragePath(Resources.MachineInstances, file_name))
            file_name = urllib.parse.quote_plus(instance.getName()) + ".curaprofile"
            instance.getWorkingProfile().saveToFile(Resources.getStoragePath(Resources.MachineInstanceProfiles, file_name))
Example #20
0
    def _createCustomFdmPrinterExtruderStack(self, machine_id: str, position: int, quality_id: str, material_id: str):
        stack_id = "custom_extruder_%s" % (position + 1)
        if self._current_fdm_printer_count > 1:
            stack_id += " #%s" % self._current_fdm_printer_count

        definition_id = "custom_extruder_%s" % (position + 1)

        # create a definition changes container for this stack
        definition_changes_parser = self._getCustomFdmPrinterDefinitionChanges(stack_id)
        definition_changes_id = definition_changes_parser["general"]["name"]
        # create a user settings container
        user_settings_parser = self._getCustomFdmPrinterUserSettings(stack_id)
        user_settings_id = user_settings_parser["general"]["name"]

        parser = configparser.ConfigParser()
        parser.add_section("general")
        parser["general"]["version"] = str(2)
        parser["general"]["name"] = "Extruder %s" % (position + 1)
        parser["general"]["id"] = stack_id

        parser.add_section("metadata")
        parser["metadata"]["type"] = "extruder_train"
        parser["metadata"]["machine"] = machine_id
        parser["metadata"]["position"] = str(position)

        parser.add_section("containers")
        parser["containers"]["0"] = user_settings_id
        parser["containers"]["1"] = "empty_quality_changes"
        parser["containers"]["2"] = quality_id
        parser["containers"]["3"] = material_id
        parser["containers"]["4"] = "empty_variant"
        parser["containers"]["5"] = definition_changes_id
        parser["containers"]["6"] = definition_id

        definition_changes_output = io.StringIO()
        definition_changes_parser.write(definition_changes_output)
        definition_changes_filename = quote_plus(definition_changes_id) + ".inst.cfg"

        user_settings_output = io.StringIO()
        user_settings_parser.write(user_settings_output)
        user_settings_filename = quote_plus(user_settings_id) + ".inst.cfg"

        extruder_output = io.StringIO()
        parser.write(extruder_output)
        extruder_filename = quote_plus(stack_id) + ".extruder.cfg"

        extruder_stack_dir = Resources.getPath(CuraApplication.ResourceTypes.ExtruderStack)
        definition_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.DefinitionChangesContainer)
        user_settings_dir = Resources.getPath(CuraApplication.ResourceTypes.UserInstanceContainer)

        with open(os.path.join(definition_changes_dir, definition_changes_filename), "w", encoding = "utf-8") as f:
            f.write(definition_changes_output.getvalue())
        with open(os.path.join(user_settings_dir, user_settings_filename), "w", encoding = "utf-8") as f:
            f.write(user_settings_output.getvalue())
        with open(os.path.join(extruder_stack_dir, extruder_filename), "w", encoding = "utf-8") as f:
            f.write(extruder_output.getvalue())
Example #21
0
    def __init__(self, **kwargs):
        plugin_path = ""
        if sys.platform == "win32":
            plugin_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "PyQt5", "plugins")
            Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path))
            QCoreApplication.addLibraryPath(plugin_path)    
        elif sys.platform == "darwin":
            plugin_path = os.path.join(Application.getInstallPrefix(), "Resources", "plugins")

        if plugin_path:
            Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path))
            QCoreApplication.addLibraryPath(plugin_path)

        os.environ["QSG_RENDER_LOOP"] = "basic"
        super().__init__(sys.argv, **kwargs)

        self._main_qml = "main.qml"
        self._engine = None
        self._renderer = None

        self.setAttribute(Qt.AA_UseDesktopOpenGL)

        try:
            self._splash = QSplashScreen(QPixmap(Resources.getPath(Resources.ImagesLocation, self.getApplicationName() + ".png")))
        except FileNotFoundError:
            self._splash = None
        else:
            self._splash.show()
            self.processEvents()

        signal.signal(signal.SIGINT, signal.SIG_DFL)
        # This is done here as a lot of plugins require a correct gl context. If you want to change the framework,
        # these checks need to be done in your <framework>Application.py class __init__().

        i18n_catalog = i18nCatalog("uranium")

        self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading plugins..."))
        self._loadPlugins()
        self._plugin_registry.checkRequiredPlugins(self.getRequiredPlugins())

        self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading machines..."))
        self.loadMachines()

        self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading preferences..."))
        try:
            file = Resources.getPath(Resources.PreferencesLocation, self.getApplicationName() + ".cfg")
            Preferences.getInstance().readFromFile(file)
        except FileNotFoundError:
            pass

        self._translators = {}

        self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading translations..."))

        self.loadQtTranslation("uranium_qt")
        self.loadQtTranslation(self.getApplicationName() + "_qt")
Example #22
0
 def _extractArchive(archive: "ZipFile", target_path: str) -> bool:
     Logger.log("d", "Removing current data in location: %s", target_path)
     Resources.factoryReset()
     Logger.log("d", "Extracting backup to location: %s", target_path)
     try:
         archive.extractall(target_path)
     except PermissionError:
         Logger.logException("e", "Unable to extract the backup due to permission errors")
         return False
     return True
Example #23
0
 def _getUpgradeTasks(self):
     storage_path_prefixes = set()
     storage_path_prefixes.add(Resources.getConfigStoragePath())
     storage_path_prefixes.add(Resources.getDataStoragePath())
     for old_configuration_type, storage_paths in self._storage_paths.items():
         for prefix in storage_path_prefixes:
             for storage_path in storage_paths:
                 path = os.path.join(prefix, storage_path)
                 for configuration_file in self._getFilesInDirectory(path):
                     yield UpgradeTask(storage_path = path, file_name = configuration_file, configuration_type = old_configuration_type)
Example #24
0
    def __init__(self):
        Resources.addSearchPath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura", "resources"))
        if not hasattr(sys, "frozen"):
            Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources"))

        self._open_file_queue = []  # Files to open when plug-ins are loaded.

        super().__init__(name = "cura", version = CuraVersion)

        self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))

        self.setRequiredPlugins([
            "CuraEngineBackend",
            "MeshView",
            "LayerView",
            "STLReader",
            "SelectionTool",
            "CameraTool",
            "GCodeWriter",
            "LocalFileOutputDevice"
        ])
        self._physics = None
        self._volume = None
        self._platform = None
        self._output_devices = {}
        self._print_information = None
        self._i18n_catalog = None
        self._previous_active_tool = None
        self._platform_activity = False
        self._scene_boundingbox = AxisAlignedBox()
        self._job_name = None
        self._center_after_select = False
        self._camera_animation = None
        self._cura_actions = None

        self.getMachineManager().activeMachineInstanceChanged.connect(self._onActiveMachineChanged)
        self.getMachineManager().addMachineRequested.connect(self._onAddMachineRequested)
        self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
        self.getController().toolOperationStopped.connect(self._onToolOperationStopped)

        Resources.addType(self.ResourceTypes.QmlFiles, "qml")
        Resources.addType(self.ResourceTypes.Firmware, "firmware")

        Preferences.getInstance().addPreference("cura/active_machine", "")
        Preferences.getInstance().addPreference("cura/active_mode", "simple")
        Preferences.getInstance().addPreference("cura/recent_files", "")
        Preferences.getInstance().addPreference("cura/categories_expanded", "")
        Preferences.getInstance().addPreference("view/center_on_select", True)
        Preferences.getInstance().addPreference("mesh/scale_to_fit", True)
        Preferences.getInstance().setDefault("local_file/last_used_type", "text/x-gcode")

        JobQueue.getInstance().jobFinished.connect(self._onJobFinished)

        self._recent_files = []
        files = Preferences.getInstance().getValue("cura/recent_files").split(";")
        for f in files:
            if not os.path.isfile(f):
                continue

            self._recent_files.append(QUrl.fromLocalFile(f))
    def __init__(self, width, height):
        super().__init__("selection", width, height, -999)

        self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "selection.shader"))
        self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader"))
        self._gl = OpenGL.getInstance().getBindingsObject()
        self._scene = Application.getInstance().getController().getScene()

        self._renderer = Application.getInstance().getRenderer()

        self._selection_map = {}
        self._output = None
Example #26
0
    def loadProfiles(self):
        storage_path = Resources.getStoragePathForType(Resources.Profiles)

        dirs = Resources.getAllPathsForType(Resources.Profiles)
        for dir in dirs:
            if not os.path.isdir(dir):
                continue

            read_only = dir != storage_path

            for root, dirs, files in os.walk(dir):
                for file_name in files:
                    path = os.path.join(root, file_name)

                    if os.path.isdir(path):
                        continue

                    profile = Profile(self, read_only)
                    try:
                        profile.loadFromFile(path)
                    except Exception as e:
                        Logger.log("e", "An exception occurred loading Profile %s: %s", path, str(e))
                        continue

                    if not self.findProfile(profile.getName(), variant_name = profile.getMachineVariantName(), material_name = profile.getMaterialName(), instance = self._active_machine):
                        self._profiles.append(profile)
                        profile.nameChanged.connect(self._onProfileNameChanged)

        for instance in self._machine_instances:
            try:
                file_name = urllib.parse.quote_plus(instance.getName()) + ".curaprofile"
                instance.getWorkingProfile().loadFromFile(Resources.getStoragePath(Resources.MachineInstanceProfiles, file_name))
            except Exception as e:
                Logger.log("w", "Could not load working profile: %s: %s", file_name, str(e))
                self._setDefaultVariantMaterialProfile(instance)

        self._protect_working_profile = True

        if self._active_machine:
            profile_name = self._active_machine.getActiveProfileName()
            if profile_name == "":
                profile_name = "Normal Quality"

            profile = self.findProfile(self._active_machine.getActiveProfileName(), instance = self._active_machine)
            if profile:
                self.setActiveProfile(profile)
            else:
                profiles = self.getProfiles(instance = self._active_machine)
                if len(profiles) > 0:
                    self.setActiveProfile(profiles[0])

        self.profilesChanged.emit()
        self._protect_working_profile = False
Example #27
0
    def render(self, renderer):
        if not self._material:
            self._material = renderer.createMaterial(
                Resources.getPath(Resources.ShadersLocation, "basic.vert"),
                Resources.getPath(Resources.ShadersLocation, "color.frag"),
            )

            self._material.setUniformValue("u_color", Color(35, 35, 35, 128))
        if self.getParent():
            renderer.queueNode(self, material=self._material, transparent=True)

        return True
    def saveAll(self):

        for instance in self.findInstanceContainers():
            if not instance.isDirty():
                continue

            try:
                data = instance.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException("e", "An exception occurred trying to serialize container %s", instance.getId())
                continue

            file_name = urllib.parse.quote_plus(instance.getId()) + ".inst.cfg"
            path = Resources.getStoragePath(Resources.InstanceContainers, file_name)
            with SaveFile(path, "wt", -1, "utf-8") as f:
                f.write(data)

        for stack in self.findContainerStacks():
            if not stack.isDirty():
                continue

            try:
                data = stack.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException("e", "An exception occurred trying to serialize container %s", stack.getId())
                continue

            file_name = urllib.parse.quote_plus(stack.getId()) + ".stack.cfg"
            path = Resources.getStoragePath(Resources.ContainerStacks, file_name)
            with SaveFile(path, "wt", -1, "utf-8") as f:
                f.write(data)

        for definition in self.findDefinitionContainers():
            try:
                data = definition.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException("e", "An exception occurred trying to serialize container %s", instance.getId())
                continue

            file_name = urllib.parse.quote_plus(definition.getId()) + ".def.cfg"
            path = Resources.getStoragePath(Resources.DefinitionContainers, file_name)
            with SaveFile(path, "wt", -1, "utf-8") as f:
                f.write(data)
Example #29
0
    def _onActiveMachineChanged(self):
        if self._settings:
            self.setMeshData(None)

        app = Application.getInstance()
        self._settings = app.getActiveMachine()
        if self._settings:
            mesh = self._settings.getPlatformMesh()
            self.setMeshData(app.getMeshFileHandler().read(Resources.getPath(Resources.MeshesLocation, mesh), app.getStorageDevice("LocalFileStorage"), center = False))
            self._texture = self._settings.getPlatformTexture()

            if self._material and self._texture:
                self._material.setUniformTexture("u_texture", Resources.getPath(Resources.ImagesLocation, self._texture))
Example #30
0
    def _upgradeFile(self, storage_path_absolute, configuration_file,
                     old_configuration_type, paths):
        configuration_file_absolute = os.path.join(storage_path_absolute,
                                                   configuration_file)

        #Read the old file.
        try:
            with open(configuration_file_absolute,
                      encoding="utf-8",
                      errors="ignore") as file_handle:
                files_data = [file_handle.read()]
        except IOError:
            Logger.log("w", "Can't open configuration file %s for reading.",
                       configuration_file_absolute)
            return False

        #Get the version number of the old file.
        try:
            old_version = self._get_version_functions[old_configuration_type](
                files_data[0])
        except:  #Version getter gives an exception. Not a valid file. Can't upgrade it then.
            return False
        version = old_version
        configuration_type = old_configuration_type
        filenames_without_extension = [os.path.splitext(configuration_file)[0]]

        #Keep converting the file until it's at one of the current versions.
        while (configuration_type, version) not in self._current_versions:
            if (configuration_type, version) not in paths:
                #No version upgrade plug-in claims to be able to upgrade this file.
                return False
            new_type, new_version, upgrade = paths[(configuration_type,
                                                    version)]
            new_filenames_without_extension = []
            new_files_data = []
            for file_idx, file_data in enumerate(files_data):
                try:
                    this_filenames_without_extension, this_files_data = upgrade(
                        file_data, filenames_without_extension[file_idx])
                except Exception as e:  #Upgrade failed due to a coding error in the plug-in.
                    Logger.logException("w",
                                        "Exception in %s upgrade with %s: %s",
                                        old_configuration_type,
                                        upgrade.__module__, str(e))
                    return False
                if not this_files_data:  #Upgrade failed.
                    return False
                new_filenames_without_extension += this_filenames_without_extension
                new_files_data += this_files_data
            filenames_without_extension = new_filenames_without_extension
            files_data = new_files_data
            version = new_version
            configuration_type = new_type

        #If the version changed, save the new files.
        if version != old_version or configuration_type != old_configuration_type:
            self._storeOldFile(storage_path_absolute, configuration_file,
                               old_version)

            #Finding out where to store these files.
            resource_type, mime_type = self._current_versions[(
                configuration_type, version)]
            storage_path = Resources.getStoragePathForType(resource_type)
            mime_type = UM.MimeTypeDatabase.getMimeType(
                mime_type)  #Get the actual MIME type object, from the name.
            if mime_type.preferredSuffix:
                extension = "." + mime_type.preferredSuffix
            elif mime_type.suffixes:
                extension = "." + mime_type.suffixes[0]
            else:
                extension = ""  #No known suffix. Put no extension behind it.
            new_filenames = [
                filename + extension
                for filename in filenames_without_extension
            ]
            configuration_files_absolute = [
                os.path.join(storage_path, filename)
                for filename in new_filenames
            ]

            for file_idx, configuration_file_absolute in enumerate(
                    configuration_files_absolute):
                try:
                    with open(os.path.join(configuration_file_absolute),
                              "w",
                              encoding="utf-8") as file_handle:
                        file_handle.write(
                            files_data[file_idx])  #Save the new file.
                except IOError:
                    Logger.log("w",
                               "Couldn't write new configuration file to %s.",
                               configuration_file_absolute)
                    return False
            Logger.log("i", "Upgraded %s to version %s.", configuration_file,
                       str(version))
            return True
        return False  #Version didn't change. Was already current.
    def getCacheLockFilename(self) -> str:
        """Get the cache lock filename including full path."""

        return Resources.getStoragePath(
            Resources.Cache, self._application.getApplicationLockFilename())
Example #32
0
    def __init__(self):
        Resources.addSearchPath(
            os.path.join(QtApplication.getInstallPrefix(), "share", "cura",
                         "resources"))
        if not hasattr(sys, "frozen"):
            Resources.addSearchPath(
                os.path.join(os.path.abspath(os.path.dirname(__file__)), "..",
                             "resources"))

        self._open_file_queue = []  # Files to open when plug-ins are loaded.

        super().__init__(name="cura", version=CuraVersion)

        self.setWindowIcon(
            QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))

        self.setRequiredPlugins([
            "CuraEngineBackend", "MeshView", "LayerView", "STLReader",
            "SelectionTool", "CameraTool", "GCodeWriter",
            "LocalFileOutputDevice"
        ])
        self._physics = None
        self._volume = None
        self._platform = None
        self._output_devices = {}
        self._print_information = None
        self._i18n_catalog = None
        self._previous_active_tool = None
        self._platform_activity = False
        self._scene_boundingbox = AxisAlignedBox()
        self._job_name = None
        self._center_after_select = False
        self._camera_animation = None
        self._cura_actions = None

        self.getMachineManager().activeMachineInstanceChanged.connect(
            self._onActiveMachineChanged)
        self.getMachineManager().addMachineRequested.connect(
            self._onAddMachineRequested)
        self.getController().getScene().sceneChanged.connect(
            self.updatePlatformActivity)
        self.getController().toolOperationStopped.connect(
            self._onToolOperationStopped)

        Resources.addType(self.ResourceTypes.QmlFiles, "qml")
        Resources.addType(self.ResourceTypes.Firmware, "firmware")

        Preferences.getInstance().addPreference("cura/active_machine", "")
        Preferences.getInstance().addPreference("cura/active_mode", "simple")
        Preferences.getInstance().addPreference("cura/recent_files", "")
        Preferences.getInstance().addPreference("cura/categories_expanded", "")
        Preferences.getInstance().addPreference("view/center_on_select", True)
        Preferences.getInstance().addPreference("mesh/scale_to_fit", True)
        Preferences.getInstance().setDefault("local_file/last_used_type",
                                             "text/x-gcode")

        JobQueue.getInstance().jobFinished.connect(self._onJobFinished)

        self._recent_files = []
        files = Preferences.getInstance().getValue("cura/recent_files").split(
            ";")
        for f in files:
            if not os.path.isfile(f):
                continue

            self._recent_files.append(QUrl.fromLocalFile(f))
Example #33
0
 def getEngineCommand(self):
     json_path = Resources.getPath(Resources.DefinitionContainers, "fdmprinter.def.json")
     return [Preferences.getInstance().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""]
Example #34
0
    def load(self, path: str, is_first_call: bool = True) -> None:
        if path == self._path:
            return

        theme_full_path = os.path.join(path, "theme.json")
        Logger.log(
            "d", "Loading theme file: {theme_full_path}".format(
                theme_full_path=theme_full_path))
        try:
            with open(theme_full_path, encoding="utf-8") as f:
                data = json.load(f)
        except EnvironmentError as e:
            Logger.error(
                "Unable to load theme file at {theme_full_path}: {err}".format(
                    theme_full_path=theme_full_path, err=e))
            return
        except UnicodeDecodeError:
            Logger.error(
                "Theme file at {theme_full_path} is corrupt (invalid UTF-8 bytes)."
                .format(theme_full_path=theme_full_path))
            return
        except json.JSONDecodeError:
            Logger.error(
                "Theme file at {theme_full_path} is corrupt (invalid JSON syntax)."
                .format(theme_full_path=theme_full_path))
            return

        # Iteratively load inherited themes
        try:
            theme_id = data["metadata"]["inherits"]
            self.load(Resources.getPath(Resources.Themes, theme_id),
                      is_first_call=False)
        except FileNotFoundError:
            Logger.log("e", "Could not find inherited theme %s", theme_id)
        except KeyError:
            pass  # No metadata or no inherits keyword in the theme.json file

        if "colors" in data:
            for name, color in data["colors"].items():
                try:
                    c = QColor(color[0], color[1], color[2], color[3])
                except IndexError:  # Color doesn't have enough components.
                    Logger.log(
                        "w",
                        "Colour {name} doesn't have enough components. Need to have 4, but had {num_components}."
                        .format(name=name, num_components=len(color)))
                    continue  # Skip this one then.
                self._colors[name] = c

        fonts_dir = os.path.join(path, "fonts")
        if os.path.isdir(fonts_dir):
            for root, dirnames, filenames in os.walk(fonts_dir):
                for filename in filenames:
                    if filename.lower().endswith(".ttf"):
                        QFontDatabase.addApplicationFont(
                            os.path.join(root, filename))

        if "fonts" in data:
            system_font_size = QCoreApplication.instance().font().pointSize()
            for name, font in data["fonts"].items():
                q_font = QFont()
                q_font.setFamily(
                    font.get("family",
                             QCoreApplication.instance().font().family()))

                if font.get("bold"):
                    q_font.setBold(font.get("bold", False))
                else:
                    q_font.setWeight(font.get("weight", 50))

                q_font.setLetterSpacing(QFont.AbsoluteSpacing,
                                        font.get("letterSpacing", 0))
                q_font.setItalic(font.get("italic", False))
                q_font.setPointSize(int(
                    font.get("size", 1) * system_font_size))
                q_font.setCapitalization(QFont.AllUppercase if font.get(
                    "capitalize", False) else QFont.MixedCase)

                self._fonts[name] = q_font

        if "sizes" in data:
            for name, size in data["sizes"].items():
                s = QSizeF()
                s.setWidth(round(size[0] * self._em_width))
                s.setHeight(round(size[1] * self._em_height))

                self._sizes[name] = s

        iconsdir = os.path.join(path, "icons")
        if os.path.isdir(iconsdir):
            for icon in os.listdir(iconsdir):
                name = os.path.splitext(icon)[0]
                self._icons[name] = QUrl.fromLocalFile(
                    os.path.join(iconsdir, icon))

        imagesdir = os.path.join(path, "images")
        if os.path.isdir(imagesdir):
            for image in os.listdir(imagesdir):
                name = os.path.splitext(image)[0]
                self._images[name] = QUrl.fromLocalFile(
                    os.path.join(imagesdir, image))

        styles = os.path.join(path, "styles.qml")
        if os.path.isfile(styles):
            c = QQmlComponent(self._engine, styles)
            context = QQmlContext(self._engine, self._engine)
            context.setContextProperty("Theme", self)
            self._styles = c.create(context)

            if c.isError():
                for error in c.errors():
                    Logger.log("e", error.toString())

        Logger.log("d", "Loaded theme %s", path)
        self._path = path

        # only emit the theme loaded signal once after all the themes in the inheritance chain have been loaded
        if is_first_call:
            self.themeLoaded.emit()
Example #35
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:
                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 = 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)
Example #36
0
    def run(self):
        self.showSplashMessage(
            self._i18n_catalog.i18nc("@info:progress", "Setting up scene..."))

        controller = self.getController()

        controller.setActiveView("SolidView")
        controller.setCameraTool("CameraTool")
        controller.setSelectionTool("SelectionTool")

        t = controller.getTool("TranslateTool")
        if t:
            t.setEnabledAxis(
                [ToolHandle.XAxis, ToolHandle.YAxis, ToolHandle.ZAxis])

        Selection.selectionChanged.connect(self.onSelectionChanged)

        root = controller.getScene().getRoot()

        # The platform is a child of BuildVolume
        self._volume = BuildVolume.BuildVolume(root)

        self.getRenderer().setBackgroundColor(QColor(245, 245, 245))

        self._physics = PlatformPhysics.PlatformPhysics(
            controller, self._volume)

        camera = Camera("3d", root)
        camera.setPosition(Vector(-80, 250, 700))
        camera.setPerspective(True)
        camera.lookAt(Vector(0, 0, 0))
        controller.getScene().setActiveCamera("3d")

        self.getController().getTool("CameraTool").setOrigin(Vector(0, 100, 0))

        self._camera_animation = CameraAnimation.CameraAnimation()
        self._camera_animation.setCameraTool(
            self.getController().getTool("CameraTool"))

        self.showSplashMessage(
            self._i18n_catalog.i18nc("@info:progress", "Loading interface..."))

        # Initialise extruder so as to listen to global container stack changes before the first global container stack is set.
        cura.Settings.ExtruderManager.getInstance()
        qmlRegisterSingletonType(cura.Settings.MachineManager, "Cura", 1, 0,
                                 "MachineManager", self.getMachineManager)
        qmlRegisterSingletonType(cura.Settings.SettingInheritanceManager,
                                 "Cura", 1, 0, "SettingInheritanceManager",
                                 self.getSettingInheritanceManager)
        qmlRegisterSingletonType(MachineActionManager.MachineActionManager,
                                 "Cura", 1, 0, "MachineActionManager",
                                 self.getMachineActionManager)
        self.setMainQml(
            Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
        self._qml_import_paths.append(
            Resources.getPath(self.ResourceTypes.QmlFiles))
        self.initializeEngine()

        if self._engine.rootObjects:
            self.closeSplash()

            for file in self.getCommandLineOption("file", []):
                self._openFile(file)
            for file_name in self._open_file_queue:  #Open all the files that were queued up while plug-ins were loading.
                self._openFile(file_name)

            self._started = True

            self.exec_()
Example #37
0
 def getLockFilename(self):
     return Resources.getStoragePath(Resources.Resources,
                                     CONFIG_LOCK_FILENAME)
Example #38
0
    def installPackage(self, filename: str) -> Optional[str]:
        """Schedules the given package file to be installed upon the next start.

        :return: The to-be-installed package_id or None if something went wrong
        """

        has_changes = False
        package_id = ""
        try:
            # Get package information
            package_info = self.getPackageInfo(filename)
            if not package_info:
                return None
            package_id = package_info["package_id"]

            # If the package is being installed but it is in the list on to remove, then it is deleted from that list.
            if package_id in self._to_remove_package_set:
                self._to_remove_package_set.remove(package_id)

            # We do not check if the same package has been installed already here because, for example, in Cura,
            # it may need to install a package with the same package-version but with a higher SDK version. So,
            # the package-version is not the only version that can be in play here.

            # Need to use the lock file to prevent concurrent I/O issues.
            with self._container_registry.lockFile():
                Logger.log(
                    "i",
                    "Package [%s] version [%s] is scheduled to be installed.",
                    package_id, package_info["package_version"])
                # Copy the file to cache dir so we don't need to rely on the original file to be present
                package_cache_dir = os.path.join(
                    os.path.abspath(Resources.getCacheStoragePath()),
                    "cura_packages")
                if not os.path.exists(package_cache_dir):
                    os.makedirs(package_cache_dir, exist_ok=True)

                target_file_path = os.path.join(package_cache_dir,
                                                package_id + ".curapackage")
                shutil.copy2(filename, target_file_path)

                self._to_install_package_dict[package_id] = {
                    "package_info": package_info,
                    "filename": target_file_path
                }
                has_changes = True
        except:
            Logger.logException("c", "Failed to install package file '%s'",
                                filename)
        finally:
            self._saveManagementData()
            if has_changes:
                self.installedPackagesChanged.emit()

                if package_id in self._packages_with_update_available:
                    # After installing the update, the check will return that not other updates are available.
                    # In that case we remove it from the list. This is actually a safe check (could be removed)
                    if not self.checkIfPackageCanUpdate(package_id):
                        # The install ensured that the package no longer has a valid update option.
                        self._packages_with_update_available.remove(package_id)
                        self.packagesWithUpdateChanged.emit()

        if has_changes:
            self.packageInstalled.emit(package_id)
            return package_id
        else:
            return None
Example #39
0
    def __init__(self):
        Resources.addSearchPath(
            os.path.join(QtApplication.getInstallPrefix(), "share", "cura",
                         "resources"))
        if not hasattr(sys, "frozen"):
            Resources.addSearchPath(
                os.path.join(os.path.abspath(os.path.dirname(__file__)), "..",
                             "resources"))

        self._open_file_queue = []  # Files to open when plug-ins are loaded.

        # Need to do this before ContainerRegistry tries to load the machines
        SettingDefinition.addSupportedProperty("settable_per_mesh",
                                               DefinitionPropertyType.Any,
                                               default=True,
                                               read_only=True)
        SettingDefinition.addSupportedProperty("settable_per_extruder",
                                               DefinitionPropertyType.Any,
                                               default=True,
                                               read_only=True)
        # this setting can be changed for each group in one-at-a-time mode
        SettingDefinition.addSupportedProperty("settable_per_meshgroup",
                                               DefinitionPropertyType.Any,
                                               default=True,
                                               read_only=True)
        SettingDefinition.addSupportedProperty("settable_globally",
                                               DefinitionPropertyType.Any,
                                               default=True,
                                               read_only=True)

        # From which stack the setting would inherit if not defined per object (handled in the engine)
        # AND for settings which are not settable_per_mesh:
        # which extruder is the only extruder this setting is obtained from
        SettingDefinition.addSupportedProperty("limit_to_extruder",
                                               DefinitionPropertyType.Function,
                                               default="-1")

        # For settings which are not settable_per_mesh and not settable_per_extruder:
        # A function which determines the glabel/meshgroup value by looking at the values of the setting in all (used) extruders
        SettingDefinition.addSupportedProperty("resolve",
                                               DefinitionPropertyType.Function,
                                               default=None,
                                               depends_on="value")

        SettingDefinition.addSettingType("extruder", None, str, Validator)

        SettingFunction.registerOperator(
            "extruderValues", cura.Settings.ExtruderManager.getExtruderValues)
        SettingFunction.registerOperator(
            "extruderValue", cura.Settings.ExtruderManager.getExtruderValue)
        SettingFunction.registerOperator(
            "resolveOrValue", cura.Settings.ExtruderManager.getResolveOrValue)

        ## Add the 4 types of profiles to storage.
        Resources.addStorageType(self.ResourceTypes.QualityInstanceContainer,
                                 "quality")
        Resources.addStorageType(self.ResourceTypes.VariantInstanceContainer,
                                 "variants")
        Resources.addStorageType(self.ResourceTypes.MaterialInstanceContainer,
                                 "materials")
        Resources.addStorageType(self.ResourceTypes.UserInstanceContainer,
                                 "user")
        Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders")
        Resources.addStorageType(self.ResourceTypes.MachineStack,
                                 "machine_instances")

        ContainerRegistry.getInstance().addResourceType(
            self.ResourceTypes.QualityInstanceContainer)
        ContainerRegistry.getInstance().addResourceType(
            self.ResourceTypes.VariantInstanceContainer)
        ContainerRegistry.getInstance().addResourceType(
            self.ResourceTypes.MaterialInstanceContainer)
        ContainerRegistry.getInstance().addResourceType(
            self.ResourceTypes.UserInstanceContainer)
        ContainerRegistry.getInstance().addResourceType(
            self.ResourceTypes.ExtruderStack)
        ContainerRegistry.getInstance().addResourceType(
            self.ResourceTypes.MachineStack)

        ##  Initialise the version upgrade manager with Cura's storage paths.
        import UM.VersionUpgradeManager  #Needs to be here to prevent circular dependencies.
        UM.VersionUpgradeManager.VersionUpgradeManager.getInstance(
        ).setCurrentVersions({
            ("quality", UM.Settings.InstanceContainer.Version):
            (self.ResourceTypes.QualityInstanceContainer,
             "application/x-uranium-instancecontainer"),
            ("machine_stack", UM.Settings.ContainerStack.Version):
            (self.ResourceTypes.MachineStack,
             "application/x-uranium-containerstack"),
            ("preferences", UM.Preferences.Version):
            (Resources.Preferences, "application/x-uranium-preferences"),
            ("user", UM.Settings.InstanceContainer.Version):
            (self.ResourceTypes.UserInstanceContainer,
             "application/x-uranium-instancecontainer")
        })

        self._machine_action_manager = MachineActionManager.MachineActionManager(
        )
        self._machine_manager = None  # This is initialized on demand.
        self._setting_inheritance_manager = None

        self._additional_components = {
        }  # Components to add to certain areas in the interface

        super().__init__(name="cura",
                         version=CuraVersion,
                         buildtype=CuraBuildType)

        self.setWindowIcon(
            QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))

        self.setRequiredPlugins([
            "CuraEngineBackend", "MeshView", "LayerView", "STLReader",
            "SelectionTool", "CameraTool", "GCodeWriter",
            "LocalFileOutputDevice"
        ])
        self._physics = None
        self._volume = None
        self._output_devices = {}
        self._print_information = None
        self._previous_active_tool = None
        self._platform_activity = False
        self._scene_bounding_box = AxisAlignedBox.Null

        self._job_name = None
        self._center_after_select = False
        self._camera_animation = None
        self._cura_actions = None
        self._started = False

        self._message_box_callback = None
        self._message_box_callback_arguments = []

        self._i18n_catalog = i18nCatalog("cura")

        self.getController().getScene().sceneChanged.connect(
            self.updatePlatformActivity)
        self.getController().toolOperationStopped.connect(
            self._onToolOperationStopped)

        Resources.addType(self.ResourceTypes.QmlFiles, "qml")
        Resources.addType(self.ResourceTypes.Firmware, "firmware")

        self.showSplashMessage(
            self._i18n_catalog.i18nc("@info:progress", "Loading machines..."))

        # Add empty variant, material and quality containers.
        # Since they are empty, they should never be serialized and instead just programmatically created.
        # We need them to simplify the switching between materials.
        empty_container = ContainerRegistry.getInstance(
        ).getEmptyInstanceContainer()
        empty_variant_container = copy.deepcopy(empty_container)
        empty_variant_container._id = "empty_variant"
        empty_variant_container.addMetaDataEntry("type", "variant")
        ContainerRegistry.getInstance().addContainer(empty_variant_container)
        empty_material_container = copy.deepcopy(empty_container)
        empty_material_container._id = "empty_material"
        empty_material_container.addMetaDataEntry("type", "material")
        ContainerRegistry.getInstance().addContainer(empty_material_container)
        empty_quality_container = copy.deepcopy(empty_container)
        empty_quality_container._id = "empty_quality"
        empty_quality_container.setName("Not supported")
        empty_quality_container.addMetaDataEntry("quality_type", "normal")
        empty_quality_container.addMetaDataEntry("type", "quality")
        ContainerRegistry.getInstance().addContainer(empty_quality_container)
        empty_quality_changes_container = copy.deepcopy(empty_container)
        empty_quality_changes_container._id = "empty_quality_changes"
        empty_quality_changes_container.addMetaDataEntry(
            "type", "quality_changes")
        ContainerRegistry.getInstance().addContainer(
            empty_quality_changes_container)

        # Set the filename to create if cura is writing in the config dir.
        self._config_lock_filename = os.path.join(
            Resources.getConfigStoragePath(), CONFIG_LOCK_FILENAME)
        self.waitConfigLockFile()
        ContainerRegistry.getInstance().load()

        Preferences.getInstance().addPreference("cura/active_mode", "simple")
        Preferences.getInstance().addPreference("cura/recent_files", "")
        Preferences.getInstance().addPreference("cura/categories_expanded", "")
        Preferences.getInstance().addPreference("cura/jobname_prefix", True)
        Preferences.getInstance().addPreference("view/center_on_select", True)
        Preferences.getInstance().addPreference("mesh/scale_to_fit", True)
        Preferences.getInstance().addPreference("mesh/scale_tiny_meshes", True)

        for key in [
                "dialog_load_path",  # dialog_save_path is in LocalFileOutputDevicePlugin
                "dialog_profile_path",
                "dialog_material_path"
        ]:

            Preferences.getInstance().addPreference("local_file/%s" % key,
                                                    os.path.expanduser("~/"))

        Preferences.getInstance().setDefault("local_file/last_used_type",
                                             "text/x-gcode")

        Preferences.getInstance().setDefault(
            "general/visible_settings", """
            machine_settings
            resolution
                layer_height
            shell
                wall_thickness
                top_bottom_thickness
            infill
                infill_sparse_density
            material
                material_print_temperature
                material_bed_temperature
                material_diameter
                material_flow
                retraction_enable
            speed
                speed_print
                speed_travel
                acceleration_print
                acceleration_travel
                jerk_print
                jerk_travel
            travel
            cooling
                cool_fan_enabled
            support
                support_enable
                support_extruder_nr
                support_type
                support_interface_density
            platform_adhesion
                adhesion_type
                adhesion_extruder_nr
                brim_width
                raft_airgap
                layer_0_z_overlap
                raft_surface_layers
            dual
                prime_tower_enable
                prime_tower_size
                prime_tower_position_x
                prime_tower_position_y
            meshfix
            blackmagic
                print_sequence
                infill_mesh
            experimental
        """.replace("\n", ";").replace(" ", ""))

        JobQueue.getInstance().jobFinished.connect(self._onJobFinished)

        self.applicationShuttingDown.connect(self.saveSettings)
        self.engineCreatedSignal.connect(self._onEngineCreated)
        self._recent_files = []
        files = Preferences.getInstance().getValue("cura/recent_files").split(
            ";")
        for f in files:
            if not os.path.isfile(f):
                continue

            self._recent_files.append(QUrl.fromLocalFile(f))
Example #40
0
    def __init__(self,
                 application: "QtApplication",
                 parent: Optional[QObject] = None) -> None:
        super().__init__(parent)

        self._application = application
        self._container_registry = self._application.getContainerRegistry()
        self._plugin_registry = self._application.getPluginRegistry()

        # JSON files that keep track of all installed packages.
        self._user_package_management_file_path = None  # type: Optional[str]
        self._bundled_package_management_file_paths = []  # type: List[str]
        for search_path in Resources.getAllPathsForType(
                Resources.BundledPackages):
            if not os.path.isdir(search_path):
                continue

            # Load all JSON files that are located in the bundled_packages directory.
            try:
                for file_name in os.listdir(search_path):
                    if not file_name.endswith(".json"):
                        continue
                    file_path = os.path.join(search_path, file_name)
                    if not os.path.isfile(file_path):
                        continue
                    self._bundled_package_management_file_paths.append(
                        file_path)
                    Logger.log(
                        "i",
                        "Found bundled packages JSON file: {location}".format(
                            location=file_path))
            except EnvironmentError as e:  # Unable to read directory. Could be corrupt disk or insufficient access to list the directory.
                Logger.log(
                    "e",
                    f"Unable to read package directory to search for packages JSON files: {str(e)}"
                )
                pass

        for search_path in (Resources.getDataStoragePath(),
                            Resources.getConfigStoragePath()):
            candidate_user_path = os.path.join(search_path, "packages.json")
            if os.path.exists(candidate_user_path):
                self._user_package_management_file_path = candidate_user_path
        if self._user_package_management_file_path is None:  # Doesn't exist yet.
            self._user_package_management_file_path = os.path.join(
                Resources.getDataStoragePath(), "packages.json")

        self._installation_dirs_dict = {
            "plugins":
            os.path.abspath(Resources.getStoragePath(Resources.Plugins))
        }  # type: Dict[str, str]

        self._bundled_package_dict = {
        }  # type: Dict[str, Dict[str, Any]] # A dict of all bundled packages
        self._installed_package_dict = {
        }  # type: Dict[str, Dict[str, Any]] # A dict of all installed packages
        self._to_remove_package_set = set(
        )  # type: Set[str] # A set of packages that need to be removed at the next start
        self._to_install_package_dict = {
        }  # type: Dict[str, Dict[str, Any]]  # A dict of packages that need to be installed at the next start
        self._dismissed_packages = set(
        )  # type: Set[str] # A set of packages that are dismissed by the user

        # There can be plugins that provide remote packages (and thus, newer / different versions for a package).
        self._available_package_versions = {
        }  # type: Dict[str, Set[UMVersion]]

        self._packages_with_update_available = set()  # type: Set[str]
Example #41
0
    def _checkSetup(self):
        if not self._extruders_model:
            self._extruders_model = Application.getInstance(
            ).getExtrudersModel()

        if not self._theme:
            self._theme = Application.getInstance().getTheme()

        if not self._enabled_shader:
            self._enabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "overhang.shader"))
            self._enabled_shader.setUniformValue(
                "u_overhangColor",
                Color(*self._theme.getColor("model_overhang").getRgb()))
            self._enabled_shader.setUniformValue("u_renderError", 0.0)

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor1",
                Color(*self._theme.getColor("model_unslicable").getRgb()))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor2",
                Color(*self._theme.getColor("model_unslicable_alt").getRgb()))
            self._disabled_shader.setUniformValue("u_width", 50.0)

        if not self._non_printing_shader:
            self._non_printing_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders,
                                  "transparent_object.shader"))
            self._non_printing_shader.setUniformValue(
                "u_diffuseColor",
                Color(*self._theme.getColor("model_non_printing").getRgb()))
            self._non_printing_shader.setUniformValue("u_opacity", 0.6)

        if not self._support_mesh_shader:
            self._support_mesh_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._support_mesh_shader.setUniformValue("u_vertical_stripes",
                                                      True)
            self._support_mesh_shader.setUniformValue("u_width", 5.0)

        if not Application.getInstance().getPreferences().getValue(
                self._show_xray_warning_preference):
            self._xray_shader = None
            self._xray_composite_shader = None
            if self._composite_pass and 'xray' in self._composite_pass.getLayerBindings(
            ):
                self._composite_pass.setLayerBindings(self._old_layer_bindings)
                self._composite_pass.setCompositeShader(
                    self._old_composite_shader)
                self._old_layer_bindings = None
                self._old_composite_shader = None
                self._enabled_shader.setUniformValue(
                    "u_renderError", 0.0)  # We don't want any error markers!.
                self._xray_warning_message.hide()
        else:
            if not self._xray_shader:
                self._xray_shader = OpenGL.getInstance().createShaderProgram(
                    Resources.getPath(Resources.Shaders, "xray.shader"))

            if not self._xray_composite_shader:
                self._xray_composite_shader = OpenGL.getInstance(
                ).createShaderProgram(
                    Resources.getPath(Resources.Shaders,
                                      "xray_composite.shader"))
                theme = Application.getInstance().getTheme()
                self._xray_composite_shader.setUniformValue(
                    "u_background_color",
                    Color(*theme.getColor("viewport_background").getRgb()))
                self._xray_composite_shader.setUniformValue(
                    "u_outline_color",
                    Color(*theme.getColor("model_selection_outline").getRgb()))
                self._xray_composite_shader.setUniformValue(
                    "u_flat_error_color_mix",
                    0.)  # Don't show flat error color in solid-view.

            renderer = self.getRenderer()
            if not self._composite_pass or not 'xray' in self._composite_pass.getLayerBindings(
            ):
                # Currently the RenderPass constructor requires a size > 0
                # This should be fixed in RenderPass's constructor.
                self._xray_pass = XRayPass.XRayPass(1, 1)
                self._enabled_shader.setUniformValue(
                    "u_renderError", 1.0)  # We don't want any error markers!.
                renderer.addRenderPass(self._xray_pass)

                if not self._composite_pass:
                    self._composite_pass = self.getRenderer().getRenderPass(
                        "composite")

                self._old_layer_bindings = self._composite_pass.getLayerBindings(
                )
                self._composite_pass.setLayerBindings(
                    ["default", "selection", "xray"])
                self._old_composite_shader = self._composite_pass.getCompositeShader(
                )
                self._composite_pass.setCompositeShader(
                    self._xray_composite_shader)
Example #42
0
    def render(self):
        if not self._layer_shader:
            if self._compatibility_mode:
                shader_filename = "layers.shader"
                shadow_shader_filename = "layers_shadow.shader"
            else:
                shader_filename = "layers3d.shader"
                shadow_shader_filename = "layers3d_shadow.shader"
            self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shader_filename))
            self._layer_shadow_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), shadow_shader_filename))
            self._current_shader = self._layer_shader
        # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers)
        self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex)))
        if not self._compatibility_mode:
            self._layer_shader.setUniformValue("u_starts_color", Color(*Application.getInstance().getTheme().getColor("layerview_starts").getRgb()))
            
        if self._layer_view:
            self._layer_shader.setUniformValue("u_max_feedrate", self._layer_view.getMaxFeedrate())
            self._layer_shader.setUniformValue("u_min_feedrate", self._layer_view.getMinFeedrate())
            self._layer_shader.setUniformValue("u_max_thickness", self._layer_view.getMaxThickness())
            self._layer_shader.setUniformValue("u_min_thickness", self._layer_view.getMinThickness())
            self._layer_shader.setUniformValue("u_max_line_width", self._layer_view.getMaxLineWidth())
            self._layer_shader.setUniformValue("u_min_line_width", self._layer_view.getMinLineWidth())
            self._layer_shader.setUniformValue("u_layer_view_type", self._layer_view.getSimulationViewType())
            self._layer_shader.setUniformValue("u_extruder_opacity", self._layer_view.getExtruderOpacities())
            self._layer_shader.setUniformValue("u_show_travel_moves", self._layer_view.getShowTravelMoves())
            self._layer_shader.setUniformValue("u_show_helpers", self._layer_view.getShowHelpers())
            self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin())
            self._layer_shader.setUniformValue("u_show_infill", self._layer_view.getShowInfill())
            self._layer_shader.setUniformValue("u_show_starts", self._layer_view.getShowStarts())
        else:
            #defaults
            self._layer_shader.setUniformValue("u_max_feedrate", 1)
            self._layer_shader.setUniformValue("u_min_feedrate", 0)
            self._layer_shader.setUniformValue("u_max_thickness", 1)
            self._layer_shader.setUniformValue("u_min_thickness", 0)
            self._layer_shader.setUniformValue("u_max_line_width", 1)
            self._layer_shader.setUniformValue("u_min_line_width", 0)
            self._layer_shader.setUniformValue("u_layer_view_type", 1)
            self._layer_shader.setUniformValue("u_extruder_opacity", [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]])
            self._layer_shader.setUniformValue("u_show_travel_moves", 0)
            self._layer_shader.setUniformValue("u_show_helpers", 1)
            self._layer_shader.setUniformValue("u_show_skin", 1)
            self._layer_shader.setUniformValue("u_show_infill", 1)
            self._layer_shader.setUniformValue("u_show_starts", 1)

        if not self._tool_handle_shader:
            self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader"))

        if not self._nozzle_shader:
            self._nozzle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader"))
            self._nozzle_shader.setUniformValue("u_color", Color(*Application.getInstance().getTheme().getColor("layerview_nozzle").getRgb()))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue("u_diffuseColor1", Color(*Application.getInstance().getTheme().getColor("model_unslicable").getRgb()))
            self._disabled_shader.setUniformValue("u_diffuseColor2", Color(*Application.getInstance().getTheme().getColor("model_unslicable_alt").getRgb()))
            self._disabled_shader.setUniformValue("u_width", 50.0)
            self._disabled_shader.setUniformValue("u_opacity", 0.6)

        self.bind()

        tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay, backface_cull = True)
        disabled_batch = RenderBatch(self._disabled_shader)
        head_position = None  # Indicates the current position of the print head
        nozzle_node = None

        for node in DepthFirstIterator(self._scene.getRoot()):

            if isinstance(node, ToolHandle):
                tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh())

            elif isinstance(node, NozzleNode):
                nozzle_node = node
                nozzle_node.setVisible(False)  # Don't set to true, we render it separately!

            elif getattr(node, "_outside_buildarea", False) and isinstance(node, SceneNode) and node.getMeshData() and node.isVisible() and not node.callDecoration("isNonPrintingMesh"):
                disabled_batch.addItem(node.getWorldTransformation(copy=False), node.getMeshData())

            elif isinstance(node, SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible():
                layer_data = node.callDecoration("getLayerData")
                if not layer_data:
                    continue

                # Render all layers below a certain number as line mesh instead of vertices.
                if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())):
                    start = 0
                    end = 0
                    element_counts = layer_data.getElementCounts()
                    for layer in sorted(element_counts.keys()):
                        # In the current layer, we show just the indicated paths
                        if layer == self._layer_view._current_layer_num:
                            # We look for the position of the head, searching the point of the current path
                            index = self._layer_view._current_path_num
                            offset = 0
                            for polygon in layer_data.getLayer(layer).polygons:
                                # The size indicates all values in the two-dimension array, and the second dimension is
                                # always size 3 because we have 3D points.
                                if index >= polygon.data.size // 3 - offset:
                                    index -= polygon.data.size // 3 - offset
                                    offset = 1  # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon
                                    continue
                                # The head position is calculated and translated
                                head_position = Vector(polygon.data[index+offset][0], polygon.data[index+offset][1], polygon.data[index+offset][2]) + node.getWorldPosition()
                                break
                            break
                        if self._layer_view._minimum_layer_num > layer:
                            start += element_counts[layer]
                        end += element_counts[layer]

                    # Calculate the range of paths in the last layer
                    current_layer_start = end
                    current_layer_end = end + self._layer_view._current_path_num * 2 # Because each point is used twice

                    # This uses glDrawRangeElements internally to only draw a certain range of lines.
                    # All the layers but the current selected layer are rendered first
                    if self._old_current_path != self._layer_view._current_path_num:
                        self._current_shader = self._layer_shadow_shader
                        self._switching_layers = False
                    if not self._layer_view.isSimulationRunning() and self._old_current_layer != self._layer_view._current_layer_num:
                        self._current_shader = self._layer_shader
                        self._switching_layers = True

                    # The first line does not have a previous line: add a MoveCombingType in front for start detection
                    # this way the first start of the layer can also be drawn 
                    prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveCombingType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]])
                    # Remove the last element 
                    prev_line_types = prev_line_types[0:layer_data._attributes["line_types"]["value"].size]
                    layer_data._attributes["prev_line_types"] =  {'opengl_type': 'float', 'value': prev_line_types, 'opengl_name': 'a_prev_line_type'}

                    layers_batch = RenderBatch(self._current_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end), backface_cull = True)
                    layers_batch.addItem(node.getWorldTransformation(), layer_data)
                    layers_batch.render(self._scene.getActiveCamera())

                    # Current selected layer is rendered
                    current_layer_batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (current_layer_start, current_layer_end))
                    current_layer_batch.addItem(node.getWorldTransformation(), layer_data)
                    current_layer_batch.render(self._scene.getActiveCamera())

                    self._old_current_layer = self._layer_view._current_layer_num
                    self._old_current_path = self._layer_view._current_path_num

                # Create a new batch that is not range-limited
                batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid)

                if self._layer_view.getCurrentLayerMesh():
                    batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerMesh())

                if self._layer_view.getCurrentLayerJumps():
                    batch.addItem(node.getWorldTransformation(), self._layer_view.getCurrentLayerJumps())

                if len(batch.items) > 0:
                    batch.render(self._scene.getActiveCamera())

        # The nozzle is drawn when once we know the correct position of the head,
        # but the user is not using the layer slider, and the compatibility mode is not enabled
        if not self._switching_layers and not self._compatibility_mode and self._layer_view.getActivity() and nozzle_node is not None:
            if head_position is not None:
                nozzle_node.setPosition(head_position)
                nozzle_batch = RenderBatch(self._nozzle_shader, type = RenderBatch.RenderType.Transparent)
                nozzle_batch.addItem(nozzle_node.getWorldTransformation(), mesh = nozzle_node.getMeshData())
                nozzle_batch.render(self._scene.getActiveCamera())

        if len(disabled_batch.items) > 0:
            disabled_batch.render(self._scene.getActiveCamera())

        # Render toolhandles on top of the layerview
        if len(tool_handle_batch.items) > 0:
            tool_handle_batch.render(self._scene.getActiveCamera())

        self.release()
Example #43
0
    def beginRendering(self):
        # Convenience setup
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._shader:
            self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader"))
            self._shader.setUniformValue("u_color", Color(32, 32, 32, 170))

        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                # For now we only render nodes that indicate that they need rendering.
                if node.getMeshData():
                    # Render origin of this node.
                    renderer.queueNode(scene.getRoot(), mesh = self._getAxisMesh(node), transparent = True)

                    # Render transparent MeshData
                    renderer.queueNode(node, shader = self._shader, transparent = True)

                    billboard_node = self._ensureNodeHasBillboard(node)

                    # Update the displayed data on the billboard.
                    data = self._matrixToHtml(node.getLocalTransformation())
                    billboard_node.setDisplayData({"name": node.getName(), "matrix": data, "depth": node.getDepth(), "parent_name": node.getParent().getName(), "has_mesh": "True"})

                # Handle group nodes
                if node.callDecoration("isGroup"):
                    # Render origin of this node.
                    renderer.queueNode(scene.getRoot(), mesh=self._getAxisMesh(node), transparent = True)
                    # Render bounding box of this node
                    renderer.queueNode(scene.getRoot(), mesh=node.getBoundingBoxMesh(), mode=Renderer.RenderLines)

                    billboard_node = self._ensureNodeHasBillboard(node)

                    # Update the displayed data on the billboard.
                    data = self._matrixToHtml(node.getLocalTransformation())
                    billboard_node.setDisplayData({"name": node.getName(), "matrix": data, "depth": node.getDepth(), "parent_name": node.getParent().getName(), "has_mesh": node.getMeshData() is not None})

                # We sometimes have nodes that are not groups, but have children. Also draw them
                elif not node.getMeshData() and len(node.getChildren()) != 0:
                    # Render origin of this node.
                    renderer.queueNode(scene.getRoot(), mesh=self._getAxisMesh(node), transparent = True)

                    billboard_node = self._ensureNodeHasBillboard(node)

                    # Update the displayed data on the billboard.
                    data = self._matrixToHtml(node.getLocalTransformation())
                    parent_name = node.getParent().getName() if node.getParent() else ""
                    billboard_node.setDisplayData({"name": node.getName(), "matrix": data, "depth": node.getDepth(), "parent_name": parent_name, "has_mesh": "False"})
                    bounding_box = node.getBoundingBox()
                    if bounding_box:
                        mesh_builder = MeshBuilder()
                        mesh_builder.addCube(
                            width=bounding_box.width,
                            height=bounding_box.height,
                            depth=bounding_box.depth,
                            center=bounding_box.center,
                            color=Color(0.0, 0.0, 1.0, 1.0)
                        )
                        mesh = mesh_builder.build()
                        renderer.queueNode(scene.getRoot(), mesh=mesh, mode=Renderer.RenderLines)
Example #44
0
 def _createSplashScreen(self):
     return QSplashScreen(
         QPixmap(
             Resources.getPath(Resources.Images,
                               self.getApplicationName() + ".png")))
Example #45
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._enabled_shader:
            self._enabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader"))
            theme = Application.getInstance().getTheme()
            self._enabled_shader.setUniformValue("u_overhangColor", Color(*theme.getColor("model_overhang").getRgb()))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader"))
            theme = Application.getInstance().getTheme()
            self._disabled_shader.setUniformValue("u_diffuseColor1", Color(*theme.getColor("model_unslicable").getRgb()))
            self._disabled_shader.setUniformValue("u_diffuseColor2", Color(*theme.getColor("model_unslicable_alt").getRgb()))
            self._disabled_shader.setUniformValue("u_width", 50.0)

        multi_extrusion = False

        global_container_stack = Application.getInstance().getGlobalContainerStack()
        if global_container_stack:
            multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1

            if multi_extrusion:
                support_extruder_nr = global_container_stack.getProperty("support_extruder_nr", "value")
                support_angle_stack = ExtruderManager.getInstance().getExtruderStack(support_extruder_nr)
                if not support_angle_stack:
                    support_angle_stack = global_container_stack
            else:
                support_angle_stack = global_container_stack

            if Preferences.getInstance().getValue("view/show_overhang"):
                angle = support_angle_stack.getProperty("support_angle", "value")
                # Make sure the overhang angle is valid before passing it to the shader
                # Note: if the overhang angle is set to its default value, it does not need to get validated (validationState = None)
                if angle is not None and global_container_stack.getProperty("support_angle", "validationState") in [None, ValidatorState.Valid]:
                    self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle)))
                else:
                    self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang.
            else:
                self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0)))


        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    uniforms = {}
                    shade_factor = 1.0

                    if not multi_extrusion:
                        if global_container_stack:
                            material = global_container_stack.findContainer({ "type": "material" })
                            material_color = material.getMetaDataEntry("color_code", default = self._extruders_model.defaultColors[0]) if material else self._extruders_model.defaultColors[0]
                        else:
                            material_color = self._extruders_model.defaultColors[0]
                    else:
                        # Get color to render this mesh in from ExtrudersModel
                        extruder_index = 0
                        extruder_id = node.callDecoration("getActiveExtruder")
                        if extruder_id:
                            extruder_index = max(0, self._extruders_model.find("id", extruder_id))
                        try:
                            material_color = self._extruders_model.getItem(extruder_index)["color"]
                        except KeyError:
                            material_color = self._extruders_model.defaultColors[0]

                        if extruder_index != ExtruderManager.getInstance().activeExtruderIndex:
                            # Shade objects that are printed with the non-active extruder 25% darker
                            shade_factor = 0.6
                    try:
                        # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
                        # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
                        uniforms["diffuse_color"] = [
                            shade_factor * int(material_color[1:3], 16) / 255,
                            shade_factor * int(material_color[3:5], 16) / 255,
                            shade_factor * int(material_color[5:7], 16) / 255,
                            1.0
                        ]
                    except ValueError:
                        pass

                    if hasattr(node, "_outside_buildarea"):
                        if node._outside_buildarea:
                            renderer.queueNode(node, shader = self._disabled_shader)
                        else:
                            renderer.queueNode(node, shader = self._enabled_shader, uniforms = uniforms)
                    else:
                        renderer.queueNode(node, material = self._enabled_shader, uniforms = uniforms)
                if node.callDecoration("isGroup") and Selection.isSelected(node):
                    renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = RenderBatch.RenderMode.LineLoop)
Example #46
0
    def __init__(self, name, version, buildtype="", **kwargs):
        if Application._instance != None:
            raise ValueError("Duplicate singleton creation")

        # If the constructor is called and there is no instance, set the instance to self.
        # This is done because we can't make constructor private
        Application._instance = self

        self._application_name = name
        self._version = version
        self._buildtype = buildtype

        os.putenv(
            "UBUNTU_MENUPROXY", "0"
        )  # For Ubuntu Unity this makes Qt use its own menu bar rather than pass it on to Unity.

        Signal._app = self
        Signal._signalQueue = self
        Resources.ApplicationIdentifier = name

        Resources.addSearchPath(
            os.path.join(os.path.dirname(sys.executable), "resources"))
        Resources.addSearchPath(
            os.path.join(Application.getInstallPrefix(), "share", "uranium",
                         "resources"))
        Resources.addSearchPath(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         "uranium", "resources"))
        Resources.addSearchPath(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         self.getApplicationName(), "resources"))
        if not hasattr(sys, "frozen"):
            Resources.addSearchPath(
                os.path.join(os.path.abspath(os.path.dirname(__file__)), "..",
                             "resources"))

        self._main_thread = threading.current_thread()

        super().__init__()  # Call super to make multiple inheritance work.
        i18nCatalog.setApplication(self)

        self._renderer = None

        PluginRegistry.addType("backend", self.setBackend)
        PluginRegistry.addType("logger", Logger.addLogger)
        PluginRegistry.addType("extension", self.addExtension)

        preferences = Preferences.getInstance()
        env_lang = locale.getdefaultlocale()[0]
        preferences.addPreference("general/language", env_lang)
        preferences.addPreference("general/visible_settings", "")

        try:
            preferences.readFromFile(
                Resources.getPath(Resources.Preferences,
                                  self._application_name + ".cfg"))
        except FileNotFoundError:
            pass

        self._controller = Controller(self)
        self._mesh_file_handler = MeshFileHandler.getInstance()
        self._mesh_file_handler.setApplication(self)
        self._workspace_file_handler = WorkspaceFileHandler.getInstance()
        self._workspace_file_handler.setApplication(self)
        self._extensions = []
        self._backend = None
        self._output_device_manager = OutputDeviceManager()

        self._required_plugins = []

        self._operation_stack = OperationStack(self.getController())

        self._plugin_registry = PluginRegistry.getInstance()

        self._plugin_registry.addPluginLocation(
            os.path.join(Application.getInstallPrefix(), "lib", "uranium"))
        self._plugin_registry.addPluginLocation(
            os.path.join(os.path.dirname(sys.executable), "plugins"))
        self._plugin_registry.addPluginLocation(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         "uranium", "plugins"))
        self._plugin_registry.addPluginLocation(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         self.getApplicationName(), "plugins"))
        # Locally installed plugins
        local_path = os.path.join(
            Resources.getStoragePath(Resources.Resources), "plugins")
        # Ensure the local plugins directory exists
        try:
            os.makedirs(local_path)
        except OSError:
            pass
        self._plugin_registry.addPluginLocation(local_path)

        if not hasattr(sys, "frozen"):
            self._plugin_registry.addPluginLocation(
                os.path.join(os.path.abspath(os.path.dirname(__file__)), "..",
                             "plugins"))

        self._plugin_registry.setApplication(self)

        ContainerRegistry.setApplication(self)
        UM.Settings.InstanceContainer.setContainerRegistry(
            self.getContainerRegistry())
        UM.Settings.ContainerStack.setContainerRegistry(
            self.getContainerRegistry())

        self._parsed_command_line = None
        self.parseCommandLine()

        self._visible_messages = []
        self._message_lock = threading.Lock()
        self.showMessageSignal.connect(self.showMessage)
        self.hideMessageSignal.connect(self.hideMessage)

        self._global_container_stack = None
Example #47
0
    def installPlugin(self, plugin_path: str):
        plugin_path = QUrl(plugin_path).toLocalFile()
        Logger.log("d", "Attempting to install a new plugin %s", plugin_path)
        local_plugin_path = os.path.join(
            Resources.getStoragePath(Resources.Resources), "plugins")
        plugin_folder = ""
        try:
            with zipfile.ZipFile(plugin_path, "r") as zip_ref:
                plugin_id = None
                for file in zip_ref.infolist():
                    if file.filename.endswith("/"):
                        plugin_id = file.filename.strip("/")
                        break

                if plugin_id is None:
                    return {
                        "status":
                        "error",
                        "message":
                        i18n_catalog.i18nc(
                            "@info:status",
                            "Failed to install plugin from <filename>{0}</filename>:\n<message>{1}</message>",
                            plugin_path, "Invalid plugin file")
                    }
                plugin_folder = os.path.join(local_plugin_path, plugin_id)

                if os.path.isdir(
                        plugin_folder
                ):  # Plugin is already installed by user (so not a bundled plugin)
                    metadata = {}
                    with zip_ref.open(plugin_id +
                                      "/plugin.json") as metadata_file:
                        metadata = json.loads(
                            metadata_file.read().decode("utf-8"))

                    if "version" in metadata:
                        new_version = Version(metadata["version"])
                        old_version = Version(
                            self.getMetaData(plugin_id)["plugin"]["version"])
                        if new_version > old_version:
                            zip_ref.extractall(plugin_folder)
                            return {
                                "status":
                                "ok",
                                "message":
                                i18n_catalog.i18nc(
                                    "@info:status",
                                    "The plugin has been installed.\n Please re-start the application to activate the plugin."
                                )
                            }

                    Logger.log(
                        "w",
                        "The plugin was already installed. Unable to install it again!"
                    )
                    return {
                        "status":
                        "duplicate",
                        "message":
                        i18n_catalog.i18nc(
                            "@info:status",
                            "Failed to install the plugin; \n<message>{0}</message>",
                            "Plugin was already installed")
                    }
                elif plugin_id in self._plugins:
                    # Plugin is already installed, but not by the user (eg; this is a bundled plugin)
                    # TODO: Right now we don't support upgrading bundled plugins at all, but we might do so in the future.
                    return {
                        "status":
                        "duplicate",
                        "message":
                        i18n_catalog.i18nc(
                            "@info:status",
                            "Failed to install the plugin; \n<message>{0}</message>",
                            "Unable to upgrade or instal bundled plugins.")
                    }

                zip_ref.extractall(plugin_folder)

        except:  # Installing a new plugin should never crash the application.
            Logger.logException(
                "d", "An exception occurred while installing plugin ")
            return {
                "status":
                "error",
                "message":
                i18n_catalog.i18nc(
                    "@info:status",
                    "Failed to install plugin from <filename>{0}</filename>:\n<message>{1}</message>",
                    plugin_folder, "Invalid plugin file")
            }

        return {
            "status":
            "ok",
            "message":
            i18n_catalog.i18nc(
                "@info:status",
                "The plugin has been installed.\n Please re-start the application to activate the plugin."
            )
        }
Example #48
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._extruders_model:
            self._extruders_model = Application.getInstance(
            ).getExtrudersModel()

        if not self._theme:
            self._theme = Application.getInstance().getTheme()

        if not self._enabled_shader:
            self._enabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "overhang.shader"))
            self._enabled_shader.setUniformValue(
                "u_overhangColor",
                Color(*self._theme.getColor("model_overhang").getRgb()))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor1",
                Color(*self._theme.getColor("model_unslicable").getRgb()))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor2",
                Color(*self._theme.getColor("model_unslicable_alt").getRgb()))
            self._disabled_shader.setUniformValue("u_width", 50.0)

        if not self._non_printing_shader:
            self._non_printing_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders,
                                  "transparent_object.shader"))
            self._non_printing_shader.setUniformValue(
                "u_diffuseColor",
                Color(*self._theme.getColor("model_non_printing").getRgb()))
            self._non_printing_shader.setUniformValue("u_opacity", 0.6)

        if not self._support_mesh_shader:
            self._support_mesh_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._support_mesh_shader.setUniformValue("u_vertical_stripes",
                                                      True)
            self._support_mesh_shader.setUniformValue("u_width", 5.0)

        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if global_container_stack:
            support_extruder_nr = global_container_stack.getExtruderPositionValueWithDefault(
                "support_extruder_nr")
            support_angle_stack = Application.getInstance().getExtruderManager(
            ).getExtruderStack(support_extruder_nr)

            if support_angle_stack is not None and Application.getInstance(
            ).getPreferences().getValue("view/show_overhang"):
                angle = support_angle_stack.getProperty(
                    "support_angle", "value")
                # Make sure the overhang angle is valid before passing it to the shader
                # Note: if the overhang angle is set to its default value, it does not need to get validated (validationState = None)
                if angle is not None and global_container_stack.getProperty(
                        "support_angle",
                        "validationState") in [None, ValidatorState.Valid]:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(90 - angle)))
                else:
                    self._enabled_shader.setUniformValue(
                        "u_overhangAngle", math.cos(math.radians(0))
                    )  #Overhang angle of 0 causes no area at all to be marked as overhang.
            else:
                self._enabled_shader.setUniformValue("u_overhangAngle",
                                                     math.cos(math.radians(0)))

        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible(
                ) and not node.callDecoration("getLayerData"):
                    uniforms = {}
                    shade_factor = 1.0

                    per_mesh_stack = node.callDecoration("getStack")

                    extruder_index = node.callDecoration(
                        "getActiveExtruderPosition")
                    if extruder_index is None:
                        extruder_index = "0"
                    extruder_index = int(extruder_index)

                    # Use the support extruder instead of the active extruder if this is a support_mesh
                    if per_mesh_stack:
                        if per_mesh_stack.getProperty("support_mesh", "value"):
                            extruder_index = int(
                                global_container_stack.
                                getExtruderPositionValueWithDefault(
                                    "support_extruder_nr"))

                    try:
                        material_color = self._extruders_model.getItem(
                            extruder_index)["color"]
                    except KeyError:
                        material_color = self._extruders_model.defaultColors[0]

                    if extruder_index != ExtruderManager.getInstance(
                    ).activeExtruderIndex:
                        # Shade objects that are printed with the non-active extruder 25% darker
                        shade_factor = 0.6

                    try:
                        # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
                        # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
                        uniforms["diffuse_color"] = [
                            shade_factor * int(material_color[1:3], 16) / 255,
                            shade_factor * int(material_color[3:5], 16) / 255,
                            shade_factor * int(material_color[5:7], 16) / 255,
                            1.0
                        ]
                    except ValueError:
                        pass

                    if node.callDecoration("isNonPrintingMesh"):
                        if per_mesh_stack and (per_mesh_stack.getProperty(
                                "infill_mesh", "value")
                                               or per_mesh_stack.getProperty(
                                                   "cutting_mesh", "value")):
                            renderer.queueNode(
                                node,
                                shader=self._non_printing_shader,
                                uniforms=uniforms,
                                transparent=True)
                        else:
                            renderer.queueNode(
                                node,
                                shader=self._non_printing_shader,
                                transparent=True)
                    elif getattr(node, "_outside_buildarea", False):
                        renderer.queueNode(node, shader=self._disabled_shader)
                    elif per_mesh_stack and per_mesh_stack.getProperty(
                            "support_mesh", "value"):
                        # Render support meshes with a vertical stripe that is darker
                        shade_factor = 0.6
                        uniforms["diffuse_color_2"] = [
                            uniforms["diffuse_color"][0] * shade_factor,
                            uniforms["diffuse_color"][1] * shade_factor,
                            uniforms["diffuse_color"][2] * shade_factor, 1.0
                        ]
                        renderer.queueNode(node,
                                           shader=self._support_mesh_shader,
                                           uniforms=uniforms)
                    else:
                        renderer.queueNode(node,
                                           shader=self._enabled_shader,
                                           uniforms=uniforms)
                if node.callDecoration("isGroup") and Selection.isSelected(
                        node):
                    renderer.queueNode(scene.getRoot(),
                                       mesh=node.getBoundingBoxMesh(),
                                       mode=RenderBatch.RenderMode.LineLoop)
Example #49
0
    def saveAll(self) -> None:
        for instance in self.findInstanceContainers():
            if not instance.isDirty():
                continue

            try:
                data = instance.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException(
                    "e",
                    "An exception occurred trying to serialize container %s",
                    instance.getId())
                continue

            mime_type = self.getMimeTypeForContainer(type(instance))
            if mime_type is not None:
                file_name = urllib.parse.quote_plus(
                    instance.getId()) + "." + mime_type.preferredSuffix
                path = Resources.getStoragePath(Resources.InstanceContainers,
                                                file_name)
                with SaveFile(path, "wt") as f:
                    f.write(data)

        for stack in self.findContainerStacks():
            if not stack.isDirty():
                continue

            try:
                data = stack.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException(
                    "e",
                    "An exception occurred trying to serialize container %s",
                    stack.getId())
                continue

            mime_type = self.getMimeTypeForContainer(type(stack))
            if mime_type is not None:
                file_name = urllib.parse.quote_plus(
                    stack.getId()) + "." + mime_type.preferredSuffix
                path = Resources.getStoragePath(Resources.ContainerStacks,
                                                file_name)
                with SaveFile(path, "wt") as f:
                    f.write(data)

        for definition in self.findDefinitionContainers():
            try:
                data = definition.serialize()
            except NotImplementedError:
                # Serializing is not supported so skip this container
                continue
            except Exception:
                Logger.logException(
                    "e",
                    "An exception occurred trying to serialize container %s",
                    definition.getId())
                continue

            mime_type = self.getMimeTypeForContainer(type(definition))
            if mime_type is not None:
                file_name = urllib.parse.quote_plus(
                    definition.getId()) + "." + mime_type.preferredSuffix
                path = Resources.getStoragePath(Resources.DefinitionContainers,
                                                file_name)
                with SaveFile(path, "wt") as f:
                    f.write(data)
Example #50
0
    def initializeBeforePluginsAreLoaded(self) -> None:
        config_path = Resources.getConfigStoragePath()

        # File to store plugin info, such as which ones to install/remove and which ones are disabled.
        # At this point we can load this here because we already know the actual Application name, so the directory name
        self._plugin_config_filename = os.path.join(
            os.path.abspath(config_path), "plugins.json")  # type: str

        from UM.Settings.ContainerRegistry import ContainerRegistry
        container_registry = ContainerRegistry.getInstance()

        try:
            with container_registry.lockFile():
                # Load the plugin info if exists
                if os.path.exists(self._plugin_config_filename):
                    Logger.log("i", "Loading plugin configuration file '%s'",
                               self._plugin_config_filename)
                    with open(self._plugin_config_filename,
                              "r",
                              encoding="utf-8") as f:
                        data = json.load(f)
                        self._disabled_plugins = data["disabled"]
                        self._plugins_to_install = data["to_install"]
                        self._plugins_to_remove = data["to_remove"]
        except:
            Logger.logException(
                "e", "Failed to load plugin configuration file '%s'",
                self._plugin_config_filename)

        # Also load data from preferences, where the plugin info used to be saved
        preferences = self._application.getPreferences()
        disabled_plugins = preferences.getValue("general/disabled_plugins")
        disabled_plugins = disabled_plugins.split(
            ",") if disabled_plugins else []
        disabled_plugins = [
            plugin for plugin in disabled_plugins if len(plugin.strip()) > 0
        ]
        for plugin_id in disabled_plugins:
            if plugin_id not in self._disabled_plugins:
                self._disabled_plugins.append(plugin_id)

        plugins_to_remove = preferences.getValue("general/plugins_to_remove")
        plugins_to_remove = plugins_to_remove.split(
            ",") if plugins_to_remove else []
        for plugin_id in plugins_to_remove:
            if plugin_id not in self._plugins_to_remove:
                self._plugins_to_remove.append(plugin_id)

        # Remove plugins that need to be removed
        for plugin_id in self._plugins_to_remove:
            self._removePlugin(plugin_id)
        self._plugins_to_remove = []
        if plugins_to_remove is not None:
            preferences.setValue("general/plugins_to_remove", "")
        self._savePluginData()

        # Install the plugins that need to be installed (overwrite existing)
        for plugin_id, plugin_info in self._plugins_to_install.items():
            self._installPlugin(plugin_id, plugin_info["filename"])
        self._plugins_to_install = dict()
        self._savePluginData()
Example #51
0
    def __init__(self, tray_icon_name=None, **kwargs):
        plugin_path = ""
        if sys.platform == "win32":
            if hasattr(sys, "frozen"):
                plugin_path = os.path.join(
                    os.path.dirname(os.path.abspath(sys.executable)), "PyQt5",
                    "plugins")
                Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path))
                QCoreApplication.addLibraryPath(plugin_path)
            else:
                import site
                for sitepackage_dir in site.getsitepackages():
                    QCoreApplication.addLibraryPath(
                        os.path.join(sitepackage_dir, "PyQt5", "plugins"))
        elif sys.platform == "darwin":
            plugin_path = os.path.join(Application.getInstallPrefix(),
                                       "Resources", "plugins")

        if plugin_path:
            Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path))
            QCoreApplication.addLibraryPath(plugin_path)

        os.environ["QSG_RENDER_LOOP"] = "basic"

        super().__init__(sys.argv, **kwargs)

        self.setAttribute(Qt.AA_UseDesktopOpenGL)
        major_version, minor_version, profile = OpenGLContext.detectBestOpenGLVersion(
        )

        if major_version is None and minor_version is None and profile is None:
            Logger.log(
                "e",
                "Startup failed because OpenGL version probing has failed: tried to create a 2.0 and 4.1 context. Exiting"
            )
            QMessageBox.critical(
                None, "Failed to probe OpenGL",
                "Could not probe OpenGL. This program requires OpenGL 2.0 or higher. Please check your video card drivers."
            )
            sys.exit(1)
        else:
            Logger.log(
                "d", "Detected most suitable OpenGL context version: %s" %
                (OpenGLContext.versionAsText(major_version, minor_version,
                                             profile)))
        OpenGLContext.setDefaultFormat(major_version,
                                       minor_version,
                                       profile=profile)

        self._plugins_loaded = False  # Used to determine when it's safe to use the plug-ins.
        self._main_qml = "main.qml"
        self._engine = None
        self._renderer = None
        self._main_window = None
        self._theme = None

        self._shutting_down = False
        self._qml_import_paths = []
        self._qml_import_paths.append(
            os.path.join(os.path.dirname(sys.executable), "qml"))
        self._qml_import_paths.append(
            os.path.join(Application.getInstallPrefix(), "Resources", "qml"))

        self.parseCommandLine()
        Logger.log("i", "Command line arguments: %s",
                   self._parsed_command_line)

        signal.signal(signal.SIGINT, signal.SIG_DFL)
        # This is done here as a lot of plugins require a correct gl context. If you want to change the framework,
        # these checks need to be done in your <framework>Application.py class __init__().

        i18n_catalog = i18nCatalog("uranium")

        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Loading plugins..."))
        # Remove and install the plugins that have been scheduled
        self._plugin_registry.initializeBeforePluginsAreLoaded()
        self._loadPlugins()
        self._plugin_registry.initializeAfterPlguinsAreLoaded()
        self._plugin_registry.checkRequiredPlugins(self.getRequiredPlugins())
        self.pluginsLoaded.emit()

        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Updating configuration..."))
        UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().upgrade()

        # Preferences might have changed. Load them again.
        # Note that the language can't be updated, so that will always revert to English.
        preferences = Preferences.getInstance()
        try:
            file_name = Resources.getPath(Resources.Preferences,
                                          self._application_name + ".cfg")
            with open(file_name, "r", encoding="utf-8") as f:
                serialized = f.read()
            preferences.deserialize(serialized)
        except FileNotFoundError:
            pass
        # Force the configuration file to be written again since the list of plugins to remove maybe changed
        Preferences.getInstance().setValue("general/plugins_to_remove", "")
        Preferences.getInstance().writeToFile(
            Resources.getStoragePath(Resources.Preferences,
                                     self.getApplicationName() + ".cfg"))

        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Loading preferences..."))
        try:
            file_name = Resources.getPath(Resources.Preferences,
                                          self.getApplicationName() + ".cfg")
            Preferences.getInstance().readFromFile(file_name)
        except FileNotFoundError:
            pass

        self.getApplicationName()

        Preferences.getInstance().addPreference(
            "%s/recent_files" % self.getApplicationName(), "")

        self._recent_files = []
        file_names = Preferences.getInstance().getValue(
            "%s/recent_files" % self.getApplicationName()).split(";")
        for file_name in file_names:
            if not os.path.isfile(file_name):
                continue

            self._recent_files.append(QUrl.fromLocalFile(file_name))

        JobQueue.getInstance().jobFinished.connect(self._onJobFinished)

        # Initialize System tray icon and make it invisible because it is used only to show pop up messages
        self._tray_icon = None
        self._tray_icon_widget = None
        if tray_icon_name:
            self._tray_icon = QIcon(
                Resources.getPath(Resources.Images, tray_icon_name))
            self._tray_icon_widget = QSystemTrayIcon(self._tray_icon)
            self._tray_icon_widget.setVisible(False)
Example #52
0
 def saveSettingValues(self):
     self._machine_settings.saveValuesToFile(
         Resources.getStoragePath(Resources.SettingsLocation,
                                  "settings.cfg"))
Example #53
0
 def _engineCreated(self):
     sidebar_component_path = os.path.join(
         Resources.getPath(
             Application.getInstance().ResourceTypes.QmlFiles),
         "PrepareSidebar.qml")
     self.addDisplayComponent("sidebar", sidebar_component_path)
Example #54
0
    def run(self):
        self._i18n_catalog = i18nCatalog("cura")

        i18nCatalog.setTagReplacements({
            "filename":
            "font color=\"black\"",
            "message":
            "font color=UM.Theme.colors.message_text;",
        })

        self.showSplashMessage(
            self._i18n_catalog.i18nc("@info:progress", "Setting up scene..."))

        controller = self.getController()

        controller.setActiveView("SolidView")
        controller.setCameraTool("CameraTool")
        controller.setSelectionTool("SelectionTool")

        t = controller.getTool("TranslateTool")
        if t:
            t.setEnabledAxis(
                [ToolHandle.XAxis, ToolHandle.YAxis, ToolHandle.ZAxis])

        Selection.selectionChanged.connect(self.onSelectionChanged)

        root = controller.getScene().getRoot()
        self._platform = Platform(root)

        self._volume = BuildVolume.BuildVolume(root)

        self.getRenderer().setBackgroundColor(QColor(245, 245, 245))

        self._physics = PlatformPhysics.PlatformPhysics(
            controller, self._volume)

        camera = Camera("3d", root)
        camera.setPosition(Vector(-80, 250, 700))
        camera.setPerspective(True)
        camera.lookAt(Vector(0, 0, 0))
        controller.getScene().setActiveCamera("3d")

        self.getController().getTool("CameraTool").setOrigin(Vector(0, 100, 0))

        self._camera_animation = CameraAnimation.CameraAnimation()
        self._camera_animation.setCameraTool(
            self.getController().getTool("CameraTool"))

        self.showSplashMessage(
            self._i18n_catalog.i18nc("@info:progress", "Loading interface..."))

        self.setMainQml(
            Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
        self.initializeEngine()

        if self._engine.rootObjects:
            self.closeSplash()

            for file in self.getCommandLineOption("file", []):
                self._openFile(file)
            for file_name in self._open_file_queue:  #Open all the files that were queued up while plug-ins were loading.
                self._openFile(file_name)

            self.exec_()
Example #55
0
    def __init__(self, **kwargs):
        plugin_path = ""
        if sys.platform == "win32":
            if hasattr(sys, "frozen"):
                plugin_path = os.path.join(
                    os.path.dirname(os.path.abspath(sys.executable)), "PyQt5",
                    "plugins")
                Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path))
                QCoreApplication.addLibraryPath(plugin_path)
            else:
                import site
                for dir in site.getsitepackages():
                    QCoreApplication.addLibraryPath(
                        os.path.join(dir, "PyQt5", "plugins"))
        elif sys.platform == "darwin":
            plugin_path = os.path.join(Application.getInstallPrefix(),
                                       "Resources", "plugins")

        if plugin_path:
            Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path))
            QCoreApplication.addLibraryPath(plugin_path)

        os.environ["QSG_RENDER_LOOP"] = "basic"

        super().__init__(sys.argv, **kwargs)

        self.setAttribute(Qt.AA_UseDesktopOpenGL)
        major_version, minor_version, profile = OpenGLContext.detectBestOpenGLVersion(
        )

        if major_version is None and minor_version is None and profile is None:
            Logger.log(
                "e",
                "Startup failed because OpenGL version probing has failed: tried to create a 2.0 and 4.1 context. Exiting"
            )
            QMessageBox.critical(
                None, "Failed to probe OpenGL",
                "Could not probe OpenGL. This program requires OpenGL 2.0 or higher. Please check your video card drivers."
            )
            sys.exit(1)
        else:
            Logger.log(
                "d", "Detected most suitable OpenGL context version: %s" %
                (OpenGLContext.versionAsText(major_version, minor_version,
                                             profile)))
        OpenGLContext.setDefaultFormat(major_version,
                                       minor_version,
                                       profile=profile)

        self._plugins_loaded = False  # Used to determine when it's safe to use the plug-ins.
        self._main_qml = "main.qml"
        self._engine = None
        self._renderer = None
        self._main_window = None
        self._theme = None

        self._shutting_down = False
        self._qml_import_paths = []
        self._qml_import_paths.append(
            os.path.join(os.path.dirname(sys.executable), "qml"))
        self._qml_import_paths.append(
            os.path.join(Application.getInstallPrefix(), "Resources", "qml"))

        try:
            self._splash = self._createSplashScreen()
        except FileNotFoundError:
            self._splash = None
        else:
            self._splash.show()
            self.processEvents()

        signal.signal(signal.SIGINT, signal.SIG_DFL)
        # This is done here as a lot of plugins require a correct gl context. If you want to change the framework,
        # these checks need to be done in your <framework>Application.py class __init__().

        i18n_catalog = i18nCatalog("uranium")

        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Loading plugins..."))
        self._loadPlugins()
        self.parseCommandLine()
        Logger.log("i", "Command line arguments: %s",
                   self._parsed_command_line)
        self._plugin_registry.checkRequiredPlugins(self.getRequiredPlugins())

        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Updating configuration..."))
        upgraded = UM.VersionUpgradeManager.VersionUpgradeManager.getInstance(
        ).upgrade()
        if upgraded:
            preferences = Preferences.getInstance(
            )  #Preferences might have changed. Load them again.
            #Note that the language can't be updated, so that will always revert to English.
            try:
                preferences.readFromFile(
                    Resources.getPath(Resources.Preferences,
                                      self._application_name + ".cfg"))
            except FileNotFoundError:
                pass

        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Loading preferences..."))
        try:
            file = Resources.getPath(Resources.Preferences,
                                     self.getApplicationName() + ".cfg")
            Preferences.getInstance().readFromFile(file)
        except FileNotFoundError:
            pass
Example #56
0
    def _getSingleExtrusionMachineExtruders(self, definition_name):

        machine_instances_dir = Resources.getPath(
            CuraApplication.ResourceTypes.MachineStack)

        machine_instance_id = None

        # Find machine instances
        for item in os.listdir(machine_instances_dir):
            file_path = os.path.join(machine_instances_dir, item)
            if not os.path.isfile(file_path):
                continue

            parser = configparser.ConfigParser(interpolation=None)
            try:
                parser.read([file_path])
            except:
                # skip, it is not a valid stack file
                continue

            if not parser.has_option("metadata", "type"):
                continue
            if "machine" != parser["metadata"]["type"]:
                continue

            if not parser.has_option("general", "id"):
                continue

            id = parser["general"]["id"]
            if id + "_settings" != definition_name:
                continue
            else:
                machine_instance_id = id
                break

        if machine_instance_id is not None:

            extruders_instances_dir = Resources.getPath(
                CuraApplication.ResourceTypes.ExtruderStack)
            #"machine",[extruders]
            extruder_instances = []

            # Find all custom extruders for found machines
            for item in os.listdir(extruders_instances_dir):
                file_path = os.path.join(extruders_instances_dir, item)
                if not os.path.isfile(file_path):
                    continue

                parser = configparser.ConfigParser(interpolation=None)
                try:
                    parser.read([file_path])
                except:
                    # skip, it is not a valid stack file
                    continue

                if not parser.has_option("metadata", "type"):
                    continue
                if "extruder_train" != parser["metadata"]["type"]:
                    continue

                if not parser.has_option("metadata", "machine"):
                    continue
                if not parser.has_option("metadata", "position"):
                    continue

                if machine_instance_id != parser["metadata"]["machine"]:
                    continue

                extruder_instances.append(parser)

        return extruder_instances
Example #57
0
    def startSplashWindowPhase(self) -> None:
        super().startSplashWindowPhase()

        self._package_manager.initialize()

        # Read preferences here (upgrade won't work) to get the language in use, so the splash window can be shown in
        # the correct language.
        try:
            preferences_filename = Resources.getPath(Resources.Preferences,
                                                     self._app_name + ".cfg")
            self._preferences.readFromFile(preferences_filename)
        except FileNotFoundError:
            Logger.log(
                "i",
                "Preferences file not found, ignore and use default language '%s'",
                self._default_language)

        signal.signal(signal.SIGINT, signal.SIG_DFL)
        # This is done here as a lot of plugins require a correct gl context. If you want to change the framework,
        # these checks need to be done in your <framework>Application.py class __init__().

        i18n_catalog = i18nCatalog("uranium")

        self._configuration_error_message = ConfigurationErrorMessage(
            self,
            i18n_catalog.i18nc("@info:status",
                               "Your configuration seems to be corrupt."),
            lifetime=0,
            title=i18n_catalog.i18nc("@info:title", "Configuration errors"))
        # Remove, install, and then loading plugins
        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Loading plugins..."))
        # Remove and install the plugins that have been scheduled
        self._plugin_registry.initializeBeforePluginsAreLoaded()
        self._loadPlugins()
        self._plugin_registry.checkRequiredPlugins(self.getRequiredPlugins())
        self.pluginsLoaded.emit()

        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Updating configuration..."))
        with self._container_registry.lockFile():
            VersionUpgradeManager.getInstance().upgrade()

        # Load preferences again because before we have loaded the plugins, we don't have the upgrade routine for
        # the preferences file. Now that we have, load the preferences file again so it can be upgraded and loaded.
        try:
            preferences_filename = Resources.getPath(Resources.Preferences,
                                                     self._app_name + ".cfg")
            with open(preferences_filename, "r", encoding="utf-8") as f:
                serialized = f.read()
            # This performs the upgrade for Preferences
            self._preferences.deserialize(serialized)
            self._preferences.setValue("general/plugins_to_remove", "")
            self._preferences.writeToFile(preferences_filename)
        except FileNotFoundError:
            Logger.log(
                "i",
                "The preferences file cannot be found, will use default values"
            )

        # Force the configuration file to be written again since the list of plugins to remove maybe changed
        self.showSplashMessage(
            i18n_catalog.i18nc("@info:progress", "Loading preferences..."))
        try:
            self._preferences_filename = Resources.getPath(
                Resources.Preferences, self._app_name + ".cfg")
            self._preferences.readFromFile(self._preferences_filename)
        except FileNotFoundError:
            Logger.log(
                "i",
                "The preferences file '%s' cannot be found, will use default values",
                self._preferences_filename)
            self._preferences_filename = Resources.getStoragePath(
                Resources.Preferences, self._app_name + ".cfg")

        # FIXME: This is done here because we now use "plugins.json" to manage plugins instead of the Preferences file,
        # but the PluginRegistry will still import data from the Preferences files if present, such as disabled plugins,
        # so we need to reset those values AFTER the Preferences file is loaded.
        self._plugin_registry.initializeAfterPluginsAreLoaded()

        # Preferences: recent files
        self._preferences.addPreference("%s/recent_files" % self._app_name, "")
        file_names = self._preferences.getValue("%s/recent_files" %
                                                self._app_name).split(";")
        for file_name in file_names:
            if not os.path.isfile(file_name):
                continue
            self._recent_files.append(QUrl.fromLocalFile(file_name))

        # Initialize System tray icon and make it invisible because it is used only to show pop up messages
        self._tray_icon = None
        if self._tray_icon_name:
            self._tray_icon = QIcon(
                Resources.getPath(Resources.Images, self._tray_icon_name))
            self._tray_icon_widget = QSystemTrayIcon(self._tray_icon)
            self._tray_icon_widget.setVisible(False)
Example #58
0
 def getCacheLockFilename(self) -> str:
     return Resources.getStoragePath(
         Resources.Cache, self._application.getApplicationLockFilename())
# Copyright (c) 2016 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

import pytest
import os

import UM.Settings.InstanceContainer
# import UM.Settings.SettingDefinition
from UM.Resources import Resources
Resources.addSearchPath(os.path.dirname(os.path.abspath(__file__)))


def test_create():
    container = UM.Settings.InstanceContainer.InstanceContainer("test")
    assert container.getId() == "test"


##  Test whether setting a property on an instance correctly updates dependencies.
#
#   This test primarily tests the SettingInstance but requires some functionality
#   from InstanceContainer that is not easily captured in a Mock object. Therefore
#   it is included here.
def test_instance_setProperty():
    instance_container = UM.Settings.InstanceContainer.InstanceContainer(
        "test")

    definition1 = UM.Settings.SettingDefinition.SettingDefinition(
        "test_0", None)
    definition1.deserialize({
        "label": "Test 0",
        "type": "float",
Example #60
-4
    def loadQtTranslation(self, file, language = "default"):
        #TODO Add support for specifying a language from preferences
        path = None
        if language == "default":
            path = self._getDefaultLanguage(file)
        else:
            path = Resources.getPath(Resources.i18n, language, "LC_MESSAGES", file + ".qm")

        # If all else fails, fall back to english.
        if not path:
            Logger.log("w", "Could not find any translations matching {0} for file {1}, falling back to english".format(language, file))
            try:
                path = Resources.getPath(Resources.i18n, "en", "LC_MESSAGES", file + ".qm")
            except FileNotFoundError:
                Logger.log("w", "Could not find English translations for file {0}. Switching to developer english.".format(file))
                return

        translator = QTranslator()
        if not translator.load(path):
            Logger.log("e", "Unable to load translations %s", file)
            return

        # Store a reference to the translator.
        # This prevents the translator from being destroyed before Qt has a chance to use it.
        self._translators[file] = translator

        # Finally, install the translator so Qt can use it.
        self.installTranslator(translator)