Merge branch 'ui_rework_4_0' into cura4.0_header

This commit is contained in:
Diego Prado Gesto 2018-11-01 09:21:33 +01:00
commit ef0ba81564
132 changed files with 14801 additions and 11456 deletions

View file

@ -1,3 +1,65 @@
[3.6.0]
*Gyroid infill
New infill pattern with enhanced strength properties. Gyroid infill is one of the strongest infill types for a given weight, has isotropic properties, and prints relatively fast with reduced material use and a fully connected part interior. Note: Slicing time can increase up to 40 seconds or more, depending on the model. Contributed by smartavionics.
*Support brim
New setting that integrates the first layer of support material with the brims geometry. This significantly improves adhesion when printing with support material. Contributed by BagelOrb.
*Cooling fan number
It is now possible to specify the cooling fan to use if your printer has multiple fans. This is implemented under Machine settings in the Extruder tab. Contributed by smartavionics.
*Settings refactor
The CuraEngine has been refactored to create a more testable, future-proof way of storing and representing settings. This makes slicing faster, and future development easier.
*Print core CC Red 0.6
The new print core CC Red 0.6 is selectable when the Ultimaker S5 profile is active. This print core is optimized for use with abrasive materials and composites.
*File name and layer display
Added M117 commands to GCODE to give real-time information about the print job file name and layer number shown on the printers display when printing via USB. Contributed by adecastilho.
*Firmware checker/Ultimaker S5
The update checker code has been improved and tested for more reliable firmware update notifications in Ultimaker Cura. The Ultimaker S5 is now included.
*Fullscreen mode shortcuts
Fullscreen mode can be toggled using the View menu or with the keyboard shortcuts: Command + Control + F (macOS), or F11 (Windows and Linux). Contributed by KangDroid.
*Configuration error message
In previous versions, Ultimaker Cura would display an error dialog explaining when something happened to user configuration files, including the option to reset to factory defaults. This would not warn about losing the current printer and print profile settings, so this information has been added.
*Rename Toolbox to Marketplace
The entry points to the Toolbox are now renamed to Marketplace.
*Materials in the Marketplace
A new tab has been added to the Marketplace that includes downloadable material profiles, to quickly and easily prepare models for a range of third-party materials.
*New third-party definitions
New profiles added for Anycube 4MAx and Tizyx K25. Contributed by jscurtu and ValentinPitre respectively.
*Improved definitions for Ender-3
The Ender-3 build plate size has been adjusted to the correct size of 235 x 235 mm, corrected the start-up sequence, and the printhead position has been adjusted when prints are purged or completed. Contributed by stelgenhof.
*Add mesh names to slicing message
Added comment generation to indicate which mesh the GCODE after this comment is constructing. Contributed by paukstelis.
*Bug fixes
- The active material is highlighted in Ultimaker Curas material manager list. This behavior is now consistent with the profile and machine manager.
- The option to use 1.75 mm diameter filament with third-party 3D printers is now fixed and does not revert back to 2.85 mm. This fix also applies the appropriate a Z-axis speed change for 1.75 mm filament printers. Contributed by kaleidoscopeit.
- A fix was created to handle OSX version 10.10, but due to the QT upgrade, users with older versions wont be able to run Ultimaker Cura on their system without a system update. This applies to OSX version 10.09 and 10.08.
- Fixed a memory leak when leaving the “Monitor” page open.
- Added performance improvements to the PolygonConnector to efficiently connect polygons that are close to each other. This also reduces the chances of the print head collide with previously printed things. Contributed by BagelOrb.
- Fixed a bug where the GCODE reader didnt show retractions.
- Changes the USBPrinting update thread to prevent flooding the printer with M105 temperature update requests. Contributed by fieldOfView.
- Fix the behavior of the "manage visible settings" button, when pressing the "cog" icon of a particular category. Contributed by fieldOfView.
- Add a new post processing script that pauses the print at a certain height that works with RepRap printers. Contributed by Kriechi.
- Fix updates to the print monitor temperatures while preheating. Contributed by fieldOfView.
- Fixed a bug where material cost is not shown unless weight is changed.
- Fixed bugs crashing the CuraEngine when TreeSupport is enabled.
- Fixed a bug where Ultimaker Cura would upload the wrong firmware after switching printers in the UI.
- Fixed a bug where the layer view was missing if the first layer was empty.
- Fixed a bug where erroneous combing movements were taking place.
- Fixed a bug where the initial layer temperature is set correctly for the first object but then never again.
- Fixed a bug where clicking the fx icon didnt respond.
[3.5.1]
*Bug fixes
- Fixed M104 temperature commands giving inaccurate results.

View file

@ -412,7 +412,7 @@ Cura.MachineAction
{
if (settingsTabs.currentIndex > 0)
{
var extruderIndex = (settingsTabs.currentIndex - 1).toString()
const extruderIndex = index.toString()
Cura.MachineManager.activeMachine.extruders[extruderIndex].compatibleMaterialDiameter = value
}
}

View file

@ -407,14 +407,9 @@ Item {
function updateFilter()
{
var new_filter = {};
if (printSequencePropertyProvider.properties.value == "one_at_a_time")
{
new_filter["settable_per_meshgroup"] = true;
}
else
{
new_filter["settable_per_mesh"] = true;
}
new_filter["settable_per_mesh"] = true;
// Don't filter on "settable_per_meshgroup" any more when `printSequencePropertyProvider.properties.value`
// is set to "one_at_a_time", because the current backend architecture isn't ready for that.
if(filterInput.text != "")
{

View file

@ -10,7 +10,7 @@ Window
{
id: base
property var selection: null
title: catalog.i18nc("@title", "Toolbox")
title: catalog.i18nc("@title", "Marketplace")
modality: Qt.ApplicationModal
flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint

View file

@ -25,14 +25,11 @@ Item
rightMargin: UM.Theme.getSize("wide_margin").width
}
height: UM.Theme.getSize("toolbox_detail_header").height
Image
Rectangle
{
id: thumbnail
width: UM.Theme.getSize("toolbox_thumbnail_medium").width
height: UM.Theme.getSize("toolbox_thumbnail_medium").height
fillMode: Image.PreserveAspectFit
source: details === null ? "" : (details.icon_url || "../images/logobot.svg")
mipmap: true
anchors
{
top: parent.top
@ -40,6 +37,14 @@ Item
leftMargin: UM.Theme.getSize("wide_margin").width
topMargin: UM.Theme.getSize("wide_margin").height
}
color: white //Always a white background for image (regardless of theme).
Image
{
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: details === null ? "" : (details.icon_url || "../images/logobot.svg")
mipmap: true
}
}
Label

View file

@ -1,5 +1,5 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 1.4

View file

@ -52,7 +52,7 @@ class PackagesModel(ListModel):
items = []
if self._metadata is None:
Logger.logException("w", "Failed to load packages for Toolbox")
Logger.logException("w", "Failed to load packages for Marketplace")
self.setItems(items)
return

View file

@ -245,7 +245,7 @@ class Toolbox(QObject, Extension):
self._dialog = self._createDialog("Toolbox.qml")
if not self._dialog:
Logger.log("e", "Unexpected error trying to create the 'Toolbox' dialog.")
Logger.log("e", "Unexpected error trying to create the 'Marketplace' dialog.")
return
self._dialog.show()
@ -254,7 +254,7 @@ class Toolbox(QObject, Extension):
self.enabledChanged.emit()
def _createDialog(self, qml_name: str) -> Optional[QObject]:
Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name)
Logger.log("d", "Marketplace: Creating dialog [%s].", qml_name)
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
if not plugin_path:
return None
@ -262,7 +262,7 @@ class Toolbox(QObject, Extension):
dialog = self._application.createQmlComponent(path, {"toolbox": self})
if not dialog:
raise Exception("Failed to create toolbox dialog")
raise Exception("Failed to create Marketplace dialog")
return dialog
def _convertPluginMetadata(self, plugin: Dict[str, Any]) -> Dict[str, Any]:
@ -578,7 +578,7 @@ class Toolbox(QObject, Extension):
# Make API Calls
# --------------------------------------------------------------------------
def _makeRequestByType(self, type: str) -> None:
Logger.log("i", "Toolbox: Requesting %s metadata from server.", type)
Logger.log("i", "Marketplace: Requesting %s metadata from server.", type)
request = QNetworkRequest(self._request_urls[type])
request.setRawHeader(*self._request_header)
if self._network_manager:
@ -586,7 +586,7 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str)
def startDownload(self, url: str) -> None:
Logger.log("i", "Toolbox: Attempting to download & install package from %s.", url)
Logger.log("i", "Marketplace: Attempting to download & install package from %s.", url)
url = QUrl(url)
self._download_request = QNetworkRequest(url)
if hasattr(QNetworkRequest, "FollowRedirectsAttribute"):
@ -603,7 +603,7 @@ class Toolbox(QObject, Extension):
@pyqtSlot()
def cancelDownload(self) -> None:
Logger.log("i", "Toolbox: User cancelled the download of a package.")
Logger.log("i", "Marketplace: User cancelled the download of a package.")
self.resetDownload()
def resetDownload(self) -> None:
@ -690,7 +690,7 @@ class Toolbox(QObject, Extension):
return
except json.decoder.JSONDecodeError:
Logger.log("w", "Toolbox: Received invalid JSON for %s.", type)
Logger.log("w", "Marketplace: Received invalid JSON for %s.", type)
break
else:
self.setViewPage("errored")
@ -717,10 +717,10 @@ class Toolbox(QObject, Extension):
self._onDownloadComplete(file_path)
def _onDownloadComplete(self, file_path: str) -> None:
Logger.log("i", "Toolbox: Download complete.")
Logger.log("i", "Marketplace: Download complete.")
package_info = self._package_manager.getPackageInfo(file_path)
if not package_info:
Logger.log("w", "Toolbox: Package file [%s] was not a valid CuraPackage.", file_path)
Logger.log("w", "Marketplace: Package file [%s] was not a valid CuraPackage.", file_path)
return
license_content = self._package_manager.getPackageLicense(file_path)
@ -819,7 +819,7 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str, str, str)
def filterModelByProp(self, model_type: str, filter_type: str, parameter: str) -> None:
if not self._models[model_type]:
Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", model_type)
Logger.log("w", "Marketplace: Couldn't filter %s model because it doesn't exist.", model_type)
return
self._models[model_type].setFilter({filter_type: parameter})
self.filterChanged.emit()
@ -827,7 +827,7 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str, "QVariantMap")
def setFilters(self, model_type: str, filter_dict: dict) -> None:
if not self._models[model_type]:
Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", model_type)
Logger.log("w", "Marketplace: Couldn't filter %s model because it doesn't exist.", model_type)
return
self._models[model_type].setFilter(filter_dict)
self.filterChanged.emit()
@ -835,7 +835,7 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str)
def removeFilters(self, model_type: str) -> None:
if not self._models[model_type]:
Logger.log("w", "Toolbox: Couldn't remove filters on %s model because it doesn't exist.", model_type)
Logger.log("w", "Marketplace: Couldn't remove filters on %s model because it doesn't exist.", model_type)
return
self._models[model_type].setFilter({})
self.filterChanged.emit()
@ -845,6 +845,7 @@ class Toolbox(QObject, Extension):
def buildMaterialsModels(self) -> None:
self._metadata["materials_showcase"] = []
self._metadata["materials_available"] = []
self._metadata["materials_generic"] = []
processed_authors = [] # type: List[str]

View file

@ -31,10 +31,10 @@ Rectangle {
anchors.fill: parent;
hoverEnabled: true;
onClicked: {
if (OutputDevice.activeCamera !== null) {
OutputDevice.setActiveCamera(null)
if (OutputDevice.activeCameraUrl != "") {
OutputDevice.setActiveCameraUrl("");
} else {
OutputDevice.setActiveCamera(modelData.camera);
OutputDevice.setActiveCameraUrl(modelData.cameraUrl);
}
}
}

View file

@ -16,7 +16,7 @@ Component {
height: maximumHeight;
onVisibleChanged: {
if (monitorFrame != null && !monitorFrame.visible) {
OutputDevice.setActiveCamera(null);
OutputDevice.setActiveCameraUrl("");
}
}
width: maximumWidth;
@ -125,8 +125,8 @@ Component {
PrinterVideoStream {
anchors.fill: parent;
camera: OutputDevice.activeCamera;
visible: OutputDevice.activeCamera != null;
cameraUrl: OutputDevice.activeCameraUrl;
visible: OutputDevice.activeCameraUrl != "";
}
}
}

View file

@ -10,43 +10,36 @@ Component {
height: maximumHeight;
width: maximumWidth;
Cura.CameraView {
Cura.NetworkMJPGImage {
id: cameraImage;
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
Component.onCompleted: {
if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.camera != null) {
OutputDevice.activePrinter.camera.start();
if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
cameraImage.start();
}
}
height: Math.floor((imageHeight === 0 ? 600 * screenScaleFactor : imageHeight) * width / imageWidth);
onVisibleChanged: {
if (visible) {
if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.camera != null) {
OutputDevice.activePrinter.camera.start();
if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
cameraImage.start();
}
} else {
if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.camera != null) {
OutputDevice.activePrinter.camera.stop();
if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
cameraImage.stop();
}
}
}
source: {
if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
return OutputDevice.activePrinter.cameraUrl;
}
}
width: Math.min(imageWidth === 0 ? 800 * screenScaleFactor : imageWidth, maximumWidth);
z: 1;
Connections
{
target: OutputDevice.activePrinter.camera;
onNewImage:
{
if (cameraImage.visible) {
cameraImage.image = OutputDevice.activePrinter.camera.latestImage;
cameraImage.update();
}
}
}
}
}
}

View file

@ -12,6 +12,7 @@ Item {
id: root;
property var printJob: null;
property var running: isRunning(printJob);
property var assigned: isAssigned(printJob);
Button {
id: button;
@ -33,6 +34,7 @@ Item {
hoverEnabled: true;
onClicked: parent.switchPopupState();
text: "\u22EE"; //Unicode; Three stacked points.
visible: printJob.state == "queued" || running ? true : false;
width: 35 * screenScaleFactor; // TODO: Theme!
}
@ -101,7 +103,7 @@ Item {
PrintJobContextMenuItem {
enabled: {
if (printJob && !running) {
if (printJob && printJob.state == "queued" && !assigned) {
if (OutputDevice && OutputDevice.queuedPrintJobs[0]) {
return OutputDevice.queuedPrintJobs[0].key != printJob.key;
}
@ -209,4 +211,10 @@ Item {
}
return ["paused", "printing", "pre_print"].indexOf(job.state) !== -1;
}
function isAssigned(job) {
if (!job) {
return false;
}
return job.assignedPrinter ? true : false;
}
}

View file

@ -46,24 +46,26 @@ Item {
width: parent.width - 2 * shadowRadius;
Column {
id: cardContents;
height: childrenRect.height;
width: parent.width;
// Main card
Item {
id: mainCard;
height: 60 * screenScaleFactor + 2 * UM.Theme.getSize("default_margin").width;
anchors {
left: parent.left;
leftMargin: UM.Theme.getSize("default_margin").width;
right: parent.right;
rightMargin: UM.Theme.getSize("default_margin").width;
}
height: 60 * screenScaleFactor + 2 * UM.Theme.getSize("default_margin").height;
width: parent.width;
// Machine icon
Item {
id: machineIcon;
anchors {
leftMargin: UM.Theme.getSize("wide_margin").width;
top: parent.top;
left: parent.left;
margins: UM.Theme.getSize("default_margin").width;
}
anchors.verticalCenter: parent.verticalCenter;
height: parent.height - 2 * UM.Theme.getSize("default_margin").width;
width: height;
@ -108,7 +110,7 @@ Item {
id: printerInfo;
anchors {
left: machineIcon.right;
leftMargin: UM.Theme.getSize("default_margin").width;
leftMargin: UM.Theme.getSize("wide_margin").width;
right: collapseIcon.left;
verticalCenter: machineIcon.verticalCenter;
}
@ -222,7 +224,6 @@ Item {
}
}
}
// Detailed card
PrinterCardDetails {
collapsed: root.collapsed;
@ -233,6 +234,7 @@ Item {
// Progress bar
PrinterCardProgressBar {
visible: printer && printer.activePrintJob != null;
width: parent.width;
}
}
}

View file

@ -28,7 +28,7 @@ Item {
right: parent.right;
rightMargin: UM.Theme.getSize("default_margin").width;
}
height: childrenRect.height + UM.Theme.getSize("wide_margin").height;
height: childrenRect.height + UM.Theme.getSize("default_margin").height;
spacing: UM.Theme.getSize("default_margin").height;
width: parent.width;
@ -39,9 +39,7 @@ Item {
printJob: root.printer ? root.printer.activePrintJob : null;
}
HorizontalLine {
visible: root.printJob;
}
HorizontalLine {}
Row {
height: childrenRect.height;
@ -61,24 +59,17 @@ Item {
visible: printJob;
}
}
PrintJobPreview {
anchors.horizontalCenter: parent.horizontalCenter;
job: root.printer && root.printer.activePrintJob ? root.printer.activePrintJob : null;
visible: root.printJob;
}
}
CameraButton {
id: showCameraButton;
anchors {
bottom: contentColumn.bottom;
bottomMargin: Math.round(1.5 * UM.Theme.getSize("default_margin").height);
left: contentColumn.left;
leftMargin: Math.round(0.5 * UM.Theme.getSize("default_margin").width);
CameraButton {
id: showCameraButton;
iconSource: "../svg/camera-icon.svg";
visible: root.printer;
}
iconSource: "../svg/camera-icon.svg";
visible: root.printJob;
}
}

View file

@ -8,7 +8,7 @@ import UM 1.3 as UM
import Cura 1.0 as Cura
Item {
property var camera: null;
property var cameraUrl: "";
Rectangle {
anchors.fill:parent;
@ -18,7 +18,7 @@ Item {
MouseArea {
anchors.fill: parent;
onClicked: OutputDevice.setActiveCamera(null);
onClicked: OutputDevice.setActiveCameraUrl("");
z: 0;
}
@ -34,33 +34,23 @@ Item {
z: 999;
}
Cura.CameraView {
Cura.NetworkMJPGImage {
id: cameraImage
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
height: Math.round((imageHeight === 0 ? 600 * screenScaleFactor : imageHeight) * width / imageWidth);
onVisibleChanged: {
if (visible) {
if (camera != null) {
camera.start();
if (cameraUrl != "") {
start();
}
} else {
if (camera != null) {
camera.stop();
}
}
}
Connections
{
target: camera
onNewImage: {
if (cameraImage.visible) {
cameraImage.image = camera.latestImage;
cameraImage.update();
if (cameraUrl != "") {
stop();
}
}
}
source: cameraUrl
width: Math.min(imageWidth === 0 ? 800 * screenScaleFactor : imageWidth, maximumWidth);
z: 1
}
@ -68,7 +58,7 @@ Item {
MouseArea {
anchors.fill: cameraImage;
onClicked: {
OutputDevice.setActiveCamera(null);
OutputDevice.setActiveCameraUrl("");
}
z: 1;
}

View file

@ -22,7 +22,6 @@ from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationM
from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice, AuthState
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutput.NetworkCamera import NetworkCamera
from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController
from .SendMaterialJob import SendMaterialJob
@ -47,7 +46,7 @@ i18n_catalog = i18nCatalog("cura")
class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
printJobsChanged = pyqtSignal()
activePrinterChanged = pyqtSignal()
activeCameraChanged = pyqtSignal()
activeCameraUrlChanged = pyqtSignal()
receivedPrintJobsChanged = pyqtSignal()
# This is a bit of a hack, as the notify can only use signals that are defined by the class that they are in.
@ -100,7 +99,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._latest_reply_handler = None # type: Optional[QNetworkReply]
self._sending_job = None
self._active_camera = None # type: Optional[NetworkCamera]
self._active_camera_url = QUrl() # type: QUrl
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False, file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
self.writeStarted.emit(self)
@ -264,30 +263,21 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def activePrinter(self) -> Optional[PrinterOutputModel]:
return self._active_printer
@pyqtProperty(QObject, notify=activeCameraChanged)
def activeCamera(self) -> Optional[NetworkCamera]:
return self._active_camera
@pyqtSlot(QObject)
def setActivePrinter(self, printer: Optional[PrinterOutputModel]) -> None:
if self._active_printer != printer:
if self._active_printer and self._active_printer.camera:
self._active_printer.camera.stop()
self._active_printer = printer
self.activePrinterChanged.emit()
@pyqtSlot(QObject)
def setActiveCamera(self, camera: Optional[NetworkCamera]) -> None:
if self._active_camera != camera:
if self._active_camera:
self._active_camera.stop()
@pyqtProperty(QUrl, notify = activeCameraUrlChanged)
def activeCameraUrl(self) -> "QUrl":
return self._active_camera_url
self._active_camera = camera
if self._active_camera:
self._active_camera.start()
self.activeCameraChanged.emit()
@pyqtSlot(QUrl)
def setActiveCameraUrl(self, camera_url: "QUrl") -> None:
if self._active_camera_url != camera_url:
self._active_camera_url = camera_url
self.activeCameraUrlChanged.emit()
def _onPostPrintJobFinished(self, reply: QNetworkReply) -> None:
if self._progress_message:
@ -548,7 +538,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def _createPrinterModel(self, data: Dict[str, Any]) -> PrinterOutputModel:
printer = PrinterOutputModel(output_controller = ClusterUM3PrinterOutputController(self),
number_of_extruders = self._number_of_extruders)
printer.setCamera(NetworkCamera("http://" + data["ip_address"] + ":8080/?action=stream"))
printer.setCameraUrl(QUrl("http://" + data["ip_address"] + ":8080/?action=stream"))
self._printers.append(printer)
return printer

View file

@ -7,7 +7,6 @@ from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutp
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutput.NetworkCamera import NetworkCamera
from cura.Settings.ContainerManager import ContainerManager
from cura.Settings.ExtruderManager import ExtruderManager
@ -18,7 +17,7 @@ from UM.i18n import i18nCatalog
from UM.Message import Message
from PyQt5.QtNetwork import QNetworkRequest
from PyQt5.QtCore import QTimer
from PyQt5.QtCore import QTimer, QUrl
from PyQt5.QtWidgets import QMessageBox
from .LegacyUM3PrinterOutputController import LegacyUM3PrinterOutputController
@ -568,7 +567,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
# Quickest way to get the firmware version is to grab it from the zeroconf.
firmware_version = self._properties.get(b"firmware_version", b"").decode("utf-8")
self._printers = [PrinterOutputModel(output_controller=self._output_controller, number_of_extruders=self._number_of_extruders, firmware_version=firmware_version)]
self._printers[0].setCamera(NetworkCamera("http://" + self._address + ":8080/?action=stream"))
self._printers[0].setCameraUrl(QUrl("http://" + self._address + ":8080/?action=stream"))
for extruder in self._printers[0].extruders:
extruder.activeMaterialChanged.connect(self.materialIdChanged)
extruder.hotendIDChanged.connect(self.hotendIdChanged)