diff --git a/.gitignore b/.gitignore index c0cb27efe0..d991fedb73 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ CuraEngine.exe LC_MESSAGES .cache *.qmlc +.mypy_cache #MacOS .DS_Store diff --git a/cmake/CuraTests.cmake b/cmake/CuraTests.cmake index ffe4616bf3..801f054bc3 100644 --- a/cmake/CuraTests.cmake +++ b/cmake/CuraTests.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. enable_testing() @@ -53,3 +53,9 @@ foreach(_plugin ${_plugins}) cura_add_test(NAME pytest-${_plugin_name} DIRECTORY ${_plugin_directory} PYTHONPATH "${_plugin_directory}|${CMAKE_SOURCE_DIR}|${URANIUM_DIR}") endif() endforeach() + +#Add code style test. +add_test( + NAME "code-style" + COMMAND ${PYTHON_EXECUTABLE} run_mypy.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +) \ No newline at end of file diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 72f2d0af09..b629332f47 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -295,7 +295,9 @@ class CuraApplication(QtApplication): Resources.addSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources")) if not hasattr(sys, "frozen"): - Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources")) + resource_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources") + Resources.addSearchPath(resource_path) + Resources.setBundledResourcesPath(resource_path) # Adds custom property types, settings types, and extra operators (functions) that need to be registered in # SettingDefinition and SettingFunction. @@ -439,7 +441,7 @@ class CuraApplication(QtApplication): "RotateTool", "ScaleTool", "SelectionTool", - "TranslateTool" + "TranslateTool", ]) self._i18n_catalog = i18nCatalog("cura") @@ -986,6 +988,8 @@ class CuraApplication(QtApplication): scene_bounding_box = None is_block_slicing_node = False active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate + + print_information = self.getPrintInformation() for node in DepthFirstIterator(self.getController().getScene().getRoot()): if ( not issubclass(type(node), CuraSceneNode) or @@ -997,6 +1001,11 @@ class CuraApplication(QtApplication): is_block_slicing_node = True count += 1 + + # After clicking the Undo button, if the build plate empty the project name needs to be set + if print_information.baseName == '': + print_information.setBaseName(node.getName()) + if not scene_bounding_box: scene_bounding_box = node.getBoundingBox() else: @@ -1004,7 +1013,7 @@ class CuraApplication(QtApplication): if other_bb is not None: scene_bounding_box = scene_bounding_box + node.getBoundingBox() - print_information = self.getPrintInformation() + if print_information: print_information.setPreSliced(is_block_slicing_node) @@ -1121,39 +1130,6 @@ class CuraApplication(QtApplication): Selection.add(node) - ## Delete all nodes containing mesh data in the scene. - # \param only_selectable. Set this to False to delete objects from all build plates - @pyqtSlot() - def deleteAll(self, only_selectable = True): - Logger.log("i", "Clearing scene") - if not self.getController().getToolsEnabled(): - return - - nodes = [] - for node in DepthFirstIterator(self.getController().getScene().getRoot()): - if not isinstance(node, SceneNode): - continue - if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"): - continue # Node that doesnt have a mesh and is not a group. - if only_selectable and not node.isSelectable(): - continue - if not node.callDecoration("isSliceable") and not node.callDecoration("getLayerData") and not node.callDecoration("isGroup"): - continue # Only remove nodes that are selectable. - if node.getParent() and node.getParent().callDecoration("isGroup"): - continue # Grouped nodes don't need resetting as their parent (the group) is resetted) - nodes.append(node) - if nodes: - op = GroupedOperation() - - for node in nodes: - op.addOperation(RemoveSceneNodeOperation(node)) - - # Reset the print information - self.getController().getScene().sceneChanged.emit(node) - - op.push() - Selection.clear() - ## Reset all translation on nodes with mesh data. @pyqtSlot() def resetAllTranslation(self): diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py index cecdfa4a0d..2b91081e4d 100644 --- a/cura/CuraPackageManager.py +++ b/cura/CuraPackageManager.py @@ -15,12 +15,10 @@ from UM.Logger import Logger from UM.Resources import Resources from UM.Version import Version - class CuraPackageManager(QObject): Version = 1 - # The prefix that's added to all files for an installed package to avoid naming conflicts with user created - # files. + # The prefix that's added to all files for an installed package to avoid naming conflicts with user created files. PREFIX_PLACE_HOLDER = "-CP;" def __init__(self, parent = None): @@ -31,13 +29,21 @@ class CuraPackageManager(QObject): self._plugin_registry = self._application.getPluginRegistry() # JSON file that keeps track of all installed packages. - self._package_management_file_path = os.path.join(os.path.abspath(Resources.getDataStoragePath()), - "packages.json") - self._installed_package_dict = {} # a dict of all installed packages - self._to_remove_package_set = set() # a set of packages that need to be removed at the next start - self._to_install_package_dict = {} # a dict of packages that need to be installed at the next start + self._bundled_package_management_file_path = os.path.join( + os.path.abspath(Resources.getBundledResourcesPath()), + "packages.json" + ) + self._user_package_management_file_path = os.path.join( + os.path.abspath(Resources.getDataStoragePath()), + "packages.json" + ) - installedPackagesChanged = pyqtSignal() # Emitted whenever the installed packages collection have been changed. + self._bundled_package_dict = {} # A dict of all bundled packages + self._installed_package_dict = {} # A dict of all installed packages + self._to_remove_package_set = set() # A set of packages that need to be removed at the next start + self._to_install_package_dict = {} # A dict of packages that need to be installed at the next start + + installedPackagesChanged = pyqtSignal() # Emitted whenever the installed packages collection have been changed. def initialize(self): self._loadManagementData() @@ -46,48 +52,62 @@ class CuraPackageManager(QObject): # (for initialize) Loads the package management file if exists def _loadManagementData(self) -> None: - if not os.path.exists(self._package_management_file_path): - Logger.log("i", "Package management file %s doesn't exist, do nothing", self._package_management_file_path) + # The bundles package management file should always be there + if not os.path.exists(self._bundled_package_management_file_path): + Logger.log("w", "Bundled package management file could not be found!") + return + # Load the bundled packages: + with open(self._bundled_package_management_file_path, "r", encoding = "utf-8") as f: + self._bundled_package_dict = json.load(f, encoding = "utf-8") + Logger.log("i", "Loaded bundled packages data from %s", self._bundled_package_management_file_path) + + # Load the user package management file + if not os.path.exists(self._user_package_management_file_path): + Logger.log("i", "User package management file %s doesn't exist, do nothing", self._user_package_management_file_path) return # Need to use the file lock here to prevent concurrent I/O from other processes/threads container_registry = self._application.getContainerRegistry() with container_registry.lockFile(): - with open(self._package_management_file_path, "r", encoding = "utf-8") as f: - management_dict = json.load(f, encoding = "utf-8") + # Load the user packages: + with open(self._user_package_management_file_path, "r", encoding="utf-8") as f: + management_dict = json.load(f, encoding="utf-8") self._installed_package_dict = management_dict.get("installed", {}) self._to_remove_package_set = set(management_dict.get("to_remove", [])) self._to_install_package_dict = management_dict.get("to_install", {}) - - Logger.log("i", "Package management file %s is loaded", self._package_management_file_path) + Logger.log("i", "Loaded user packages management file from %s", self._user_package_management_file_path) def _saveManagementData(self) -> None: # Need to use the file lock here to prevent concurrent I/O from other processes/threads container_registry = self._application.getContainerRegistry() with container_registry.lockFile(): - with open(self._package_management_file_path, "w", encoding = "utf-8") as f: + with open(self._user_package_management_file_path, "w", encoding = "utf-8") as f: data_dict = {"version": CuraPackageManager.Version, "installed": self._installed_package_dict, "to_remove": list(self._to_remove_package_set), "to_install": self._to_install_package_dict} data_dict["to_remove"] = list(data_dict["to_remove"]) - json.dump(data_dict, f) - Logger.log("i", "Package management file %s is saved", self._package_management_file_path) + json.dump(data_dict, f, sort_keys = True, indent = 4) + Logger.log("i", "Package management file %s was saved", self._user_package_management_file_path) # (for initialize) Removes all packages that have been scheduled to be removed. def _removeAllScheduledPackages(self) -> None: for package_id in self._to_remove_package_set: self._purgePackage(package_id) + del self._installed_package_dict[package_id] self._to_remove_package_set.clear() self._saveManagementData() # (for initialize) Installs all packages that have been scheduled to be installed. def _installAllScheduledPackages(self) -> None: - for package_id, installation_package_data in self._to_install_package_dict.items(): - self._installPackage(installation_package_data) - self._to_install_package_dict.clear() - self._saveManagementData() + + while self._to_install_package_dict: + package_id, package_info = list(self._to_install_package_dict.items())[0] + self._installPackage(package_info) + self._installed_package_dict[package_id] = self._to_install_package_dict[package_id] + del self._to_install_package_dict[package_id] + self._saveManagementData() # Checks the given package is installed. If so, return a dictionary that contains the package's information. def getInstalledPackageInfo(self, package_id: str) -> Optional[dict]: @@ -99,87 +119,66 @@ class CuraPackageManager(QObject): return package_info if package_id in self._installed_package_dict: - package_info = self._installed_package_dict.get(package_id) + package_info = self._installed_package_dict[package_id]["package_info"] return package_info - for section, packages in self.getAllInstalledPackagesInfo().items(): - for package in packages: - if package["package_id"] == package_id: - return package + if package_id in self._bundled_package_dict: + package_info = self._bundled_package_dict[package_id]["package_info"] + return package_info return None def getAllInstalledPackagesInfo(self) -> dict: - installed_package_id_set = set(self._installed_package_dict.keys()) | set(self._to_install_package_dict.keys()) - installed_package_id_set = installed_package_id_set.difference(self._to_remove_package_set) + # Add bundled, installed, and to-install packages to the set of installed package IDs + all_installed_ids = set() - managed_package_id_set = installed_package_id_set | self._to_remove_package_set - - # TODO: For absolutely no reason, this function seems to run in a loop - # even though no loop is ever called with it. + if self._bundled_package_dict.keys(): + all_installed_ids = all_installed_ids.union(set(self._bundled_package_dict.keys())) + if self._installed_package_dict.keys(): + all_installed_ids = all_installed_ids.union(set(self._installed_package_dict.keys())) + if self._to_install_package_dict.keys(): + all_installed_ids = all_installed_ids.union(set(self._to_install_package_dict.keys())) + all_installed_ids = all_installed_ids.difference(self._to_remove_package_set) # map of -> -> installed_packages_dict = {} - for package_id in installed_package_id_set: + for package_id in all_installed_ids: + + # Skip required plugins as they should not be tampered with if package_id in Application.getInstance().getRequiredPlugins(): continue + + package_info = None + # Add bundled plugins + if package_id in self._bundled_package_dict: + package_info = self._bundled_package_dict[package_id]["package_info"] + + # Add installed plugins + if package_id in self._installed_package_dict: + package_info = self._installed_package_dict[package_id]["package_info"] + + # Add to install plugins if package_id in self._to_install_package_dict: package_info = self._to_install_package_dict[package_id]["package_info"] - else: - package_info = self._installed_package_dict[package_id] - package_info["is_bundled"] = False - package_type = package_info["package_type"] - if package_type not in installed_packages_dict: - installed_packages_dict[package_type] = [] - installed_packages_dict[package_type].append( package_info ) + if package_info is None: + continue # We also need to get information from the plugin registry such as if a plugin is active package_info["is_active"] = self._plugin_registry.isActivePlugin(package_id) - # Also get all bundled plugins - all_metadata = self._plugin_registry.getAllMetaData() - for item in all_metadata: - if item == {}: - continue + # If the package ID is in bundled, label it as such + package_info["is_bundled"] = package_info["package_id"] in self._bundled_package_dict.keys() - plugin_package_info = self.__convertPluginMetadataToPackageMetadata(item) - # Only gather the bundled plugins here. - package_id = plugin_package_info["package_id"] - if package_id in managed_package_id_set: - continue - if package_id in Application.getInstance().getRequiredPlugins(): - continue - - plugin_package_info["is_bundled"] = True if plugin_package_info["author"]["display_name"] == "Ultimaker B.V." else False - plugin_package_info["is_active"] = self._plugin_registry.isActivePlugin(package_id) - package_type = "plugin" - if package_type not in installed_packages_dict: - installed_packages_dict[package_type] = [] - installed_packages_dict[package_type].append( plugin_package_info ) + # If there is not a section in the dict for this type, add it + if package_info["package_type"] not in installed_packages_dict: + installed_packages_dict[package_info["package_type"]] = [] + + # Finally, add the data + installed_packages_dict[package_info["package_type"]].append(package_info) return installed_packages_dict - def __convertPluginMetadataToPackageMetadata(self, plugin_metadata: dict) -> dict: - package_metadata = { - "package_id": plugin_metadata["id"], - "package_type": "plugin", - "display_name": plugin_metadata["plugin"]["name"], - "description": plugin_metadata["plugin"].get("description"), - "package_version": plugin_metadata["plugin"]["version"], - "cura_version": int(plugin_metadata["plugin"]["api"]), - "website": "", - "author_id": plugin_metadata["plugin"].get("author", "UnknownID"), - "author": { - "author_id": plugin_metadata["plugin"].get("author", "UnknownID"), - "display_name": plugin_metadata["plugin"].get("author", ""), - "email": "", - "website": "", - }, - "tags": ["plugin"], - } - return package_metadata - # Checks if the given package is installed. def isPackageInstalled(self, package_id: str) -> bool: return self.getInstalledPackageInfo(package_id) is not None @@ -293,7 +292,7 @@ class CuraPackageManager(QObject): from cura.CuraApplication import CuraApplication installation_dirs_dict = { "materials": Resources.getStoragePath(CuraApplication.ResourceTypes.MaterialInstanceContainer), - "quality": Resources.getStoragePath(CuraApplication.ResourceTypes.QualityInstanceContainer), + "qualities": Resources.getStoragePath(CuraApplication.ResourceTypes.QualityInstanceContainer), "plugins": os.path.abspath(Resources.getStoragePath(Resources.Plugins)), } diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index debc765084..650f5fd880 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -14,6 +14,8 @@ from UM.i18n import i18nCatalog from UM.Logger import Logger from UM.Qt.Duration import Duration from UM.Scene.SceneNode import SceneNode +from UM.i18n import i18nCatalog +from UM.MimeTypeDatabase import MimeTypeDatabase catalog = i18nCatalog("cura") @@ -321,7 +323,7 @@ class PrintInformation(QObject): # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its # extension. This cuts the extension off if necessary. - name = os.path.splitext(name)[0] + check_name = os.path.splitext(name)[0] filename_parts = os.path.basename(base_name).split(".") # If it's a gcode, also always update the job name @@ -332,21 +334,21 @@ class PrintInformation(QObject): # if this is a profile file, always update the job name # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again - is_empty = name == "" - if is_gcode or is_project_file or (is_empty or (self._base_name == "" and self._base_name != name)): + is_empty = check_name == "" + if is_gcode or is_project_file or (is_empty or (self._base_name == "" and self._base_name != check_name)): # Only take the file name part, Note : file name might have 'dot' in name as well - if is_project_file: - # This is for .curaproject - self._base_name = ".".join(filename_parts) - elif len(filename_parts) > 1: - if "gcode" in filename_parts: - gcode_index = filename_parts.index('gcode') - self._base_name = ".".join(filename_parts[0:gcode_index]) - else: - self._base_name = name - else: - self._base_name = name + data = '' + try: + mime_type = MimeTypeDatabase.getMimeTypeForFile(name) + data = mime_type.stripExtension(name) + except: + Logger.log("w", "Unsupported Mime Type Database file extension") + + if data is not None: + self._base_name = data + else: + self._base_name = '' self._updateJobName() diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 5fecb7aa17..76f98c5a8a 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -385,7 +385,8 @@ class ExtruderManager(QObject): # Register the extruder trains by position for extruder_train in extruder_trains: - self._extruder_trains[global_stack_id][extruder_train.getMetaDataEntry("position")] = extruder_train + extruder_position = extruder_train.getMetaDataEntry("position") + self._extruder_trains[global_stack_id][extruder_position] = extruder_train # regardless of what the next stack is, we have to set it again, because of signal routing. ??? extruder_train.setParent(global_stack) diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py index 8dcaaf302e..5e944b401f 100644 --- a/cura/Settings/ExtruderStack.py +++ b/cura/Settings/ExtruderStack.py @@ -38,7 +38,7 @@ class ExtruderStack(CuraContainerStack): # # This will set the next stack and ensure that we register this stack as an extruder. @override(ContainerStack) - def setNextStack(self, stack: CuraContainerStack) -> None: + def setNextStack(self, stack: CuraContainerStack, connect_signals: bool = True) -> None: super().setNextStack(stack) stack.addExtruder(self) self.addMetaDataEntry("machine", stack.id) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 5d8a4505a5..f76ac1ab3f 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -125,7 +125,7 @@ class GlobalStack(CuraContainerStack): # # This will simply raise an exception since the Global stack cannot have a next stack. @override(ContainerStack) - def setNextStack(self, next_stack: ContainerStack) -> None: + def setNextStack(self, stack: CuraContainerStack, connect_signals: bool = True) -> None: raise Exceptions.InvalidOperationError("Global stack cannot have a next stack!") # protected: @@ -153,6 +153,23 @@ class GlobalStack(CuraContainerStack): return True + ## Perform some sanity checks on the global stack + # Sanity check for extruders; they must have positions 0 and up to machine_extruder_count - 1 + def isValid(self): + container_registry = ContainerRegistry.getInstance() + extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = self.getId()) + + machine_extruder_count = self.getProperty("machine_extruder_count", "value") + extruder_check_position = set() + for extruder_train in extruder_trains: + extruder_position = extruder_train.getMetaDataEntry("position") + extruder_check_position.add(extruder_position) + + for check_position in range(machine_extruder_count): + if str(check_position) not in extruder_check_position: + return False + return True + ## private: global_stack_mime = MimeType( diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 8943734f3e..68263081ce 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -6,6 +6,7 @@ import time #Type hinting. from typing import List, Dict, TYPE_CHECKING, Optional +from UM.ConfigurationErrorMessage import ConfigurationErrorMessage from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.Interfaces import ContainerInterface @@ -166,8 +167,6 @@ class MachineManager(QObject): if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacksMetadata(id = active_machine_id): # An active machine was saved, so restore it. self.setActiveMachine(active_machine_id) - # Make sure _active_container_stack is properly initiated - ExtruderManager.getInstance().setActiveExtruderIndex(0) def _onOutputDevicesChanged(self) -> None: self._printer_output_devices = [] @@ -358,6 +357,10 @@ class MachineManager(QObject): return global_stack = containers[0] + if not global_stack.isValid(): + # Mark global stack as invalid + ConfigurationErrorMessage.getInstance().addFaultyContainers(global_stack.getId()) + return # We're done here ExtruderManager.getInstance().setActiveExtruderIndex(0) # Switch to first extruder self._global_container_stack = global_stack self._application.setGlobalContainerStack(global_stack) diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 6c2fb9a59d..9eec09b202 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -15,6 +15,7 @@ from UM.Math.Vector import Vector from UM.Mesh.MeshBuilder import MeshBuilder from UM.Mesh.MeshReader import MeshReader from UM.Scene.GroupDecorator import GroupDecorator +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType from cura.Settings.ExtruderManager import ExtruderManager from cura.Scene.CuraSceneNode import CuraSceneNode @@ -25,6 +26,15 @@ from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch MYPY = False + +MimeTypeDatabase.addMimeType( + MimeType( + name = "application/x-cura-project-file", + comment = "Cura Project File", + suffixes = ["curaproject.3mf"] + ) +) + try: if not MYPY: import xml.etree.cElementTree as ET diff --git a/plugins/ChangeLogPlugin/ChangeLog.txt b/plugins/ChangeLogPlugin/ChangeLog.txt index d132f17b5c..9cb9a60e79 100755 --- a/plugins/ChangeLogPlugin/ChangeLog.txt +++ b/plugins/ChangeLogPlugin/ChangeLog.txt @@ -66,8 +66,8 @@ Generate a cube mesh to prevent support material generation in specific areas of *Real bridging - smartavionics New experimental feature that detects bridges, adjusting the print speed, slow and fan speed to enhance print quality on bridging parts. -*Updated CuraEngine executable - thopiekar -The CuraEngine executable now contains a dedicated icon, author information and a license. +*Updated CuraEngine executable - thopiekar & Ultimaker B.V. ❤️ +The CuraEngine executable contains a dedicated icon, author and license info on Windows now. The icon has been designed by Ultimaker B.V. *Use RapidJSON and ClipperLib from system libraries Application updated to use verified copies of libraries, reducing maintenance time keeping them up to date (the operating system is now responsible), as well as reducing the amount of code shipped (as necessary code is already on the user’s system). diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index ceb5fbdb5d..696b3b180b 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from UM.Application import Application @@ -22,12 +22,16 @@ from cura.Settings.ExtruderManager import ExtruderManager import numpy import math import re +from typing import Dict, List, NamedTuple, Optional, Union from collections import namedtuple -# This parser is intented for interpret the common firmware codes among all the different flavors +Position = NamedTuple("Position", [("x", float), ("y", float), ("z", float), ("f", float), ("e", float)]) + +## This parser is intended to interpret the common firmware codes among all the +# different flavors class FlavorParser: - def __init__(self): + def __init__(self) -> None: Application.getInstance().hideMessageSignal.connect(self._onHideMessage) self._cancelled = False self._message = None @@ -44,19 +48,18 @@ class FlavorParser: Application.getInstance().getPreferences().addPreference("gcodereader/show_caution", True) - def _clearValues(self): + def _clearValues(self) -> None: self._extruder_number = 0 self._extrusion_length_offset = [0] self._layer_type = LayerPolygon.Inset0Type self._layer_number = 0 self._previous_z = 0 self._layer_data_builder = LayerDataBuilder.LayerDataBuilder() - self._center_is_zero = False self._is_absolute_positioning = True # It can be absolute (G90) or relative (G91) self._is_absolute_extrusion = True # It can become absolute (M82, default) or relative (M83) @staticmethod - def _getValue(line, code): + def _getValue(line: str, code: str) -> Optional[Union[str, int, float]]: n = line.find(code) if n < 0: return None @@ -71,29 +74,29 @@ class FlavorParser: except: return None - def _getInt(self, line, code): + def _getInt(self, line: str, code: str) -> Optional[int]: value = self._getValue(line, code) try: return int(value) except: return None - def _getFloat(self, line, code): + def _getFloat(self, line: str, code: str) -> Optional[float]: value = self._getValue(line, code) try: return float(value) except: return None - def _onHideMessage(self, message): + def _onHideMessage(self, message: str) -> None: if message == self._message: self._cancelled = True @staticmethod - def _getNullBoundingBox(): + def _getNullBoundingBox() -> AxisAlignedBox: return AxisAlignedBox(minimum=Vector(0, 0, 0), maximum=Vector(10, 10, 10)) - def _createPolygon(self, layer_thickness, path, extruder_offsets): + def _createPolygon(self, layer_thickness: float, path: List[List[Union[float, int]]], extruder_offsets: List[float]) -> bool: countvalid = 0 for point in path: if point[5] > 0: @@ -139,12 +142,12 @@ class FlavorParser: this_layer.polygons.append(this_poly) return True - def _createEmptyLayer(self, layer_number): + def _createEmptyLayer(self, layer_number: int) -> None: self._layer_data_builder.addLayer(layer_number) self._layer_data_builder.setLayerHeight(layer_number, 0) self._layer_data_builder.setLayerThickness(layer_number, 0) - def _calculateLineWidth(self, current_point, previous_point, current_extrusion, previous_extrusion, layer_thickness): + def _calculateLineWidth(self, current_point: Position, previous_point: Position, current_extrusion: float, previous_extrusion: float, layer_thickness: float) -> float: # Area of the filament Af = (self._filament_diameter / 2) ** 2 * numpy.pi # Length of the extruded filament @@ -166,7 +169,7 @@ class FlavorParser: return 0.35 return line_width - def _gCode0(self, position, params, path): + def _gCode0(self, position: Position, params: Position, path: List[List[Union[float, int]]]) -> Position: x, y, z, f, e = position if self._is_absolute_positioning: @@ -202,7 +205,7 @@ class FlavorParser: _gCode1 = _gCode0 ## Home the head. - def _gCode28(self, position, params, path): + def _gCode28(self, position: Position, params: Position, path: List[List[Union[float, int]]]) -> Position: return self._position( params.x if params.x is not None else position.x, params.y if params.y is not None else position.y, @@ -211,20 +214,20 @@ class FlavorParser: position.e) ## Set the absolute positioning - def _gCode90(self, position, params, path): + def _gCode90(self, position: Position, params: Position, path: List[List[Union[float, int]]]) -> Position: self._is_absolute_positioning = True self._is_absolute_extrusion = True return position ## Set the relative positioning - def _gCode91(self, position, params, path): + def _gCode91(self, position: Position, params: Position, path: List[List[Union[float, int]]]) -> Position: self._is_absolute_positioning = False self._is_absolute_extrusion = False return position ## Reset the current position to the values specified. # For example: G92 X10 will set the X to 10 without any physical motion. - def _gCode92(self, position, params, path): + def _gCode92(self, position: Position, params: Position, path: List[List[Union[float, int]]]) -> Position: if params.e is not None: # Sometimes a G92 E0 is introduced in the middle of the GCode so we need to keep those offsets for calculate the line_width self._extrusion_length_offset[self._extruder_number] += position.e[self._extruder_number] - params.e @@ -236,7 +239,7 @@ class FlavorParser: params.f if params.f is not None else position.f, position.e) - def processGCode(self, G, line, position, path): + def processGCode(self, G: int, line: str, position: Position, path: List[List[Union[float, int]]]) -> Position: func = getattr(self, "_gCode%s" % G, None) line = line.split(";", 1)[0] # Remove comments (if any) if func is not None: @@ -257,27 +260,25 @@ class FlavorParser: f = float(item[1:]) / 60 if item[0] == "E": e = float(item[1:]) - if self._is_absolute_positioning and ((x is not None and x < 0) or (y is not None and y < 0)): - self._center_is_zero = True params = self._position(x, y, z, f, e) return func(position, params, path) return position - def processTCode(self, T, line, position, path): + def processTCode(self, T: int, line: str, position: Position, path: List[List[Union[float, int]]]) -> Position: self._extruder_number = T if self._extruder_number + 1 > len(position.e): self._extrusion_length_offset.extend([0] * (self._extruder_number - len(position.e) + 1)) position.e.extend([0] * (self._extruder_number - len(position.e) + 1)) return position - def processMCode(self, M, line, position, path): + def processMCode(self, M: int, line: str, position: Position, path: List[List[Union[float, int]]]) -> Position: pass _type_keyword = ";TYPE:" _layer_keyword = ";LAYER:" ## For showing correct x, y offsets for each extruder - def _extruderOffsets(self): + def _extruderOffsets(self) -> Dict[int, List[float]]: result = {} for extruder in ExtruderManager.getInstance().getExtruderStacks(): result[int(extruder.getMetaData().get("position", "0"))] = [ @@ -285,7 +286,7 @@ class FlavorParser: extruder.getProperty("machine_nozzle_offset_y", "value")] return result - def processGCodeStream(self, stream): + def processGCodeStream(self, stream: str) -> Optional[CuraSceneNode]: Logger.log("d", "Preparing to load GCode") self._cancelled = False # We obtain the filament diameter from the selected extruder to calculate line widths @@ -453,10 +454,9 @@ class FlavorParser: Logger.log("w", "File doesn't contain any valid layers") settings = Application.getInstance().getGlobalContainerStack() - machine_width = settings.getProperty("machine_width", "value") - machine_depth = settings.getProperty("machine_depth", "value") - - if not self._center_is_zero: + if not settings.getProperty("machine_center_is_zero", "value"): + machine_width = settings.getProperty("machine_width", "value") + machine_depth = settings.getProperty("machine_depth", "value") scene_node.setPosition(Vector(-machine_width / 2, 0, machine_depth / 2)) Logger.log("d", "GCode loading finished") diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index b821fa2cb3..a576d6b49f 100755 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -5,10 +5,20 @@ from UM.FileHandler.FileReader import FileReader from UM.Mesh.MeshReader import MeshReader from UM.i18n import i18nCatalog from UM.Application import Application +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType catalog = i18nCatalog("cura") from . import MarlinFlavorParser, RepRapFlavorParser + +MimeTypeDatabase.addMimeType( + MimeType( + name = "application/x-cura-gcode-file", + comment = "Cura GCode File", + suffixes = ["gcode", "gcode.gz"] + ) +) + # Class for loading and parsing G-code files class GCodeReader(MeshReader): diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index f25e249db1..c01d48be4c 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -66,9 +66,9 @@ class GCodeWriter(MeshWriter): active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate scene = Application.getInstance().getController().getScene() - gcode_dict = getattr(scene, "gcode_dict") - if not gcode_dict: + if not hasattr(scene, "gcode_dict"): return False + gcode_dict = getattr(scene, "gcode_dict") gcode_list = gcode_dict.get(active_build_plate, None) if gcode_list is not None: has_settings = False diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index ded59bf934..7d5b317475 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -56,8 +56,6 @@ class MachineSettingsAction(MachineAction): if self._isEmptyDefinitionChanges(definition_changes_id): return - self._container_registry.removeContainer(definition_changes_id) - def _reset(self): if not self._global_container_stack: return diff --git a/plugins/MachineSettingsAction/plugin.json b/plugins/MachineSettingsAction/plugin.json index af63e3a9c8..703a145deb 100644 --- a/plugins/MachineSettingsAction/plugin.json +++ b/plugins/MachineSettingsAction/plugin.json @@ -2,7 +2,7 @@ "name": "Machine Settings action", "author": "fieldOfView", "version": "1.0.0", - "description": "Provides a way to change machine settings (such as build volume, nozzle size, etc)", + "description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).", "api": 4, "i18n-catalog": "cura" } diff --git a/plugins/Toolbox/resources/qml/Toolbox.qml b/plugins/Toolbox/resources/qml/Toolbox.qml index cdbe2f0710..2a56898503 100644 --- a/plugins/Toolbox/resources/qml/Toolbox.qml +++ b/plugins/Toolbox/resources/qml/Toolbox.qml @@ -12,11 +12,14 @@ Window property var selection: null title: catalog.i18nc("@title", "Toolbox") modality: Qt.ApplicationModal + flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint + width: 720 * screenScaleFactor height: 640 * screenScaleFactor - minimumWidth: 720 * screenScaleFactor - maximumWidth: 720 * screenScaleFactor - minimumHeight: 350 * screenScaleFactor + minimumWidth: width + maximumWidth: minimumWidth + minimumHeight: height + maximumHeight: minimumHeight color: UM.Theme.getColor("sidebar") UM.I18nCatalog { @@ -76,7 +79,7 @@ Window { id: footer visible: toolbox.restartRequired - height: toolbox.restartRequired ? UM.Theme.getSize("toolbox_footer").height : 0 + height: visible ? UM.Theme.getSize("toolbox_footer").height : 0 } // TODO: Clean this up: Connections diff --git a/plugins/Toolbox/resources/qml/ToolboxActionButtonStyle.qml b/plugins/Toolbox/resources/qml/ToolboxActionButtonStyle.qml new file mode 100644 index 0000000000..eff74278c9 --- /dev/null +++ b/plugins/Toolbox/resources/qml/ToolboxActionButtonStyle.qml @@ -0,0 +1,29 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Toolbox is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import UM 1.1 as UM + +ButtonStyle +{ + background: Rectangle + { + implicitWidth: UM.Theme.getSize("toolbox_action_button").width + implicitHeight: UM.Theme.getSize("toolbox_action_button").height + color: "transparent" + border + { + width: UM.Theme.getSize("default_lining").width + color: UM.Theme.getColor("lining") + } + } + label: Label + { + text: control.text + color: UM.Theme.getColor("text") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } +} \ No newline at end of file diff --git a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml index 6c87f9d2e2..04b055ed66 100644 --- a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.3 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -9,7 +9,7 @@ import UM 1.1 as UM Item { id: page - property var details: base.selection + property var details: base.selection || {} anchors.fill: parent ToolboxBackColumn { @@ -32,6 +32,7 @@ Item height: UM.Theme.getSize("toolbox_thumbnail_medium").height fillMode: Image.PreserveAspectFit source: details.icon_url || "../images/logobot.svg" + mipmap: true anchors { top: parent.top @@ -53,7 +54,7 @@ Item rightMargin: UM.Theme.getSize("wide_margin").width bottomMargin: UM.Theme.getSize("default_margin").height } - text: details.name + text: details.name || "" font: UM.Theme.getFont("large") wrapMode: Text.WordWrap width: parent.width @@ -62,7 +63,7 @@ Item Label { id: description - text: details.description + text: details.description || "" anchors { top: title.bottom @@ -114,6 +115,7 @@ Item } font: UM.Theme.getFont("very_small") color: UM.Theme.getColor("text") + linkColor: UM.Theme.getColor("text_link") onLinkActivated: Qt.openUrlExternally(link) } } diff --git a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml index 1c58b46b96..229ab5afb3 100644 --- a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml +++ b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml @@ -8,6 +8,7 @@ import UM 1.1 as UM Item { + property var packageData anchors.topMargin: UM.Theme.getSize("default_margin").height height: visible ? childrenRect.height : 0 visible: packageData.type == "material" && packageData.has_configs @@ -36,8 +37,8 @@ Item Label { anchors.verticalCenter: parent.verticalCenter - elide: styleData.elideMode - text: styleData.value + elide: Text.ElideRight + text: styleData.value || "" color: UM.Theme.getColor("text") font: UM.Theme.getFont("default_bold") } @@ -55,8 +56,8 @@ Item Label { anchors.verticalCenter: parent.verticalCenter - elide: styleData.elideMode - text: styleData.value + elide: Text.ElideRight + text: styleData.value || "" color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("default") } @@ -67,8 +68,8 @@ Item Label { anchors.verticalCenter: parent.verticalCenter - elide: styleData.elideMode - text: styleData.value + elide: Text.ElideRight + text: styleData.value || "" color: UM.Theme.getColor("text_medium") font: UM.Theme.getFont("default") } diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml index 920065ca9d..120a422b53 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.3 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -33,6 +33,7 @@ Item height: UM.Theme.getSize("toolbox_thumbnail_medium").height fillMode: Image.PreserveAspectFit source: details.icon_url || "../images/logobot.svg" + mipmap: true anchors { top: parent.top @@ -54,8 +55,9 @@ Item rightMargin: UM.Theme.getSize("wide_margin").width bottomMargin: UM.Theme.getSize("default_margin").height } - text: details.name + text: details.name || "" font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") wrapMode: Text.WordWrap width: parent.width height: UM.Theme.getSize("toolbox_property_label").height @@ -113,7 +115,7 @@ Item text: { var date = new Date(details.last_updated) - return date.toLocaleString(Qt.locale()) + return date.toLocaleString(UM.Preferences.getValue("general/language")) } font: UM.Theme.getFont("very_small") color: UM.Theme.getColor("text") @@ -133,6 +135,7 @@ Item } font: UM.Theme.getFont("very_small") color: UM.Theme.getColor("text") + linkColor: UM.Theme.getColor("text_link") onLinkActivated: Qt.openUrlExternally(link) } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml index b2b41d30ea..80d50616e8 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml @@ -10,9 +10,8 @@ Item { id: tile property bool installed: toolbox.isInstalled(model.id) - property var packageData: model width: detailList.width - UM.Theme.getSize("wide_margin").width - height: Math.max(UM.Theme.getSize("toolbox_detail_tile").height, childrenRect.height + UM.Theme.getSize("default_margin").height) + height: normalData.height + compatibilityChart.height + 4 * UM.Theme.getSize("default_margin").height Item { id: normalData @@ -46,6 +45,7 @@ Item font: UM.Theme.getFont("default") } } + Item { id: controls @@ -76,58 +76,9 @@ Item } enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model) //Don't allow installing while another download is running. opacity: enabled ? 1.0 : 0.5 - style: ButtonStyle - { - background: Rectangle - { - implicitWidth: 96 - implicitHeight: 30 - color: - { - if (installed) - { - return UM.Theme.getColor("action_button_disabled") - } - else - { - if ( control.hovered ) - { - return UM.Theme.getColor("primary_hover") - } - else - { - return UM.Theme.getColor("primary") - } - } - } - } - label: Label - { - text: control.text - color: - { - if (installed) - { - return UM.Theme.getColor("action_button_disabled_text") - } - else - { - if ( control.hovered ) - { - return UM.Theme.getColor("button_text_hover") - } - else - { - return UM.Theme.getColor("button_text") - } - } - } - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - font: UM.Theme.getFont("default_bold") - } - } + property alias installed: tile.installed + style: UM.Theme.styles.toolbox_action_button onClicked: { if (installed) @@ -164,6 +115,7 @@ Item id: compatibilityChart anchors.top: normalData.bottom width: normalData.width + packageData: model } Rectangle diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml index 12578d15f6..5b9697eda2 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml @@ -9,9 +9,7 @@ import UM 1.1 as UM Column { - // HACK: GridLayouts don't render to the correct height with odd numbers of - // items, so if odd, add some extra space. - height: grid.model.items.length % 2 == 0 ? childrenRect.height : childrenRect.height + UM.Theme.getSize("toolbox_thumbnail_small").height + height: childrenRect.height width: parent.width spacing: UM.Theme.getSize("default_margin").height Label @@ -36,6 +34,7 @@ Column delegate: ToolboxDownloadsGridTile { Layout.preferredWidth: (grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns + Layout.preferredHeight: UM.Theme.getSize("toolbox_thumbnail_small").height } } } diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml index e0e25982db..17b28fe136 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.3 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 @@ -34,10 +34,11 @@ Item Image { anchors.centerIn: parent - width: UM.Theme.getSize("toolbox_thumbnail_small").width - 26 - height: UM.Theme.getSize("toolbox_thumbnail_small").height - 26 + width: UM.Theme.getSize("toolbox_thumbnail_small").width - UM.Theme.getSize("wide_margin").width + height: UM.Theme.getSize("toolbox_thumbnail_small").height - UM.Theme.getSize("wide_margin").width fillMode: Image.PreserveAspectFit source: model.icon_url || "../images/logobot.svg" + mipmap: true } } Column diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml index a699e9dae6..f665404df7 100644 --- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml @@ -1,7 +1,7 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.3 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM @@ -9,7 +9,7 @@ import UM 1.1 as UM Item { width: UM.Theme.getSize("toolbox_thumbnail_large").width - height: childrenRect.height + height: thumbnail.height + packageName.height Rectangle { id: highlight @@ -40,14 +40,16 @@ Item height: UM.Theme.getSize("toolbox_thumbnail_large").height - 2 * UM.Theme.getSize("default_margin").height fillMode: Image.PreserveAspectFit source: model.icon_url || "../images/logobot.svg" + mipmap: true } } Label { + id: packageName text: model.name anchors { - bottom: parent.bottom + top: thumbnail.bottom horizontalCenter: parent.horizontalCenter } verticalAlignment: Text.AlignVCenter diff --git a/plugins/Toolbox/resources/qml/ToolboxFooter.qml b/plugins/Toolbox/resources/qml/ToolboxFooter.qml index 098a52d49a..980ac5f8c9 100644 --- a/plugins/Toolbox/resources/qml/ToolboxFooter.qml +++ b/plugins/Toolbox/resources/qml/ToolboxFooter.qml @@ -14,8 +14,7 @@ Item height: visible ? Math.floor(UM.Theme.getSize("toolbox_footer").height) : 0 Label { - visible: toolbox.restartRequired - text: catalog.i18nc("@info", "You will need to restart Cura before changes in plugins have effect.") + text: catalog.i18nc("@info", "You will need to restart Cura before changes in packages have effect.") height: Math.floor(UM.Theme.getSize("toolbox_footer_button").height) verticalAlignment: Text.AlignVCenter anchors @@ -38,7 +37,6 @@ Item right: parent.right rightMargin: UM.Theme.getSize("wide_margin").width } - visible: toolbox.restartRequired iconName: "dialog-restart" onClicked: toolbox.restart() style: ButtonStyle @@ -49,7 +47,7 @@ Item implicitHeight: Math.floor(UM.Theme.getSize("toolbox_footer_button").height) color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary") } - label: Text + label: Label { color: UM.Theme.getColor("button_text") font: UM.Theme.getFont("default_bold") @@ -61,7 +59,7 @@ Item } ToolboxShadow { - visible: toolbox.restartRequired + visible: footer.visible anchors.bottom: footer.top reversed: true } diff --git a/plugins/Toolbox/resources/qml/ToolboxHeader.qml b/plugins/Toolbox/resources/qml/ToolboxHeader.qml index 59dbe23ea4..88495e3f63 100644 --- a/plugins/Toolbox/resources/qml/ToolboxHeader.qml +++ b/plugins/Toolbox/resources/qml/ToolboxHeader.qml @@ -24,7 +24,8 @@ Item ToolboxTabButton { text: catalog.i18nc("@title:tab", "Plugins") - active: toolbox.viewCategory == "plugin" + active: toolbox.viewCategory == "plugin" && enabled + enabled: toolbox.viewPage != "loading" && toolbox.viewPage != "errored" onClicked: { toolbox.filterModelByProp("packages", "type", "plugin") @@ -35,7 +36,8 @@ Item ToolboxTabButton { text: catalog.i18nc("@title:tab", "Materials") - active: toolbox.viewCategory == "material" + active: toolbox.viewCategory == "material" && enabled + enabled: toolbox.viewPage != "loading" && toolbox.viewPage != "errored" onClicked: { toolbox.filterModelByProp("authors", "package_types", "material") diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml index ff27e004b2..6004832a57 100644 --- a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml @@ -1,21 +1,18 @@ // Copyright (c) 2018 Ultimaker B.V. // Toolbox is released under the terms of the LGPLv3 or higher. -import QtQuick 2.2 +import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM Item { + height: UM.Theme.getSize("toolbox_installed_tile").height + width: parent.width property bool canUpdate: false property bool isEnabled: true - height: UM.Theme.getSize("toolbox_installed_tile").height - anchors - { - left: parent.left - right: parent.right - } + Rectangle { color: UM.Theme.getColor("lining") @@ -23,197 +20,86 @@ Item height: UM.Theme.getSize("default_lining").height anchors.bottom: parent.bottom } - Column + Row { - id: pluginInfo - property var color: isEnabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining") + id: tileRow height: parent.height - anchors + width: parent.width + spacing: UM.Theme.getSize("default_margin").width + topPadding: UM.Theme.getSize("default_margin").height + + CheckBox { - left: parent.left - top: parent.top - right: authorInfo.left - topMargin: UM.Theme.getSize("default_margin").height - rightMargin: UM.Theme.getSize("default_margin").width - } - Label - { - text: model.name - width: parent.width - height: UM.Theme.getSize("toolbox_property_label").height - wrapMode: Text.WordWrap - verticalAlignment: Text.AlignVCenter - font: UM.Theme.getFont("default_bold") - color: pluginInfo.color - } - Text - { - text: model.description - width: parent.width - height: UM.Theme.getSize("toolbox_property_label").height - clip: true - wrapMode: Text.WordWrap - color: pluginInfo.color - elide: Text.ElideRight - } - } - Column - { - id: authorInfo - height: parent.height - width: Math.floor(UM.Theme.getSize("toolbox_action_button").width * 1.25) - anchors - { - top: parent.top - topMargin: UM.Theme.getSize("default_margin").height - right: pluginActions.left - rightMargin: UM.Theme.getSize("default_margin").width - } - Label - { - text: - { - if (model.author_email) - { - return "" + model.author_name + "" - } - else - { - return model.author_name - } - } - width: parent.width - height: UM.Theme.getSize("toolbox_property_label").height - wrapMode: Text.WordWrap - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignLeft - onLinkActivated: Qt.openUrlExternally("mailto:" + model.author_email + "?Subject=Cura: " + model.name + " Plugin") - color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining") - } - } - Column - { - id: pluginActions - width: childrenRect.width - height: childrenRect.height - spacing: UM.Theme.getSize("default_margin").height - anchors - { - top: parent.top - right: parent.right - topMargin: UM.Theme.getSize("default_margin").height - } - Button { - id: removeButton - text: - { - if (model.is_bundled) - { - return isEnabled ? catalog.i18nc("@action:button", "Disable") : catalog.i18nc("@action:button", "Enable") - } - else - { - return catalog.i18nc("@action:button", "Uninstall") - } - } + id: disableButton + checked: isEnabled + visible: model.type == "plugin" + width: visible ? UM.Theme.getSize("checkbox").width : 0 enabled: !toolbox.isDownloading - style: ButtonStyle + style: UM.Theme.styles.checkbox + onClicked: toolbox.isEnabled(model.id) ? toolbox.disable(model.id) : toolbox.enable(model.id) + } + Column + { + id: pluginInfo + topPadding: UM.Theme.getSize("default_margin").height / 2 + property var color: model.type === "plugin" && !isEnabled ? UM.Theme.getColor("lining") : UM.Theme.getColor("text") + width: tileRow.width - (authorInfo.width + pluginActions.width + 2 * tileRow.spacing + ((disableButton.visible) ? disableButton.width + tileRow.spacing : 0)) + Label { - background: Rectangle - { - implicitWidth: UM.Theme.getSize("toolbox_action_button").width - implicitHeight: UM.Theme.getSize("toolbox_action_button").height - color: "transparent" - border - { - width: UM.Theme.getSize("default_lining").width - color: UM.Theme.getColor("lining") - } - } - label: Text - { - text: control.text - color: UM.Theme.getColor("text") - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } + text: model.name + width: parent.width + height: UM.Theme.getSize("toolbox_property_label").height + wrapMode: Text.WordWrap + font: UM.Theme.getFont("default_bold") + color: pluginInfo.color } - onClicked: + Label { - if (model.is_bundled) + text: model.description + maximumLineCount: 3 + elide: Text.ElideRight + width: parent.width + wrapMode: Text.WordWrap + color: pluginInfo.color + } + } + Column + { + id: authorInfo + width: Math.floor(UM.Theme.getSize("toolbox_action_button").width * 1.25) + + Label + { + text: { - if (toolbox.isEnabled(model.id)) + if (model.author_email) { - toolbox.disable(model.id) + return "" + model.author_name + "" } else { - toolbox.enable(model.id) + return model.author_name } } - else - { - toolbox.uninstall(model.id) - } + width: parent.width + height: UM.Theme.getSize("toolbox_property_label").height + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + onLinkActivated: Qt.openUrlExternally("mailto:" + model.author_email + "?Subject=Cura: " + model.name + " Plugin") + color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining") + linkColor: UM.Theme.getColor("text_link") } } - Button + ToolboxInstalledTileActions { - id: updateButton - text: catalog.i18nc("@action:button", "Update") - visible: canUpdate - style: ButtonStyle - { - background: Rectangle - { - implicitWidth: UM.Theme.getSize("toolbox_action_button").width - implicitHeight: UM.Theme.getSize("toolbox_action_button").height - color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary") - } - label: Label - { - text: control.text - color: control.hovered ? UM.Theme.getColor("button_text") : UM.Theme.getColor("button_text_hover") - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - font: UM.Theme.getFont("default_bold") - } - } - onClicked: - { - toolbox.update(model.id); - } + id: pluginActions } - ProgressBar + Connections { - id: progressbar - anchors - { - left: updateButton.left - right: updateButton.right - top: updateButton.bottom - topMargin: Math.floor(UM.Theme.getSize("default_margin") / 4) - } - value: toolbox.isDownloading ? toolbox.downloadProgress : 0 - visible: toolbox.isDownloading - style: ProgressBarStyle - { - background: Rectangle - { - color: UM.Theme.getColor("lining") - implicitHeight: Math.floor(UM.Theme.getSize("toolbox_progress_bar").height) - } - progress: Rectangle - { - color: UM.Theme.getColor("primary") - } - } + target: toolbox + onEnabledChanged: isEnabled = toolbox.isEnabled(model.id) + onMetadataChanged: canUpdate = toolbox.canUpdate(model.id) } } - Connections - { - target: toolbox - onEnabledChanged: isEnabled = toolbox.isEnabled(model.id) - onMetadataChanged: canUpdate = toolbox.canUpdate(model.id) - } -} +} \ No newline at end of file diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml new file mode 100644 index 0000000000..1921bcb58e --- /dev/null +++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml @@ -0,0 +1,93 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Toolbox is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import UM 1.1 as UM + +Column +{ + width: UM.Theme.getSize("toolbox_action_button").width + spacing: UM.Theme.getSize("narrow_margin").height + + Item + { + width: parent.width + height: childrenRect.height + visible: canUpdate + Button + { + id: updateButton + text: catalog.i18nc("@action:button", "Update") + style: ButtonStyle + { + background: Rectangle + { + implicitWidth: UM.Theme.getSize("toolbox_action_button").width + implicitHeight: UM.Theme.getSize("toolbox_action_button").height + color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary") + } + label: Label + { + text: control.text + color: control.hovered ? UM.Theme.getColor("button_text") : UM.Theme.getColor("button_text_hover") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + font: UM.Theme.getFont("default_bold") + } + } + onClicked: toolbox.update(model.id) + } + ProgressBar + { + id: progressbar + width: parent.width + value: toolbox.isDownloading ? toolbox.downloadProgress : 0 + visible: toolbox.isDownloading + style: ProgressBarStyle + { + background: Rectangle + { + color: "transparent" + implicitHeight: UM.Theme.getSize("toolbox_action_button").height + } + progress: Rectangle + { + // TODO Define a good color that fits the purpuse + color: "blue" + opacity: 0.5 + } + } + } + } + Button + { + id: removeButton + text: catalog.i18nc("@action:button", "Uninstall") + visible: !model.is_bundled + enabled: !toolbox.isDownloading + style: ButtonStyle + { + background: Rectangle + { + implicitWidth: UM.Theme.getSize("toolbox_action_button").width + implicitHeight: UM.Theme.getSize("toolbox_action_button").height + color: "transparent" + border + { + width: UM.Theme.getSize("default_lining").width + color: UM.Theme.getColor("lining") + } + } + label: Label + { + text: control.text + color: UM.Theme.getColor("text") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + onClicked: toolbox.uninstall(model.id) + } +} \ No newline at end of file diff --git a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml b/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml index 33bc466d29..b8baf7bc83 100644 --- a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml +++ b/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml @@ -42,7 +42,7 @@ UM.Dialog anchors.right: parent.right anchors.topMargin: UM.Theme.getSize("default_margin").height readOnly: true - text: licenseDialog.licenseContent + text: licenseDialog.licenseContent || "" } } rightButtons: diff --git a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml index a61e77d241..22fb6d73ca 100644 --- a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml +++ b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml @@ -25,7 +25,7 @@ Button height: UM.Theme.getSize("sidebar_header_highlight").height } } - label: Text + label: Label { text: control.text color: @@ -43,7 +43,7 @@ Button return UM.Theme.getColor("topbar_button_text_inactive"); } } - font: control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium") + font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic") verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter } diff --git a/plugins/Toolbox/src/PackagesModel.py b/plugins/Toolbox/src/PackagesModel.py index 611d24af9d..5ec3eba1d8 100644 --- a/plugins/Toolbox/src/PackagesModel.py +++ b/plugins/Toolbox/src/PackagesModel.py @@ -28,8 +28,9 @@ class PackagesModel(ListModel): self.addRoleName(Qt.UserRole + 11, "download_url") self.addRoleName(Qt.UserRole + 12, "last_updated") self.addRoleName(Qt.UserRole + 13, "is_bundled") - self.addRoleName(Qt.UserRole + 14, "has_configs") - self.addRoleName(Qt.UserRole + 15, "supported_configs") + self.addRoleName(Qt.UserRole + 14, "is_enabled") + self.addRoleName(Qt.UserRole + 15, "has_configs") + self.addRoleName(Qt.UserRole + 16, "supported_configs") # List of filters for queries. The result is the union of the each list of results. self._filter = {} # type: Dict[str, str] @@ -52,20 +53,26 @@ class PackagesModel(ListModel): configs_model = ConfigsModel() configs_model.setConfigs(package["data"]["supported_configs"]) + if "author_id" not in package["author"] or "display_name" not in package["author"]: + package["author"]["author_id"] = "" + package["author"]["display_name"] = "" + # raise Exception("Detected a package with malformed author data.") + items.append({ "id": package["package_id"], "type": package["package_type"], "name": package["display_name"], "version": package["package_version"], - "author_id": package["author"]["author_id"] if "author_id" in package["author"] else package["author"]["name"], - "author_name": package["author"]["display_name"] if "display_name" in package["author"] else package["author"]["name"], - "author_email": package["author"]["email"] if "email" in package["author"] else "None", - "description": package["description"], + "author_id": package["author"]["author_id"], + "author_name": package["author"]["display_name"], + "author_email": package["author"]["email"] if "email" in package["author"] else None, + "description": package["description"] if "description" in package else None, "icon_url": package["icon_url"] if "icon_url" in package else None, "image_urls": package["image_urls"] if "image_urls" in package else None, "download_url": package["download_url"] if "download_url" in package else None, "last_updated": package["last_updated"] if "last_updated" in package else None, "is_bundled": package["is_bundled"] if "is_bundled" in package else False, + "is_enabled": package["is_enabled"] if "is_enabled" in package else False, "has_configs": has_configs, "supported_configs": configs_model }) diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 2f6f39d005..3ee6787cf4 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -13,19 +13,17 @@ from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkRepl from UM.Application import Application from UM.Logger import Logger from UM.PluginRegistry import PluginRegistry -from UM.Qt.Bindings.PluginsModel import PluginsModel from UM.Extension import Extension from UM.i18n import i18nCatalog from UM.Version import Version +import cura from cura.CuraApplication import CuraApplication from .AuthorsModel import AuthorsModel from .PackagesModel import PackagesModel -from .ConfigsModel import ConfigsModel i18n_catalog = i18nCatalog("cura") - ## The Toolbox class is responsible of communicating with the server through the API class Toolbox(QObject, Extension): def __init__(self, parent=None) -> None: @@ -34,7 +32,7 @@ class Toolbox(QObject, Extension): self._application = Application.getInstance() self._package_manager = None self._plugin_registry = Application.getInstance().getPluginRegistry() - self._packages_version = self._plugin_registry.APIVersion + self._packages_version = self._getPackagesVersion() self._api_version = 1 self._api_url = "https://api-staging.ultimaker.com/cura-packages/v{api_version}/cura/v{package_version}".format( api_version = self._api_version, package_version = self._packages_version) @@ -66,22 +64,22 @@ class Toolbox(QObject, Extension): # Data: self._metadata = { - "authors": [], - "packages": [], - "plugins_showcase": [], - "plugins_installed": [], - "materials_showcase": [], + "authors": [], + "packages": [], + "plugins_showcase": [], + "plugins_installed": [], + "materials_showcase": [], "materials_installed": [] } # Models: self._models = { - "authors": AuthorsModel(self), - "packages": PackagesModel(self), - "plugins_showcase": PackagesModel(self), - "plugins_available": PackagesModel(self), - "plugins_installed": PackagesModel(self), - "materials_showcase": AuthorsModel(self), + "authors": AuthorsModel(self), + "packages": PackagesModel(self), + "plugins_showcase": PackagesModel(self), + "plugins_available": PackagesModel(self), + "plugins_installed": PackagesModel(self), + "materials_showcase": AuthorsModel(self), "materials_available": PackagesModel(self), "materials_installed": PackagesModel(self) } @@ -154,6 +152,13 @@ class Toolbox(QObject, Extension): def _onAppInitialized(self) -> None: self._package_manager = Application.getInstance().getCuraPackageManager() + def _getPackagesVersion(self) -> int: + if not hasattr(cura, "CuraVersion"): + return self._plugin_registry.APIVersion + if not hasattr(cura.CuraVersion, "CuraPackagesVersion"): + return self._plugin_registry.APIVersion + return cura.CuraVersion.CuraPackagesVersion + @pyqtSlot() def browsePackages(self) -> None: # Create the network manager: @@ -244,7 +249,6 @@ class Toolbox(QObject, Extension): @pyqtSlot() def restart(self): - self._package_manager._removeAllScheduledPackages() CuraApplication.getInstance().windowClosed() # Checks @@ -326,8 +330,8 @@ class Toolbox(QObject, Extension): # Handlers for Network Events # -------------------------------------------------------------------------- - def _onNetworkAccessibleChanged(self, accessible: int) -> None: - if accessible == 0: + def _onNetworkAccessibleChanged(self, network_accessibility: QNetworkAccessManager.NetworkAccessibility) -> None: + if network_accessibility == QNetworkAccessManager.NotAccessible: self.resetDownload() def _onRequestFinished(self, reply: QNetworkReply) -> None: @@ -347,50 +351,55 @@ class Toolbox(QObject, Extension): if reply.operation() == QNetworkAccessManager.GetOperation: for type, url in self._request_urls.items(): if reply.url() == url: - try: - json_data = json.loads(bytes(reply.readAll()).decode("utf-8")) + if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200: + try: + json_data = json.loads(bytes(reply.readAll()).decode("utf-8")) + + # Check for errors: + if "errors" in json_data: + for error in json_data["errors"]: + Logger.log("e", "%s", error["title"]) + return + + # Create model and apply metadata: + if not self._models[type]: + Logger.log("e", "Could not find the %s model.", type) + break + + # HACK: Eventually get rid of the code from here... + if type is "plugins_showcase" or type is "materials_showcase": + self._metadata["plugins_showcase"] = json_data["data"]["plugin"]["packages"] + self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"]) + self._metadata["materials_showcase"] = json_data["data"]["material"]["authors"] + self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"]) + else: + # ...until here. + # This hack arises for multiple reasons but the main + # one is because there are not separate API calls + # for different kinds of showcases. + self._metadata[type] = json_data["data"] + self._models[type].setMetadata(self._metadata[type]) + + # Do some auto filtering + # TODO: Make multiple API calls in the future to handle this + if type is "packages": + self._models[type].setFilter({"type": "plugin"}) + if type is "authors": + self._models[type].setFilter({"package_types": "material"}) + + self.metadataChanged.emit() + + if self.loadingComplete() is True: + self.setViewPage("overview") - # Check for errors: - if "errors" in json_data: - for error in json_data["errors"]: - Logger.log("e", "%s", error["title"]) return - - # Create model and apply metadata: - if not self._models[type]: - Logger.log("e", "Could not find the %s model.", type) + except json.decoder.JSONDecodeError: + Logger.log("w", "Toolbox: Received invalid JSON for %s.", type) break - - # HACK: Eventually get rid of the code from here... - if type is "plugins_showcase" or type is "materials_showcase": - self._metadata["plugins_showcase"] = json_data["data"]["plugin"]["packages"] - self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"]) - self._metadata["materials_showcase"] = json_data["data"]["material"]["authors"] - self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"]) - else: - # ...until here. - # This hack arises for multiple reasons but the main - # one is because there are not separate API calls - # for different kinds of showcases. - self._metadata[type] = json_data["data"] - self._models[type].setMetadata(self._metadata[type]) - - # Do some auto filtering - # TODO: Make multiple API calls in the future to handle this - if type is "packages": - self._models[type].setFilter({"type": "plugin"}) - if type is "authors": - self._models[type].setFilter({"package_types": "material"}) - - self.metadataChanged.emit() - - if self.loadingComplete() is True: - self.setViewPage("overview") - + else: + self.setViewPage("errored") + self.resetDownload() return - except json.decoder.JSONDecodeError: - Logger.log("w", "Toolbox: Received invalid JSON for %s.", type) - break else: # Ignore any operation that is not a get operation @@ -403,7 +412,7 @@ class Toolbox(QObject, Extension): if bytes_sent == bytes_total: self.setIsDownloading(False) self._download_reply.downloadProgress.disconnect(self._onDownloadProgress) - # Optional[Dict[str, Any]]: return self._active_package diff --git a/plugins/UFPWriter/__init__.py b/plugins/UFPWriter/__init__.py index 9db6b042f8..a2ec99044f 100644 --- a/plugins/UFPWriter/__init__.py +++ b/plugins/UFPWriter/__init__.py @@ -11,6 +11,16 @@ except ImportError: from UM.i18n import i18nCatalog #To translate the file format description. from UM.Mesh.MeshWriter import MeshWriter #For the binary mode flag. +from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType + + +MimeTypeDatabase.addMimeType( + MimeType( + name = "application/x-cura-stl-file", + comment = "Cura UFP File", + suffixes = ["ufp"] + ) +) i18n_catalog = i18nCatalog("cura") diff --git a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py index ac011a5557..e53dc3e467 100644 --- a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py @@ -188,14 +188,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): b"name": system_info["name"].encode("utf-8"), b"address": address.encode("utf-8"), b"firmware_version": system_info["firmware"].encode("utf-8"), - b"manual": b"true" + b"manual": b"true", + b"machine": str(system_info['hardware']["typeid"]).encode("utf-8") } - if "hardware" in system_info and 'typeid' in system_info["hardware"]: - properties[b"machine"] = str(system_info['hardware']["typeid"]).encode("utf-8") - else: - properties[b"machine"] = system_info["variant"].encode("utf-8") - if has_cluster_capable_firmware: # Cluster needs an additional request, before it's completed. properties[b"incomplete"] = b"true" diff --git a/plugins/UM3NetworkPrinting/plugin.json b/plugins/UM3NetworkPrinting/plugin.json index 5a845a0516..e7b59fadd6 100644 --- a/plugins/UM3NetworkPrinting/plugin.json +++ b/plugins/UM3NetworkPrinting/plugin.json @@ -1,7 +1,7 @@ { "name": "UM3 Network Connection", "author": "Ultimaker B.V.", - "description": "Manages network connections to Ultimaker 3 printers", + "description": "Manages network connections to Ultimaker 3 printers.", "version": "1.0.0", "api": 4, "i18n-catalog": "cura" diff --git a/plugins/UltimakerMachineActions/plugin.json b/plugins/UltimakerMachineActions/plugin.json index c9bb1a89e4..57b3e6bc8f 100644 --- a/plugins/UltimakerMachineActions/plugin.json +++ b/plugins/UltimakerMachineActions/plugin.json @@ -2,7 +2,7 @@ "name": "Ultimaker machine actions", "author": "Ultimaker B.V.", "version": "1.0.0", - "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc)", + "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).", "api": 4, "i18n-catalog": "cura" } diff --git a/plugins/UserAgreement/plugin.json b/plugins/UserAgreement/plugin.json index aa5dbb1258..b10abc5640 100644 --- a/plugins/UserAgreement/plugin.json +++ b/plugins/UserAgreement/plugin.json @@ -2,7 +2,7 @@ "name": "UserAgreement", "author": "Ultimaker B.V.", "version": "1.0.0", - "description": "Ask the user once if he/she agrees with our license", + "description": "Ask the user once if he/she agrees with our license.", "api": 4, "i18n-catalog": "cura" } diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e3bcda9f95..7e726c5c60 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -227,6 +227,7 @@ { "label": "Outer nozzle diameter", "description": "The outer diameter of the tip of the nozzle.", + "unit": "mm", "default_value": 1, "type": "float", "settable_per_mesh": false, @@ -238,6 +239,7 @@ { "label": "Nozzle length", "description": "The height difference between the tip of the nozzle and the lowest part of the print head.", + "unit": "mm", "default_value": 3, "type": "float", "settable_per_mesh": false, @@ -261,6 +263,7 @@ { "label": "Heat zone length", "description": "The distance from the tip of the nozzle in which heat from the nozzle is transferred to the filament.", + "unit": "mm", "default_value": 16, "type": "float", "settable_per_mesh": false, @@ -271,6 +274,7 @@ { "label": "Filament Park Distance", "description": "The distance from the tip of the nozzle where to park the filament when an extruder is no longer used.", + "unit": "mm", "default_value": 16, "value": "machine_heat_zone_length", "type": "float", diff --git a/resources/definitions/printrbot_simple.def.json b/resources/definitions/printrbot_simple.def.json index 7c86617ce5..e56a9d8647 100644 --- a/resources/definitions/printrbot_simple.def.json +++ b/resources/definitions/printrbot_simple.def.json @@ -32,7 +32,7 @@ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;home X/Y\nG28 Z0 ;home Z\nG92 E0 ;zero the extruded length\nG29 ;initiate auto bed leveling sequence\nG92 X132.4 Y20 ;correct bed origin (G29 changes it)" + "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;home X/Y\nG28 Z0 ;home Z\nG92 E0 ;zero the extruded length\nG29 ;initiate auto bed leveling sequence" }, "machine_end_gcode": { "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM106 S0 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit\nG1 Z+1 E-5 F9000 ;move Z up a bit and retract even more\nG28 X0 Y0 ;home X/Y, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" diff --git a/resources/definitions/ultimaker_s5.def.json b/resources/definitions/ultimaker_s5.def.json index c8c8d258d3..8af77e22ac 100644 --- a/resources/definitions/ultimaker_s5.def.json +++ b/resources/definitions/ultimaker_s5.def.json @@ -37,7 +37,7 @@ "overrides": { "machine_name": { "default_value": "Ultimaker S5" }, "machine_width": { "default_value": 330 }, - "machine_depth": { "default_value": 245 }, + "machine_depth": { "default_value": 240 }, "machine_height": { "default_value": 300 }, "machine_heated_bed": { "default_value": true }, "machine_nozzle_heat_up_speed": { "default_value": 1.4 }, diff --git a/resources/definitions/vertex_k8400.def.json b/resources/definitions/vertex_k8400.def.json index 8abf9acd7f..92c016aa70 100644 --- a/resources/definitions/vertex_k8400.def.json +++ b/resources/definitions/vertex_k8400.def.json @@ -8,7 +8,7 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "platform": "Vertex_build_panel.stl", - "platform_offset": [0, -2, 0], + "platform_offset": [0, -3, 0], "supports_usb_connection": true, "supported_actions": ["MachineSettingsAction"] }, diff --git a/resources/definitions/vertex_k8400_dual.def.json b/resources/definitions/vertex_k8400_dual.def.json index fc006a1d5f..e4b4f609c1 100644 --- a/resources/definitions/vertex_k8400_dual.def.json +++ b/resources/definitions/vertex_k8400_dual.def.json @@ -8,7 +8,7 @@ "file_formats": "text/x-gcode", "icon": "icon_ultimaker2", "platform": "Vertex_build_panel.stl", - "platform_offset": [0, -2, 0], + "platform_offset": [0, -3, 0], "machine_extruder_trains": { "0": "vertex_k8400_dual_1st", "1": "vertex_k8400_dual_2nd" diff --git a/resources/i18n/de_DE/cura.po b/resources/i18n/de_DE/cura.po index 2c44fd7da5..046c5a30d6 100644 --- a/resources/i18n/de_DE/cura.po +++ b/resources/i18n/de_DE/cura.po @@ -3558,7 +3558,7 @@ msgstr "Druckeinrichtung deaktiviert\nG-Code-Dateien können nicht geändert wer #: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:380 msgctxt "@label Hours and minutes" msgid "00h 00min" -msgstr "00 Stunden 00 Minuten" +msgstr "00 St. 00 M." #: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:398 msgctxt "@tooltip" @@ -5493,7 +5493,7 @@ msgstr "Cura-Profil-Reader" #~ msgctxt "@label" #~ msgid "00h 00min" -#~ msgstr "00 Stunden 00 Minuten" +#~ msgstr "00 St. 00 M." #~ msgctxt "@tooltip" #~ msgid "Time information" @@ -5517,7 +5517,7 @@ msgstr "Cura-Profil-Reader" #~ msgctxt "@label" #~ msgid "Check material compatibility" -#~ msgstr "Materialkompatibilität prüfen" #~ msgctxt "name" #~ msgid "UM3 Network Connection (Cluster)" diff --git a/resources/packages.json b/resources/packages.json new file mode 100644 index 0000000000..8d58f226b0 --- /dev/null +++ b/resources/packages.json @@ -0,0 +1,1153 @@ +{ + "3MFReader": { + "package_info": { + "package_id": "3MFReader", + "package_type": "plugin", + "display_name": "3MF Reader", + "description": "Provides support for reading 3MF files.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "3MFWriter": { + "package_info": { + "package_id": "3MFWriter", + "package_type": "plugin", + "display_name": "3MF Writer", + "description": "Provides support for writing 3MF files.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "AutoSave": { + "package_info": { + "package_id": "AutoSave", + "package_type": "plugin", + "display_name": "Auto-Save", + "description": "Automatically saves Preferences, Machines and Profiles after changes.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "ChangeLogPlugin": { + "package_info": { + "package_id": "ChangeLogPlugin", + "package_type": "plugin", + "display_name": "Change Log", + "description": "Shows changes since latest checked version.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "CuraEngineBackend": { + "package_info": { + "package_id": "CuraEngineBackend", + "package_type": "plugin", + "display_name": "CuraEngine Backend", + "description": "Provides the link to the CuraEngine slicing backend.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "CuraProfileReader": { + "package_info": { + "package_id": "CuraProfileReader", + "package_type": "plugin", + "display_name": "Cura Profile Reader", + "description": "Provides support for importing Cura profiles.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "CuraProfileWriter": { + "package_info": { + "package_id": "CuraProfileWriter", + "package_type": "plugin", + "display_name": "Cura Profile Writer", + "description": "Provides support for exporting Cura profiles.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "FirmwareUpdateChecker": { + "package_info": { + "package_id": "FirmwareUpdateChecker", + "package_type": "plugin", + "display_name": "Firmware Update Checker", + "description": "Checks for firmware updates.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "GCodeGzReader": { + "package_info": { + "package_id": "GCodeGzReader", + "package_type": "plugin", + "display_name": "Compressed G-code Reader", + "description": "Reads g-code from a compressed archive.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "GCodeGzWriter": { + "package_info": { + "package_id": "GCodeGzWriter", + "package_type": "plugin", + "display_name": "Compressed G-code Writer", + "description": "Writes g-code to a compressed archive.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "GCodeProfileReader": { + "package_info": { + "package_id": "GCodeProfileReader", + "package_type": "plugin", + "display_name": "G-Code Profile Reader", + "description": "Provides support for importing profiles from g-code files.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "GCodeReader": { + "package_info": { + "package_id": "GCodeReader", + "package_type": "plugin", + "display_name": "G-Code Reader", + "description": "Allows loading and displaying G-code files.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "VictorLarchenko", + "display_name": "Victor Larchenko", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "GCodeWriter": { + "package_info": { + "package_id": "GCodeWriter", + "package_type": "plugin", + "display_name": "G-Code Writer", + "description": "Writes g-code to a file.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "ImageReader": { + "package_info": { + "package_id": "ImageReader", + "package_type": "plugin", + "display_name": "Image Reader", + "description": "Enables ability to generate printable geometry from 2D image files.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "LegacyProfileReader": { + "package_info": { + "package_id": "LegacyProfileReader", + "package_type": "plugin", + "display_name": "Legacy Cura Profile Reader", + "description": "Provides support for importing profiles from legacy Cura versions.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "MachineSettingsAction": { + "package_info": { + "package_id": "MachineSettingsAction", + "package_type": "plugin", + "display_name": "Machine Settings Action", + "description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "fieldOfView", + "display_name": "fieldOfView", + "email": null, + "website": "https://ultimaker.com" + } + } + }, + "ModelChecker": { + "package_info": { + "package_id": "ModelChecker", + "package_type": "plugin", + "display_name": "Model Checker", + "description": "Checks models and print configuration for possible printing issues and give suggestions.", + "package_version": "0.1.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "MonitorStage": { + "package_info": { + "package_id": "MonitorStage", + "package_type": "plugin", + "display_name": "Monitor Stage", + "description": "Provides a monitor stage in Cura.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "PerObjectSettingsTool": { + "package_info": { + "package_id": "PerObjectSettingsTool", + "package_type": "plugin", + "display_name": "Per-Object Settings Tool", + "description": "Provides the per-model settings.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "PostProcessingPlugin": { + "package_info": { + "package_id": "PostProcessingPlugin", + "package_type": "plugin", + "display_name": "Post Processing", + "description": "Extension that allows for user created scripts for post processing.", + "package_version": "2.2.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "PrepareStage": { + "package_info": { + "package_id": "PrepareStage", + "package_type": "plugin", + "display_name": "Prepare Stage", + "description": "Provides a prepare stage in Cura.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "RemovableDriveOutputDevice": { + "package_info": { + "package_id": "RemovableDriveOutputDevice", + "package_type": "plugin", + "display_name": "Removable Drive Output Device", + "description": "Provides removable drive hotplugging and writing support.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "SimulationView": { + "package_info": { + "package_id": "SimulationView", + "package_type": "plugin", + "display_name": "Simulation View", + "description": "Provides the Simulation view.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "SliceInfoPlugin": { + "package_info": { + "package_id": "SliceInfoPlugin", + "package_type": "plugin", + "display_name": "Slice Info", + "description": "Submits anonymous slice info. Can be disabled through preferences.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "SolidView": { + "package_info": { + "package_id": "SolidView", + "package_type": "plugin", + "display_name": "Solid View", + "description": "Provides a normal solid mesh view.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "SupportEraser": { + "package_info": { + "package_id": "SupportEraser", + "package_type": "plugin", + "display_name": "Support Eraser Tool", + "description": "Creates an eraser mesh to block the printing of support in certain places.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "Toolbox": { + "package_info": { + "package_id": "Toolbox", + "package_type": "plugin", + "display_name": "Toolbox", + "description": "Find, manage and install new Cura packages.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "UFPWriter": { + "package_info": { + "package_id": "UFPWriter", + "package_type": "plugin", + "display_name": "UFP Writer", + "description": "Provides support for writing Ultimaker Format Packages.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "UltimakerMachineActions": { + "package_info": { + "package_id": "UltimakerMachineActions", + "package_type": "plugin", + "display_name": "Ultimaker Machine Actions", + "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "UM3NetworkPrinting": { + "package_info": { + "package_id": "UM3NetworkPrinting", + "package_type": "plugin", + "display_name": "UM3 Network Printing", + "description": "Manages network connections to Ultimaker 3 printers.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "USBPrinting": { + "package_info": { + "package_id": "USBPrinting", + "package_type": "plugin", + "display_name": "USB Printing", + "description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "UserAgreement": { + "package_info": { + "package_id": "UserAgreement", + "package_type": "plugin", + "display_name": "User Agreement", + "description": "Ask the user once if he/she agrees with our license.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade21to22": { + "package_info": { + "package_id": "VersionUpgrade21to22", + "package_type": "plugin", + "display_name": "Version Upgrade 2.1 to 2.2", + "description": "Upgrades configurations from Cura 2.1 to Cura 2.2.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade22to24": { + "package_info": { + "package_id": "VersionUpgrade22to24", + "package_type": "plugin", + "display_name": "Version Upgrade 2.2 to 2.4", + "description": "Upgrades configurations from Cura 2.2 to Cura 2.4.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade25to26": { + "package_info": { + "package_id": "VersionUpgrade25to26", + "package_type": "plugin", + "display_name": "Version Upgrade 2.5 to 2.6", + "description": "Upgrades configurations from Cura 2.5 to Cura 2.6.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade26to27": { + "package_info": { + "package_id": "VersionUpgrade26to27", + "package_type": "plugin", + "display_name": "Version Upgrade 2.6 to 2.7", + "description": "Upgrades configurations from Cura 2.6 to Cura 2.7.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade27to30": { + "package_info": { + "package_id": "VersionUpgrade27to30", + "package_type": "plugin", + "display_name": "Version Upgrade 2.7 to 3.0", + "description": "Upgrades configurations from Cura 2.7 to Cura 3.0.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade30to31": { + "package_info": { + "package_id": "VersionUpgrade30to31", + "package_type": "plugin", + "display_name": "Version Upgrade 3.0 to 3.1", + "description": "Upgrades configurations from Cura 3.0 to Cura 3.1.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade32to33": { + "package_info": { + "package_id": "VersionUpgrade32to33", + "package_type": "plugin", + "display_name": "Version Upgrade 3.2 to 3.3", + "description": "Upgrades configurations from Cura 3.2 to Cura 3.3.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "VersionUpgrade33to34": { + "package_info": { + "package_id": "VersionUpgrade33to34", + "package_type": "plugin", + "display_name": "Version Upgrade 3.3 to 3.4", + "description": "Upgrades configurations from Cura 3.3 to Cura 3.4.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "X3DReader": { + "package_info": { + "package_id": "X3DReader", + "package_type": "plugin", + "display_name": "X3D Reader", + "description": "Provides support for reading X3D files.", + "package_version": "0.5.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "SevaAlekseyev", + "display_name": "Seva Alekseyev", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "XmlMaterialProfile": { + "package_info": { + "package_id": "XMLMaterialProfile", + "package_type": "plugin", + "display_name": "XML Material Profiles", + "description": "Provides capabilities to read and write XML-based material profiles.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "XRayView": { + "package_info": { + "package_id": "XRayView", + "package_type": "plugin", + "display_name": "X-Ray View", + "description": "Provides the X-Ray view.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "plugins@ultimaker.com", + "website": "https://ultimaker.com" + } + } + }, + "DagomaChromatikPLA": { + "package_info": { + "package_id": "DagomaChromatikPLA", + "package_type": "material", + "display_name": "Dagoma Chromatik PLA", + "description": "Filament testé et approuvé pour les imprimantes 3D Dagoma. Chromatik est l'idéal pour débuter et suivre les tutoriels premiers pas. Il vous offre qualité et résistance pour chacune de vos impressions.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://dagoma.fr/boutique/filaments.html", + "author": { + "author_id": "Dagoma", + "display_name": "Dagoma", + "email": null, + "website": "https://dagoma.fr" + } + } + }, + "FABtotumABS": { + "package_info": { + "package_id": "FABtotumABS", + "package_type": "material", + "display_name": "FABtotum ABS", + "description": "This material is easy to be extruded but it is not the simplest to use. It is one of the most used in 3D printing to get very well finished objects. It is not sustainable and its smoke can be dangerous if inhaled. The reason to prefer this filament to PLA is mainly because of its precision and mechanical specs. ABS (for plastic) stands for Acrylonitrile Butadiene Styrene and it is a thermoplastic which is widely used in everyday objects. It can be printed with any FFF 3D printer which can get to high temperatures as it must be extruded in a range between 220° and 245°, so it’s compatible with all versions of the FABtotum Personal fabricator.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=40", + "author": { + "author_id": "FABtotum", + "display_name": "FABtotum S.R.L.", + "email": "info@fabtotum.com", + "website": "https://www.fabtotum.com" + } + } + }, + "FABtotumNylon": { + "package_info": { + "package_id": "FABtotumNylon", + "package_type": "material", + "display_name": "FABtotum Nylon", + "description": "When 3D printing started this material was not listed among the extrudable filaments. It is flexible as well as resistant to tractions. It is well known for its uses in textile but also in industries which require a strong and flexible material. There are different kinds of Nylon: 3D printing mostly uses Nylon 6 and Nylon 6.6, which are the most common. It requires higher temperatures to be printed, so a 3D printer must be able to reach them (around 240°C): the FABtotum, of course, can.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=53", + "author": { + "author_id": "FABtotum", + "display_name": "FABtotum S.R.L.", + "email": "info@fabtotum.com", + "website": "https://www.fabtotum.com" + } + } + }, + "FABtotumPLA": { + "package_info": { + "package_id": "FABtotumPLA", + "package_type": "material", + "display_name": "FABtotum PLA", + "description": "It is the most common filament used for 3D printing. It is studied to be bio-degradable as it comes from corn starch’s sugar mainly. It is completely made of renewable sources and has no footprint on polluting. PLA stands for PolyLactic Acid and it is a thermoplastic that today is still considered the easiest material to be 3D printed. It can be extruded at lower temperatures: the standard range of FABtotum’s one is between 185° and 195°.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=39", + "author": { + "author_id": "FABtotum", + "display_name": "FABtotum S.R.L.", + "email": "info@fabtotum.com", + "website": "https://www.fabtotum.com" + } + } + }, + "FABtotumTPU": { + "package_info": { + "package_id": "FABtotumTPU", + "package_type": "material", + "display_name": "FABtotum TPU Shore 98A", + "description": "", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=66", + "author": { + "author_id": "FABtotum", + "display_name": "FABtotum S.R.L.", + "email": "info@fabtotum.com", + "website": "https://www.fabtotum.com" + } + } + }, + "FiberlogyHDPLA": { + "package_info": { + "package_id": "FiberlogyHDPLA", + "package_type": "material", + "display_name": "Fiberlogy HD PLA", + "description": "With our HD PLA you have many more options. You can use this material in two ways. Choose the one you like best. You can use it as a normal PLA and get prints characterized by a very good adhesion between the layers and high precision. You can also make your prints acquire similar properties to that of ABS – better impact resistance and high temperature resistance. All you need is an oven. Yes, an oven! By annealing our HD PLA in an oven, in accordance with the manual, you will avoid all the inconveniences of printing with ABS, such as unpleasant odour or hazardous fumes.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "http://fiberlogy.com/en/fiberlogy-filaments/filament-hd-pla/", + "author": { + "author_id": "Fiberlogy", + "diplay_name": "Fiberlogy S.A.", + "email": "grzegorz.h@fiberlogy.com", + "website": "http://fiberlogy.com" + } + } + }, + "Filo3DPLA": { + "package_info": { + "package_id": "Filo3DPLA", + "package_type": "material", + "display_name": "Filo3D PLA", + "description": "Fast, safe and reliable printing. PLA is ideal for the fast and reliable printing of parts and prototypes with a great surface quality.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://dagoma.fr", + "author": { + "author_id": "Dagoma", + "display_name": "Dagoma", + "email": null, + "website": "https://dagoma.fr" + } + } + }, + "IMADE3DJellyBOXPETG": { + "package_info": { + "package_id": "IMADE3DJellyBOXPETG", + "package_type": "material", + "display_name": "IMADE3D JellyBOX PETG", + "description": "", + "package_version": "1.0.0", + "cura_version": 4, + "website": "http://shop.imade3d.com/filament.html", + "author": { + "author_id": "IMADE3D", + "display_name": "IMADE3D", + "email": "info@imade3d.com", + "website": "https://www.imade3d.com" + } + } + }, + "IMADE3DJellyBOXPLA": { + "package_info": { + "package_id": "IMADE3DJellyBOXPLA", + "package_type": "material", + "display_name": "IMADE3D JellyBOX PLA", + "description": "", + "package_version": "1.0.0", + "cura_version": 4, + "website": "http://shop.imade3d.com/filament.html", + "author": { + "author_id": "IMADE3D", + "display_name": "IMADE3D", + "email": "info@imade3d.com", + "website": "https://www.imade3d.com" + } + } + }, + "OctofiberPLA": { + "package_info": { + "package_id": "OctofiberPLA", + "package_type": "material", + "display_name": "Octofiber PLA", + "description": "PLA material from Octofiber.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://nl.octofiber.com/3d-printing-filament/pla.html", + "author": { + "author_id": "Octofiber", + "display_name": "Octofiber", + "email": "info@octofiber.com", + "website": "https://nl.octofiber.com" + } + } + }, + "PolyFlexPLA": { + "package_info": { + "package_id": "PolyFlexPLA", + "package_type": "material", + "display_name": "PolyFlex™ PLA", + "description": "PolyFlex™ is a highly flexible yet easy to print 3D printing material. Featuring good elasticity and a large strain-to- failure, PolyFlex™ opens up a completely new realm of applications.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "http://www.polymaker.com/shop/polyflex/", + "author": { + "author_id": "Polymaker", + "display_name": "Polymaker L.L.C.", + "email": "inquiry@polymaker.com", + "website": "https://www.polymaker.com" + } + } + }, + "PolyMaxPLA": { + "package_info": { + "package_id": "PolyMaxPLA", + "package_type": "material", + "display_name": "PolyMax™ PLA", + "description": "PolyMax™ PLA is a 3D printing material with excellent mechanical properties and printing quality. PolyMax™ PLA has an impact resistance of up to nine times that of regular PLA, and better overall mechanical properties than ABS.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "http://www.polymaker.com/shop/polymax/", + "author": { + "author_id": "Polymaker", + "display_name": "Polymaker L.L.C.", + "email": "inquiry@polymaker.com", + "website": "https://www.polymaker.com" + } + } + }, + "PolyPlusPLA": { + "package_info": { + "package_id": "PolyPlusPLA", + "package_type": "material", + "display_name": "PolyPlus™ PLA True Colour", + "description": "PolyPlus™ PLA is a premium PLA designed for all desktop FDM/FFF 3D printers. It is produced with our patented Jam-Free™ technology that ensures consistent extrusion and prevents jams.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "http://www.polymaker.com/shop/polyplus-true-colour/", + "author": { + "author_id": "Polymaker", + "display_name": "Polymaker L.L.C.", + "email": "inquiry@polymaker.com", + "website": "https://www.polymaker.com" + } + } + }, + "PolyWoodPLA": { + "package_info": { + "package_id": "PolyWoodPLA", + "package_type": "material", + "display_name": "PolyWood™ PLA", + "description": "PolyWood™ is a wood mimic printing material that contains no actual wood ensuring a clean Jam-Free™ printing experience.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "http://www.polymaker.com/shop/polywood/", + "author": { + "author_id": "Polymaker", + "display_name": "Polymaker L.L.C.", + "email": "inquiry@polymaker.com", + "website": "https://www.polymaker.com" + } + } + }, + "UltimakerABS": { + "package_info": { + "package_id": "UltimakerABS", + "package_type": "material", + "display_name": "Ultimaker ABS", + "description": "Example package for material and quality profiles for Ultimaker materials.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com/products/materials/abs", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "materials@ultimaker.com", + "website": "https://ultimaker.com", + "description": "Professional 3D printing made accessible.", + "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials" + } + } + }, + "UltimakerCPE": { + "package_info": { + "package_id": "UltimakerCPE", + "package_type": "material", + "display_name": "Ultimaker CPE", + "description": "Example package for material and quality profiles for Ultimaker materials.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com/products/materials/abs", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "materials@ultimaker.com", + "website": "https://ultimaker.com", + "description": "Professional 3D printing made accessible.", + "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials" + } + } + }, + "UltimakerNylon": { + "package_info": { + "package_id": "UltimakerNylon", + "package_type": "material", + "display_name": "Ultimaker Nylon", + "description": "Example package for material and quality profiles for Ultimaker materials.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com/products/materials/abs", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "materials@ultimaker.com", + "website": "https://ultimaker.com", + "description": "Professional 3D printing made accessible.", + "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials" + } + } + }, + "UltimakerPC": { + "package_info": { + "package_id": "UltimakerPC", + "package_type": "material", + "display_name": "Ultimaker PC", + "description": "Example package for material and quality profiles for Ultimaker materials.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com/products/materials/pc", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "materials@ultimaker.com", + "website": "https://ultimaker.com", + "description": "Professional 3D printing made accessible.", + "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials" + } + } + }, + "UltimakerPLA": { + "package_info": { + "package_id": "UltimakerPLA", + "package_type": "material", + "display_name": "Ultimaker PLA", + "description": "Example package for material and quality profiles for Ultimaker materials.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com/products/materials/abs", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "materials@ultimaker.com", + "website": "https://ultimaker.com", + "description": "Professional 3D printing made accessible.", + "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials" + } + } + }, + "UltimakerPVA": { + "package_info": { + "package_id": "UltimakerPVA", + "package_type": "material", + "display_name": "Ultimaker PVA", + "description": "Example package for material and quality profiles for Ultimaker materials.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://ultimaker.com/products/materials/abs", + "author": { + "author_id": "Ultimaker", + "display_name": "Ultimaker B.V.", + "email": "materials@ultimaker.com", + "website": "https://ultimaker.com", + "description": "Professional 3D printing made accessible.", + "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials" + } + } + }, + "VertexDeltaABS": { + "package_info": { + "package_id": "VertexDeltaABS", + "package_type": "material", + "display_name": "Vertex Delta ABS", + "description": "ABS material and quality files for the Delta Vertex K8800.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://vertex3dprinter.eu", + "author": { + "author_id": "Velleman", + "display_name": "Velleman N.V.", + "email": "info@velleman.eu", + "website": "https://www.vellemanprojects.eu" + } + } + }, + "VertexDeltaPET": { + "package_info": { + "package_id": "VertexDeltaPET", + "package_type": "material", + "display_name": "Vertex Delta PET", + "description": "ABS material and quality files for the Delta Vertex K8800.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://vertex3dprinter.eu", + "author": { + "author_id": "Velleman", + "display_name": "Velleman N.V.", + "email": "info@velleman.eu", + "website": "https://www.vellemanprojects.eu" + } + } + }, + "VertexDeltaPLA": { + "package_info": { + "package_id": "VertexDeltaPLA", + "package_type": "material", + "display_name": "Vertex Delta PLA", + "description": "ABS material and quality files for the Delta Vertex K8800.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://vertex3dprinter.eu", + "author": { + "author_id": "Velleman", + "display_name": "Velleman N.V.", + "email": "info@velleman.eu", + "website": "https://www.vellemanprojects.eu" + } + } + }, + "VertexDeltaTPU": { + "package_info": { + "package_id": "VertexDeltaTPU", + "package_type": "material", + "display_name": "Vertex Delta TPU", + "description": "ABS material and quality files for the Delta Vertex K8800.", + "package_version": "1.0.0", + "cura_version": 4, + "website": "https://vertex3dprinter.eu", + "author": { + "author_id": "Velleman", + "display_name": "Velleman N.V.", + "email": "info@velleman.eu", + "website": "https://www.vellemanprojects.eu" + } + } + } +} diff --git a/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg deleted file mode 100644 index 18625e80eb..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 4 -name = M1 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = fine -weight = 2 - -[values] -layer_height = 0.04375 -layer_height_0 = 0.2625 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg deleted file mode 100644 index 311a797b27..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 4 -name = M2 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = high -weight = 1 - -[values] -layer_height = 0.0875 -layer_height_0 = 0.2625 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg deleted file mode 100644 index 1fe974f6d2..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 4 -name = M3 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = normal -weight = 0 - -[values] -layer_height = 0.13125 -layer_height_0 = 0.2625 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg deleted file mode 100644 index 091035d137..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg +++ /dev/null @@ -1,23 +0,0 @@ -[general] -version = 4 -name = M4 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = fast -weight = -1 -global_quality = true - -[values] -layer_height = 0.175 -layer_height_0 = 0.2625 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg deleted file mode 100644 index 1a22bbc236..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 4 -name = M5 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = faster -weight = -2 - -[values] -layer_height = 0.21875 -layer_height_0 = 0.2625 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg deleted file mode 100644 index d89eb9e6d8..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 4 -name = M6 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = draft -weight = -3 - -[values] -layer_height = 0.2625 -layer_height_0 = 0.2625 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg deleted file mode 100644 index 2e71c79b49..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[general] -version = 4 -name = M7 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = turbo -weight = -4 - -[values] -layer_height = 0.30625 -layer_height_0 = 0.30625 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg deleted file mode 100644 index 362d4b9539..0000000000 --- a/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg +++ /dev/null @@ -1,23 +0,0 @@ -[general] -version = 4 -name = M8 Quality -definition = malyan_m200 - -[metadata] -setting_version = 4 -type = quality -quality_type = hyper -weight = -5 -global_quality = true - -[values] -layer_height = 0.35 -layer_height_0 = 0.35 -wall_thickness = 1.05 -top_bottom_thickness = 0.72 -infill_sparse_density = 22 -speed_print = 50 -speed_layer_0 = =round(speed_print * 30 / 50) -speed_topbottom = 20 -cool_min_layer_time = 5 -cool_min_speed = 10 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg index 72338b0319..72c16ebc1d 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.25_PP_Normal_Quality.inst.cfg @@ -25,11 +25,11 @@ jerk_enabled = True jerk_print = 25 line_width = =machine_nozzle_size * 0.92 machine_min_cool_heat_time_window = 15 -material_bed_temperature_layer_0 = 90 -material_final_print_temperature = 195 -material_initial_print_temperature = 200 -material_print_temperature = 205 -material_print_temperature_layer_0 = 208 +material_bed_temperature_layer_0 = =material_bed_temperature + 5 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature - 15 +material_print_temperature_layer_0 = =material_print_temperature + 3 multiple_mesh_overlap = 0 prime_tower_enable = False prime_tower_size = 16 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print.inst.cfg index a72664aa53..b2c44dab01 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Draft_Print.inst.cfg @@ -26,5 +26,6 @@ speed_wall = =math.ceil(speed_print * 45 / 60) speed_wall_0 = =math.ceil(speed_wall * 35 / 45) wall_thickness = 1 -infill_line_width = 0.4 -speed_infill = 50 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 50 / 60) + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print.inst.cfg index 9c0cbabe05..0470956c6d 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Fast_Print.inst.cfg @@ -25,5 +25,6 @@ speed_topbottom = =math.ceil(speed_print * 30 / 60) speed_wall = =math.ceil(speed_print * 40 / 60) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) -infill_line_width = 0.4 -speed_infill = 45 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 45 / 60) + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_High_Quality.inst.cfg index c9cdf862bf..497071e01a 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_High_Quality.inst.cfg @@ -24,5 +24,6 @@ speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) -infill_line_width = 0.4 -speed_infill = 40 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 40 / 50) + diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality.inst.cfg index 6392f372d6..f080adb06f 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_ABS_Normal_Quality.inst.cfg @@ -23,5 +23,5 @@ speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 55) speed_wall = =math.ceil(speed_print * 30 / 55) -infill_line_width = 0.4 -speed_infill = 40 +infill_line_width = =round(line_width * 0.4 / 0.35, 2) +speed_infill = =math.ceil(speed_print * 40 / 55) diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg index b510b74c8a..744b49b03b 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Draft_Print.inst.cfg @@ -23,8 +23,7 @@ speed_wall = =math.ceil(speed_print * 45 / 60) speed_wall_0 = =math.ceil(speed_wall * 35 / 45) wall_thickness = 1 -jerk_travel = 50 infill_pattern = zigzag -speed_infill = 50 +speed_infill = =math.ceil(speed_print * 50 / 60) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg index 5a5411f0ea..58757c6dd1 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Fast_Print.inst.cfg @@ -22,8 +22,6 @@ speed_topbottom = =math.ceil(speed_print * 30 / 60) speed_wall = =math.ceil(speed_print * 40 / 60) speed_wall_0 = =math.ceil(speed_wall * 30 / 40) -jerk_travel = 50 - infill_pattern = zigzag -speed_infill = 50 +speed_infill = =math.ceil(speed_print * 50 / 60) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg index 7bb2ed31e9..010ad9114a 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_High_Quality.inst.cfg @@ -23,8 +23,6 @@ speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 50) speed_wall = =math.ceil(speed_print * 30 / 50) -jerk_travel = 50 - infill_pattern = zigzag -speed_infill = 40 +speed_infill = =math.ceil(speed_print * 40 / 50) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg index ed166d0eef..386350212d 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_CPE_Normal_Quality.inst.cfg @@ -21,8 +21,6 @@ speed_layer_0 = 20 speed_topbottom = =math.ceil(speed_print * 30 / 55) speed_wall = =math.ceil(speed_print * 30 / 55) -jerk_travel = 50 - infill_pattern = zigzag -speed_infill = 45 +speed_infill = =math.ceil(speed_print * 45 / 55) prime_tower_purge_volume = 1 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Draft_Print.inst.cfg index bee5fdad75..e53cd8f7a8 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Draft_Print.inst.cfg @@ -29,11 +29,11 @@ line_width = =machine_nozzle_size * 0.95 machine_min_cool_heat_time_window = 15 machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 -material_bed_temperature_layer_0 = 95 -material_final_print_temperature = 205 -material_initial_print_temperature = 210 -material_print_temperature = 215 -material_print_temperature_layer_0 = 220 +material_bed_temperature_layer_0 = =material_bed_temperature + 5 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature - 5 +material_print_temperature_layer_0 = =material_print_temperature + 5 material_standby_temperature = 100 multiple_mesh_overlap = 0 prime_tower_enable = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Fast_Print.inst.cfg index b5cbde326a..e9d08feaff 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Fast_Print.inst.cfg @@ -29,11 +29,11 @@ line_width = =machine_nozzle_size * 0.95 machine_min_cool_heat_time_window = 15 machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 -material_bed_temperature_layer_0 = 95 -material_final_print_temperature = 195 -material_initial_print_temperature = 205 -material_print_temperature = 207 -material_print_temperature_layer_0 = 210 +material_bed_temperature_layer_0 = =material_bed_temperature + 5 +material_final_print_temperature = =material_print_temperature - 12 +material_initial_print_temperature = =material_print_temperature - 2 +material_print_temperature = =default_material_print_temperature - 13 +material_print_temperature_layer_0 = =material_print_temperature + 3 material_standby_temperature = 100 multiple_mesh_overlap = 0 prime_tower_enable = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Normal_Quality.inst.cfg index 8f41897c6c..58d9e1639a 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_PP_Normal_Quality.inst.cfg @@ -29,11 +29,11 @@ line_width = =machine_nozzle_size * 0.95 machine_min_cool_heat_time_window = 15 machine_nozzle_cool_down_speed = 0.85 machine_nozzle_heat_up_speed = 1.5 -material_bed_temperature_layer_0 = 95 -material_final_print_temperature = 195 -material_initial_print_temperature = 200 -material_print_temperature = 205 -material_print_temperature_layer_0 = 208 +material_bed_temperature_layer_0 = =material_bed_temperature + 5 +material_final_print_temperature = =material_print_temperature - 10 +material_initial_print_temperature = =material_print_temperature - 5 +material_print_temperature = =default_material_print_temperature - 15 +material_print_temperature_layer_0 = =material_print_temperature + 3 material_standby_temperature = 100 multiple_mesh_overlap = 0 prime_tower_enable = False diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Draft_Print.inst.cfg index c2405c0c39..56249427bf 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Draft_Print.inst.cfg @@ -18,6 +18,7 @@ brim_width = 8.75 cool_fan_speed_max = 100 cool_min_layer_time_fan_speed_max = 6 cool_min_speed = 4 +gradual_infill_step_height = =5 * layer_height infill_line_width = =round(line_width * 0.38 / 0.38, 2) infill_overlap = 0 infill_pattern = cross_3d @@ -40,7 +41,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 12 retraction_extra_prime_amount = 0.8 retraction_extrusion_window = 1 -retraction_hop = 1.5 retraction_hop_only_when_collides = True retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 @@ -61,5 +61,3 @@ travel_avoid_distance = 1.5 wall_0_inset = 0 wall_line_width_x = =line_width wall_thickness = 0.76 - -jerk_travel = 50 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Fast_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Fast_Print.inst.cfg index 489c485c72..e362ffd25d 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Fast_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Fast_Print.inst.cfg @@ -18,6 +18,7 @@ brim_width = 8.75 cool_fan_speed_max = 100 cool_min_layer_time_fan_speed_max = 6 cool_min_speed = 4 +gradual_infill_step_height = =5 * layer_height infill_line_width = =round(line_width * 0.38 / 0.38, 2) infill_overlap = 0 infill_pattern = cross_3d @@ -40,7 +41,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 12 retraction_extra_prime_amount = 0.8 retraction_extrusion_window = 1 -retraction_hop = 1.5 retraction_hop_only_when_collides = True retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 @@ -62,4 +62,3 @@ wall_0_inset = 0 wall_line_width_x = =line_width wall_thickness = 0.76 -jerk_travel = 50 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Normal_Quality.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Normal_Quality.inst.cfg index c6f07fdb12..8ffe0afae6 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.4_TPU_Normal_Quality.inst.cfg @@ -18,6 +18,7 @@ brim_width = 8.75 cool_fan_speed_max = 100 cool_min_layer_time_fan_speed_max = 6 cool_min_speed = 4 +gradual_infill_step_height = =5 * layer_height infill_line_width = =round(line_width * 0.38 / 0.38, 2) infill_overlap = 0 infill_pattern = cross_3d @@ -39,7 +40,6 @@ prime_tower_wipe_enabled = True retraction_count_max = 12 retraction_extra_prime_amount = 0.8 retraction_extrusion_window = 1 -retraction_hop = 1.5 retraction_hop_only_when_collides = True retraction_min_travel = =line_width * 2 retraction_prime_speed = 15 @@ -61,4 +61,3 @@ wall_0_inset = 0 wall_line_width_x = =line_width wall_thickness = 0.76 -jerk_travel = 50 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Draft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Draft_Print.inst.cfg index 80cd8e7e2e..ce41b2e867 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Draft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Draft_Print.inst.cfg @@ -17,17 +17,15 @@ cool_fan_speed_max = =100 cool_min_speed = 2 gradual_infill_step_height = =3 * layer_height infill_line_width = =round(line_width * 0.65 / 0.75, 2) -infill_pattern = cubic line_width = =machine_nozzle_size * 0.9375 machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_final_print_temperature = =max(-273.15, material_print_temperature - 15) material_initial_print_temperature = =max(-273.15, material_print_temperature - 10) material_print_temperature = =default_material_print_temperature + 10 -prime_tower_enable = False +prime_tower_enable = True support_angle = 70 support_line_width = =line_width * 0.75 -support_pattern = ='triangles' support_xy_distance = =wall_line_width_0 * 1.5 top_bottom_thickness = =layer_height * 4 wall_line_width = =round(line_width * 0.75 / 0.75, 2) @@ -36,8 +34,9 @@ wall_thickness = =wall_line_width_0 + wall_line_width_x retract_at_layer_change = False speed_print = 45 -speed_wall = =round(speed_print * 40 / 45) -speed_wall_0 = =round(speed_print * 35 / 45) -speed_topbottom = =round(speed_print * 35 / 45) +speed_topbottom = =math.ceil(speed_print * 35 / 45) +speed_wall = =math.ceil(speed_print * 40 / 45) +speed_wall_x = =speed_wall +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) infill_sparse_density = 15 layer_height_0 = 0.4 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Superdraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Superdraft_Print.inst.cfg index f0aed44aea..32cd95c926 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Superdraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Superdraft_Print.inst.cfg @@ -17,18 +17,16 @@ cool_fan_speed_max = =100 cool_min_speed = 2 gradual_infill_step_height = =3 * layer_height infill_line_width = =round(line_width * 0.65 / 0.75, 2) -infill_pattern = cubic line_width = =machine_nozzle_size * 0.9375 machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_final_print_temperature = =max(-273.15, material_print_temperature - 15) material_initial_print_temperature = =max(-273.15, material_print_temperature - 10) material_print_temperature = =default_material_print_temperature + 15 -prime_tower_enable = False +prime_tower_enable = True raft_margin = 10 support_angle = 70 support_line_width = =line_width * 0.75 -support_pattern = ='triangles' support_xy_distance = =wall_line_width_0 * 1.5 top_bottom_thickness = =layer_height * 4 wall_line_width = =round(line_width * 0.75 / 0.75, 2) @@ -36,8 +34,9 @@ wall_line_width_x = =round(wall_line_width * 0.625 / 0.75, 2) wall_thickness = =wall_line_width_0 + wall_line_width_x retract_at_layer_change = False speed_print = 45 -speed_wall = =round(speed_print * 40 / 45) -speed_wall_0 = =round(speed_print * 35 / 45) -speed_topbottom = =round(speed_print * 35 / 45) +speed_topbottom = =math.ceil(speed_print * 35 / 45) +speed_wall = =math.ceil(speed_print * 40 / 45) +speed_wall_x = =speed_wall +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) infill_sparse_density = 15 layer_height_0 = 0.4 diff --git a/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Verydraft_Print.inst.cfg b/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Verydraft_Print.inst.cfg index 5e75dc8e4e..19530cce71 100644 --- a/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Verydraft_Print.inst.cfg +++ b/resources/quality/ultimaker_s5/um_s5_aa0.8_PLA_Verydraft_Print.inst.cfg @@ -17,17 +17,15 @@ cool_fan_speed_max = =100 cool_min_speed = 2 gradual_infill_step_height = =3 * layer_height infill_line_width = =round(line_width * 0.65 / 0.75, 2) -infill_pattern = cubic line_width = =machine_nozzle_size * 0.9375 machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_final_print_temperature = =max(-273.15, material_print_temperature - 15) material_initial_print_temperature = =max(-273.15, material_print_temperature - 10) material_print_temperature = =default_material_print_temperature + 10 -prime_tower_enable = False +prime_tower_enable = True support_angle = 70 support_line_width = =line_width * 0.75 -support_pattern = ='triangles' support_xy_distance = =wall_line_width_0 * 1.5 top_bottom_thickness = =layer_height * 4 wall_line_width = =round(line_width * 0.75 / 0.75, 2) @@ -35,8 +33,9 @@ wall_line_width_x = =round(wall_line_width * 0.625 / 0.75, 2) wall_thickness = =wall_line_width_0 + wall_line_width_x retract_at_layer_change = False speed_print = 45 -speed_wall = =round(speed_print * 40 / 45) -speed_wall_0 = =round(speed_print * 35 / 45) -speed_topbottom = =round(speed_print * 35 / 45) +speed_topbottom = =math.ceil(speed_print * 35 / 45) +speed_wall = =math.ceil(speed_print * 40 / 45) +speed_wall_x = =speed_wall +speed_wall_0 = =math.ceil(speed_wall * 35 / 40) infill_sparse_density = 15 layer_height_0 = 0.4 diff --git a/resources/themes/cura-light/styles.qml b/resources/themes/cura-light/styles.qml index 6b454b7cf1..14e7d196a7 100755 --- a/resources/themes/cura-light/styles.qml +++ b/resources/themes/cura-light/styles.qml @@ -1033,4 +1033,59 @@ QtObject { label: Item { } } } + + property Component toolbox_action_button: Component { + ButtonStyle + { + background: Rectangle + { + implicitWidth: UM.Theme.getSize("toolbox_action_button").width + implicitHeight: UM.Theme.getSize("toolbox_action_button").height + color: + { + if (control.installed) + { + return UM.Theme.getColor("action_button_disabled") + } + else + { + if (control.hovered) + { + return UM.Theme.getColor("primary_hover") + } + else + { + return UM.Theme.getColor("primary") + } + } + + } + } + label: Label + { + text: control.text + color: + { + if (control.installed) + { + return UM.Theme.getColor("action_button_disabled_text") + } + else + { + if (control.hovered) + { + return UM.Theme.getColor("button_text_hover") + } + else + { + return UM.Theme.getColor("button_text") + } + } + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + font: UM.Theme.getFont("default_bold") + } + } + } } diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index c78a51a3a9..f2309fb4a9 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -69,8 +69,6 @@ "colors": { - - "sidebar": [255, 255, 255, 255], "lining": [192, 193, 194, 255], "viewport_overlay": [0, 0, 0, 192], @@ -458,8 +456,8 @@ "toolbox_property_label": [1.0, 2.0], "toolbox_heading_label": [1.0, 4.0], "toolbox_header": [1.0, 4.0], - "toolbox_action_button": [8.0, 2.5], "toolbox_progress_bar": [8.0, 0.5], - "toolbox_chart_row": [1.0, 2.0] + "toolbox_chart_row": [1.0, 2.0], + "toolbox_action_button": [8.0, 2.5] } } diff --git a/run_mypy.py b/run_mypy.py index 88adea8db9..a72c555b8a 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -46,14 +46,9 @@ def main(): print("------------- Checking module {mod}".format(**locals())) result = subprocess.run([sys.executable, mypyModule, "-p", mod]) if result.returncode != 0: - print(""" - Module {mod} failed checking. :( - """.format(**locals())) - break + print("\nModule {mod} failed checking. :(".format(**locals())) + return 1 else: - print(""" - - Done checking. All is good. - """) + print("\n\nDone checking. All is good.") return 0 sys.exit(main())