Merge branch 'master' into feature_intent_per_quality

This commit is contained in:
Remco Burema 2019-06-25 18:09:30 +02:00
commit ad4e78c8e4
21 changed files with 371 additions and 75 deletions

View File

@ -8,11 +8,11 @@ assignees: ''
--- ---
<!-- <!--
The following template is useful for filing new issues. Processing an issue will go much faster when this is filled out, and issues which do not use this template WILL BE REMOVED. Processing an issue will go much faster when this is filled out, and issues which do not use this template WILL BE REMOVED and no fix will be considered!
Before filing, PLEASE check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment. Before filing, PLEASE check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment.
Also, please note the application version in the title of the issue. For example: "[3.2.1] Cannot connect to 3rd-party printer". Please do not write things like "Request:" or "[BUG]" in the title; this is what labels are for. Also, please note the application version in the title of the issue. For example: "[3.2.1] Cannot connect to 3rd-party printer". Please do NOT write things like "Request:" or "[BUG]" in the title; this is what labels are for.
It is also helpful to attach a project (.3mf or .curaproject) file and Cura log file so we can debug issues quicker. Information about how to find the log file can be found at https://github.com/Ultimaker/Cura#logging-issues It is also helpful to attach a project (.3mf or .curaproject) file and Cura log file so we can debug issues quicker. Information about how to find the log file can be found at https://github.com/Ultimaker/Cura#logging-issues
@ -40,4 +40,4 @@ Thank you for using Cura!
<!-- What should happen after the above steps have been followed --> <!-- What should happen after the above steps have been followed -->
**Additional information** **Additional information**
<!-- Extra information relevant to the issue, like screenshots --> <!-- Extra information relevant to the issue, like screenshots. Don't forget to attach the log files with this issue report. -->

View File

@ -8,7 +8,6 @@ from UM.PluginRegistry import PluginRegistry
from UM.Logger import Logger from UM.Logger import Logger
from UM.Settings.ContainerFormatError import ContainerFormatError from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.InstanceContainer import InstanceContainer # The new profile to make. from UM.Settings.InstanceContainer import InstanceContainer # The new profile to make.
from cura.CuraApplication import CuraApplication #To get the current setting version.
from cura.ReaderWriters.ProfileReader import ProfileReader from cura.ReaderWriters.ProfileReader import ProfileReader
import zipfile import zipfile
@ -32,7 +31,7 @@ class CuraProfileReader(ProfileReader):
def read(self, file_name: str) -> List[Optional[InstanceContainer]]: def read(self, file_name: str) -> List[Optional[InstanceContainer]]:
try: try:
with zipfile.ZipFile(file_name, "r") as archive: with zipfile.ZipFile(file_name, "r") as archive:
results = [] #type: List[Optional[InstanceContainer]] results = [] # type: List[Optional[InstanceContainer]]
for profile_id in archive.namelist(): for profile_id in archive.namelist():
with archive.open(profile_id) as f: with archive.open(profile_id) as f:
serialized = f.read() serialized = f.read()
@ -68,7 +67,7 @@ class CuraProfileReader(ProfileReader):
return [] return []
version = int(parser["general"]["version"]) version = int(parser["general"]["version"])
if InstanceContainer.Version != version or "metadata" not in parser or "setting_version" not in parser["metadata"] or parser["metadata"]["setting_version"] != str(CuraApplication.SettingVersion): if InstanceContainer.Version != version:
name = parser["general"]["name"] name = parser["general"]["name"]
return self._upgradeProfileVersion(serialized, name, version) return self._upgradeProfileVersion(serialized, name, version)
else: else:
@ -107,9 +106,11 @@ class CuraProfileReader(ProfileReader):
if source_format in plugin["version_upgrade"] and plugin["version_upgrade"][source_format][1] == InstanceContainer.Version] if source_format in plugin["version_upgrade"] and plugin["version_upgrade"][source_format][1] == InstanceContainer.Version]
if not profile_convert_funcs: if not profile_convert_funcs:
Logger.log("w", "Unable to find an upgrade path for the profile [%s]", profile_id)
return [] return []
filenames, outputs = profile_convert_funcs[0](serialized, profile_id) filenames, outputs = profile_convert_funcs[0](serialized, profile_id)
if filenames is None and outputs is None: if filenames is None and outputs is None:
Logger.log("w", "The conversion failed to return any usable data for [%s]", profile_id)
return [] return []
return list(zip(outputs, filenames)) return list(zip(outputs, filenames))

View File

@ -81,7 +81,7 @@ Item
enabled: visible && !(printJob.state == "pausing" || printJob.state == "resuming"); enabled: visible && !(printJob.state == "pausing" || printJob.state == "resuming");
onClicked: { onClicked: {
if (printJob.state == "paused") { if (printJob.state == "paused") {
printJob.setState("print"); printJob.setState("resume");
popUp.close(); popUp.close();
return; return;
} }

View File

@ -22,10 +22,6 @@ Item
// The print job which all other data is derived from // The print job which all other data is derived from
property var printJob: null property var printJob: null
// If the printer is a cloud printer or not. Other items base their enabled state off of this boolean. In the future
// they might not need to though.
property bool cloudConnection: Cura.MachineManager.activeMachineIsUsingCloudConnection
width: parent.width width: parent.width
height: childrenRect.height height: childrenRect.height
@ -217,7 +213,7 @@ Item
} }
width: 32 * screenScaleFactor // TODO: Theme! width: 32 * screenScaleFactor // TODO: Theme!
height: 32 * screenScaleFactor // TODO: Theme! height: 32 * screenScaleFactor // TODO: Theme!
enabled: !cloudConnection enabled: OutputDevice.supportsPrintJobActions
onClicked: enabled ? contextMenu.switchPopupState() : {} onClicked: enabled ? contextMenu.switchPopupState() : {}
visible: visible:
{ {
@ -250,7 +246,7 @@ Item
MonitorInfoBlurb MonitorInfoBlurb
{ {
id: contextMenuDisabledInfo id: contextMenuDisabledInfo
text: catalog.i18nc("@info", "These options are not available because you are monitoring a cloud printer.") text: catalog.i18nc("@info", "Please update your printer's firmware to manage the queue remotely.")
target: contextMenuButton target: contextMenuButton
} }
} }

View File

@ -172,8 +172,7 @@ Item
} }
width: 36 * screenScaleFactor // TODO: Theme! width: 36 * screenScaleFactor // TODO: Theme!
height: 36 * screenScaleFactor // TODO: Theme! height: 36 * screenScaleFactor // TODO: Theme!
enabled: !cloudConnection enabled: OutputDevice.supportsPrintJobActions
onClicked: enabled ? contextMenu.switchPopupState() : {} onClicked: enabled ? contextMenu.switchPopupState() : {}
visible: visible:
{ {
@ -206,7 +205,7 @@ Item
MonitorInfoBlurb MonitorInfoBlurb
{ {
id: contextMenuDisabledInfo id: contextMenuDisabledInfo
text: catalog.i18nc("@info", "These options are not available because you are monitoring a cloud printer.") text: catalog.i18nc("@info", "Please update your printer's firmware to manage the queue remotely.")
target: contextMenuButton target: contextMenuButton
} }
@ -244,7 +243,6 @@ Item
} }
} }
// Divider // Divider
Rectangle Rectangle
{ {

View File

@ -42,7 +42,6 @@ Item
} }
height: 18 * screenScaleFactor // TODO: Theme! height: 18 * screenScaleFactor // TODO: Theme!
width: childrenRect.width width: childrenRect.width
visible: !cloudConnection
UM.RecolorImage UM.RecolorImage
{ {
@ -65,7 +64,7 @@ Item
color: UM.Theme.getColor("monitor_text_link") color: UM.Theme.getColor("monitor_text_link")
font: UM.Theme.getFont("medium") // 14pt, regular font: UM.Theme.getFont("medium") // 14pt, regular
linkColor: UM.Theme.getColor("monitor_text_link") linkColor: UM.Theme.getColor("monitor_text_link")
text: catalog.i18nc("@label link to connect manager", "Go to Cura Connect") text: catalog.i18nc("@label link to connect manager", "Manage in browser")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }
@ -73,9 +72,7 @@ Item
MouseArea MouseArea
{ {
anchors.fill: manageQueueLabel anchors.fill: manageQueueLabel
enabled: !cloudConnection onClicked: OutputDevice.openPrintJobControlPanel()
hoverEnabled: !cloudConnection
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
onEntered: onEntered:
{ {
manageQueueText.font.underline = true manageQueueText.font.underline = true
@ -198,8 +195,7 @@ Item
color: UM.Theme.getColor("monitor_card_background") color: UM.Theme.getColor("monitor_card_background")
border.color: UM.Theme.getColor("monitor_card_border") border.color: UM.Theme.getColor("monitor_card_border")
radius: 2 * screenScaleFactor // TODO: Theme! radius: 2 * screenScaleFactor // TODO: Theme!
visible: OutputDevice.printJobs.length == 0
visible: printJobList.model.length == 0
Row Row
{ {
@ -249,14 +245,14 @@ Item
color: UM.Theme.getColor("monitor_text_link") color: UM.Theme.getColor("monitor_text_link")
font: UM.Theme.getFont("medium") // 14pt, regular font: UM.Theme.getFont("medium") // 14pt, regular
linkColor: UM.Theme.getColor("monitor_text_link") linkColor: UM.Theme.getColor("monitor_text_link")
text: catalog.i18nc("@label link to connect manager", "View print history") text: catalog.i18nc("@label link to connect manager", "Manage in browser")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
MouseArea MouseArea
{ {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel() onClicked: OutputDevice.openPrintJobControlPanel()
onEntered: onEntered:
{ {
viewPrintHistoryText.font.underline = true viewPrintHistoryText.font.underline = true

View File

@ -96,6 +96,21 @@ class CloudApiClient:
reply = self._manager.post(self._createEmptyRequest(url), b"") reply = self._manager.post(self._createEmptyRequest(url), b"")
self._addCallback(reply, on_finished, CloudPrintResponse) self._addCallback(reply, on_finished, CloudPrintResponse)
## Send a print job action to the cluster for the given print job.
# \param cluster_id: The ID of the cluster.
# \param cluster_job_id: The ID of the print job within the cluster.
# \param action: The name of the action to execute.
def doPrintJobAction(self, cluster_id: str, cluster_job_id: str, action: str, data: Optional[Dict[str, Any]] = None) -> None:
body = b""
if data:
try:
body = json.dumps({"data": data}).encode()
except JSONDecodeError as err:
Logger.log("w", "Could not encode body: %s", err)
return
url = "{}/clusters/{}/print_jobs/{}/action/{}".format(self.CLUSTER_API_ROOT, cluster_id, cluster_job_id, action)
self._manager.post(self._createEmptyRequest(url), body)
## We override _createEmptyRequest in order to add the user credentials. ## We override _createEmptyRequest in order to add the user credentials.
# \param url: The URL to request # \param url: The URL to request
# \param content_type: The type of the body contents. # \param content_type: The type of the body contents.

View File

@ -1,5 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -13,10 +14,13 @@ class CloudOutputController(PrinterOutputController):
# The cloud connection only supports fetching the printer and queue status and adding a job to the queue. # The cloud connection only supports fetching the printer and queue status and adding a job to the queue.
# To let the UI know this we mark all features below as False. # To let the UI know this we mark all features below as False.
self.can_pause = False self.can_pause = True
self.can_abort = False self.can_abort = True
self.can_pre_heat_bed = False self.can_pre_heat_bed = False
self.can_pre_heat_hotends = False self.can_pre_heat_hotends = False
self.can_send_raw_gcode = False self.can_send_raw_gcode = False
self.can_control_manually = False self.can_control_manually = False
self.can_update_firmware = False self.can_update_firmware = False
def setJobState(self, job: "PrintJobOutputModel", state: str):
self._output_device.setJobState(job.key, state)

View File

@ -6,6 +6,7 @@ from time import time
from typing import Dict, List, Optional, Set, cast from typing import Dict, List, Optional, Set, cast
from PyQt5.QtCore import QObject, QUrl, pyqtProperty, pyqtSignal, pyqtSlot from PyQt5.QtCore import QObject, QUrl, pyqtProperty, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QDesktopServices
from UM import i18nCatalog from UM import i18nCatalog
from UM.Backend.Backend import BackendState from UM.Backend.Backend import BackendState
@ -15,6 +16,7 @@ from UM.Message import Message
from UM.PluginRegistry import PluginRegistry from UM.PluginRegistry import PluginRegistry
from UM.Qt.Duration import Duration, DurationFormat from UM.Qt.Duration import Duration, DurationFormat
from UM.Scene.SceneNode import SceneNode from UM.Scene.SceneNode import SceneNode
from UM.Version import Version
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
@ -48,6 +50,9 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
# The interval with which the remote clusters are checked # The interval with which the remote clusters are checked
CHECK_CLUSTER_INTERVAL = 10.0 # seconds CHECK_CLUSTER_INTERVAL = 10.0 # seconds
# The minimum version of firmware that support print job actions over cloud.
PRINT_JOB_ACTIONS_MIN_VERSION = Version("5.3.0")
# Signal triggered when the print jobs in the queue were changed. # Signal triggered when the print jobs in the queue were changed.
printJobsChanged = pyqtSignal() printJobsChanged = pyqtSignal()
@ -359,6 +364,13 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
).show() ).show()
self.writeFinished.emit() self.writeFinished.emit()
## Whether the printer that this output device represents supports print job actions via the cloud.
@pyqtProperty(bool, notify = _clusterPrintersChanged)
def supportsPrintJobActions(self) -> bool:
version_number = self.printers[0].firmwareVersion.split(".")
firmware_version = Version([version_number[0], version_number[1], version_number[2]])
return firmware_version >= self.PRINT_JOB_ACTIONS_MIN_VERSION
## Gets the number of printers in the cluster. ## Gets the number of printers in the cluster.
# We use a minimum of 1 because cloud devices are always a cluster and printer discovery needs it. # We use a minimum of 1 because cloud devices are always a cluster and printer discovery needs it.
@pyqtProperty(int, notify = _clusterPrintersChanged) @pyqtProperty(int, notify = _clusterPrintersChanged)
@ -399,6 +411,22 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
return [print_job for print_job in self._print_jobs if return [print_job for print_job in self._print_jobs if
print_job.assignedPrinter is not None and print_job.state != "queued"] print_job.assignedPrinter is not None and print_job.state != "queued"]
def setJobState(self, print_job_uuid: str, state: str) -> None:
self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, state)
@pyqtSlot(str)
def sendJobToTop(self, print_job_uuid: str) -> None:
self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "move",
{"list": "queued", "to_position": 0})
@pyqtSlot(str)
def deleteJobFromQueue(self, print_job_uuid: str) -> None:
self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "remove")
@pyqtSlot(str)
def forceSendJob(self, print_job_uuid: str) -> None:
self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "force")
@pyqtSlot(int, result = str) @pyqtSlot(int, result = str)
def formatDuration(self, seconds: int) -> str: def formatDuration(self, seconds: int) -> str:
return Duration(seconds).getDisplayString(DurationFormat.Format.Short) return Duration(seconds).getDisplayString(DurationFormat.Format.Short)
@ -411,6 +439,18 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
def getDateCompleted(self, time_remaining: int) -> str: def getDateCompleted(self, time_remaining: int) -> str:
return formatDateCompleted(time_remaining) return formatDateCompleted(time_remaining)
@pyqtProperty(bool, notify=printJobsChanged)
def receivedPrintJobs(self) -> bool:
return bool(self._print_jobs)
@pyqtSlot()
def openPrintJobControlPanel(self) -> None:
QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com"))
@pyqtSlot()
def openPrinterControlPanel(self) -> None:
QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com"))
## TODO: The following methods are required by the monitor page QML, but are not actually available using cloud. ## TODO: The following methods are required by the monitor page QML, but are not actually available using cloud.
# TODO: We fake the methods here to not break the monitor page. # TODO: We fake the methods here to not break the monitor page.
@ -422,30 +462,6 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
def setActiveCameraUrl(self, camera_url: "QUrl") -> None: def setActiveCameraUrl(self, camera_url: "QUrl") -> None:
pass pass
@pyqtProperty(bool, notify = printJobsChanged)
def receivedPrintJobs(self) -> bool:
return bool(self._print_jobs)
@pyqtSlot()
def openPrintJobControlPanel(self) -> None:
pass
@pyqtSlot()
def openPrinterControlPanel(self) -> None:
pass
@pyqtSlot(str)
def sendJobToTop(self, print_job_uuid: str) -> None:
pass
@pyqtSlot(str)
def deleteJobFromQueue(self, print_job_uuid: str) -> None:
pass
@pyqtSlot(str)
def forceSendJob(self, print_job_uuid: str) -> None:
pass
@pyqtProperty("QVariantList", notify = _clusterPrintersChanged) @pyqtProperty("QVariantList", notify = _clusterPrintersChanged)
def connectedPrintersTypeCount(self) -> List[Dict[str, str]]: def connectedPrintersTypeCount(self) -> List[Dict[str, str]]:
return [] return []

View File

@ -91,7 +91,6 @@ class CloudClusterPrintJobStatus(BaseCloudModel):
def createOutputModel(self, controller: CloudOutputController) -> UM3PrintJobOutputModel: def createOutputModel(self, controller: CloudOutputController) -> UM3PrintJobOutputModel:
model = UM3PrintJobOutputModel(controller, self.uuid, self.name) model = UM3PrintJobOutputModel(controller, self.uuid, self.name)
self.updateOutputModel(model) self.updateOutputModel(model)
return model return model
## Creates a new configuration model ## Creates a new configuration model

View File

@ -140,6 +140,11 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
if self._printer_selection_dialog is not None: if self._printer_selection_dialog is not None:
self._printer_selection_dialog.show() self._printer_selection_dialog.show()
## Whether the printer that this output device represents supports print job actions via the local network.
@pyqtProperty(bool, constant=True)
def supportsPrintJobActions(self) -> bool:
return True
@pyqtProperty(int, constant=True) @pyqtProperty(int, constant=True)
def clusterSize(self) -> int: def clusterSize(self) -> int:
return self._cluster_size return self._cluster_size

View File

@ -27,7 +27,7 @@ from UM.Version import Version
from . import ClusterUM3OutputDevice, LegacyUM3OutputDevice from . import ClusterUM3OutputDevice, LegacyUM3OutputDevice
from .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager from .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
from .Cloud.CloudOutputDevice import CloudOutputDevice # typing from .Cloud.CloudOutputDevice import CloudOutputDevice # typing
if TYPE_CHECKING: if TYPE_CHECKING:
from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtNetwork import QNetworkReply

View File

@ -72,9 +72,9 @@ class TestCloudOutputDevice(TestCase):
controller_fields = { controller_fields = {
"_output_device": self.device, "_output_device": self.device,
"can_abort": False, "can_abort": True,
"can_control_manually": False, "can_control_manually": False,
"can_pause": False, "can_pause": True,
"can_pre_heat_bed": False, "can_pre_heat_bed": False,
"can_pre_heat_hotends": False, "can_pre_heat_hotends": False,
"can_send_raw_gcode": False, "can_send_raw_gcode": False,

View File

@ -66,7 +66,7 @@
"material_print_temperature_layer_0": { "default_value": 220 }, "material_print_temperature_layer_0": { "default_value": 220 },
"material_initial_print_temperature": { "default_value": 220 }, "material_initial_print_temperature": { "default_value": 220 },
"material_final_print_temperature": { "default_value": 220 }, "material_final_print_temperature": { "default_value": 220 },
"retraction_amount": { "default_value": 4 }, "retraction_amount": { "default_value": 6.5 },
"speed_print": { "default_value": 40 }, "speed_print": { "default_value": 40 },
"speed_infill": { "default_value": 60 }, "speed_infill": { "default_value": 60 },

View File

@ -4635,11 +4635,11 @@
"label": "Enable Prime Blob", "label": "Enable Prime Blob",
"description": "Whether to prime the filament with a blob before printing. Turning this setting on will ensure that the extruder will have material ready at the nozzle before printing. Printing Brim or Skirt can act like priming too, in which case turning this setting off saves some time.", "description": "Whether to prime the filament with a blob before printing. Turning this setting on will ensure that the extruder will have material ready at the nozzle before printing. Printing Brim or Skirt can act like priming too, in which case turning this setting off saves some time.",
"type": "bool", "type": "bool",
"resolve": "any(extruderValues('prime_blob_enable'))",
"default_value": false, "default_value": false,
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"enabled": false "enabled": false,
"warning_value": "True if resolveOrValue('print_sequence') == 'one_at_a_time' else None"
}, },
"extruder_prime_pos_x": "extruder_prime_pos_x":
{ {

View File

@ -0,0 +1,78 @@
{
"id": "flsun_qq_s",
"version": 2,
"name": "FLSUN QQ-S",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "Cataldo URSO",
"manufacturer": "FLSUN",
"file_formats": "text/x-gcode",
"has_materials": true,
"preferred_quality_type": "draft",
"machine_extruder_trains": {
"0": "flsun_qq_s_extruder_0"
}
},
"overrides": {
"machine_center_is_zero": {
"default_value": true
},
"machine_shape": {
"default_value": "elliptic"
},
"machine_width": {
"default_value": 260
},
"machine_depth": {
"default_value": 260
},
"machine_height": {
"default_value": 370
},
"z_seam_type": {
"default_value": "back"
},
"top_thickness": {
"default_value": 5
},
"bottom_layers": {
"default_value": 4
},
"gantry_height": {
"default_value": 0
},
"machine_nozzle_size": {
"default_value": 0.4
},
"material_diameter": {
"default_value": 1.75
},
"machine_start_gcode": {
"default_value": "G21\nG90\nM82\nM107 T0\nM190 S{material_bed_temperature}\nM109 S{material_print_temperature} T0\nG28\nG92 E0\nG0 E3 F200\nG92 E0\n"
},
"machine_end_gcode": {
"default_value": "M107 T0\nM104 S0\nM104 S0 T1\nM140 S0\nG92 E0\nG91\nG1 E-1 F300 \nG1 Z+0.5 E-5 X-20 Y-20 F9000\nG28 X0 Y0\nM84 ;steppers off\nG90 ;absolute positioning\n"
},
"infill_sparse_density": {
"default_value": 10
},
"machine_head_with_fans_polygon": {
"default_value": [
[0, 0],
[0, 0],
[0, 0],
[0, 0]
]
},
"retraction_enable": {
"default_value": true
},
"machine_heated_bed": {
"default_value": true
},
"machine_gcode_flavor": {
"default_value": "Repetier"
}
}
}

View File

@ -0,0 +1,132 @@
{
"id": "geeetech_a30",
"version": 2,
"name": "Geeetech A30",
"inherits": "fdmprinter",
"metadata": {
"author": "William & Cataldo URSO",
"manufacturer": "Shenzhen Geeetech Technology",
"setting_version": 8,
"file_formats": "text/x-gcode",
"visible": true,
"has_materials": true,
"preferred_quality_type": "draft",
"machine_extruder_trains": {
"0": "geeetech_a30_extruder_0"
}
},
"overrides": {
"machine_name": {
"default_value": "Geeetech A30"
},
"machine_start_gcode": {
"default_value": "G28 ;Home\nM190 S{material_bed_temperature}\nM109 S{material_print_temperature} T0\nG1 Z15.0 F6000 ;Move the platform down 15mm\nG92 E0\nG1 F200 E3\nG92 E0"
},
"machine_end_gcode": {
"default_value": "M104 S0;Cooling the heat end\nM140 S0;Cooling the heat bed\nG92 E1\nG1 E-1 F300\nG28 X0 Y0;Home X axis and Y axis\nM84"
},
"machine_width": {
"default_value": 320
},
"machine_height": {
"default_value": 420
},
"machine_depth": {
"default_value": 320
},
"machine_heated_bed": {
"default_value": true
},
"machine_center_is_zero": {
"default_value": false
},
"material_diameter": {
"default_value": 1.75
},
"material_bed_temperature": {
"default_value": 60
},
"machine_nozzle_size": {
"default_value": 0.4
},
"layer_height": {
"default_value": 0.1
},
"layer_height_0": {
"default_value": 0.3
},
"retraction_amount": {
"default_value": 2
},
"retraction_speed": {
"default_value": 25
},
"retraction_retract_speed": {
"default_value": 25
},
"retraction_prime_speed": {
"default_value": 25
},
"adhesion_type": {
"default_value": "skirt"
},
"machine_head_polygon": {
"default_value": [
[-75, 35],
[18, 35],
[18, -18],
[-75, -18]
]
},
"machine_head_with_fans_polygon": {
"default_value": [
[-75, 35],
[18, 35],
[18, -18],
[-75, -18]
]
},
"gantry_height": {
"default_value": 55
},
"machine_max_feedrate_x": {
"default_value": 300
},
"machine_max_feedrate_y": {
"default_value": 300
},
"machine_max_feedrate_z": {
"default_value": 7
},
"machine_max_feedrate_e": {
"default_value": 50
},
"machine_max_acceleration_x": {
"default_value": 2000
},
"machine_max_acceleration_y": {
"default_value": 2000
},
"machine_max_acceleration_z": {
"default_value": 100
},
"machine_max_acceleration_e": {
"default_value": 10000
},
"machine_acceleration": {
"default_value": 2000
},
"machine_max_jerk_xy": {
"default_value": 10
},
"machine_max_jerk_z": {
"default_value": 1
},
"machine_max_jerk_e": {
"default_value": 5
},
"machine_gcode_flavor": {
"default_value": "Repetier"
}
}
}

View File

@ -79,7 +79,7 @@
"prime_tower_position_x": { "value": "machine_depth - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) - 30" }, "prime_tower_position_x": { "value": "machine_depth - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) - 30" },
"prime_tower_wipe_enabled": { "default_value": false }, "prime_tower_wipe_enabled": { "default_value": false },
"prime_blob_enable": { "enabled": true, "default_value": true }, "prime_blob_enable": { "enabled": true, "default_value": true, "value": "resolveOrValue('print_sequence') != 'one_at_a_time'" },
"acceleration_enabled": { "value": "True" }, "acceleration_enabled": { "value": "True" },
"acceleration_layer_0": { "value": "acceleration_topbottom" }, "acceleration_layer_0": { "value": "acceleration_topbottom" },

View File

@ -0,0 +1,16 @@
{
"id": "flsun_qq_s_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
"machine": "flsun_qq_s",
"position": "0"
},
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 }
}
}

View File

@ -0,0 +1,16 @@
{
"id": "geeetech_a30_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
"machine": "geeetech_a30",
"position": "0"
},
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 }
}
}

View File

@ -91,27 +91,27 @@ SettingItem
} }
width: height width: height
color:
{
if (!enabled)
{
return UM.Theme.getColor("setting_control_disabled")
}
if (control.containsMouse || control.activeFocus)
{
return UM.Theme.getColor("setting_control_highlight")
}
return UM.Theme.getColor("setting_control")
}
radius: UM.Theme.getSize("setting_control_radius").width radius: UM.Theme.getSize("setting_control_radius").width
border.width: UM.Theme.getSize("default_lining").width border.width: UM.Theme.getSize("default_lining").width
border.color: border.color:
{ {
if (!enabled) if(!enabled)
{ {
return UM.Theme.getColor("setting_control_disabled_border") return UM.Theme.getColor("setting_control_disabled_border")
} }
switch (propertyProvider.properties.validationState)
{
case "ValidatorState.Invalid":
case "ValidatorState.Exception":
case "ValidatorState.MinimumError":
case "ValidatorState.MaximumError":
return UM.Theme.getColor("setting_validation_error");
case "ValidatorState.MinimumWarning":
case "ValidatorState.MaximumWarning":
return UM.Theme.getColor("setting_validation_warning");
}
// Validation is OK.
if (control.containsMouse || control.activeFocus) if (control.containsMouse || control.activeFocus)
{ {
return UM.Theme.getColor("setting_control_border_highlight") return UM.Theme.getColor("setting_control_border_highlight")
@ -119,6 +119,30 @@ SettingItem
return UM.Theme.getColor("setting_control_border") return UM.Theme.getColor("setting_control_border")
} }
color: {
if (!enabled)
{
return UM.Theme.getColor("setting_control_disabled")
}
switch (propertyProvider.properties.validationState)
{
case "ValidatorState.Invalid":
case "ValidatorState.Exception":
case "ValidatorState.MinimumError":
case "ValidatorState.MaximumError":
return UM.Theme.getColor("setting_validation_error_background")
case "ValidatorState.MinimumWarning":
case "ValidatorState.MaximumWarning":
return UM.Theme.getColor("setting_validation_warning_background")
}
// Validation is OK.
if (control.containsMouse || control.activeFocus)
{
return UM.Theme.getColor("setting_control_highlight")
}
return UM.Theme.getColor("setting_control")
}
UM.RecolorImage UM.RecolorImage
{ {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter