Merge branch 'master' into fieldOfView-feature_firmware_updater

Conflicts:
	cura/PrinterOutput/PrinterOutputModel.py - Bunch of code that was moved.
	plugins/USBPrinting/USBPrinterOutputDevice.py - Collisions with code style fixes.
	plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml - Bunch of code that was moved.
This commit is contained in:
Ghostkeeper 2018-10-15 16:52:22 +02:00
commit b5d8c1af6f
No known key found for this signature in database
GPG key ID: 5252B696FB5E7C7A
27 changed files with 253 additions and 94 deletions

View file

@ -1,15 +1,26 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtGui import QImage from PyQt5.QtGui import QImage
from PyQt5.QtQuick import QQuickImageProvider from PyQt5.QtQuick import QQuickImageProvider
from PyQt5.QtCore import QSize from PyQt5.QtCore import QSize
from UM.Application import Application from UM.Application import Application
## Creates screenshots of the current scene.
class CameraImageProvider(QQuickImageProvider): class CameraImageProvider(QQuickImageProvider):
def __init__(self): def __init__(self):
super().__init__(QQuickImageProvider.Image) super().__init__(QQuickImageProvider.Image)
## Request a new image. ## Request a new image.
#
# The image will be taken using the current camera position.
# Only the actual objects in the scene will get rendered. Not the build
# plate and such!
# \param id The ID for the image to create. This is the requested image
# source, with the "image:" scheme and provider identifier removed. It's
# a Qt thing, they'll provide this parameter.
# \param size The dimensions of the image to scale to.
def requestImage(self, id, size): def requestImage(self, id, size):
for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices(): for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices():
try: try:

View file

@ -130,9 +130,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
# We need to check if the manager needs to be re-created. If we don't, we get some issues when OSX goes to # We need to check if the manager needs to be re-created. If we don't, we get some issues when OSX goes to
# sleep. # sleep.
if time_since_last_response > self._recreate_network_manager_time: if time_since_last_response > self._recreate_network_manager_time:
if self._last_manager_create_time is None: if self._last_manager_create_time is None or time() - self._last_manager_create_time > self._recreate_network_manager_time:
self._createNetworkManager()
elif time() - self._last_manager_create_time > self._recreate_network_manager_time:
self._createNetworkManager() self._createNetworkManager()
assert(self._manager is not None) assert(self._manager is not None)
elif self._connection_state == ConnectionState.closed: elif self._connection_state == ConnectionState.closed:

View file

@ -175,7 +175,7 @@ class PrinterOutputModel(QObject):
def getController(self) -> "PrinterOutputController": def getController(self) -> "PrinterOutputController":
return self._controller return self._controller
@pyqtProperty(str, notify=nameChanged) @pyqtProperty(str, notify = nameChanged)
def name(self) -> str: def name(self) -> str:
return self._name return self._name

View file

@ -1,9 +1,12 @@
# Copyright (c) 2017 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.
import os
from PyQt5.QtCore import QUrl from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices from PyQt5.QtGui import QDesktopServices
from typing import Set
from UM.Extension import Extension from UM.Extension import Extension
from UM.Application import Application from UM.Application import Application
from UM.Logger import Logger from UM.Logger import Logger
@ -13,6 +16,7 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
from cura.Settings.GlobalStack import GlobalStack from cura.Settings.GlobalStack import GlobalStack
from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob
from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
i18n_catalog = i18nCatalog("cura") i18n_catalog = i18nCatalog("cura")
@ -21,32 +25,31 @@ i18n_catalog = i18nCatalog("cura")
# The plugin is currently only usable for applications maintained by Ultimaker. But it should be relatively easy # The plugin is currently only usable for applications maintained by Ultimaker. But it should be relatively easy
# to change it to work for other applications. # to change it to work for other applications.
class FirmwareUpdateChecker(Extension): class FirmwareUpdateChecker(Extension):
JEDI_VERSION_URL = "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources"
def __init__(self): def __init__(self) -> None:
super().__init__() super().__init__()
# Initialize the Preference called `latest_checked_firmware` that stores the last version
# checked for the UM3. In the future if we need to check other printers' firmware
Application.getInstance().getPreferences().addPreference("info/latest_checked_firmware", "")
# Listen to a Signal that indicates a change in the list of printers, just if the user has enabled the # Listen to a Signal that indicates a change in the list of printers, just if the user has enabled the
# 'check for updates' option # "check for updates" option
Application.getInstance().getPreferences().addPreference("info/automatic_update_check", True) Application.getInstance().getPreferences().addPreference("info/automatic_update_check", True)
if Application.getInstance().getPreferences().getValue("info/automatic_update_check"): if Application.getInstance().getPreferences().getValue("info/automatic_update_check"):
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
self._download_url = None
self._check_job = None self._check_job = None
self._checked_printer_names = set() # type: Set[str]
## Callback for the message that is spawned when there is a new version. ## Callback for the message that is spawned when there is a new version.
def _onActionTriggered(self, message, action): def _onActionTriggered(self, message, action):
if action == "download": if action == FirmwareUpdateCheckerMessage.STR_ACTION_DOWNLOAD:
if self._download_url is not None: machine_id = message.getMachineId()
QDesktopServices.openUrl(QUrl(self._download_url)) download_url = message.getDownloadUrl()
if download_url is not None:
def _onSetDownloadUrl(self, download_url): if QDesktopServices.openUrl(QUrl(download_url)):
self._download_url = download_url Logger.log("i", "Redirected browser to {0} to show newly available firmware.".format(download_url))
else:
Logger.log("e", "Can't reach URL: {0}".format(download_url))
else:
Logger.log("e", "Can't find URL for {0}".format(machine_id))
def _onContainerAdded(self, container): def _onContainerAdded(self, container):
# Only take care when a new GlobalStack was added # Only take care when a new GlobalStack was added
@ -63,13 +66,18 @@ class FirmwareUpdateChecker(Extension):
# \param silent type(boolean) Suppresses messages other than "new version found" messages. # \param silent type(boolean) Suppresses messages other than "new version found" messages.
# This is used when checking for a new firmware version at startup. # This is used when checking for a new firmware version at startup.
def checkFirmwareVersion(self, container = None, silent = False): def checkFirmwareVersion(self, container = None, silent = False):
# Do not run multiple check jobs in parallel container_name = container.definition.getName()
if self._check_job is not None: if container_name in self._checked_printer_names:
Logger.log("i", "A firmware update check is already running, do nothing.") return
self._checked_printer_names.add(container_name)
metadata = container.definition.getMetaData().get("firmware_update_info")
if metadata is None:
Logger.log("i", "No machine with name {0} in list of firmware to check.".format(container_name))
return return
self._check_job = FirmwareUpdateCheckerJob(container = container, silent = silent, url = self.JEDI_VERSION_URL, self._check_job = FirmwareUpdateCheckerJob(container = container, silent = silent,
callback = self._onActionTriggered, machine_name = container_name, metadata = metadata,
set_download_url_callback = self._onSetDownloadUrl) callback = self._onActionTriggered)
self._check_job.start() self._check_job.start()
self._check_job.finished.connect(self._onJobFinished) self._check_job.finished.connect(self._onJobFinished)

View file

@ -1,13 +1,18 @@
# Copyright (c) 2017 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 UM.Application import Application from UM.Application import Application
from UM.Message import Message from UM.Message import Message
from UM.Logger import Logger from UM.Logger import Logger
from UM.Job import Job from UM.Job import Job
from UM.Version import Version
import urllib.request import urllib.request
import codecs from urllib.error import URLError
from typing import Dict, Optional
from .FirmwareUpdateCheckerLookup import FirmwareUpdateCheckerLookup, getSettingsKeyForMachine
from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura") i18n_catalog = i18nCatalog("cura")
@ -15,46 +20,86 @@ i18n_catalog = i18nCatalog("cura")
## This job checks if there is an update available on the provided URL. ## This job checks if there is an update available on the provided URL.
class FirmwareUpdateCheckerJob(Job): class FirmwareUpdateCheckerJob(Job):
def __init__(self, container = None, silent = False, url = None, callback = None, set_download_url_callback = None): STRING_ZERO_VERSION = "0.0.0"
STRING_EPSILON_VERSION = "0.0.1"
ZERO_VERSION = Version(STRING_ZERO_VERSION)
EPSILON_VERSION = Version(STRING_EPSILON_VERSION)
def __init__(self, container, silent, machine_name, metadata, callback) -> None:
super().__init__() super().__init__()
self._container = container self._container = container
self.silent = silent self.silent = silent
self._url = url
self._callback = callback self._callback = callback
self._set_download_url_callback = set_download_url_callback
def run(self): self._machine_name = machine_name
if not self._url: self._metadata = metadata
Logger.log("e", "Can not check for a new release. URL not set!") self._lookups = None # type:Optional[FirmwareUpdateCheckerLookup]
return self._headers = {} # type:Dict[str, str] # Don't set headers yet.
def getUrlResponse(self, url: str) -> str:
result = self.STRING_ZERO_VERSION
try: try:
request = urllib.request.Request(url, headers = self._headers)
response = urllib.request.urlopen(request)
result = response.read().decode("utf-8")
except URLError:
Logger.log("w", "Could not reach '{0}', if this URL is old, consider removal.".format(url))
return result
def parseVersionResponse(self, response: str) -> Version:
raw_str = response.split("\n", 1)[0].rstrip()
return Version(raw_str)
def getCurrentVersion(self) -> Version:
max_version = self.ZERO_VERSION
if self._lookups is None:
return max_version
machine_urls = self._lookups.getCheckUrls()
if machine_urls is not None:
for url in machine_urls:
version = self.parseVersionResponse(self.getUrlResponse(url))
if version > max_version:
max_version = version
if max_version < self.EPSILON_VERSION:
Logger.log("w", "MachineID {0} not handled!".format(self._lookups.getMachineName()))
return max_version
def run(self):
if self._lookups is None:
self._lookups = FirmwareUpdateCheckerLookup(self._machine_name, self._metadata)
try:
# Initialize a Preference that stores the last version checked for this printer.
Application.getInstance().getPreferences().addPreference(
getSettingsKeyForMachine(self._lookups.getMachineId()), "")
# Get headers
application_name = Application.getInstance().getApplicationName() application_name = Application.getInstance().getApplicationName()
headers = {"User-Agent": "%s - %s" % (application_name, Application.getInstance().getVersion())} application_version = Application.getInstance().getVersion()
request = urllib.request.Request(self._url, headers = headers) self._headers = {"User-Agent": "%s - %s" % (application_name, application_version)}
current_version_file = urllib.request.urlopen(request)
reader = codecs.getreader("utf-8")
# get machine name from the definition container # get machine name from the definition container
machine_name = self._container.definition.getName() machine_name = self._container.definition.getName()
machine_name_parts = machine_name.lower().split(" ")
# If it is not None, then we compare between the checked_version and the current_version # If it is not None, then we compare between the checked_version and the current_version
# Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended or any machine_id = self._lookups.getMachineId()
# other Ultimaker 3 that will come in the future if machine_id is not None:
if len(machine_name_parts) >= 2 and machine_name_parts[:2] == ["ultimaker", "3"]: Logger.log("i", "You have a(n) {0} in the printer list. Let's check the firmware!".format(machine_name))
Logger.log("i", "You have a UM3 in printer list. Let's check the firmware!")
# Nothing to parse, just get the string current_version = self.getCurrentVersion()
# TODO: In the future may be done by parsing a JSON file with diferent version for each printer model
current_version = reader(current_version_file).readline().rstrip()
# If it is the first time the version is checked, the checked_version is '' # If it is the first time the version is checked, the checked_version is ""
checked_version = Application.getInstance().getPreferences().getValue("info/latest_checked_firmware") setting_key_str = getSettingsKeyForMachine(machine_id)
checked_version = Version(Application.getInstance().getPreferences().getValue(setting_key_str))
# If the checked_version is '', it's because is the first time we check firmware and in this case # If the checked_version is "", it's because is the first time we check firmware and in this case
# we will not show the notification, but we will store it for the next time # we will not show the notification, but we will store it for the next time
Application.getInstance().getPreferences().setValue("info/latest_checked_firmware", current_version) Application.getInstance().getPreferences().setValue(setting_key_str, current_version)
Logger.log("i", "Reading firmware version of %s: checked = %s - latest = %s", machine_name, checked_version, current_version) Logger.log("i", "Reading firmware version of %s: checked = %s - latest = %s", machine_name, checked_version, current_version)
# The first time we want to store the current version, the notification will not be shown, # The first time we want to store the current version, the notification will not be shown,
@ -62,28 +107,11 @@ class FirmwareUpdateCheckerJob(Job):
# notify the user when no new firmware version is available. # notify the user when no new firmware version is available.
if (checked_version != "") and (checked_version != current_version): if (checked_version != "") and (checked_version != current_version):
Logger.log("i", "SHOWING FIRMWARE UPDATE MESSAGE") Logger.log("i", "SHOWING FIRMWARE UPDATE MESSAGE")
message = FirmwareUpdateCheckerMessage(machine_id, machine_name, self._lookups.getRedirectUserUrl())
message = Message(i18n_catalog.i18nc(
"@info Don't translate {machine_name}, since it gets replaced by a printer name!",
"New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(
machine_name=machine_name),
title=i18n_catalog.i18nc(
"@info:title The %s gets replaced with the printer name.",
"New %s firmware available") % machine_name)
message.addAction("download",
i18n_catalog.i18nc("@action:button", "How to update"),
"[no_icon]",
"[no_description]",
button_style=Message.ActionButtonStyle.LINK,
button_align=Message.ActionButtonStyle.BUTTON_ALIGN_LEFT)
# If we do this in a cool way, the download url should be available in the JSON file
if self._set_download_url_callback:
self._set_download_url_callback("https://ultimaker.com/en/resources/20500-upgrade-firmware")
message.actionTriggered.connect(self._callback) message.actionTriggered.connect(self._callback)
message.show() message.show()
else:
Logger.log("i", "No machine with name {0} in list of firmware to check.".format(machine_name))
except Exception as e: except Exception as e:
Logger.log("w", "Failed to check for new version: %s", e) Logger.log("w", "Failed to check for new version: %s", e)

View file

@ -0,0 +1,35 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import List, Optional
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura")
def getSettingsKeyForMachine(machine_id: int) -> str:
return "info/latest_checked_firmware_for_{0}".format(machine_id)
class FirmwareUpdateCheckerLookup:
def __init__(self, machine_name, machine_json) -> None:
# Parse all the needed lookup-tables from the ".json" file(s) in the resources folder.
self._machine_id = machine_json.get("id")
self._machine_name = machine_name.lower() # Lower in-case upper-case chars are added to the original json.
self._check_urls = [] # type:List[str]
for check_url in machine_json.get("check_urls"):
self._check_urls.append(check_url)
self._redirect_user = machine_json.get("update_url")
def getMachineId(self) -> Optional[int]:
return self._machine_id
def getMachineName(self) -> Optional[int]:
return self._machine_name
def getCheckUrls(self) -> Optional[List[str]]:
return self._check_urls
def getRedirectUserUrl(self) -> Optional[str]:
return self._redirect_user

View file

@ -0,0 +1,37 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.i18n import i18nCatalog
from UM.Message import Message
i18n_catalog = i18nCatalog("cura")
# Make a separate class, since we need an extra field: The machine-id that this message is about.
class FirmwareUpdateCheckerMessage(Message):
STR_ACTION_DOWNLOAD = "download"
def __init__(self, machine_id: int, machine_name: str, download_url: str) -> None:
super().__init__(i18n_catalog.i18nc(
"@info Don't translate {machine_name}, since it gets replaced by a printer name!",
"New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(
machine_name = machine_name),
title = i18n_catalog.i18nc(
"@info:title The %s gets replaced with the printer name.",
"New %s firmware available") % machine_name)
self._machine_id = machine_id
self._download_url = download_url
self.addAction(self.STR_ACTION_DOWNLOAD,
i18n_catalog.i18nc("@action:button", "How to update"),
"[no_icon]",
"[no_description]",
button_style = Message.ActionButtonStyle.LINK,
button_align = Message.ActionButtonStyle.BUTTON_ALIGN_LEFT)
def getMachineId(self) -> int:
return self._machine_id
def getDownloadUrl(self) -> str:
return self._download_url

View file

@ -51,7 +51,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600] self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600]
# Instead of using a timer, we really need the update to be as a thread, as reading from serial can block. # Instead of using a timer, we really need the update to be as a thread, as reading from serial can block.
self._update_thread = Thread(target=self._update, daemon=True) self._update_thread = Thread(target = self._update, daemon = True)
self._last_temperature_request = None # type: Optional[int] self._last_temperature_request = None # type: Optional[int]
@ -172,15 +172,19 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
except SerialException: except SerialException:
Logger.log("w", "An exception occured while trying to create serial connection") Logger.log("w", "An exception occured while trying to create serial connection")
return return
CuraApplication.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
self._onGlobalContainerStackChanged()
self.setConnectionState(ConnectionState.connected)
self._update_thread.start()
def _onGlobalContainerStackChanged(self):
container_stack = CuraApplication.getInstance().getGlobalContainerStack() container_stack = CuraApplication.getInstance().getGlobalContainerStack()
num_extruders = container_stack.getProperty("machine_extruder_count", "value") num_extruders = container_stack.getProperty("machine_extruder_count", "value")
# Ensure that a printer is created. # Ensure that a printer is created.
controller = GenericOutputController(self) controller = GenericOutputController(self)
controller.setCanUpdateFirmware(True) controller.setCanUpdateFirmware(True)
self._printers = [PrinterOutputModel(output_controller=controller, number_of_extruders=num_extruders)] self._printers = [PrinterOutputModel(output_controller = controller, number_of_extruders = num_extruders)]
self._printers[0].updateName(container_stack.getName()) self._printers[0].updateName(container_stack.getName())
self.setConnectionState(ConnectionState.connected)
self._update_thread.start()
def close(self): def close(self):
super().close() super().close()

View file

@ -41,6 +41,9 @@
[30, 34] [30, 34]
] ]
}, },
"material_diameter": {
"default_value": 1.75
},
"acceleration_enabled": { "acceleration_enabled": {
"default_value": true "default_value": true
}, },
@ -56,6 +59,9 @@
"jerk_travel": { "jerk_travel": {
"default_value": 20 "default_value": 20
}, },
"layer_height": {
"default_value": 0.10
},
"layer_height_0": { "layer_height_0": {
"default_value": 0.2 "default_value": 0.2
}, },

View file

@ -1217,11 +1217,11 @@
"connect_skin_polygons": "connect_skin_polygons":
{ {
"label": "Connect Top/Bottom Polygons", "label": "Connect Top/Bottom Polygons",
"description": "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality.", "description": "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality.",
"type": "bool", "type": "bool",
"default_value": false, "default_value": false,
"enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern == 'concentric'", "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern == 'concentric'",
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "top_bottom_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"skin_angles": "skin_angles":

View file

@ -6,6 +6,7 @@
"visible": true, "visible": true,
"author": "Ultimaker", "author": "Ultimaker",
"manufacturer": "MakerBot", "manufacturer": "MakerBot",
"machine_x3g_variant": "r1",
"file_formats": "application/x3g", "file_formats": "application/x3g",
"platform_offset": [ 0, 0, 0], "platform_offset": [ 0, 0, 0],
"machine_extruder_trains": "machine_extruder_trains":

View file

@ -24,7 +24,16 @@
}, },
"first_start_actions": [ "DiscoverUM3Action" ], "first_start_actions": [ "DiscoverUM3Action" ],
"supported_actions": [ "DiscoverUM3Action" ], "supported_actions": [ "DiscoverUM3Action" ],
"supports_usb_connection": false "supports_usb_connection": false,
"firmware_update_info": {
"id": 9066,
"check_urls":
[
"http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
"http://software.ultimaker.com/releases/firmware/9066/stable/version.txt"
],
"update_url": "https://ultimaker.com/firmware"
}
}, },

View file

@ -23,7 +23,16 @@
"1": "ultimaker3_extended_extruder_right" "1": "ultimaker3_extended_extruder_right"
}, },
"first_start_actions": [ "DiscoverUM3Action" ], "first_start_actions": [ "DiscoverUM3Action" ],
"supported_actions": [ "DiscoverUM3Action" ] "supported_actions": [ "DiscoverUM3Action" ],
"firmware_update_info": {
"id": 9511,
"check_urls":
[
"http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources",
"http://software.ultimaker.com/releases/firmware/9511/stable/version.txt"
],
"update_url": "https://ultimaker.com/firmware"
}
}, },
"overrides": { "overrides": {

View file

@ -30,7 +30,12 @@
"first_start_actions": [ "DiscoverUM3Action" ], "first_start_actions": [ "DiscoverUM3Action" ],
"supported_actions": [ "DiscoverUM3Action" ], "supported_actions": [ "DiscoverUM3Action" ],
"supports_usb_connection": false, "supports_usb_connection": false,
"weight": -1 "weight": -1,
"firmware_update_info": {
"id": 9051,
"check_urls": ["http://software.ultimaker.com/releases/firmware/9051/stable/version.txt"],
"update_url": "https://ultimaker.com/firmware"
}
}, },
"overrides": { "overrides": {

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.5 }, "machine_nozzle_size": { "default_value": 0.5 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.5 }, "machine_nozzle_size": { "default_value": 0.5 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -11,6 +11,6 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 2.85 } "material_diameter": { "default_value": 1.75 }
} }
} }

View file

@ -44,7 +44,7 @@ Column
Repeater Repeater
{ {
id: extrudersRepeater id: extrudersRepeater
model: activePrinter!=null ? activePrinter.extruders : null model: activePrinter != null ? activePrinter.extruders : null
ExtruderBox ExtruderBox
{ {

View file

@ -14,11 +14,19 @@ Item
implicitHeight: Math.floor(childrenRect.height + UM.Theme.getSize("default_margin").height * 2) implicitHeight: Math.floor(childrenRect.height + UM.Theme.getSize("default_margin").height * 2)
property var outputDevice: null property var outputDevice: null
Connections
{
target: Cura.MachineManager
onGlobalContainerChanged:
{
outputDevice = Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null;
}
}
Rectangle Rectangle
{ {
height: childrenRect.height height: childrenRect.height
color: UM.Theme.getColor("setting_category") color: UM.Theme.getColor("setting_category")
property var activePrinter: outputDevice != null ? outputDevice.activePrinter : null
Label Label
{ {
@ -28,7 +36,7 @@ Item
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.margins: UM.Theme.getSize("default_margin").width anchors.margins: UM.Theme.getSize("default_margin").width
text: outputDevice != null ? activePrinter.name : "" text: outputDevice != null ? outputDevice.activePrinter.name : ""
} }
Label Label