diff --git a/cura_app.py b/cura_app.py index cb97792662..5184a5ab8b 100755 --- a/cura_app.py +++ b/cura_app.py @@ -29,9 +29,13 @@ parser.add_argument("--debug", known_args = vars(parser.parse_known_args()[0]) if with_sentry_sdk: - sentry_env = "production" - if ApplicationMetadata.CuraVersion == "master": + sentry_env = "unknown" # Start off with a "IDK" + if hasattr(sys, "frozen"): + sentry_env = "production" # A frozen build is a "real" distribution. + elif ApplicationMetadata.CuraVersion == "master": sentry_env = "development" + elif "beta" in ApplicationMetadata.CuraVersion or "BETA" in ApplicationMetadata.CuraVersion: + sentry_env = "beta" try: if ApplicationMetadata.CuraVersion.split(".")[2] == "99": sentry_env = "nightly" diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 2e395c9efa..be90f02d37 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -4,7 +4,8 @@ from configparser import ConfigParser import zipfile import os -from typing import cast, Dict, List, Optional, Tuple +import json +from typing import cast, Dict, List, Optional, Tuple, Any import xml.etree.ElementTree as ET @@ -732,7 +733,25 @@ class ThreeMFWorkspaceReader(WorkspaceReader): base_file_name = os.path.basename(file_name) self.setWorkspaceName(base_file_name) - return nodes + + return nodes, self._loadMetadata(file_name) + + @staticmethod + def _loadMetadata(file_name: str) -> Dict[str, Dict[str, Any]]: + archive = zipfile.ZipFile(file_name, "r") + + metadata_files = [name for name in archive.namelist() if name.endswith("plugin_metadata.json")] + + result = dict() + + for metadata_file in metadata_files: + try: + plugin_id = metadata_file.split("/")[0] + result[plugin_id] = json.loads(archive.open("%s/plugin_metadata.json" % plugin_id).read().decode("utf-8")) + except Exception: + Logger.logException("w", "Unable to retrieve metadata for %s", metadata_file) + + return result def _processQualityChanges(self, global_stack): if self._machine_info.quality_changes_info is None: diff --git a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py b/plugins/3MFWriter/ThreeMFWorkspaceWriter.py index 33df0bfe90..10a21f445b 100644 --- a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py +++ b/plugins/3MFWriter/ThreeMFWorkspaceWriter.py @@ -73,11 +73,25 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter): version_config_parser.write(version_file_string) archive.writestr(version_file, version_file_string.getvalue()) + self._writePluginMetadataToArchive(archive) + # Close the archive & reset states. archive.close() mesh_writer.setStoreArchive(False) return True + @staticmethod + def _writePluginMetadataToArchive(archive: zipfile.ZipFile) -> None: + file_name_template = "%s/plugin_metadata.json" + + for plugin_id, metadata in Application.getInstance().getWorkspaceMetadataStorage().getAllData().items(): + file_name = file_name_template % plugin_id + file_in_archive = zipfile.ZipInfo(file_name) + # We have to set the compress type of each file as well (it doesn't keep the type of the entire archive) + file_in_archive.compress_type = zipfile.ZIP_DEFLATED + import json + archive.writestr(file_in_archive, json.dumps(metadata, separators = (", ", ": "), indent = 4, skipkeys = True)) + ## Helper function that writes ContainerStacks, InstanceContainers and DefinitionContainers to the archive. # \param container That follows the \type{ContainerInterface} to archive. # \param archive The archive to write to. diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 640aabd30c..9860804542 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -1,5 +1,6 @@ # Copyright (c) 2015 Ultimaker B.V. # Uranium is released under the terms of the LGPLv3 or higher. +from typing import Optional from UM.Mesh.MeshWriter import MeshWriter from UM.Math.Vector import Vector @@ -40,7 +41,7 @@ class ThreeMFWriter(MeshWriter): } self._unit_matrix_string = self._convertMatrixToString(Matrix()) - self._archive = None + self._archive = None # type: Optional[zipfile.ZipFile] self._store_archive = False def _convertMatrixToString(self, matrix): diff --git a/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml b/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml index 3e7cdc9df8..c37bb099d0 100644 --- a/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml +++ b/plugins/Toolbox/resources/qml/dialogs/ToolboxLicenseDialog.qml @@ -5,6 +5,7 @@ import QtQuick 2.10 import QtQuick.Dialogs 1.1 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 import QtQuick.Controls.Styles 1.4 // TODO: Switch to QtQuick.Controls 2.x and remove QtQuick.Controls.Styles @@ -20,31 +21,63 @@ UM.Dialog minimumHeight: UM.Theme.getSize("license_window_minimum").height width: minimumWidth height: minimumHeight + backgroundColor: UM.Theme.getColor("main_background") + margin: screenScaleFactor * 10 - Item + ColumnLayout { anchors.fill: parent + spacing: UM.Theme.getSize("thick_margin").height UM.I18nCatalog{id: catalog; name: "cura"} - Label { id: licenseHeader - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - text: licenseModel.headerText + Layout.fillWidth: true + text: catalog.i18nc("@label", "You need to accept the license to install the package") wrapMode: Text.Wrap renderType: Text.NativeRendering } + + Row { + id: packageRow + + anchors.left: parent.left + anchors.right: parent.right + height: childrenRect.height + spacing: UM.Theme.getSize("default_margin").width + leftPadding: UM.Theme.getSize("narrow_margin").width + + Image + { + id: icon + width: 30 * screenScaleFactor + height: width + fillMode: Image.PreserveAspectFit + source: licenseModel.iconUrl || "../../images/logobot.svg" + mipmap: true + } + + Label + { + id: packageName + text: licenseModel.packageName + font.bold: true + anchors.verticalCenter: icon.verticalCenter + height: contentHeight + wrapMode: Text.Wrap + renderType: Text.NativeRendering + } + + + } + TextArea { id: licenseText - anchors.top: licenseHeader.bottom - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right + Layout.fillWidth: true + Layout.fillHeight: true anchors.topMargin: UM.Theme.getSize("default_margin").height readOnly: true text: licenseModel.licenseText @@ -57,7 +90,7 @@ UM.Dialog leftPadding: UM.Theme.getSize("dialog_primary_button_padding").width rightPadding: UM.Theme.getSize("dialog_primary_button_padding").width - text: catalog.i18nc("@button", "Agree") + text: licenseModel.acceptButtonText onClicked: { handler.onLicenseAccepted() } } ] @@ -67,7 +100,7 @@ UM.Dialog Cura.SecondaryButton { id: declineButton - text: catalog.i18nc("@button", "Decline and remove from account") + text: licenseModel.declineButtonText onClicked: { handler.onLicenseDeclined() } } ] diff --git a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py index f19cac047a..d79d031949 100644 --- a/plugins/Toolbox/src/CloudSync/DownloadPresenter.py +++ b/plugins/Toolbox/src/CloudSync/DownloadPresenter.py @@ -62,7 +62,8 @@ class DownloadPresenter: "received": 0, "total": 1, # make sure this is not considered done yet. Also divByZero-safe "file_written": None, - "request_data": request_data + "request_data": request_data, + "package_model": item } self._started = True @@ -128,7 +129,14 @@ class DownloadPresenter: if not item["file_written"]: return False - success_items = {package_id : value["file_written"] for package_id, value in self._progress.items()} + success_items = { + package_id: + { + "package_path": value["file_written"], + "icon_url": value["package_model"]["icon_url"] + } + for package_id, value in self._progress.items() + } error_items = [package_id for package_id in self._error] self._progress_message.hide() diff --git a/plugins/Toolbox/src/CloudSync/LicenseModel.py b/plugins/Toolbox/src/CloudSync/LicenseModel.py index c3b5ee5d31..bb62cb8abd 100644 --- a/plugins/Toolbox/src/CloudSync/LicenseModel.py +++ b/plugins/Toolbox/src/CloudSync/LicenseModel.py @@ -6,31 +6,52 @@ catalog = i18nCatalog("cura") # Model for the ToolboxLicenseDialog class LicenseModel(QObject): - dialogTitleChanged = pyqtSignal() - headerChanged = pyqtSignal() - licenseTextChanged = pyqtSignal() + DEFAULT_DECLINE_BUTTON_TEXT = catalog.i18nc("@button", "Decline") + ACCEPT_BUTTON_TEXT = catalog.i18nc("@button", "Agree") - def __init__(self) -> None: + dialogTitleChanged = pyqtSignal() + packageNameChanged = pyqtSignal() + licenseTextChanged = pyqtSignal() + iconChanged = pyqtSignal() + + def __init__(self, decline_button_text: str = DEFAULT_DECLINE_BUTTON_TEXT) -> None: super().__init__() self._current_page_idx = 0 self._page_count = 1 self._dialogTitle = "" - self._header_text = "" self._license_text = "" self._package_name = "" + self._icon_url = "" + self._decline_button_text = decline_button_text + + @pyqtProperty(str, constant = True) + def acceptButtonText(self): + return self.ACCEPT_BUTTON_TEXT + + @pyqtProperty(str, constant = True) + def declineButtonText(self): + return self._decline_button_text @pyqtProperty(str, notify=dialogTitleChanged) def dialogTitle(self) -> str: return self._dialogTitle - @pyqtProperty(str, notify=headerChanged) - def headerText(self) -> str: - return self._header_text + @pyqtProperty(str, notify=packageNameChanged) + def packageName(self) -> str: + return self._package_name def setPackageName(self, name: str) -> None: - self._header_text = name + ": " + catalog.i18nc("@label", "This plugin contains a license.\nYou need to accept this license to install this plugin.\nDo you agree with the terms below?") - self.headerChanged.emit() + self._package_name = name + self.packageNameChanged.emit() + + @pyqtProperty(str, notify=iconChanged) + def iconUrl(self) -> str: + return self._icon_url + + def setIconUrl(self, url: str): + self._icon_url = url + self.iconChanged.emit() @pyqtProperty(str, notify=licenseTextChanged) def licenseText(self) -> str: diff --git a/plugins/Toolbox/src/CloudSync/LicensePresenter.py b/plugins/Toolbox/src/CloudSync/LicensePresenter.py index cefe6f4037..74fc2a3099 100644 --- a/plugins/Toolbox/src/CloudSync/LicensePresenter.py +++ b/plugins/Toolbox/src/CloudSync/LicensePresenter.py @@ -17,6 +17,7 @@ class LicensePresenter(QObject): def __init__(self, app: CuraApplication) -> None: super().__init__() + self._catalog = i18nCatalog("cura") self._dialog = None # type: Optional[QObject] self._package_manager = app.getPackageManager() # type: PackageManager # Emits List[Dict[str, [Any]] containing for example @@ -25,7 +26,8 @@ class LicensePresenter(QObject): self._current_package_idx = 0 self._package_models = [] # type: List[Dict] - self._license_model = LicenseModel() # type: LicenseModel + decline_button_text = self._catalog.i18nc("@button", "Decline and remove from account") + self._license_model = LicenseModel(decline_button_text=decline_button_text) # type: LicenseModel self._app = app @@ -34,7 +36,7 @@ class LicensePresenter(QObject): ## Show a license dialog for multiple packages where users can read a license and accept or decline them # \param plugin_path: Root directory of the Toolbox plugin # \param packages: Dict[package id, file path] - def present(self, plugin_path: str, packages: Dict[str, str]) -> None: + def present(self, plugin_path: str, packages: Dict[str, Dict[str, str]]) -> None: path = os.path.join(plugin_path, self._compatibility_dialog_path) self._initState(packages) @@ -42,7 +44,7 @@ class LicensePresenter(QObject): if self._dialog is None: context_properties = { - "catalog": i18nCatalog("cura"), + "catalog": self._catalog, "licenseModel": self._license_model, "handler": self } @@ -60,18 +62,20 @@ class LicensePresenter(QObject): self._package_models[self._current_package_idx]["accepted"] = False self._checkNextPage() - def _initState(self, packages: Dict[str, str]) -> None: + def _initState(self, packages: Dict[str, Dict[str, str]]) -> None: self._package_models = [ { "package_id" : package_id, - "package_path" : package_path, + "package_path" : item["package_path"], + "icon_url" : item["icon_url"], "accepted" : None #: None: no answer yet } - for package_id, package_path in packages.items() + for package_id, item in packages.items() ] def _presentCurrentPackage(self) -> None: package_model = self._package_models[self._current_package_idx] + package_info = self._package_manager.getPackageInfo(package_model["package_path"]) license_content = self._package_manager.getPackageLicense(package_model["package_path"]) if license_content is None: # Implicitly accept when there is no license @@ -79,7 +83,8 @@ class LicensePresenter(QObject): return self._license_model.setCurrentPageIdx(self._current_package_idx) - self._license_model.setPackageName(package_model["package_id"]) + self._license_model.setPackageName(package_info["display_name"]) + self._license_model.setIconUrl(package_model["icon_url"]) self._license_model.setLicenseText(license_content) if self._dialog: self._dialog.open() # Does nothing if already open diff --git a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py index e97bdbcbc4..4b8b3cf7f9 100644 --- a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py +++ b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py @@ -63,9 +63,9 @@ class SyncOrchestrator(Extension): self._download_presenter.download(mutations) ## Called when a set of packages have finished downloading - # \param success_items: Dict[package_id, file_path] + # \param success_items: Dict[package_id, Dict[str, str]] # \param error_items: List[package_id] - def _onDownloadFinished(self, success_items: Dict[str, str], error_items: List[str]) -> None: + def _onDownloadFinished(self, success_items: Dict[str, Dict[str, str]], error_items: List[str]) -> None: if error_items: message = i18n_catalog.i18nc("@info:generic", "{} plugins failed to download".format(len(error_items))) self._showErrorMessage(message) diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index e0d04bed5b..72e1f59615 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -154,10 +154,11 @@ class Toolbox(QObject, Extension): def getLicenseDialogPluginFileLocation(self) -> str: return self._license_dialog_plugin_file_location - def openLicenseDialog(self, plugin_name: str, license_content: str, plugin_file_location: str) -> None: + def openLicenseDialog(self, plugin_name: str, license_content: str, plugin_file_location: str, icon_url: str) -> None: # Set page 1/1 when opening the dialog for a single package self._license_model.setCurrentPageIdx(0) self._license_model.setPageCount(1) + self._license_model.setIconUrl(icon_url) self._license_model.setPackageName(plugin_name) self._license_model.setLicenseText(license_content) @@ -670,14 +671,17 @@ class Toolbox(QObject, Extension): return license_content = self._package_manager.getPackageLicense(file_path) + package_id = package_info["package_id"] if license_content is not None: - self.openLicenseDialog(package_info["package_id"], license_content, file_path) + # get the icon url for package_id, make sure the result is a string, never None + icon_url = next((x["icon_url"] for x in self.packagesModel.items if x["id"] == package_id), None) or "" + self.openLicenseDialog(package_info["display_name"], license_content, file_path, icon_url) return - package_id = self.install(file_path) - if package_id != package_info["package_id"]: - Logger.error("Installed package {} does not match {}".format(package_id, package_info["package_id"])) - self.subscribe(package_id) + installed_id = self.install(file_path) + if installed_id != package_id: + Logger.error("Installed package {} does not match {}".format(installed_id, package_id)) + self.subscribe(installed_id) # Getter & Setters for Properties: # -------------------------------------------------------------------------- @@ -699,14 +703,14 @@ class Toolbox(QObject, Extension): def isDownloading(self) -> bool: return self._is_downloading - def setActivePackage(self, package: Dict[str, Any]) -> None: + def setActivePackage(self, package: QObject) -> None: if self._active_package != package: self._active_package = package self.activePackageChanged.emit() ## The active package is the package that is currently being downloaded @pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged) - def activePackage(self) -> Optional[Dict[str, Any]]: + def activePackage(self) -> Optional[QObject]: return self._active_package def setViewCategory(self, category: str = "plugin") -> None: diff --git a/resources/definitions/renkforce_rf100.def.json b/resources/definitions/renkforce_rf100.def.json index 2ff34a7519..8ebd9c02fe 100644 --- a/resources/definitions/renkforce_rf100.def.json +++ b/resources/definitions/renkforce_rf100.def.json @@ -18,10 +18,10 @@ "default_value": "skirt" }, "bottom_thickness": { - "value": "0.5" + "value": "0.6" }, "brim_width": { - "value": "2.0" + "value": "3.0" }, "cool_fan_enabled": { "value": "True" @@ -39,19 +39,28 @@ "value": "True" }, "cool_min_layer_time": { - "value": "5.0" + "value": "1.0" }, "cool_min_speed": { - "value": "10.0" + "value": "5.0" }, "infill_before_walls": { "value": "True" }, + "infill_line_width": { + "value": "0.6" + }, "infill_overlap": { "value": "15.0" }, + "infill_sparse_density": { + "value": "26.0" + }, + "ironing_enabled": { + "value": "True" + }, "layer_0_z_overlap": { - "value": "0.22" + "value": "0.11" }, "layer_height_0": { "value": "0.3" @@ -60,11 +69,23 @@ "value": "100" }, "machine_end_gcode": { - "default_value": ";End GCode\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 E-5 X-20 Y-20 ;retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG0 Z{machine_height} ;move the platform all the way down\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM84 ;steppers off\nG90 ;absolute positioning\nM117 Done" + "default_value": ";End GCode\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-4 F300 ;move Z up a bit and retract filament even more\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG0 Z{machine_height} F1800 ;move the platform all the way down\nG28 X0 Y0 F1800 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning\nM117 Done" }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "machine_head_with_fans_polygon": + { + "default_value": [ + [-26, -27], + [38, -27], + [38, 55], + [-26, 55] + ] + }, + "gantry_height": { + "value": "8" + }, "machine_height": { "value": "100" }, @@ -72,7 +93,7 @@ "default_value": "Renkforce RF100" }, "machine_start_gcode": { - "default_value": ";Start GCode\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\n;Put printing message on LCD screen\nM117 Printing..." + "default_value": ";Sliced at: {day} {date} {time}\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG1 Z5.0 F1800 ;move Z to 5mm\nG28 X0 Y0 F1800 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstop\nG92 E0 ;zero the extruded length\nG1 F200 E6.0 ;extrude 6.0mm of feed stock to build pressure\nG1 Z5.0 F300 ;move the platform down 5mm\nG92 E0 ;zero the extruded length again\nG1 F1800\n;Put printing message on LCD screen\nM117 Printing..." }, "machine_width": { "value": "100" @@ -90,7 +111,7 @@ "value": "True" }, "raft_airgap": { - "value": "0.22" + "value": "0.33" }, "raft_base_line_spacing": { "value": "3.0" @@ -111,22 +132,25 @@ "value": "0.27" }, "raft_margin": { - "value": "5.0" + "value": "6.0" + }, + "raft_speed": { + "value": "20.0" }, "raft_surface_layers": { - "value": "2.0" + "value": "2" }, "raft_surface_line_spacing": { - "value": "3.0" + "value": "0.4" }, "raft_surface_line_width": { "value": "0.4" }, "raft_surface_thickness": { - "value": "0.27" + "value": "0.1" }, "retraction_amount": { - "value": "2.0" + "value": "5.0" }, "retraction_combing": { "default_value": "all" @@ -134,15 +158,12 @@ "retraction_enable": { "value": "True" }, - "retraction_hop_enabled": { + "retraction_hop": { "value": "1.0" }, "retraction_min_travel": { "value": "1.5" }, - "retraction_speed": { - "value": "40.0" - }, "skin_overlap": { "value": "15.0" }, @@ -185,6 +206,9 @@ "support_infill_rate": { "value": "15 if support_enable else 0 if support_tree_enable else 15" }, + "support_line_width": { + "value": "0.6" + }, "support_pattern": { "default_value": "lines" }, @@ -192,13 +216,13 @@ "default_value": "everywhere" }, "support_xy_distance": { - "value": "0.5" + "value": "0.7" }, "support_z_distance": { - "value": "0.1" + "value": "0.35" }, - "top_thickness": { - "value": "0.5" + "top_bottom_thickness": { + "value": "0.8" }, "wall_thickness": { "value": "0.8" diff --git a/resources/definitions/renkforce_rf100_v2.def.json b/resources/definitions/renkforce_rf100_v2.def.json new file mode 100644 index 0000000000..bd012eff06 --- /dev/null +++ b/resources/definitions/renkforce_rf100_v2.def.json @@ -0,0 +1,231 @@ +{ + "version": 2, + "name": "Renkforce RF100 V2", + "inherits": "fdmprinter", + "metadata": { + "author": "Simon Peter (based on RF100.ini by Conrad Electronic SE)", + "file_formats": "text/x-gcode", + "manufacturer": "Renkforce", + "visible": true, + "machine_extruder_trains": + { + "0": "renkforce_rf100_extruder_0" + } + }, + + "overrides": { + "adhesion_type": { + "default_value": "skirt" + }, + "bottom_thickness": { + "value": "0.6" + }, + "brim_width": { + "value": "3.0" + }, + "cool_fan_enabled": { + "value": "True" + }, + "cool_fan_full_at_height": { + "value": "0.5" + }, + "cool_fan_speed_max": { + "value": "100.0" + }, + "cool_fan_speed_min": { + "value": "100.0" + }, + "cool_lift_head": { + "value": "True" + }, + "cool_min_layer_time": { + "value": "1.0" + }, + "cool_min_speed": { + "value": "5.0" + }, + "infill_before_walls": { + "value": "True" + }, + "infill_line_width": { + "value": "0.6" + }, + "infill_overlap": { + "value": "15.0" + }, + "infill_sparse_density": { + "value": "26.0" + }, + "ironing_enabled": { + "value": "True" + }, + "layer_0_z_overlap": { + "value": "0.11" + }, + "layer_height_0": { + "value": "0.3" + }, + "machine_depth": { + "value": "120" + }, + "machine_end_gcode": { + "default_value": ";End GCode\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-4 F300 ;move Z up a bit and retract filament even more\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG0 Z{machine_height} F1800 ;move the platform all the way down\nG28 X0 Y0 F1800 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning\nM117 Done" + }, + "machine_gcode_flavor": { + "default_value": "RepRap (Marlin/Sprinter)" + }, + "machine_head_with_fans_polygon": + { + "default_value": [ + [-26, -27], + [38, -27], + [38, 55], + [-26, 55] + ] + }, + "gantry_height": { + "value": "8" + }, + "machine_height": { + "value": "120" + }, + "machine_name": { + "default_value": "Renkforce RF100 V2" + }, + "machine_start_gcode": { + "default_value": ";Sliced at: {day} {date} {time}\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG1 Z5.0 F1800 ;move Z to 5mm\nG28 X0 Y0 F1800 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstop\nG92 E0 ;zero the extruded length\nG1 F200 E6.0 ;extrude 6.0mm of feed stock to build pressure\nG1 Z5.0 F300 ;move the platform down 5mm\nG92 E0 ;zero the extruded length again\nG1 F1800\n;Put printing message on LCD screen\nM117 Printing..." + }, + "machine_width": { + "value": "120" + }, + "material_bed_temperature": { + "enabled": false + }, + "material_flow": { + "value": "110" + }, + "material_print_temperature": { + "value": "210.0" + }, + "ooze_shield_enabled": { + "value": "True" + }, + "raft_airgap": { + "value": "0.33" + }, + "raft_base_line_spacing": { + "value": "3.0" + }, + "raft_base_line_width": { + "value": "1.0" + }, + "raft_base_thickness": { + "value": "0.3" + }, + "raft_interface_line_spacing": { + "value": "3.0" + }, + "raft_interface_line_width": { + "value": "0.4" + }, + "raft_interface_thickness": { + "value": "0.27" + }, + "raft_margin": { + "value": "6.0" + }, + "raft_speed": { + "value": "20.0" + }, + "raft_surface_layers": { + "value": "2" + }, + "raft_surface_line_spacing": { + "value": "0.4" + }, + "raft_surface_line_width": { + "value": "0.4" + }, + "raft_surface_thickness": { + "value": "0.1" + }, + "retraction_amount": { + "value": "5.0" + }, + "retraction_combing": { + "default_value": "all" + }, + "retraction_enable": { + "value": "True" + }, + "retraction_hop": { + "value": "1.0" + }, + "retraction_min_travel": { + "value": "1.5" + }, + "skin_overlap": { + "value": "15.0" + }, + "skirt_brim_minimal_length": { + "value": "150.0" + }, + "skirt_gap": { + "value": "3.0" + }, + "skirt_line_count": { + "value": "3" + }, + "speed_infill": { + "value": "50.0" + }, + "speed_layer_0": { + "value": "15.0" + }, + "speed_print": { + "value": "50.0" + }, + "speed_topbottom": { + "value": "30.0" + }, + "speed_travel": { + "value": "50.0" + }, + "speed_wall_0": { + "value": "25.0" + }, + "speed_wall_x": { + "value": "35.0" + }, + "support_angle": { + "value": "60.0" + }, + "support_enable": { + "value": "False" + }, + "support_infill_rate": { + "value": "15 if support_enable else 0 if support_tree_enable else 15" + }, + "support_line_width": { + "value": "0.6" + }, + "support_pattern": { + "default_value": "lines" + }, + "support_type": { + "default_value": "everywhere" + }, + "support_xy_distance": { + "value": "0.7" + }, + "support_z_distance": { + "value": "0.35" + }, + "top_bottom_thickness": { + "value": "0.8" + }, + "wall_thickness": { + "value": "0.8" + } + } +} diff --git a/resources/definitions/renkforce_rf100_xl.def.json b/resources/definitions/renkforce_rf100_xl.def.json new file mode 100644 index 0000000000..f7707913e2 --- /dev/null +++ b/resources/definitions/renkforce_rf100_xl.def.json @@ -0,0 +1,219 @@ +{ + "version": 2, + "name": "Renkforce RF100 XL", + "inherits": "fdmprinter", + "metadata": { + "author": "Simon Peter (based on RF100.ini by Conrad Electronic SE)", + "file_formats": "text/x-gcode", + "manufacturer": "Renkforce", + "visible": true, + "machine_extruder_trains": + { + "0": "renkforce_rf100_xl_extruder_0" + } + }, + + "overrides": { + "adhesion_type": { + "default_value": "skirt" + }, + "bottom_thickness": { + "value": "0.6" + }, + "brim_width": { + "value": "3.0" + }, + "cool_fan_enabled": { + "value": "True" + }, + "cool_fan_full_at_height": { + "value": "0.5" + }, + "cool_fan_speed_max": { + "value": "100.0" + }, + "cool_fan_speed_min": { + "value": "100.0" + }, + "cool_lift_head": { + "value": "True" + }, + "cool_min_layer_time": { + "value": "1.0" + }, + "cool_min_speed": { + "value": "5.0" + }, + "infill_before_walls": { + "value": "True" + }, + "infill_line_width": { + "value": "0.6" + }, + "infill_overlap": { + "value": "15.0" + }, + "infill_sparse_density": { + "value": "26.0" + }, + "ironing_enabled": { + "value": "True" + }, + "layer_0_z_overlap": { + "value": "0.11" + }, + "layer_height_0": { + "value": "0.3" + }, + "machine_depth": { + "value": "200" + }, + "machine_end_gcode": { + "default_value": ";End GCode\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-4 F300 ;move Z up a bit and retract filament even more\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG0 Z{machine_height} F1800 ;move the platform all the way down\nG28 X0 Y0 F1800 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning\nM117 Done" + }, + "machine_gcode_flavor": { + "default_value": "RepRap (Marlin/Sprinter)" + }, + "machine_heated_bed": { + "default_value": "true" + }, + "machine_height": { + "value": "200" + }, + "machine_name": { + "default_value": "Renkforce RF100 XL" + }, + "machine_start_gcode": { + "default_value": ";Sliced at: {day} {date} {time}\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG1 Z5.0 F1800 ;move Z to 5mm\nG28 X0 Y0 F1800 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstop\nG92 E0 ;zero the extruded length\nG1 F200 E6.0 ;extrude 6.0mm of feed stock to build pressure\nG1 Z5.0 F300 ;move the platform down 5mm\nG92 E0 ;zero the extruded length again\nG1 F1800\n;Put printing message on LCD screen\nM117 Printing..." + }, + "machine_width": { + "value": "200" + }, + "material_bed_temperature": { + "value": "70" + }, + "material_print_temperature": { + "value": "210.0" + }, + "ooze_shield_enabled": { + "value": "True" + }, + "raft_airgap": { + "value": "0.33" + }, + "raft_base_line_spacing": { + "value": "3.0" + }, + "raft_base_line_width": { + "value": "1.0" + }, + "raft_base_thickness": { + "value": "0.3" + }, + "raft_interface_line_spacing": { + "value": "3.0" + }, + "raft_interface_line_width": { + "value": "0.4" + }, + "raft_interface_thickness": { + "value": "0.27" + }, + "raft_margin": { + "value": "6.0" + }, + "raft_speed": { + "value": "20.0" + }, + "raft_surface_layers": { + "value": "2" + }, + "raft_surface_line_spacing": { + "value": "0.4" + }, + "raft_surface_line_width": { + "value": "0.4" + }, + "raft_surface_thickness": { + "value": "0.1" + }, + "retraction_amount": { + "value": "5.0" + }, + "retraction_combing": { + "default_value": "all" + }, + "retraction_enable": { + "value": "True" + }, + "retraction_hop": { + "value": "1.0" + }, + "retraction_min_travel": { + "value": "1.5" + }, + "skin_overlap": { + "value": "15.0" + }, + "skirt_brim_minimal_length": { + "value": "150.0" + }, + "skirt_gap": { + "value": "3.0" + }, + "skirt_line_count": { + "value": "3" + }, + "speed_infill": { + "value": "50.0" + }, + "speed_layer_0": { + "value": "15.0" + }, + "speed_print": { + "value": "50.0" + }, + "speed_topbottom": { + "value": "30.0" + }, + "speed_travel": { + "value": "50.0" + }, + "speed_wall_0": { + "value": "25.0" + }, + "speed_wall_x": { + "value": "35.0" + }, + "support_angle": { + "value": "60.0" + }, + "support_enable": { + "value": "False" + }, + "support_infill_rate": { + "value": "15 if support_enable else 0 if support_tree_enable else 15" + }, + "support_line_width": { + "value": "0.6" + }, + "support_pattern": { + "default_value": "lines" + }, + "support_type": { + "default_value": "everywhere" + }, + "support_xy_distance": { + "value": "0.7" + }, + "support_z_distance": { + "value": "0.35" + }, + "top_bottom_thickness": { + "value": "0.8" + }, + "wall_thickness": { + "value": "0.8" + } + } +} diff --git a/resources/extruders/renkforce_rf100_xl_extruder_0.def.json b/resources/extruders/renkforce_rf100_xl_extruder_0.def.json new file mode 100644 index 0000000000..718a3738c4 --- /dev/null +++ b/resources/extruders/renkforce_rf100_xl_extruder_0.def.json @@ -0,0 +1,15 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "renkforce_rf100_xl", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/qml/MainWindow/ApplicationMenu.qml b/resources/qml/MainWindow/ApplicationMenu.qml index 1ddb0410b2..05e349841b 100644 --- a/resources/qml/MainWindow/ApplicationMenu.qml +++ b/resources/qml/MainWindow/ApplicationMenu.qml @@ -127,8 +127,8 @@ Item icon: StandardIcon.Question onYes: { - CuraApplication.deleteAll(); - Cura.Actions.resetProfile.trigger(); + CuraApplication.resetWorkspace() + Cura.Actions.resetProfile.trigger() UM.Controller.setActiveStage("PrepareStage") } } diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index c2a70143c3..ab32bff619 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -202,8 +202,9 @@ Item // dragging a tool handle. Rectangle { - x: -base.x + base.mouseX + UM.Theme.getSize("default_margin").width - y: -base.y + base.mouseY + UM.Theme.getSize("default_margin").height + id: toolInfo + x: visible ? -base.x + base.mouseX + UM.Theme.getSize("default_margin").width: 0 + y: visible ? -base.y + base.mouseY + UM.Theme.getSize("default_margin").height: 0 width: toolHint.width + UM.Theme.getSize("default_margin").width height: toolHint.height;