Merge branch 'master' of github.com:Ultimaker/Cura into CURA-7090-addition

This commit is contained in:
Dimitriovski 2020-01-27 13:25:35 +01:00
commit 2e0fef3bd4
No known key found for this signature in database
GPG key ID: 4E62757E2B0D304D
16 changed files with 670 additions and 71 deletions

View file

@ -29,9 +29,13 @@ parser.add_argument("--debug",
known_args = vars(parser.parse_known_args()[0]) known_args = vars(parser.parse_known_args()[0])
if with_sentry_sdk: if with_sentry_sdk:
sentry_env = "production" sentry_env = "unknown" # Start off with a "IDK"
if ApplicationMetadata.CuraVersion == "master": if hasattr(sys, "frozen"):
sentry_env = "production" # A frozen build is a "real" distribution.
elif ApplicationMetadata.CuraVersion == "master":
sentry_env = "development" sentry_env = "development"
elif "beta" in ApplicationMetadata.CuraVersion or "BETA" in ApplicationMetadata.CuraVersion:
sentry_env = "beta"
try: try:
if ApplicationMetadata.CuraVersion.split(".")[2] == "99": if ApplicationMetadata.CuraVersion.split(".")[2] == "99":
sentry_env = "nightly" sentry_env = "nightly"

View file

@ -4,7 +4,8 @@
from configparser import ConfigParser from configparser import ConfigParser
import zipfile import zipfile
import os 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 import xml.etree.ElementTree as ET
@ -732,7 +733,25 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
base_file_name = os.path.basename(file_name) base_file_name = os.path.basename(file_name)
self.setWorkspaceName(base_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): def _processQualityChanges(self, global_stack):
if self._machine_info.quality_changes_info is None: if self._machine_info.quality_changes_info is None:

View file

@ -73,11 +73,25 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
version_config_parser.write(version_file_string) version_config_parser.write(version_file_string)
archive.writestr(version_file, version_file_string.getvalue()) archive.writestr(version_file, version_file_string.getvalue())
self._writePluginMetadataToArchive(archive)
# Close the archive & reset states. # Close the archive & reset states.
archive.close() archive.close()
mesh_writer.setStoreArchive(False) mesh_writer.setStoreArchive(False)
return True 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. ## Helper function that writes ContainerStacks, InstanceContainers and DefinitionContainers to the archive.
# \param container That follows the \type{ContainerInterface} to archive. # \param container That follows the \type{ContainerInterface} to archive.
# \param archive The archive to write to. # \param archive The archive to write to.

View file

@ -1,5 +1,6 @@
# Copyright (c) 2015 Ultimaker B.V. # Copyright (c) 2015 Ultimaker B.V.
# Uranium is released under the terms of the LGPLv3 or higher. # Uranium is released under the terms of the LGPLv3 or higher.
from typing import Optional
from UM.Mesh.MeshWriter import MeshWriter from UM.Mesh.MeshWriter import MeshWriter
from UM.Math.Vector import Vector from UM.Math.Vector import Vector
@ -40,7 +41,7 @@ class ThreeMFWriter(MeshWriter):
} }
self._unit_matrix_string = self._convertMatrixToString(Matrix()) self._unit_matrix_string = self._convertMatrixToString(Matrix())
self._archive = None self._archive = None # type: Optional[zipfile.ZipFile]
self._store_archive = False self._store_archive = False
def _convertMatrixToString(self, matrix): def _convertMatrixToString(self, matrix):

View file

@ -5,6 +5,7 @@ import QtQuick 2.10
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
import QtQuick.Window 2.2 import QtQuick.Window 2.2
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
// TODO: Switch to QtQuick.Controls 2.x and remove QtQuick.Controls.Styles // 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 minimumHeight: UM.Theme.getSize("license_window_minimum").height
width: minimumWidth width: minimumWidth
height: minimumHeight height: minimumHeight
backgroundColor: UM.Theme.getColor("main_background")
margin: screenScaleFactor * 10
Item ColumnLayout
{ {
anchors.fill: parent anchors.fill: parent
spacing: UM.Theme.getSize("thick_margin").height
UM.I18nCatalog{id: catalog; name: "cura"} UM.I18nCatalog{id: catalog; name: "cura"}
Label Label
{ {
id: licenseHeader id: licenseHeader
anchors.top: parent.top Layout.fillWidth: true
anchors.left: parent.left text: catalog.i18nc("@label", "You need to accept the license to install the package")
anchors.right: parent.right
text: licenseModel.headerText
wrapMode: Text.Wrap wrapMode: Text.Wrap
renderType: Text.NativeRendering 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 TextArea
{ {
id: licenseText id: licenseText
anchors.top: licenseHeader.bottom Layout.fillWidth: true
anchors.bottom: parent.bottom Layout.fillHeight: true
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.topMargin: UM.Theme.getSize("default_margin").height
readOnly: true readOnly: true
text: licenseModel.licenseText text: licenseModel.licenseText
@ -57,7 +90,7 @@ UM.Dialog
leftPadding: UM.Theme.getSize("dialog_primary_button_padding").width leftPadding: UM.Theme.getSize("dialog_primary_button_padding").width
rightPadding: 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() } onClicked: { handler.onLicenseAccepted() }
} }
] ]
@ -67,7 +100,7 @@ UM.Dialog
Cura.SecondaryButton Cura.SecondaryButton
{ {
id: declineButton id: declineButton
text: catalog.i18nc("@button", "Decline and remove from account") text: licenseModel.declineButtonText
onClicked: { handler.onLicenseDeclined() } onClicked: { handler.onLicenseDeclined() }
} }
] ]

View file

@ -62,7 +62,8 @@ class DownloadPresenter:
"received": 0, "received": 0,
"total": 1, # make sure this is not considered done yet. Also divByZero-safe "total": 1, # make sure this is not considered done yet. Also divByZero-safe
"file_written": None, "file_written": None,
"request_data": request_data "request_data": request_data,
"package_model": item
} }
self._started = True self._started = True
@ -128,7 +129,14 @@ class DownloadPresenter:
if not item["file_written"]: if not item["file_written"]:
return False 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] error_items = [package_id for package_id in self._error]
self._progress_message.hide() self._progress_message.hide()

View file

@ -6,31 +6,52 @@ catalog = i18nCatalog("cura")
# Model for the ToolboxLicenseDialog # Model for the ToolboxLicenseDialog
class LicenseModel(QObject): class LicenseModel(QObject):
dialogTitleChanged = pyqtSignal() DEFAULT_DECLINE_BUTTON_TEXT = catalog.i18nc("@button", "Decline")
headerChanged = pyqtSignal() ACCEPT_BUTTON_TEXT = catalog.i18nc("@button", "Agree")
licenseTextChanged = pyqtSignal()
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__() super().__init__()
self._current_page_idx = 0 self._current_page_idx = 0
self._page_count = 1 self._page_count = 1
self._dialogTitle = "" self._dialogTitle = ""
self._header_text = ""
self._license_text = "" self._license_text = ""
self._package_name = "" 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) @pyqtProperty(str, notify=dialogTitleChanged)
def dialogTitle(self) -> str: def dialogTitle(self) -> str:
return self._dialogTitle return self._dialogTitle
@pyqtProperty(str, notify=headerChanged) @pyqtProperty(str, notify=packageNameChanged)
def headerText(self) -> str: def packageName(self) -> str:
return self._header_text return self._package_name
def setPackageName(self, name: str) -> None: 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._package_name = name
self.headerChanged.emit() 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) @pyqtProperty(str, notify=licenseTextChanged)
def licenseText(self) -> str: def licenseText(self) -> str:

View file

@ -17,6 +17,7 @@ class LicensePresenter(QObject):
def __init__(self, app: CuraApplication) -> None: def __init__(self, app: CuraApplication) -> None:
super().__init__() super().__init__()
self._catalog = i18nCatalog("cura")
self._dialog = None # type: Optional[QObject] self._dialog = None # type: Optional[QObject]
self._package_manager = app.getPackageManager() # type: PackageManager self._package_manager = app.getPackageManager() # type: PackageManager
# Emits List[Dict[str, [Any]] containing for example # Emits List[Dict[str, [Any]] containing for example
@ -25,7 +26,8 @@ class LicensePresenter(QObject):
self._current_package_idx = 0 self._current_package_idx = 0
self._package_models = [] # type: List[Dict] 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 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 ## 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 plugin_path: Root directory of the Toolbox plugin
# \param packages: Dict[package id, file path] # \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) path = os.path.join(plugin_path, self._compatibility_dialog_path)
self._initState(packages) self._initState(packages)
@ -42,7 +44,7 @@ class LicensePresenter(QObject):
if self._dialog is None: if self._dialog is None:
context_properties = { context_properties = {
"catalog": i18nCatalog("cura"), "catalog": self._catalog,
"licenseModel": self._license_model, "licenseModel": self._license_model,
"handler": self "handler": self
} }
@ -60,18 +62,20 @@ class LicensePresenter(QObject):
self._package_models[self._current_package_idx]["accepted"] = False self._package_models[self._current_package_idx]["accepted"] = False
self._checkNextPage() self._checkNextPage()
def _initState(self, packages: Dict[str, str]) -> None: def _initState(self, packages: Dict[str, Dict[str, str]]) -> None:
self._package_models = [ self._package_models = [
{ {
"package_id" : package_id, "package_id" : package_id,
"package_path" : package_path, "package_path" : item["package_path"],
"icon_url" : item["icon_url"],
"accepted" : None #: None: no answer yet "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: def _presentCurrentPackage(self) -> None:
package_model = self._package_models[self._current_package_idx] 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"]) license_content = self._package_manager.getPackageLicense(package_model["package_path"])
if license_content is None: if license_content is None:
# Implicitly accept when there is no license # Implicitly accept when there is no license
@ -79,7 +83,8 @@ class LicensePresenter(QObject):
return return
self._license_model.setCurrentPageIdx(self._current_package_idx) 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) self._license_model.setLicenseText(license_content)
if self._dialog: if self._dialog:
self._dialog.open() # Does nothing if already open self._dialog.open() # Does nothing if already open

View file

@ -63,9 +63,9 @@ class SyncOrchestrator(Extension):
self._download_presenter.download(mutations) self._download_presenter.download(mutations)
## Called when a set of packages have finished downloading ## 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] # \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: if error_items:
message = i18n_catalog.i18nc("@info:generic", "{} plugins failed to download".format(len(error_items))) message = i18n_catalog.i18nc("@info:generic", "{} plugins failed to download".format(len(error_items)))
self._showErrorMessage(message) self._showErrorMessage(message)

View file

@ -154,10 +154,11 @@ class Toolbox(QObject, Extension):
def getLicenseDialogPluginFileLocation(self) -> str: def getLicenseDialogPluginFileLocation(self) -> str:
return self._license_dialog_plugin_file_location 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 # Set page 1/1 when opening the dialog for a single package
self._license_model.setCurrentPageIdx(0) self._license_model.setCurrentPageIdx(0)
self._license_model.setPageCount(1) self._license_model.setPageCount(1)
self._license_model.setIconUrl(icon_url)
self._license_model.setPackageName(plugin_name) self._license_model.setPackageName(plugin_name)
self._license_model.setLicenseText(license_content) self._license_model.setLicenseText(license_content)
@ -670,14 +671,17 @@ class Toolbox(QObject, Extension):
return return
license_content = self._package_manager.getPackageLicense(file_path) license_content = self._package_manager.getPackageLicense(file_path)
package_id = package_info["package_id"]
if license_content is not None: 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 return
package_id = self.install(file_path) installed_id = self.install(file_path)
if package_id != package_info["package_id"]: if installed_id != package_id:
Logger.error("Installed package {} does not match {}".format(package_id, package_info["package_id"])) Logger.error("Installed package {} does not match {}".format(installed_id, package_id))
self.subscribe(package_id) self.subscribe(installed_id)
# Getter & Setters for Properties: # Getter & Setters for Properties:
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
@ -699,14 +703,14 @@ class Toolbox(QObject, Extension):
def isDownloading(self) -> bool: def isDownloading(self) -> bool:
return self._is_downloading return self._is_downloading
def setActivePackage(self, package: Dict[str, Any]) -> None: def setActivePackage(self, package: QObject) -> None:
if self._active_package != package: if self._active_package != package:
self._active_package = package self._active_package = package
self.activePackageChanged.emit() self.activePackageChanged.emit()
## The active package is the package that is currently being downloaded ## The active package is the package that is currently being downloaded
@pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged) @pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged)
def activePackage(self) -> Optional[Dict[str, Any]]: def activePackage(self) -> Optional[QObject]:
return self._active_package return self._active_package
def setViewCategory(self, category: str = "plugin") -> None: def setViewCategory(self, category: str = "plugin") -> None:

View file

@ -18,10 +18,10 @@
"default_value": "skirt" "default_value": "skirt"
}, },
"bottom_thickness": { "bottom_thickness": {
"value": "0.5" "value": "0.6"
}, },
"brim_width": { "brim_width": {
"value": "2.0" "value": "3.0"
}, },
"cool_fan_enabled": { "cool_fan_enabled": {
"value": "True" "value": "True"
@ -39,19 +39,28 @@
"value": "True" "value": "True"
}, },
"cool_min_layer_time": { "cool_min_layer_time": {
"value": "5.0" "value": "1.0"
}, },
"cool_min_speed": { "cool_min_speed": {
"value": "10.0" "value": "5.0"
}, },
"infill_before_walls": { "infill_before_walls": {
"value": "True" "value": "True"
}, },
"infill_line_width": {
"value": "0.6"
},
"infill_overlap": { "infill_overlap": {
"value": "15.0" "value": "15.0"
}, },
"infill_sparse_density": {
"value": "26.0"
},
"ironing_enabled": {
"value": "True"
},
"layer_0_z_overlap": { "layer_0_z_overlap": {
"value": "0.22" "value": "0.11"
}, },
"layer_height_0": { "layer_height_0": {
"value": "0.3" "value": "0.3"
@ -60,11 +69,23 @@
"value": "100" "value": "100"
}, },
"machine_end_gcode": { "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": { "machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)" "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": { "machine_height": {
"value": "100" "value": "100"
}, },
@ -72,7 +93,7 @@
"default_value": "Renkforce RF100" "default_value": "Renkforce RF100"
}, },
"machine_start_gcode": { "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": { "machine_width": {
"value": "100" "value": "100"
@ -90,7 +111,7 @@
"value": "True" "value": "True"
}, },
"raft_airgap": { "raft_airgap": {
"value": "0.22" "value": "0.33"
}, },
"raft_base_line_spacing": { "raft_base_line_spacing": {
"value": "3.0" "value": "3.0"
@ -111,22 +132,25 @@
"value": "0.27" "value": "0.27"
}, },
"raft_margin": { "raft_margin": {
"value": "5.0" "value": "6.0"
},
"raft_speed": {
"value": "20.0"
}, },
"raft_surface_layers": { "raft_surface_layers": {
"value": "2.0" "value": "2"
}, },
"raft_surface_line_spacing": { "raft_surface_line_spacing": {
"value": "3.0" "value": "0.4"
}, },
"raft_surface_line_width": { "raft_surface_line_width": {
"value": "0.4" "value": "0.4"
}, },
"raft_surface_thickness": { "raft_surface_thickness": {
"value": "0.27" "value": "0.1"
}, },
"retraction_amount": { "retraction_amount": {
"value": "2.0" "value": "5.0"
}, },
"retraction_combing": { "retraction_combing": {
"default_value": "all" "default_value": "all"
@ -134,15 +158,12 @@
"retraction_enable": { "retraction_enable": {
"value": "True" "value": "True"
}, },
"retraction_hop_enabled": { "retraction_hop": {
"value": "1.0" "value": "1.0"
}, },
"retraction_min_travel": { "retraction_min_travel": {
"value": "1.5" "value": "1.5"
}, },
"retraction_speed": {
"value": "40.0"
},
"skin_overlap": { "skin_overlap": {
"value": "15.0" "value": "15.0"
}, },
@ -185,6 +206,9 @@
"support_infill_rate": { "support_infill_rate": {
"value": "15 if support_enable else 0 if support_tree_enable else 15" "value": "15 if support_enable else 0 if support_tree_enable else 15"
}, },
"support_line_width": {
"value": "0.6"
},
"support_pattern": { "support_pattern": {
"default_value": "lines" "default_value": "lines"
}, },
@ -192,13 +216,13 @@
"default_value": "everywhere" "default_value": "everywhere"
}, },
"support_xy_distance": { "support_xy_distance": {
"value": "0.5" "value": "0.7"
}, },
"support_z_distance": { "support_z_distance": {
"value": "0.1" "value": "0.35"
}, },
"top_thickness": { "top_bottom_thickness": {
"value": "0.5" "value": "0.8"
}, },
"wall_thickness": { "wall_thickness": {
"value": "0.8" "value": "0.8"

View file

@ -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"
}
}
}

View file

@ -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"
}
}
}

View file

@ -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 }
}
}

View file

@ -127,8 +127,8 @@ Item
icon: StandardIcon.Question icon: StandardIcon.Question
onYes: onYes:
{ {
CuraApplication.deleteAll(); CuraApplication.resetWorkspace()
Cura.Actions.resetProfile.trigger(); Cura.Actions.resetProfile.trigger()
UM.Controller.setActiveStage("PrepareStage") UM.Controller.setActiveStage("PrepareStage")
} }
} }

View file

@ -202,8 +202,9 @@ Item
// dragging a tool handle. // dragging a tool handle.
Rectangle Rectangle
{ {
x: -base.x + base.mouseX + UM.Theme.getSize("default_margin").width id: toolInfo
y: -base.y + base.mouseY + UM.Theme.getSize("default_margin").height 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 width: toolHint.width + UM.Theme.getSize("default_margin").width
height: toolHint.height; height: toolHint.height;