mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 06:57:28 -06:00
Merge branch 'master' of https://github.com/Ultimaker/Cura
This commit is contained in:
commit
155408d77d
25 changed files with 751 additions and 170 deletions
|
@ -28,11 +28,12 @@ class CuraAPI(QObject):
|
|||
# The main reason for this is that we want to prevent consumers of API to have a dependency on CuraApplication.
|
||||
# Since the API is intended to be used by plugins, the cura application should have already created this.
|
||||
def __new__(cls, application: Optional["CuraApplication"] = None):
|
||||
if cls.__instance is None:
|
||||
if application is None:
|
||||
raise Exception("Upon first time creation, the application must be set.")
|
||||
cls.__instance = super(CuraAPI, cls).__new__(cls)
|
||||
cls._application = application
|
||||
if cls.__instance is not None:
|
||||
raise RuntimeError("Tried to create singleton '{class_name}' more than once.".format(class_name = CuraAPI.__name__))
|
||||
if application is None:
|
||||
raise RuntimeError("Upon first time creation, the application must be set.")
|
||||
cls.__instance = super(CuraAPI, cls).__new__(cls)
|
||||
cls._application = application
|
||||
return cls.__instance
|
||||
|
||||
def __init__(self, application: Optional["CuraApplication"] = None) -> None:
|
||||
|
|
|
@ -747,6 +747,11 @@ class MachineManager(QObject):
|
|||
result = [] # type: List[str]
|
||||
for setting_instance in container.findInstances():
|
||||
setting_key = setting_instance.definition.key
|
||||
if setting_key == "print_sequence":
|
||||
old_value = container.getProperty(setting_key, "value")
|
||||
Logger.log("d", "Reset setting [%s] in [%s] because its old value [%s] is no longer valid", setting_key, container, old_value)
|
||||
result.append(setting_key)
|
||||
continue
|
||||
if not self._global_container_stack.getProperty(setting_key, "type") in ("extruder", "optional_extruder"):
|
||||
continue
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -72,18 +72,25 @@ class DisplayFilenameAndLayerOnLCD(Script):
|
|||
lcd_text = "M117 Printing " + name + " - Layer "
|
||||
i = self.getSettingValueByKey("startNum")
|
||||
for layer in data:
|
||||
display_text = lcd_text + str(i) + " " + name
|
||||
display_text = lcd_text + str(i)
|
||||
layer_index = data.index(layer)
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if line.startswith(";LAYER_COUNT:"):
|
||||
max_layer = line
|
||||
max_layer = max_layer.split(":")[1]
|
||||
if self.getSettingValueByKey("startNum") == 0:
|
||||
max_layer = str(int(max_layer) - 1)
|
||||
if line.startswith(";LAYER:"):
|
||||
if self.getSettingValueByKey("maxlayer"):
|
||||
display_text = display_text + " of " + max_layer
|
||||
if not self.getSettingValueByKey("scroll"):
|
||||
display_text = display_text + " " + name
|
||||
else:
|
||||
display_text = display_text + "!"
|
||||
if not self.getSettingValueByKey("scroll"):
|
||||
display_text = display_text + " " + name + "!"
|
||||
else:
|
||||
display_text = display_text + "!"
|
||||
line_index = lines.index(line)
|
||||
lines.insert(line_index + 1, display_text)
|
||||
i += 1
|
||||
|
|
|
@ -20,6 +20,8 @@ UM.Dialog{
|
|||
maximumHeight: minimumHeight
|
||||
margin: 0
|
||||
|
||||
property string actionButtonText: subscribedPackagesModel.hasIncompatiblePackages && !subscribedPackagesModel.hasCompatiblePackages ? catalog.i18nc("@button", "Dismiss") : catalog.i18nc("@button", "Next")
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: root
|
||||
|
@ -125,26 +127,6 @@ UM.Dialog{
|
|||
color: UM.Theme.getColor("text")
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
UM.TooltipArea
|
||||
{
|
||||
width: childrenRect.width;
|
||||
height: childrenRect.height;
|
||||
text: catalog.i18nc("@info:tooltip", "Dismisses the package and won't be shown in this dialog anymore")
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: packageIcon.verticalCenter
|
||||
Label
|
||||
{
|
||||
text: "(Dismiss)"
|
||||
font: UM.Theme.getFont("small")
|
||||
color: UM.Theme.getColor("text")
|
||||
MouseArea
|
||||
{
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
onClicked: handler.dismissIncompatiblePackage(subscribedPackagesModel, model.package_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +140,7 @@ UM.Dialog{
|
|||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.margins: UM.Theme.getSize("default_margin").height
|
||||
text: catalog.i18nc("@button", "Next")
|
||||
text: actionButtonText
|
||||
onClicked: accept()
|
||||
leftPadding: UM.Theme.getSize("dialog_primary_button_padding").width
|
||||
rightPadding: UM.Theme.getSize("dialog_primary_button_padding").width
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
]
|
||||
|
|
|
@ -8,11 +8,12 @@ from UM import i18nCatalog
|
|||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
from UM.Signal import Signal
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.CuraApplication import CuraApplication, ApplicationMetadata
|
||||
from ..CloudApiModel import CloudApiModel
|
||||
from .SubscribedPackagesModel import SubscribedPackagesModel
|
||||
from ..UltimakerCloudScope import UltimakerCloudScope
|
||||
|
||||
from typing import List, Dict, Any
|
||||
|
||||
class CloudPackageChecker(QObject):
|
||||
def __init__(self, application: CuraApplication) -> None:
|
||||
|
@ -25,12 +26,12 @@ class CloudPackageChecker(QObject):
|
|||
|
||||
self._application.initializationFinished.connect(self._onAppInitialized)
|
||||
self._i18n_catalog = i18nCatalog("cura")
|
||||
self._sdk_version = ApplicationMetadata.CuraSDKVersion
|
||||
|
||||
# This is a plugin, so most of the components required are not ready when
|
||||
# this is initialized. Therefore, we wait until the application is ready.
|
||||
def _onAppInitialized(self) -> None:
|
||||
self._package_manager = self._application.getPackageManager()
|
||||
|
||||
# initial check
|
||||
self._fetchUserSubscribedPackages()
|
||||
# check again whenever the login state changes
|
||||
|
@ -38,25 +39,51 @@ class CloudPackageChecker(QObject):
|
|||
|
||||
def _fetchUserSubscribedPackages(self) -> None:
|
||||
if self._application.getCuraAPI().account.isLoggedIn:
|
||||
self._getUserPackages()
|
||||
self._getUserSubscribedPackages()
|
||||
|
||||
def _handleCompatibilityData(self, json_data) -> None:
|
||||
user_subscribed_packages = [plugin["package_id"] for plugin in json_data]
|
||||
def _getUserSubscribedPackages(self) -> None:
|
||||
Logger.debug("Requesting subscribed packages metadata from server.")
|
||||
url = CloudApiModel.api_url_user_packages
|
||||
self._application.getHttpRequestManager().get(url,
|
||||
callback = self._onUserPackagesRequestFinished,
|
||||
error_callback = self._onUserPackagesRequestFinished,
|
||||
scope = self._scope)
|
||||
|
||||
def _onUserPackagesRequestFinished(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"] = None) -> None:
|
||||
if error is not None or reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
|
||||
Logger.log("w",
|
||||
"Requesting user packages failed, response code %s while trying to connect to %s",
|
||||
reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url())
|
||||
return
|
||||
|
||||
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
|
||||
self._handleCompatibilityData(json_data["data"])
|
||||
except json.decoder.JSONDecodeError:
|
||||
Logger.log("w", "Received invalid JSON for user subscribed packages from the Web Marketplace")
|
||||
|
||||
def _handleCompatibilityData(self, subscribed_packages_payload: List[Dict[str, Any]]) -> None:
|
||||
user_subscribed_packages = [plugin["package_id"] for plugin in subscribed_packages_payload]
|
||||
user_installed_packages = self._package_manager.getUserInstalledPackages()
|
||||
|
||||
# We need to re-evaluate the dismissed packages
|
||||
# (i.e. some package might got updated to the correct SDK version in the meantime,
|
||||
# hence remove them from the Dismissed Incompatible list)
|
||||
self._package_manager.reEvaluateDismissedPackages(subscribed_packages_payload, self._sdk_version)
|
||||
user_dismissed_packages = self._package_manager.getDismissedPackages()
|
||||
if user_dismissed_packages:
|
||||
user_installed_packages += user_dismissed_packages
|
||||
# We check if there are packages installed in Cloud Marketplace but not in Cura marketplace
|
||||
|
||||
# We check if there are packages installed in Web Marketplace but not in Cura marketplace
|
||||
package_discrepancy = list(set(user_subscribed_packages).difference(user_installed_packages))
|
||||
|
||||
self._model.setMetadata(json_data)
|
||||
self._model.addDiscrepancies(package_discrepancy)
|
||||
self._model.initialize()
|
||||
|
||||
if not self._model.hasCompatiblePackages:
|
||||
return None
|
||||
|
||||
if package_discrepancy:
|
||||
self._model.addDiscrepancies(package_discrepancy)
|
||||
self._model.initialize(subscribed_packages_payload)
|
||||
self._handlePackageDiscrepancies()
|
||||
|
||||
def _handlePackageDiscrepancies(self) -> None:
|
||||
|
@ -76,35 +103,4 @@ class CloudPackageChecker(QObject):
|
|||
|
||||
def _onSyncButtonClicked(self, sync_message: Message, sync_message_action: str) -> None:
|
||||
sync_message.hide()
|
||||
self.discrepancies.emit(self._model)
|
||||
|
||||
def _getUserPackages(self) -> None:
|
||||
Logger.log("d", "Requesting subscribed packages metadata from server.")
|
||||
url = CloudApiModel.api_url_user_packages
|
||||
|
||||
self._application.getHttpRequestManager().get(url,
|
||||
callback = self._onUserPackagesRequestFinished,
|
||||
error_callback = self._onUserPackagesRequestFinished,
|
||||
scope = self._scope)
|
||||
|
||||
def _onUserPackagesRequestFinished(self,
|
||||
reply: "QNetworkReply",
|
||||
error: Optional["QNetworkReply.NetworkError"] = None) -> None:
|
||||
if error is not None or reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
|
||||
Logger.log("w",
|
||||
"Requesting user packages failed, response code %s while trying to connect to %s",
|
||||
reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url())
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
self._handleCompatibilityData(json_data["data"])
|
||||
except json.decoder.JSONDecodeError:
|
||||
Logger.log("w", "Received invalid JSON for user packages")
|
||||
self.discrepancies.emit(self._model)
|
|
@ -28,13 +28,12 @@ class DiscrepanciesPresenter(QObject):
|
|||
assert self._dialog
|
||||
self._dialog.accepted.connect(lambda: self._onConfirmClicked(model))
|
||||
|
||||
@pyqtSlot("QVariant", str)
|
||||
def dismissIncompatiblePackage(self, model: SubscribedPackagesModel, package_id: str) -> None:
|
||||
model.dismissPackage(package_id) # update the model to update the view
|
||||
self._package_manager.dismissPackage(package_id) # adds this package_id as dismissed in the user config file
|
||||
|
||||
def _onConfirmClicked(self, model: SubscribedPackagesModel) -> None:
|
||||
# If there are incompatible packages - automatically dismiss them
|
||||
if model.getIncompatiblePackages():
|
||||
self._package_manager.dismissAllIncompatiblePackages(model.getIncompatiblePackages())
|
||||
# For now, all compatible packages presented to the user should be installed.
|
||||
# Later, we might remove items for which the user unselected the package
|
||||
model.setItems(model.getCompatiblePackages())
|
||||
self.packageMutations.emit(model)
|
||||
if model.getCompatiblePackages():
|
||||
model.setItems(model.getCompatiblePackages())
|
||||
self.packageMutations.emit(model)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -37,27 +37,18 @@ class SubscribedPackagesModel(ListModel):
|
|||
return True
|
||||
return False
|
||||
|
||||
# Sets the "is_compatible" to True for the given package, in memory
|
||||
|
||||
@pyqtSlot()
|
||||
def dismissPackage(self, package_id: str) -> None:
|
||||
package = self.find(key="package_id", value=package_id)
|
||||
if package != -1:
|
||||
self.setProperty(package, property="is_dismissed", value=True)
|
||||
Logger.debug("Package {} has been dismissed".format(package_id))
|
||||
|
||||
def setMetadata(self, data: List[Dict[str, List[Any]]]) -> None:
|
||||
self._metadata = data
|
||||
|
||||
def addDiscrepancies(self, discrepancy: List[str]) -> None:
|
||||
self._discrepancies = discrepancy
|
||||
|
||||
def getCompatiblePackages(self):
|
||||
return [x for x in self._items if x["is_compatible"]]
|
||||
def getCompatiblePackages(self) -> List[Dict[str, Any]]:
|
||||
return [package for package in self._items if package["is_compatible"]]
|
||||
|
||||
def initialize(self) -> None:
|
||||
def getIncompatiblePackages(self) -> List[str]:
|
||||
return [package["package_id"] for package in self._items if not package["is_compatible"]]
|
||||
|
||||
def initialize(self, subscribed_packages_payload: List[Dict[str, Any]]) -> None:
|
||||
self._items.clear()
|
||||
for item in self._metadata:
|
||||
for item in subscribed_packages_payload:
|
||||
if item["package_id"] not in self._discrepancies:
|
||||
continue
|
||||
package = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -5984,7 +5984,7 @@
|
|||
"print_sequence":
|
||||
{
|
||||
"label": "Print Sequence",
|
||||
"description": "Whether to print all models one layer at a time or to wait for one model to finish, before moving on to the next. One at a time mode is only possible if all models are separated in such a way that the whole print head can move in between and all models are lower than the distance between the nozzle and the X/Y axes.",
|
||||
"description": "Whether to print all models one layer at a time or to wait for one model to finish, before moving on to the next. One at a time mode is possible if a) only one extruder is enabled and b) all models are separated in such a way that the whole print head can move in between and all models are lower than the distance between the nozzle and the X/Y axes. ",
|
||||
"type": "enum",
|
||||
"options":
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
|
231
resources/definitions/renkforce_rf100_v2.def.json
Normal file
231
resources/definitions/renkforce_rf100_v2.def.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
219
resources/definitions/renkforce_rf100_xl.def.json
Normal file
219
resources/definitions/renkforce_rf100_xl.def.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
15
resources/extruders/renkforce_rf100_xl_extruder_0.def.json
Normal file
15
resources/extruders/renkforce_rf100_xl_extruder_0.def.json
Normal 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 }
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ Item
|
|||
id: createMenuButton
|
||||
text: catalog.i18nc("@action:button", "Create")
|
||||
iconName: "list-add"
|
||||
enabled: Cura.MachineManager.activeMachine.hasMaterials
|
||||
onClicked:
|
||||
{
|
||||
forceActiveFocus();
|
||||
|
@ -174,7 +175,7 @@ Item
|
|||
forceActiveFocus();
|
||||
importMaterialDialog.open();
|
||||
}
|
||||
visible: true
|
||||
enabled: Cura.MachineManager.activeMachine.hasMaterials
|
||||
}
|
||||
|
||||
// Export button
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue