diff --git a/cura/API/Account.py b/cura/API/Account.py
index 4868204a94..e190fe9b42 100644
--- a/cura/API/Account.py
+++ b/cura/API/Account.py
@@ -10,7 +10,7 @@ from UM.Message import Message
from UM.i18n import i18nCatalog
from cura.OAuth2.AuthorizationService import AuthorizationService
from cura.OAuth2.Models import OAuth2Settings
-from cura.UltimakerCloud import UltimakerCloudAuthentication
+from cura.UltimakerCloud import UltimakerCloudConstants
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
@@ -69,7 +69,7 @@ class Account(QObject):
self._last_sync_str = "-"
self._callback_port = 32118
- self._oauth_root = UltimakerCloudAuthentication.CuraCloudAccountAPIRoot
+ self._oauth_root = UltimakerCloudConstants.CuraCloudAccountAPIRoot
self._oauth_settings = OAuth2Settings(
OAUTH_SERVER_URL= self._oauth_root,
diff --git a/cura/API/ConnectionStatus.py b/cura/API/ConnectionStatus.py
index 332e519ca9..007f03fdd1 100644
--- a/cura/API/ConnectionStatus.py
+++ b/cura/API/ConnectionStatus.py
@@ -4,14 +4,14 @@ from PyQt5.QtCore import QObject, pyqtSignal, QTimer, pyqtProperty
from PyQt5.QtNetwork import QNetworkReply
from UM.TaskManagement.HttpRequestManager import HttpRequestManager
-from cura.UltimakerCloud import UltimakerCloudAuthentication
+from cura.UltimakerCloud import UltimakerCloudConstants
class ConnectionStatus(QObject):
"""Status info for some web services"""
UPDATE_INTERVAL = 10.0 # seconds
- ULTIMAKER_CLOUD_STATUS_URL = UltimakerCloudAuthentication.CuraCloudAPIRoot + "/connect/v1/"
+ ULTIMAKER_CLOUD_STATUS_URL = UltimakerCloudConstants.CuraCloudAPIRoot + "/connect/v1/"
__instance = None # type: Optional[ConnectionStatus]
diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py
index 3af6ebeaf8..90197f8037 100755
--- a/cura/CuraApplication.py
+++ b/cura/CuraApplication.py
@@ -106,7 +106,7 @@ from cura.UI.RecommendedMode import RecommendedMode
from cura.UI.TextManager import TextManager
from cura.UI.WelcomePagesModel import WelcomePagesModel
from cura.UI.WhatsNewPagesModel import WhatsNewPagesModel
-from cura.UltimakerCloud import UltimakerCloudAuthentication
+from cura.UltimakerCloud import UltimakerCloudConstants
from cura.Utils.NetworkingUtil import NetworkingUtil
from . import BuildVolume
from . import CameraAnimation
@@ -207,6 +207,7 @@ class CuraApplication(QtApplication):
self._first_start_machine_actions_model = None
self._welcome_pages_model = WelcomePagesModel(self, parent = self)
self._add_printer_pages_model = AddPrinterPagesModel(self, parent = self)
+ self._add_printer_pages_model_without_cancel = AddPrinterPagesModel(self, parent = self)
self._whats_new_pages_model = WhatsNewPagesModel(self, parent = self)
self._text_manager = TextManager(parent = self)
@@ -255,11 +256,11 @@ class CuraApplication(QtApplication):
@pyqtProperty(str, constant=True)
def ultimakerCloudApiRootUrl(self) -> str:
- return UltimakerCloudAuthentication.CuraCloudAPIRoot
+ return UltimakerCloudConstants.CuraCloudAPIRoot
@pyqtProperty(str, constant = True)
def ultimakerCloudAccountRootUrl(self) -> str:
- return UltimakerCloudAuthentication.CuraCloudAccountAPIRoot
+ return UltimakerCloudConstants.CuraCloudAccountAPIRoot
@pyqtProperty(str, constant=True)
def ultimakerDigitalFactoryUrl(self) -> str:
@@ -651,7 +652,7 @@ class CuraApplication(QtApplication):
return self._global_container_stack
@override(Application)
- def setGlobalContainerStack(self, stack: "GlobalStack") -> None:
+ def setGlobalContainerStack(self, stack: Optional["GlobalStack"]) -> None:
self._setLoadingHint(self._i18n_catalog.i18nc("@info:progress", "Initializing Active Machine..."))
super().setGlobalContainerStack(stack)
@@ -816,6 +817,7 @@ class CuraApplication(QtApplication):
self._output_device_manager.start()
self._welcome_pages_model.initialize()
self._add_printer_pages_model.initialize()
+ self._add_printer_pages_model_without_cancel.initialize(cancellable = False)
self._whats_new_pages_model.initialize()
# Detect in which mode to run and execute that mode
@@ -853,6 +855,7 @@ class CuraApplication(QtApplication):
self.callLater(self._openFile, file_name)
initializationFinished = pyqtSignal()
+ showAddPrintersUncancellableDialog = pyqtSignal() # Used to show the add printers dialog with a greyed background
def runWithoutGUI(self):
"""Run Cura without GUI elements and interaction (server mode)."""
@@ -943,6 +946,10 @@ class CuraApplication(QtApplication):
def getAddPrinterPagesModel(self, *args) -> "AddPrinterPagesModel":
return self._add_printer_pages_model
+ @pyqtSlot(result = QObject)
+ def getAddPrinterPagesModelWithoutCancel(self, *args) -> "AddPrinterPagesModel":
+ return self._add_printer_pages_model_without_cancel
+
@pyqtSlot(result = QObject)
def getWhatsNewPagesModel(self, *args) -> "WhatsNewPagesModel":
return self._whats_new_pages_model
diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py
index aa8552bebb..776d540867 100644
--- a/cura/Machines/Models/BaseMaterialsModel.py
+++ b/cura/Machines/Models/BaseMaterialsModel.py
@@ -154,7 +154,7 @@ class BaseMaterialsModel(ListModel):
# Update the available materials (ContainerNode) for the current active machine and extruder setup.
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
- if not global_stack.hasMaterials:
+ if not global_stack or not global_stack.hasMaterials:
return # There are no materials for this machine, so nothing to do.
extruder_list = global_stack.extruderList
if self._extruder_position > len(extruder_list):
diff --git a/cura/OAuth2/AuthorizationRequestServer.py b/cura/OAuth2/AuthorizationRequestServer.py
index 74b0b5f012..4ed3975638 100644
--- a/cura/OAuth2/AuthorizationRequestServer.py
+++ b/cura/OAuth2/AuthorizationRequestServer.py
@@ -2,6 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher.
from http.server import HTTPServer
+from socketserver import ThreadingMixIn
from typing import Callable, Any, TYPE_CHECKING
if TYPE_CHECKING:
@@ -9,7 +10,7 @@ if TYPE_CHECKING:
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers
-class AuthorizationRequestServer(HTTPServer):
+class AuthorizationRequestServer(ThreadingMixIn, HTTPServer):
"""The authorization request callback handler server.
This subclass is needed to be able to pass some data to the request handler. This cannot be done on the request
diff --git a/cura/OAuth2/LocalAuthorizationServer.py b/cura/OAuth2/LocalAuthorizationServer.py
index a41de2d406..ac14b00985 100644
--- a/cura/OAuth2/LocalAuthorizationServer.py
+++ b/cura/OAuth2/LocalAuthorizationServer.py
@@ -81,7 +81,7 @@ class LocalAuthorizationServer:
if self._web_server:
try:
- self._web_server.server_close()
+ self._web_server.shutdown()
except OSError:
# OS error can happen if the socket was already closed. We really don't care about that case.
pass
diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py
index 5086c68a73..423df167cd 100755
--- a/cura/Settings/MachineManager.py
+++ b/cura/Settings/MachineManager.py
@@ -22,6 +22,7 @@ from UM.Settings.SettingFunction import SettingFunction
from UM.Signal import postponeSignals, CompressTechnique
import cura.CuraApplication # Imported like this to prevent circular references.
+from UM.Util import parseBool
from cura.Machines.ContainerNode import ContainerNode
from cura.Machines.ContainerTree import ContainerTree
@@ -37,6 +38,7 @@ from cura.Settings.ExtruderStack import ExtruderStack
from cura.Settings.cura_empty_instance_containers import (empty_definition_changes_container, empty_variant_container,
empty_material_container, empty_quality_container,
empty_quality_changes_container, empty_intent_container)
+from cura.UltimakerCloud.UltimakerCloudConstants import META_UM_LINKED_TO_ACCOUNT
from .CuraStackBuilder import CuraStackBuilder
@@ -288,9 +290,15 @@ class MachineManager(QObject):
self.activeStackValueChanged.emit()
@pyqtSlot(str)
- def setActiveMachine(self, stack_id: str) -> None:
+ def setActiveMachine(self, stack_id: Optional[str]) -> None:
self.blurSettings.emit() # Ensure no-one has focus.
+ if not stack_id:
+ self._application.setGlobalContainerStack(None)
+ self.globalContainerChanged.emit()
+ self._application.showAddPrintersUncancellableDialog.emit()
+ return
+
container_registry = CuraContainerRegistry.getInstance()
containers = container_registry.findContainerStacks(id = stack_id)
if not containers:
@@ -494,6 +502,10 @@ class MachineManager(QObject):
group_size = int(self.activeMachine.getMetaDataEntry("group_size", "-1"))
return group_size > 1
+ @pyqtProperty(bool, notify = printerConnectedStatusChanged)
+ def activeMachineIsLinkedToCurrentAccount(self) -> bool:
+ return parseBool(self.activeMachine.getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "True"))
+
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineHasNetworkConnection(self) -> bool:
# A network connection is only available if any output device is actually a network connected device.
@@ -715,6 +727,8 @@ class MachineManager(QObject):
other_machine_stacks = [s for s in machine_stacks if s["id"] != machine_id]
if other_machine_stacks:
self.setActiveMachine(other_machine_stacks[0]["id"])
+ else:
+ self.setActiveMachine(None)
metadatas = CuraContainerRegistry.getInstance().findContainerStacksMetadata(id = machine_id)
if not metadatas:
diff --git a/cura/UI/AddPrinterPagesModel.py b/cura/UI/AddPrinterPagesModel.py
index b06f220374..9b35dbcacc 100644
--- a/cura/UI/AddPrinterPagesModel.py
+++ b/cura/UI/AddPrinterPagesModel.py
@@ -10,12 +10,11 @@ from .WelcomePagesModel import WelcomePagesModel
#
class AddPrinterPagesModel(WelcomePagesModel):
- def initialize(self) -> None:
+ def initialize(self, cancellable: bool = True) -> None:
self._pages.append({"id": "add_network_or_local_printer",
"page_url": self._getBuiltinWelcomePagePath("AddNetworkOrLocalPrinterContent.qml"),
"next_page_id": "machine_actions",
"next_page_button_text": self._catalog.i18nc("@action:button", "Add"),
- "previous_page_button_text": self._catalog.i18nc("@action:button", "Cancel"),
})
self._pages.append({"id": "add_printer_by_ip",
"page_url": self._getBuiltinWelcomePagePath("AddPrinterByIpContent.qml"),
@@ -30,6 +29,9 @@ class AddPrinterPagesModel(WelcomePagesModel):
"page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"),
"should_show_function": self.shouldShowMachineActions,
})
+ if cancellable:
+ self._pages[0]["previous_page_button_text"] = self._catalog.i18nc("@action:button", "Cancel")
+
self.setItems(self._pages)
diff --git a/cura/UltimakerCloud/UltimakerCloudAuthentication.py b/cura/UltimakerCloud/UltimakerCloudConstants.py
similarity index 90%
rename from cura/UltimakerCloud/UltimakerCloudAuthentication.py
rename to cura/UltimakerCloud/UltimakerCloudConstants.py
index 707b814d34..f3f862b689 100644
--- a/cura/UltimakerCloud/UltimakerCloudAuthentication.py
+++ b/cura/UltimakerCloud/UltimakerCloudConstants.py
@@ -9,6 +9,10 @@ DEFAULT_CLOUD_API_VERSION = "1" # type: str
DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str
DEFAULT_DIGITAL_FACTORY_URL = "https://digitalfactory.ultimaker.com" # type: str
+# Container Metadata keys
+META_UM_LINKED_TO_ACCOUNT = "um_linked_to_account"
+"""(bool) Whether a cloud printer is linked to an Ultimaker account"""
+
try:
from cura.CuraVersion import CuraCloudAPIRoot # type: ignore
if CuraCloudAPIRoot == "":
diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py
index 639c63b45f..56158922dc 100644
--- a/plugins/CuraDrive/src/Settings.py
+++ b/plugins/CuraDrive/src/Settings.py
@@ -1,13 +1,13 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from cura.UltimakerCloud import UltimakerCloudAuthentication
+from cura.UltimakerCloud import UltimakerCloudConstants
class Settings:
# Keeps the plugin settings.
DRIVE_API_VERSION = 1
- DRIVE_API_URL = "{}/cura-drive/v{}".format(UltimakerCloudAuthentication.CuraCloudAPIRoot, str(DRIVE_API_VERSION))
+ DRIVE_API_URL = "{}/cura-drive/v{}".format(UltimakerCloudConstants.CuraCloudAPIRoot, str(DRIVE_API_VERSION))
AUTO_BACKUP_ENABLED_PREFERENCE_KEY = "cura_drive/auto_backup_enabled"
AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date"
diff --git a/plugins/PostProcessingPlugin/scripts/Stretch.py b/plugins/PostProcessingPlugin/scripts/Stretch.py
index 480ba60606..e56a9f48b1 100644
--- a/plugins/PostProcessingPlugin/scripts/Stretch.py
+++ b/plugins/PostProcessingPlugin/scripts/Stretch.py
@@ -289,6 +289,13 @@ class Stretcher:
self.layergcode = self.layergcode + sout + "\n"
ipos = ipos + 1
else:
+ # The command is intended to be passed through unmodified via
+ # the comment field. In the case of an extruder only move, though,
+ # the extruder and potentially the feed rate are modified.
+ # We need to update self.outpos accordingly so that subsequent calls
+ # to stepToGcode() knows about the extruder and feed rate change.
+ self.outpos.step_e = layer_steps[i].step_e
+ self.outpos.step_f = layer_steps[i].step_f
self.layergcode = self.layergcode + layer_steps[i].comment + "\n"
def workOnSequence(self, orig_seq, modif_seq):
diff --git a/plugins/Toolbox/src/CloudApiModel.py b/plugins/Toolbox/src/CloudApiModel.py
index b4ff00c6cd..bef37d8173 100644
--- a/plugins/Toolbox/src/CloudApiModel.py
+++ b/plugins/Toolbox/src/CloudApiModel.py
@@ -1,13 +1,13 @@
from typing import Union
from cura import ApplicationMetadata
-from cura.UltimakerCloud import UltimakerCloudAuthentication
+from cura.UltimakerCloud import UltimakerCloudConstants
class CloudApiModel:
sdk_version = ApplicationMetadata.CuraSDKVersion # type: Union[str, int]
- cloud_api_version = UltimakerCloudAuthentication.CuraCloudAPIVersion # type: str
- cloud_api_root = UltimakerCloudAuthentication.CuraCloudAPIRoot # type: str
+ cloud_api_version = UltimakerCloudConstants.CuraCloudAPIVersion # type: str
+ cloud_api_root = UltimakerCloudConstants.CuraCloudAPIRoot # type: str
api_url = "{cloud_api_root}/cura-packages/v{cloud_api_version}/cura/v{sdk_version}".format(
cloud_api_root = cloud_api_root,
cloud_api_version = cloud_api_version,
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
index ab14d7ff06..713ee25170 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
@@ -13,7 +13,7 @@ from UM.TaskManagement.HttpRequestManager import HttpRequestManager
from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope
from cura.API import Account
from cura.CuraApplication import CuraApplication
-from cura.UltimakerCloud import UltimakerCloudAuthentication
+from cura.UltimakerCloud import UltimakerCloudConstants
from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope
from .ToolPathUploader import ToolPathUploader
from ..Models.BaseModel import BaseModel
@@ -35,7 +35,7 @@ class CloudApiClient:
"""
# The cloud URL to use for this remote cluster.
- ROOT_PATH = UltimakerCloudAuthentication.CuraCloudAPIRoot
+ ROOT_PATH = UltimakerCloudConstants.CuraCloudAPIRoot
CLUSTER_API_ROOT = "{}/connect/v1".format(ROOT_PATH)
CURA_API_ROOT = "{}/cura/v1".format(ROOT_PATH)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
index f0b1bb130c..33c9caba05 100644
--- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
@@ -1,21 +1,23 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os
-from typing import Dict, List, Optional
+from typing import Dict, List, Optional, Set
-from PyQt5.QtCore import QTimer
from PyQt5.QtNetwork import QNetworkReply
+from PyQt5.QtWidgets import QMessageBox
from UM import i18nCatalog
from UM.Logger import Logger # To log errors talking to the API.
from UM.Message import Message
from UM.Settings.Interfaces import ContainerInterface
from UM.Signal import Signal
+from UM.Util import parseBool
from cura.API import Account
from cura.API.Account import SyncState
from cura.CuraApplication import CuraApplication
from cura.Settings.CuraStackBuilder import CuraStackBuilder
from cura.Settings.GlobalStack import GlobalStack
+from cura.UltimakerCloud.UltimakerCloudConstants import META_UM_LINKED_TO_ACCOUNT
from .CloudApiClient import CloudApiClient
from .CloudOutputDevice import CloudOutputDevice
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
@@ -30,6 +32,7 @@ class CloudOutputDeviceManager:
META_CLUSTER_ID = "um_cloud_cluster_id"
META_NETWORK_KEY = "um_network_key"
+
SYNC_SERVICE_NAME = "CloudOutputDeviceManager"
# The translation catalog for this device.
@@ -41,9 +44,14 @@ class CloudOutputDeviceManager:
def __init__(self) -> None:
# Persistent dict containing the remote clusters for the authenticated user.
self._remote_clusters = {} # type: Dict[str, CloudOutputDevice]
+
+ # Dictionary containing all the cloud printers loaded in Cura
+ self._um_cloud_printers = {} # type: Dict[str, GlobalStack]
+
self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
self._api = CloudApiClient(CuraApplication.getInstance(), on_error = lambda error: Logger.log("e", str(error)))
self._account.loginStateChanged.connect(self._onLoginStateChanged)
+ self._removed_printers_message = None # type: Optional[Message]
# Ensure we don't start twice.
self._running = False
@@ -98,23 +106,41 @@ class CloudOutputDeviceManager:
def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None:
"""Callback for when the request for getting the clusters is finished."""
+ self._um_cloud_printers = {m.getMetaDataEntry(self.META_CLUSTER_ID): m for m in
+ CuraApplication.getInstance().getContainerRegistry().findContainerStacks(
+ type = "machine") if m.getMetaDataEntry(self.META_CLUSTER_ID, None)}
new_clusters = []
all_clusters = {c.cluster_id: c for c in clusters} # type: Dict[str, CloudClusterResponse]
online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse]
+ # Add the new printers in Cura. If a printer was previously added and is rediscovered, set its metadata to
+ # reflect that and mark the printer not removed from the account
for device_id, cluster_data in all_clusters.items():
if device_id not in self._remote_clusters:
new_clusters.append(cluster_data)
-
+ if device_id in self._um_cloud_printers and not parseBool(self._um_cloud_printers[device_id].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")):
+ self._um_cloud_printers[device_id].setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True)
self._onDevicesDiscovered(new_clusters)
- removed_device_keys = set(self._remote_clusters.keys()) - set(online_clusters.keys())
- for device_id in removed_device_keys:
+ # Hide the current removed_printers_message, if there is any
+ if self._removed_printers_message:
+ self._removed_printers_message.actionTriggered.disconnect(self._onRemovedPrintersMessageActionTriggered)
+ self._removed_printers_message.hide()
+
+ # Remove the CloudOutput device for offline printers
+ offline_device_keys = set(self._remote_clusters.keys()) - set(online_clusters.keys())
+ for device_id in offline_device_keys:
self._onDiscoveredDeviceRemoved(device_id)
- if new_clusters or removed_device_keys:
- self.discoveredDevicesChanged.emit()
+ # Handle devices that were previously added in Cura but do not exist in the account anymore (i.e. they were
+ # removed from the account)
+ removed_device_keys = set(self._um_cloud_printers.keys()) - set(all_clusters.keys())
if removed_device_keys:
+ self._devicesRemovedFromAccount(removed_device_keys)
+
+ if new_clusters or offline_device_keys or removed_device_keys:
+ self.discoveredDevicesChanged.emit()
+ if offline_device_keys:
# If the removed device was active we should connect to the new active device
self._connectToActiveMachine()
@@ -144,10 +170,13 @@ class CloudOutputDeviceManager:
if machine_manager.getMachine(device.printerType, {self.META_CLUSTER_ID: device.key}) is None \
and machine_manager.getMachine(device.printerType, {self.META_NETWORK_KEY: cluster_data.host_name + "*"}) is None: # The host name is part of the network key.
new_devices.append(device)
-
elif device.getId() not in self._remote_clusters:
self._remote_clusters[device.getId()] = device
remote_clusters_added = True
+ # If a printer that was removed from the account is re-added, change its metadata to mark it not removed
+ # from the account
+ elif not parseBool(self._um_cloud_printers[device.key].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")):
+ self._um_cloud_printers[device.key].setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True)
# Inform the Cloud printers model about new devices.
new_devices_list_of_dicts = [{
@@ -163,7 +192,11 @@ class CloudOutputDeviceManager:
self._connectToActiveMachine()
return
- new_devices.sort(key = lambda x: x.name.lower())
+ # Sort new_devices on online status first, alphabetical second.
+ # Since the first device might be activated in case there is no active printer yet,
+ # it would be nice to prioritize online devices
+ online_cluster_names = {c.friendly_name.lower() for c in clusters if c.is_online and not c.friendly_name is None}
+ new_devices.sort(key = lambda x: ("a{}" if x.name.lower() in online_cluster_names else "b{}").format(x.name.lower()))
image_path = os.path.join(
CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "",
@@ -204,19 +237,97 @@ class CloudOutputDeviceManager:
max_disp_devices = 3
if len(new_devices) > max_disp_devices:
num_hidden = len(new_devices) - max_disp_devices + 1
- device_name_list = ["- {} ({})".format(device.name, device.printerTypeName) for device in new_devices[0:num_hidden]]
- device_name_list.append(self.I18N_CATALOG.i18nc("info:hidden list items", "- and {} others", num_hidden))
+ device_name_list = ["
{} ({})".format(device.name, device.printerTypeName) for device in new_devices[0:num_hidden]]
+ device_name_list.append(self.I18N_CATALOG.i18nc("info:hidden list items", "... and {} others", num_hidden))
device_names = "\n".join(device_name_list)
else:
- device_names = "\n".join(["- {} ({})".format(device.name, device.printerTypeName) for device in new_devices])
+ device_names = "\n".join(["{} ({})".format(device.name, device.printerTypeName) for device in new_devices])
message_text = self.I18N_CATALOG.i18nc(
"info:status",
- "Cloud printers added from your account:\n{}",
+ "Cloud printers added from your account:\n",
device_names
)
message.setText(message_text)
+ def _devicesRemovedFromAccount(self, removed_device_ids: Set[str]) -> None:
+ """
+ Removes the CloudOutputDevice from the received device ids and marks the specific printers as "removed from
+ account". In addition, it generates a message to inform the user about the printers that are no longer linked to
+ his/her account. The message is not generated if all the printers have been previously reported as not linked
+ to the account.
+
+ :param removed_device_ids: Set of device ids, whose CloudOutputDevice needs to be removed
+ :return: None
+ """
+
+ if not CuraApplication.getInstance().getCuraAPI().account.isLoggedIn:
+ return
+
+ # Do not report device ids which have been previously marked as non-linked to the account
+ ignored_device_ids = set()
+ for device_id in removed_device_ids:
+ if not parseBool(self._um_cloud_printers[device_id].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")):
+ ignored_device_ids.add(device_id)
+ # Keep the reported_device_ids list in a class variable, so that the message button actions can access it and
+ # take the necessary steps to fulfill their purpose.
+ self.reported_device_ids = removed_device_ids - ignored_device_ids
+ if not self.reported_device_ids:
+ return
+
+ # Generate message
+ self._removed_printers_message = Message(
+ title = self.I18N_CATALOG.i18ncp(
+ "info:status",
+ "Cloud connection is not available for a printer",
+ "Cloud connection is not available for some printers",
+ len(self.reported_device_ids)
+ )
+ )
+ device_names = "\n".join(["{} ({})".format(self._um_cloud_printers[device].name, self._um_cloud_printers[device].definition.name) for device in self.reported_device_ids])
+ message_text = self.I18N_CATALOG.i18ncp(
+ "info:status",
+ "The following cloud printer is not linked to your account:\n",
+ "The following cloud printers are not linked to your account:\n",
+ len(self.reported_device_ids)
+ )
+ message_text += self.I18N_CATALOG.i18nc(
+ "info:status",
+ "\nTo establish a connection, please visit the "
+ "Ultimaker Digital Factory.",
+ device_names
+ )
+ self._removed_printers_message.setText(message_text)
+ self._removed_printers_message.addAction("keep_printer_configurations_action",
+ name = self.I18N_CATALOG.i18nc("@action:button", "Keep printer configurations"),
+ icon = "",
+ description = "Keep the configuration of the cloud printer(s) synced with Cura which are not linked to your account.",
+ button_align = Message.ActionButtonAlignment.ALIGN_RIGHT)
+ self._removed_printers_message.addAction("remove_printers_action",
+ name = self.I18N_CATALOG.i18nc("@action:button", "Remove printers"),
+ icon = "",
+ description = "Remove the cloud printer(s) which are not linked to your account.",
+ button_style = Message.ActionButtonStyle.SECONDARY,
+ button_align = Message.ActionButtonAlignment.ALIGN_LEFT)
+ self._removed_printers_message.actionTriggered.connect(self._onRemovedPrintersMessageActionTriggered)
+
+ output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
+
+ # Remove the output device from the printers
+ for device_id in removed_device_ids:
+ device = self._um_cloud_printers.get(device_id, None) # type: Optional[GlobalStack]
+ if not device:
+ continue
+ if device_id in output_device_manager.getOutputDeviceIds():
+ output_device_manager.removeOutputDevice(device_id)
+ if device_id in self._remote_clusters:
+ del self._remote_clusters[device_id]
+
+ # Update the printer's metadata to mark it as not linked to the account
+ device.setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, False)
+
+ self._removed_printers_message.show()
+
def _onDiscoveredDeviceRemoved(self, device_id: str) -> None:
device = self._remote_clusters.pop(device_id, None) # type: Optional[CloudOutputDevice]
if not device:
@@ -302,3 +413,24 @@ class CloudOutputDeviceManager:
container_cluster_id = container.getMetaDataEntry(self.META_CLUSTER_ID, None)
if container_cluster_id in self._remote_clusters.keys():
del self._remote_clusters[container_cluster_id]
+
+ def _onRemovedPrintersMessageActionTriggered(self, removed_printers_message: Message, action: str) -> None:
+ if action == "keep_printer_configurations_action":
+ removed_printers_message.hide()
+ elif action == "remove_printers_action":
+ machine_manager = CuraApplication.getInstance().getMachineManager()
+ remove_printers_ids = {self._um_cloud_printers[i].getId() for i in self.reported_device_ids}
+ all_ids = {m.getId() for m in CuraApplication.getInstance().getContainerRegistry().findContainerStacks(type = "machine")}
+
+ question_title = self.I18N_CATALOG.i18nc("@title:window", "Remove printers?")
+ question_content = self.I18N_CATALOG.i18nc("@label", "You are about to remove {} printer(s) from Cura. This action cannot be undone. \nAre you sure you want to continue?".format(len(remove_printers_ids)))
+ if remove_printers_ids == all_ids:
+ question_content = self.I18N_CATALOG.i18nc("@label", "You are about to remove all printers from Cura. This action cannot be undone. \nAre you sure you want to continue?")
+ result = QMessageBox.question(None, question_title, question_content)
+ if result == QMessageBox.No:
+ return
+
+ for machine_cloud_id in self.reported_device_ids:
+ machine_manager.setActiveMachine(self._um_cloud_printers[machine_cloud_id].getId())
+ machine_manager.removeMachine(self._um_cloud_printers[machine_cloud_id].getId())
+ removed_printers_message.hide()
diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
index 7978c0cdba..6fe4d4242b 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
@@ -465,7 +465,7 @@ class XmlMaterialProfile(InstanceContainer):
return "materials"
@classmethod
- def getVersionFromSerialized(cls, serialized: str) -> Optional[int]:
+ def getVersionFromSerialized(cls, serialized: str) -> int:
data = ET.fromstring(serialized)
version = XmlMaterialProfile.Version
diff --git a/resources/definitions/dagoma_delta.def.json b/resources/definitions/dagoma_delta.def.json
new file mode 100644
index 0000000000..6ff837e757
--- /dev/null
+++ b/resources/definitions/dagoma_delta.def.json
@@ -0,0 +1,68 @@
+{
+ "name": "Dagoma Delta",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": false,
+ "author": "Dagoma",
+ "manufacturer": "Dagoma"
+ },
+ "overrides": {
+ "machine_width": {
+ "default_value": 195.55
+ },
+ "machine_height": {
+ "default_value": 205
+ },
+ "machine_depth": {
+ "default_value": 195.55
+ },
+ "machine_center_is_zero": {
+ "default_value": true
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [-36, -42],
+ [-36, 42],
+ [36, 42],
+ [36, -42]
+ ]
+ },
+ "gantry_height": {
+ "value": "0"
+ },
+ "machine_shape": {
+ "default_value": "elliptic"
+ },
+ "machine_start_gcode": {
+ "default_value": ";Gcode by Cura\nG90\nG28\nM107\nM109 R100\nG29\nM109 S{material_print_temperature_layer_0} U-55 X55 V-85 Y-85 W0.26 Z0.26\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n"
+ },
+ "machine_end_gcode": {
+ "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n"
+ },
+ "default_material_print_temperature": {
+ "default_value": 205
+ },
+ "speed_print": {
+ "default_value": 40
+ },
+ "retraction_amount": {
+ "default_value": 3.8
+ },
+ "retraction_speed": {
+ "default_value": 60
+ },
+ "adhesion_type": {
+ "default_value": "skirt"
+ },
+ "skirt_line_count": {
+ "default_value": 2
+ },
+ "layer_height_0": {
+ "default_value": 0.26
+ },
+ "top_bottom_thickness": {
+ "default_value": 1
+ }
+ }
+}
diff --git a/resources/definitions/dagoma_disco.def.json b/resources/definitions/dagoma_disco.def.json
new file mode 100644
index 0000000000..a62948c9a7
--- /dev/null
+++ b/resources/definitions/dagoma_disco.def.json
@@ -0,0 +1,62 @@
+{
+ "name": "Dagoma Disco",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": false,
+ "author": "Dagoma",
+ "manufacturer": "Dagoma"
+ },
+ "overrides": {
+ "machine_width": {
+ "default_value": 205
+ },
+ "machine_height": {
+ "default_value": 205
+ },
+ "machine_depth": {
+ "default_value": 205
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [-17, -70],
+ [-17, 40],
+ [17, 40],
+ [17, -70]
+ ]
+ },
+ "gantry_height": {
+ "value": "10"
+ },
+ "default_material_print_temperature": {
+ "default_value": 205
+ },
+ "material_standby_temperature": {
+ "default_value": 90
+ },
+ "speed_print": {
+ "default_value": 60
+ },
+ "retraction_amount": {
+ "default_value": 3.5
+ },
+ "retraction_speed": {
+ "default_value": 50
+ },
+ "adhesion_type": {
+ "default_value": "skirt"
+ },
+ "skirt_line_count": {
+ "default_value": 2
+ },
+ "layer_height_0": {
+ "default_value": 0.26
+ },
+ "top_bottom_thickness": {
+ "default_value": 1
+ }
+ }
+}
diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json
index 1032a249f8..16ce5585e4 100644
--- a/resources/definitions/dagoma_discoeasy200.def.json
+++ b/resources/definitions/dagoma_discoeasy200.def.json
@@ -1,82 +1,34 @@
{
"name": "Dagoma DiscoEasy200",
"version": 2,
- "inherits": "fdmprinter",
+ "inherits": "dagoma_disco",
"metadata": {
"visible": true,
"author": "Dagoma",
"manufacturer": "Dagoma",
"file_formats": "text/x-gcode",
"platform": "dagoma_discoeasy200.3mf",
- "platform_offset": [0, -57.3, -11],
+ "platform_offset": [0, -57, -39],
"has_machine_quality": true,
"has_materials": true,
"preferred_material": "chromatik_pla",
"machine_extruder_trains":
{
- "0": "dagoma_discoeasy200_extruder_0",
- "1": "dagoma_discoeasy200_extruder_1"
+ "0": "dagoma_discoeasy200_extruder"
}
},
"overrides": {
+ "machine_name": {
+ "default_value": "Dagoma DiscoEasy200"
+ },
"machine_extruder_count": {
- "default_value": 2
- },
- "machine_extruders_share_heater": {
- "default_value": true
- },
- "machine_width": {
- "default_value": 205
- },
- "machine_height": {
- "default_value": 205
- },
- "machine_depth": {
- "default_value": 205
- },
- "machine_center_is_zero": {
- "default_value": false
- },
- "machine_head_with_fans_polygon": {
- "default_value": [
- [-17, -70],
- [-17, 40],
- [17, 40],
- [17, -70]
- ]
- },
- "gantry_height": {
- "value": "10"
+ "default_value": 1
},
"machine_start_gcode": {
- "default_value": ";Gcode by Cura\nG90\nM106 S255\nG28 X Y\nG1 X50\nM109 R90\nG28\nM104 S{material_print_temperature_layer_0}\nG29\nM107\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E10\nG92 E0\nG1 Z3\nG1 F6000\n"
+ "default_value": ";Begin Start Gcode for Dagoma DiscoEasy 200\n;Sliced: {date} {time}\n;Initial extruder: {initial_extruder_nr}\n\nG90 ;Absolute positioning\nM106 S255 ;Fan on full\nG28 X Y ;Home stop X Y\nG1 X100 ;Centre back during cooldown in case of oozing\nM109 R{material_standby_temperature} ;Cooldown in case too hot\nG28 ;Centre\nG29 ;Auto-level\nM104 S{material_print_temperature_layer_0} ;Pre-heat\nM107 ;Fan off\nG0 X100 Y5 Z0.5 ;Front centre for degunk\nM109 S{material_print_temperature_layer_0} ;Wait for initial temp\nM83 ;E Relative\nG1 E10 F200 ;Degunk\nG1 E-3 F5000 ;Retract\nG0 Z3 ;Withdraw\nM82 ;E absolute\nG92 E0 ;E reset\nG1 F6000 ;Set feedrate\n\n;Finish Start Gcode for Dagoma DiscoEasy 200\n"
},
"machine_end_gcode": {
- "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 F3000\nG90\nG28 X Y\nM107\nM84\n"
- },
- "default_material_print_temperature": {
- "default_value": 205
- },
- "speed_print": {
- "default_value": 60
- },
- "retraction_amount": {
- "default_value": 3.5
- },
- "retraction_speed": {
- "default_value": 50
- },
- "adhesion_type": {
- "default_value": "skirt"
- },
- "skirt_line_count": {
- "default_value": 2
- },
- "layer_height_0": {
- "default_value": 0.26
- },
- "top_bottom_thickness": {
- "default_value": 1
+ "default_value": ";Begin End Gcode for Dagoma DiscoEasy 200\n\nM106 S255 ;Fan on full\nM104 S0 ;Cool hotend\nM140 S0 ;Cool heated bed\nG91 ;Relative positioning\nG1 E-3 F5000 ;Retract filament to stop oozing\nG0 Z+3 ;Withdraw\nG90 ;Absolute positioning\nG28 X Y ;Home\nM109 R{material_standby_temperature} ;Wait until head has cooled to standby temp\nM107 ;Fan off\nM18 ;Stepper motors off\n\n;Finish End Gcode for Dagoma DiscoEasy 200\n"
}
}
}
diff --git a/resources/definitions/dagoma_discoeasy200_bicolor.def.json b/resources/definitions/dagoma_discoeasy200_bicolor.def.json
new file mode 100644
index 0000000000..4786c03fc2
--- /dev/null
+++ b/resources/definitions/dagoma_discoeasy200_bicolor.def.json
@@ -0,0 +1,38 @@
+{
+ "name": "Dagoma DiscoEasy200 Bicolor",
+ "version": 2,
+ "inherits": "dagoma_disco",
+ "metadata": {
+ "visible": true,
+ "author": "Dagoma",
+ "manufacturer": "Dagoma",
+ "file_formats": "text/x-gcode",
+ "platform": "dagoma_discoeasy200_bicolor.3mf",
+ "platform_offset": [0, -57.3, -11],
+ "has_machine_quality": true,
+ "has_materials": true,
+ "preferred_material": "chromatik_pla",
+ "machine_extruder_trains":
+ {
+ "0": "dagoma_discoeasy200_extruder_0",
+ "1": "dagoma_discoeasy200_extruder_1"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Dagoma DiscoEasy200 Bicolor"
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ },
+ "machine_extruders_share_heater": {
+ "default_value": true
+ },
+ "machine_start_gcode": {
+ "default_value": ";Begin Start Gcode for Dagoma DiscoEasy 200 Bicolor\n;Sliced: {date} {time}\n;Initial extruder: {initial_extruder_nr}\n\nG90 ;Absolute positioning\nM106 S255 ;Fan on full\nG28 X Y ;Home stop X Y\nG1 X100 ;Centre back during cooldown in case of oozing\nM109 R{material_standby_temperature} ;Cooldown in case too hot\nG28 ;Centre\nG29 ;Auto-level\nM104 S{material_print_temperature_layer_0} ;Pre-heat\nM107 ;Fan off\nG0 X100 Y5 Z0.5 ;Front centre for degunk\nM109 S{material_print_temperature_layer_0} ;Wait for initial temp\n;M83 ;E Relative\n;G1 E60 F3000 ;Reverse multi-extruder retract\n;G1 E10 F200 ;Degunk\n;G1 E-3 F5000 ;Retract\nG0 Z3 ;Withdraw\n;M82 ;E absolute\n;G92 E0 ;E reset\n;G1 F6000 ;Set feedrate\n\n;Finish Start Gcode for Dagoma DiscoEasy 200 Bicolor\n"
+ },
+ "machine_end_gcode": {
+ "default_value": ";Begin End Gcode for Dagoma DiscoEasy 200 Bicolor\n\nM106 S255 ;Fan on full\nM104 S0 ;Cool hotend\nM140 S0 ;Cool heated bed\nG91 ;Relative positioning\nG1 E-3 F5000 ;Retract filament to stop oozing\nG1 E-60 F5000 ;Retract filament multi-extruder\nG0 Z+3 ;Withdraw\nG90 ; Absolute positioning\nG28 X Y ;Home\nM109 R{material_standby_temperature} ;Wait until head has cooled to standby temp\nM107 ;Fan off\nM18 ;Stepper motors off\n\n;Finish End Gcode for Dagoma DiscoEasy 200 Bicolor\n"
+ }
+ }
+}
diff --git a/resources/definitions/dagoma_discoultimate.def.json b/resources/definitions/dagoma_discoultimate.def.json
index 13ab591212..ec41318e86 100644
--- a/resources/definitions/dagoma_discoultimate.def.json
+++ b/resources/definitions/dagoma_discoultimate.def.json
@@ -1,82 +1,34 @@
{
"name": "Dagoma DiscoUltimate",
"version": 2,
- "inherits": "fdmprinter",
+ "inherits": "dagoma_disco",
"metadata": {
"visible": true,
"author": "Dagoma",
"manufacturer": "Dagoma",
"file_formats": "text/x-gcode",
"platform": "dagoma_discoultimate.3mf",
- "platform_offset": [0, -58.5, -11],
+ "platform_offset": [0, -58.5, -39.5],
"has_machine_quality": true,
"has_materials": true,
"preferred_material": "chromatik_pla",
"machine_extruder_trains":
{
- "0": "dagoma_discoultimate_extruder_0",
- "1": "dagoma_discoultimate_extruder_1"
+ "0": "dagoma_discoultimate_extruder"
}
},
"overrides": {
+ "machine_name": {
+ "default_value": "Dagoma DiscoUltimate"
+ },
"machine_extruder_count": {
- "default_value": 2
- },
- "machine_extruders_share_heater": {
- "default_value": true
- },
- "machine_width": {
- "default_value": 205
- },
- "machine_height": {
- "default_value": 205
- },
- "machine_depth": {
- "default_value": 205
- },
- "machine_center_is_zero": {
- "default_value": false
- },
- "machine_head_with_fans_polygon": {
- "default_value": [
- [-17, -70],
- [-17, 40],
- [17, 40],
- [17, -70]
- ]
- },
- "gantry_height": {
- "value": "10"
+ "default_value": 1
},
"machine_start_gcode": {
- "default_value": ";Gcode by Cura\nG90\nM106 S255\nG28 X Y\nG1 X50\nM109 R90\nG28\nM104 S{material_print_temperature_layer_0}\nG29\nM107\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E10\nG92 E0\nG1 Z3\nG1 F6000\n"
+ "default_value": ";Begin Start Gcode for Dagoma DiscoUltimate\n;Sliced: {date} {time}\n;Initial extruder: {initial_extruder_nr}\n\nG90 ;Absolute positioning\nM106 S255 ;Fan on full\nG28 X Y ;Home stop X Y\nG1 X100 ;Centre back during cooldown in case of oozing\nM109 R{material_standby_temperature} ;Cooldown in case too hot\nG28 ;Centre\nG29 ;Auto-level\nM104 S{material_print_temperature_layer_0} ;Pre-heat\nM107 ;Fan off\nG0 X100 Y5 Z0.5 ;Front centre for degunk\nM109 S{material_print_temperature_layer_0} ;Wait for initial temp\nM83 ;E Relative\nG1 E10 F200 ;Degunk\nG1 E-3 F5000 ;Retract\nG0 Z3 ;Withdraw\nM82 ;E absolute\nG92 E0 ;E reset\nG1 F6000 ;Set feedrate\n\n;Finish Start Gcode for Dagoma DiscoUltimate\n"
},
"machine_end_gcode": {
- "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 F3000\nG90\nG28 X Y\nM107\nM84\n"
- },
- "default_material_print_temperature": {
- "default_value": 205
- },
- "speed_print": {
- "default_value": 60
- },
- "retraction_amount": {
- "default_value": 3.5
- },
- "retraction_speed": {
- "default_value": 50
- },
- "adhesion_type": {
- "default_value": "skirt"
- },
- "skirt_line_count": {
- "default_value": 2
- },
- "layer_height_0": {
- "default_value": 0.26
- },
- "top_bottom_thickness": {
- "default_value": 1
+ "default_value": ";Begin End Gcode for Dagoma DiscoUltimate\n\nM106 S255 ;Fan on full\nM104 S0 ;Cool hotend\nM140 S0 ;Cool heated bed\nG91 ;Relative positioning\nG1 E-3 F5000 ;Retract filament to stop oozing\nG0 Z+3 ;Withdraw\nG90 ;Absolute positioning\nG28 X Y ;Home\nM109 R{material_standby_temperature} ;Wait until head has cooled to standby temp\nM107 ;Fan off\nM18 ;Stepper motors off\n\n;Finish End Gcode for Dagoma DiscoUltimate\n"
}
}
}
diff --git a/resources/definitions/dagoma_discoultimate_bicolor.def.json b/resources/definitions/dagoma_discoultimate_bicolor.def.json
new file mode 100644
index 0000000000..3b5215c944
--- /dev/null
+++ b/resources/definitions/dagoma_discoultimate_bicolor.def.json
@@ -0,0 +1,38 @@
+{
+ "name": "Dagoma DiscoUltimate Bicolor",
+ "version": 2,
+ "inherits": "dagoma_disco",
+ "metadata": {
+ "visible": true,
+ "author": "Dagoma",
+ "manufacturer": "Dagoma",
+ "file_formats": "text/x-gcode",
+ "platform": "dagoma_discoultimate_bicolor.3mf",
+ "platform_offset": [0, -58.5, -11],
+ "has_machine_quality": true,
+ "has_materials": true,
+ "preferred_material": "chromatik_pla",
+ "machine_extruder_trains":
+ {
+ "0": "dagoma_discoultimate_extruder_0",
+ "1": "dagoma_discoultimate_extruder_1"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Dagoma DiscoUltimate Bicolor"
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ },
+ "machine_extruders_share_heater": {
+ "default_value": true
+ },
+ "machine_start_gcode": {
+ "default_value": ";Begin Start Gcode for Dagoma DiscoUltimate Bicolor\n;Sliced: {date} {time}\n;Initial extruder: {initial_extruder_nr}\n\nG90 ;Absolute positioning\nM106 S255 ;Fan on full\nG28 X Y ;Home stop X Y\nG1 X100 ;Centre back during cooldown in case of oozing\nM109 R{material_standby_temperature} ;Cooldown in case too hot\nG28 ;Centre\nG29 ;Auto-level\nM104 S{material_print_temperature_layer_0} ;Pre-heat\nM107 ;Fan off\nG0 X100 Y5 Z0.5 ;Front centre for degunk\nM109 S{material_print_temperature_layer_0} ;Wait for initial temp\n;M83 ;E Relative\n;G1 E60 F3000 ;Reverse multi-extruder retract\n;G1 E10 F200 ;Degunk\n;G1 E-3 F5000 ;Retract\nG0 Z3 ;Withdraw\n;M82 ;E absolute\n;G92 E0 ;E reset\n;G1 F6000 ;Set feedrate\n\n;Finish Start Gcode for Dagoma DiscoUltimate Bicolor\n"
+ },
+ "machine_end_gcode": {
+ "default_value": ";Begin End Gcode for Dagoma DiscoUltimate Bicolor\n\nM106 S255 ;Fan on full\nM104 S0 ;Cool hotend\nM140 S0 ;Cool heated bed\nG91 ;Relative positioning\nG1 E-3 F5000 ;Retract filament to stop oozing\nG1 E-60 F5000 ;Retract filament multi-extruder\nG0 Z+3 ;Withdraw\nG90 ; Absolute positioning\nG28 X Y ;Home\nM109 R{material_standby_temperature} ;Wait until head has cooled to standby temp\nM107 ;Fan off\nM18 ;Stepper motors off\n\n;Finish End Gcode for Dagoma DiscoUltimate Bicolor\n"
+ }
+ }
+}
diff --git a/resources/definitions/dagoma_magis.def.json b/resources/definitions/dagoma_magis.def.json
index e7c0847e7e..e3c9c3e693 100644
--- a/resources/definitions/dagoma_magis.def.json
+++ b/resources/definitions/dagoma_magis.def.json
@@ -1,7 +1,7 @@
{
"name": "Dagoma Magis",
"version": 2,
- "inherits": "fdmprinter",
+ "inherits": "dagoma_delta",
"metadata": {
"visible": true,
"author": "Dagoma",
@@ -14,65 +14,12 @@
"preferred_material": "chromatik_pla",
"machine_extruder_trains":
{
- "0": "dagoma_magis_extruder_0"
+ "0": "dagoma_magis_extruder"
}
},
"overrides": {
- "machine_width": {
- "default_value": 195.55
- },
- "machine_height": {
- "default_value": 205
- },
- "machine_depth": {
- "default_value": 195.55
- },
- "machine_center_is_zero": {
- "default_value": true
- },
- "machine_head_with_fans_polygon": {
- "default_value": [
- [-36, -42],
- [-36, 42],
- [36, 42],
- [36, -42]
- ]
- },
- "gantry_height": {
- "value": "0"
- },
- "machine_shape": {
- "default_value": "elliptic"
- },
- "machine_start_gcode": {
- "default_value": ";Gcode by Cura\nG90\nG28\nM107\nM109 R100\nG29\nM109 S{material_print_temperature_layer_0} U-55 X55 V-85 Y-85 W0.26 Z0.26\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n"
- },
- "machine_end_gcode": {
- "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n"
- },
- "default_material_print_temperature": {
- "default_value": 205
- },
- "speed_print": {
- "default_value": 40
- },
- "retraction_amount": {
- "default_value": 3.8
- },
- "retraction_speed": {
- "default_value": 60
- },
- "adhesion_type": {
- "default_value": "skirt"
- },
- "skirt_line_count": {
- "default_value": 2
- },
- "layer_height_0": {
- "default_value": 0.26
- },
- "top_bottom_thickness": {
- "default_value": 1
+ "machine_name": {
+ "default_value": "Dagoma Magis"
}
}
}
diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json
index f6a6ccf511..24d3f8ab8d 100644
--- a/resources/definitions/dagoma_neva.def.json
+++ b/resources/definitions/dagoma_neva.def.json
@@ -1,7 +1,7 @@
{
- "name": "Dagoma NEVA",
+ "name": "Dagoma Neva",
"version": 2,
- "inherits": "fdmprinter",
+ "inherits": "dagoma_delta",
"metadata": {
"visible": true,
"author": "Dagoma",
@@ -14,65 +14,12 @@
"preferred_material": "chromatik_pla",
"machine_extruder_trains":
{
- "0": "dagoma_neva_extruder_0"
+ "0": "dagoma_neva_extruder"
}
},
"overrides": {
- "machine_width": {
- "default_value": 195.55
- },
- "machine_height": {
- "default_value": 205
- },
- "machine_depth": {
- "default_value": 195.55
- },
- "machine_center_is_zero": {
- "default_value": true
- },
- "machine_head_with_fans_polygon": {
- "default_value": [
- [-36, -42],
- [-36, 42],
- [36, 42],
- [36, -42]
- ]
- },
- "gantry_height": {
- "value": "0"
- },
- "machine_shape": {
- "default_value": "elliptic"
- },
- "machine_start_gcode": {
- "default_value": ";Gcode by Cura\nG90\nG28\nM107\nM109 R100\nG29\nM109 S{material_print_temperature_layer_0} U-55 X55 V-85 Y-85 W0.26 Z0.26\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n"
- },
- "machine_end_gcode": {
- "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n"
- },
- "default_material_print_temperature": {
- "default_value": 205
- },
- "speed_print": {
- "default_value": 40
- },
- "retraction_amount": {
- "default_value": 3.8
- },
- "retraction_speed": {
- "default_value": 60
- },
- "adhesion_type": {
- "default_value": "skirt"
- },
- "skirt_line_count": {
- "default_value": 2
- },
- "layer_height_0": {
- "default_value": 0.26
- },
- "top_bottom_thickness": {
- "default_value": 1
+ "machine_name": {
+ "default_value": "Dagoma Neva"
}
}
}
diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json
index 85d18078e9..f863d78b3a 100644
--- a/resources/definitions/fdmprinter.def.json
+++ b/resources/definitions/fdmprinter.def.json
@@ -2082,7 +2082,7 @@
"description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.",
"unit": "mm",
"type": "float",
- "default_value": 2.24,
+ "default_value": 0,
"value": "top_layers * layer_height / math.tan(math.radians(max_skin_angle_for_expansion))",
"minimum_value": "0",
"enabled": "(top_layers > 0 or bottom_layers > 0) and (top_skin_expand_distance > 0 or bottom_skin_expand_distance > 0)",
diff --git a/resources/definitions/ultimaker_original.def.json b/resources/definitions/ultimaker_original.def.json
index 10359f2fe6..34d22934d6 100644
--- a/resources/definitions/ultimaker_original.def.json
+++ b/resources/definitions/ultimaker_original.def.json
@@ -55,7 +55,7 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "G21 ;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 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E6 ;extrude 6 mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."
+ "default_value": "G21 ;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 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E6 ;extrude 6 mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 Y50 F9000\n;Put printing message on LCD screen\nM117 Printing..."
},
"machine_end_gcode": {
"value": "'M104 S0 ;extruder heater off' + ('\\nM140 S0 ;heated bed heater off' if machine_heated_bed else '') + '\\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-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\\nM84 ;steppers off\\nG90 ;absolute positioning'"
diff --git a/resources/extruders/dagoma_discoeasy200_extruder.def.json b/resources/extruders/dagoma_discoeasy200_extruder.def.json
new file mode 100644
index 0000000000..7bef0a7649
--- /dev/null
+++ b/resources/extruders/dagoma_discoeasy200_extruder.def.json
@@ -0,0 +1,21 @@
+{
+ "version": 2,
+ "name": "Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "dagoma_discoeasy200",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
diff --git a/resources/extruders/dagoma_discoeasy200_extruder_0.def.json b/resources/extruders/dagoma_discoeasy200_extruder_0.def.json
index f2ca729582..af1c2c42e9 100644
--- a/resources/extruders/dagoma_discoeasy200_extruder_0.def.json
+++ b/resources/extruders/dagoma_discoeasy200_extruder_0.def.json
@@ -3,7 +3,7 @@
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "dagoma_discoeasy200",
+ "machine": "dagoma_discoeasy200_bicolor",
"position": "0"
},
@@ -18,10 +18,10 @@
"default_value": 1.75
},
"machine_extruder_start_code": {
- "default_value": "\n;Start T0\nG92 E0\nG1 E-{retraction_amount} F10000\nG92 E0G1 E1.5 F3000\nG1 E-60 F10000\nG92 E0\n"
+ "default_value": ";Start T0\nM83\nG1 E{retraction_amount} F3000\nG1 E60 F3000\nG1 E-{retraction_amount} F5000\nM82\nG92 E0"
},
"machine_extruder_end_code": {
- "default_value": "\nG92 E0\nG1 E{retraction_amount} F3000\nG92 E0\nG1 E60 F3000\nG92 E0\nG1 E-{retraction_amount} F5000\n;End T0\n\n"
+ "default_value": "M83\nG1 E-{retraction_amount} F10000\nG1 E1.5 F3000\nG1 E-60 F10000\nM82\nG92 E0\n;End T0"
}
}
}
diff --git a/resources/extruders/dagoma_discoeasy200_extruder_1.def.json b/resources/extruders/dagoma_discoeasy200_extruder_1.def.json
index ac5fe5015d..f01a805270 100644
--- a/resources/extruders/dagoma_discoeasy200_extruder_1.def.json
+++ b/resources/extruders/dagoma_discoeasy200_extruder_1.def.json
@@ -3,7 +3,7 @@
"name": "Extruder 2",
"inherits": "fdmextruder",
"metadata": {
- "machine": "dagoma_discoeasy200",
+ "machine": "dagoma_discoeasy200_bicolor",
"position": "1"
},
@@ -18,10 +18,10 @@
"default_value": 1.75
},
"machine_extruder_start_code": {
- "default_value": "\n;Start T1\nG92 E0\nG1 E-{retraction_amount} F10000\nG92 E0G1 E1.5 F3000\nG1 E-60 F10000\nG92 E0\n"
+ "default_value": ";Start T1\nM83\nG1 E{retraction_amount} F3000\nG1 E60 F3000\nG1 E-{retraction_amount} F5000\nM82\nG92 E0"
},
"machine_extruder_end_code": {
- "default_value": "\nG92 E0\nG1 E{retraction_amount} F3000\nG92 E0\nG1 E60 F3000\nG92 E0\nG1 E-{retraction_amount} F5000\n;End T1\n\n"
+ "default_value": "M83\nG1 E-{retraction_amount} F10000\nG1 E1.5 F3000\nG1 E-60 F10000\nM82\nG92 E0\n;End T1"
}
}
}
diff --git a/resources/extruders/dagoma_discoultimate_extruder.def.json b/resources/extruders/dagoma_discoultimate_extruder.def.json
new file mode 100644
index 0000000000..a53145f429
--- /dev/null
+++ b/resources/extruders/dagoma_discoultimate_extruder.def.json
@@ -0,0 +1,21 @@
+{
+ "version": 2,
+ "name": "Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "dagoma_discoultimate",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
diff --git a/resources/extruders/dagoma_discoultimate_extruder_0.def.json b/resources/extruders/dagoma_discoultimate_extruder_0.def.json
index 878d6fdc75..766d5b2902 100644
--- a/resources/extruders/dagoma_discoultimate_extruder_0.def.json
+++ b/resources/extruders/dagoma_discoultimate_extruder_0.def.json
@@ -3,7 +3,7 @@
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "dagoma_discoultimate",
+ "machine": "dagoma_discoultimate_bicolor",
"position": "0"
},
@@ -18,10 +18,10 @@
"default_value": 1.75
},
"machine_extruder_start_code": {
- "default_value": "\n;Start T0\nG92 E0\nG1 E-{retraction_amount} F10000\nG92 E0G1 E1.5 F3000\nG1 E-60 F10000\nG92 E0\n"
+ "default_value": ";Start T0\nM83\nG1 E{retraction_amount} F3000\nG1 E60 F3000\nG1 E-{retraction_amount} F5000\nM82\nG92 E0"
},
"machine_extruder_end_code": {
- "default_value": "\nG92 E0\nG1 E{retraction_amount} F3000\nG92 E0\nG1 E60 F3000\nG92 E0\nG1 E-{retraction_amount} F5000\n;End T0\n\n"
+ "default_value": "M83\nG1 E-{retraction_amount} F10000\nG1 E1.5 F3000\nG1 E-60 F10000\nM82\nG92 E0\n;End T0"
}
}
}
diff --git a/resources/extruders/dagoma_discoultimate_extruder_1.def.json b/resources/extruders/dagoma_discoultimate_extruder_1.def.json
index e6f8031e03..f71b875261 100644
--- a/resources/extruders/dagoma_discoultimate_extruder_1.def.json
+++ b/resources/extruders/dagoma_discoultimate_extruder_1.def.json
@@ -3,7 +3,7 @@
"name": "Extruder 2",
"inherits": "fdmextruder",
"metadata": {
- "machine": "dagoma_discoultimate",
+ "machine": "dagoma_discoultimate_bicolor",
"position": "1"
},
@@ -18,10 +18,10 @@
"default_value": 1.75
},
"machine_extruder_start_code": {
- "default_value": "\n;Start T1\nG92 E0\nG1 E-{retraction_amount} F10000\nG92 E0G1 E1.5 F3000\nG1 E-60 F10000\nG92 E0\n"
+ "default_value": ";Start T1\nM83\nG1 E{retraction_amount} F3000\nG1 E60 F3000\nG1 E-{retraction_amount} F5000\nM82\nG92 E0"
},
"machine_extruder_end_code": {
- "default_value": "\nG92 E0\nG1 E{retraction_amount} F3000\nG92 E0\nG1 E60 F3000\nG92 E0\nG1 E-{retraction_amount} F5000\n;End T1\n\n"
+ "default_value": "M83\nG1 E-{retraction_amount} F10000\nG1 E1.5 F3000\nG1 E-60 F10000\nM82\nG92 E0\n;End T1"
}
}
}
diff --git a/resources/extruders/dagoma_magis_extruder_0.def.json b/resources/extruders/dagoma_magis_extruder.def.json
similarity index 93%
rename from resources/extruders/dagoma_magis_extruder_0.def.json
rename to resources/extruders/dagoma_magis_extruder.def.json
index 0a5850f2ed..06cf6127ce 100644
--- a/resources/extruders/dagoma_magis_extruder_0.def.json
+++ b/resources/extruders/dagoma_magis_extruder.def.json
@@ -1,6 +1,6 @@
{
"version": 2,
- "name": "Extruder 1",
+ "name": "Extruder",
"inherits": "fdmextruder",
"metadata": {
"machine": "dagoma_magis",
diff --git a/resources/extruders/dagoma_neva_extruder_0.def.json b/resources/extruders/dagoma_neva_extruder.def.json
similarity index 93%
rename from resources/extruders/dagoma_neva_extruder_0.def.json
rename to resources/extruders/dagoma_neva_extruder.def.json
index 95035f63f2..3fa26ab5c9 100644
--- a/resources/extruders/dagoma_neva_extruder_0.def.json
+++ b/resources/extruders/dagoma_neva_extruder.def.json
@@ -1,6 +1,6 @@
{
"version": 2,
- "name": "Extruder 1",
+ "name": "Extruder",
"inherits": "fdmextruder",
"metadata": {
"machine": "dagoma_neva",
diff --git a/resources/meshes/dagoma_discoeasy200.3mf b/resources/meshes/dagoma_discoeasy200.3mf
index 9c2c674cfc..d71b5da20a 100644
Binary files a/resources/meshes/dagoma_discoeasy200.3mf and b/resources/meshes/dagoma_discoeasy200.3mf differ
diff --git a/resources/meshes/dagoma_discoeasy200_bicolor.3mf b/resources/meshes/dagoma_discoeasy200_bicolor.3mf
new file mode 100644
index 0000000000..9c2c674cfc
Binary files /dev/null and b/resources/meshes/dagoma_discoeasy200_bicolor.3mf differ
diff --git a/resources/meshes/dagoma_discoultimate.3mf b/resources/meshes/dagoma_discoultimate.3mf
index 71b1e4dfba..f68fe2677c 100644
Binary files a/resources/meshes/dagoma_discoultimate.3mf and b/resources/meshes/dagoma_discoultimate.3mf differ
diff --git a/resources/meshes/dagoma_discoultimate_bicolor.3mf b/resources/meshes/dagoma_discoultimate_bicolor.3mf
new file mode 100644
index 0000000000..71b1e4dfba
Binary files /dev/null and b/resources/meshes/dagoma_discoultimate_bicolor.3mf differ
diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml
index ed2c6dc5fe..8ba651a5b0 100644
--- a/resources/qml/Cura.qml
+++ b/resources/qml/Cura.qml
@@ -84,6 +84,21 @@ UM.MainWindow
CuraApplication.purgeWindows()
}
+ Connections
+ {
+ // This connection is used when there is no ActiveMachine and the user is logged in
+ target: CuraApplication
+ onShowAddPrintersUncancellableDialog:
+ {
+ Cura.Actions.parent = backgroundItem
+
+ // Reuse the welcome dialog item to show "Add a printer" only.
+ welcomeDialogItem.model = CuraApplication.getAddPrinterPagesModelWithoutCancel()
+ welcomeDialogItem.progressBarVisible = false
+ welcomeDialogItem.visible = true
+ }
+ }
+
Connections
{
target: CuraApplication
@@ -117,6 +132,15 @@ UM.MainWindow
welcomeDialogItem.progressBarVisible = false
welcomeDialogItem.visible = true
}
+
+ // Reuse the welcome dialog item to show the "Add printers" dialog. Triggered when there is no active
+ // machine and the user is logged in.
+ if (!Cura.MachineManager.activeMachine && Cura.API.account.isLoggedIn)
+ {
+ welcomeDialogItem.model = CuraApplication.getAddPrinterPagesModelWithoutCancel()
+ welcomeDialogItem.progressBarVisible = false
+ welcomeDialogItem.visible = true
+ }
}
}
diff --git a/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml b/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml
index b7fe022d78..a5ee7b5986 100644
--- a/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml
+++ b/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml
@@ -14,8 +14,8 @@ UM.Dialog
id: base
title: catalog.i18nc("@title:window", "Discard or Keep changes")
- width: UM.Theme.getSize("popup_dialog").width
- height: UM.Theme.getSize("popup_dialog").height
+ minimumWidth: UM.Theme.getSize("popup_dialog").width
+ minimumHeight: UM.Theme.getSize("popup_dialog").height
property var changesModel: Cura.UserChangesModel{ id: userChangesModel}
onVisibilityChanged:
{
@@ -80,6 +80,8 @@ UM.Dialog
property var extruder_name: userChangesModel.getItem(styleData.row).extruder
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width
+ anchors.right: parent.right
+ elide: Text.ElideRight
font: UM.Theme.getFont("system")
text:
{
diff --git a/resources/qml/Dialogs/WorkspaceSummaryDialog.qml b/resources/qml/Dialogs/WorkspaceSummaryDialog.qml
index 6fe9607274..670766204f 100644
--- a/resources/qml/Dialogs/WorkspaceSummaryDialog.qml
+++ b/resources/qml/Dialogs/WorkspaceSummaryDialog.qml
@@ -143,7 +143,7 @@ UM.Dialog
{
width: parent.width
height: childrenRect.height
- model: Cura.MachineManager.activeMachine.extruderList
+ model: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.extruderList : null
delegate: Column
{
height: childrenRect.height
diff --git a/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml b/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml
index 9891fc1d69..cb498bcef0 100644
--- a/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml
+++ b/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml
@@ -33,7 +33,7 @@ Cura.ExpandablePopup
}
contentPadding: UM.Theme.getSize("default_lining").width
- enabled: Cura.MachineManager.activeMachine.hasMaterials || Cura.MachineManager.activeMachine.hasVariants || Cura.MachineManager.activeMachine.hasVariantBuildplates; //Only let it drop down if there is any configuration that you could change.
+ enabled: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.hasMaterials || Cura.MachineManager.activeMachine.hasVariants || Cura.MachineManager.activeMachine.hasVariantBuildplates : false; //Only let it drop down if there is any configuration that you could change.
headerItem: Item
{
@@ -46,7 +46,7 @@ Cura.ExpandablePopup
model: extrudersModel
delegate: Item
{
- Layout.fillWidth: true
+ Layout.preferredWidth: Math.round(parent.width / extrudersModel.count)
Layout.fillHeight: true
// Extruder icon. Shows extruder index and has the same color as the active material.
@@ -84,7 +84,7 @@ Cura.ExpandablePopup
{
id: variantLabel
- visible: Cura.MachineManager.activeMachine.hasVariants
+ visible: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.hasVariants : false
text: model.variant
elide: Text.ElideRight
@@ -114,7 +114,7 @@ Cura.ExpandablePopup
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
- visible: !Cura.MachineManager.activeMachine.hasMaterials && (Cura.MachineManager.activeMachine.hasVariants || Cura.MachineManager.activeMachine.hasVariantBuildplates)
+ visible: Cura.MachineManager.activeMachine ? !Cura.MachineManager.activeMachine.hasMaterials && (Cura.MachineManager.activeMachine.hasVariants || Cura.MachineManager.activeMachine.hasVariantBuildplates) : false
anchors
{
diff --git a/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml b/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml
index 65f5bcce8c..010e2e77b0 100644
--- a/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml
+++ b/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml
@@ -244,7 +244,7 @@ Item
Row
{
height: visible ? UM.Theme.getSize("print_setup_big_item").height : 0
- visible: Cura.MachineManager.activeMachine.hasMaterials
+ visible: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.hasMaterials : false
Label
{
@@ -305,7 +305,7 @@ Item
Row
{
height: visible ? UM.Theme.getSize("print_setup_big_item").height : 0
- visible: Cura.MachineManager.activeMachine.hasVariants
+ visible: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.hasVariants : false
Label
{
diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml
index f227dddaf9..92f0024b23 100644
--- a/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml
+++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedSupportSelector.qml
@@ -130,7 +130,11 @@ Item
target: extruderModel
onModelChanged:
{
- supportExtruderCombobox.color = supportExtruderCombobox.model.getItem(supportExtruderCombobox.currentIndex).color
+ var maybeColor = supportExtruderCombobox.model.getItem(supportExtruderCombobox.currentIndex).color
+ if (maybeColor)
+ {
+ supportExtruderCombobox.color = maybeColor
+ }
}
}
onCurrentIndexChanged:
diff --git a/resources/qml/PrinterSelector/MachineSelector.qml b/resources/qml/PrinterSelector/MachineSelector.qml
index 56a3d858ec..0907767eea 100644
--- a/resources/qml/PrinterSelector/MachineSelector.qml
+++ b/resources/qml/PrinterSelector/MachineSelector.qml
@@ -35,14 +35,21 @@ Cura.ExpandablePopup
}
}
- readonly property string connectionStatusMessage: {
+ function getConnectionStatusMessage() {
if (connectionStatus == "printer_cloud_not_available")
{
if(Cura.API.connectionStatus.isInternetReachable)
{
if (Cura.API.account.isLoggedIn)
{
- return catalog.i18nc("@status", "The cloud printer is offline. Please check if the printer is turned on and connected to the internet.")
+ if (Cura.MachineManager.activeMachineIsLinkedToCurrentAccount)
+ {
+ return catalog.i18nc("@status", "The cloud printer is offline. Please check if the printer is turned on and connected to the internet.")
+ }
+ else
+ {
+ return catalog.i18nc("@status", "This printer is not linked to your account. Please visit the Ultimaker Digital Factory to establish a connection.")
+ }
}
else
{
@@ -139,12 +146,13 @@ Cura.ExpandablePopup
{
id: connectionStatusTooltipHoverArea
anchors.fill: parent
- hoverEnabled: connectionStatusMessage !== ""
+ hoverEnabled: getConnectionStatusMessage() !== ""
acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks
onEntered:
{
machineSelector.mouseArea.entered() // we want both this and the outer area to be entered
+ tooltip.tooltipText = getConnectionStatusMessage()
tooltip.show()
}
onExited: { tooltip.hide() }
@@ -155,7 +163,7 @@ Cura.ExpandablePopup
id: tooltip
width: 250 * screenScaleFactor
- tooltipText: connectionStatusMessage
+ tooltipText: getConnectionStatusMessage()
arrowSize: UM.Theme.getSize("button_tooltip_arrow").width
x: connectionStatusImage.x - UM.Theme.getSize("narrow_margin").width
y: connectionStatusImage.y + connectionStatusImage.height + UM.Theme.getSize("narrow_margin").height
diff --git a/resources/qml/PrinterSelector/MachineSelectorList.qml b/resources/qml/PrinterSelector/MachineSelectorList.qml
index a7c041630f..18b1a68b20 100644
--- a/resources/qml/PrinterSelector/MachineSelectorList.qml
+++ b/resources/qml/PrinterSelector/MachineSelectorList.qml
@@ -28,11 +28,11 @@ ListView
delegate: MachineSelectorButton
{
- text: model.name
+ text: model.name ? model.name : ""
width: listView.width
outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
- checked: Cura.MachineManager.activeMachine.id == model.id
+ checked: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.id == model.id : false
onClicked:
{
diff --git a/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_fast.inst.cfg
new file mode 100644
index 0000000000..8e126094cc
--- /dev/null
+++ b/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_fast.inst.cfg
@@ -0,0 +1,26 @@
+[general]
+version = 4
+name = Fast
+definition = dagoma_discoeasy200_bicolor
+
+[metadata]
+setting_version = 15
+type = quality
+quality_type = draft
+weight = -2
+material = chromatik_pla
+
+[values]
+layer_height = 0.2
+line_width = =machine_nozzle_size * 0.875
+
+material_print_temperature = =default_material_print_temperature + 10
+material_bed_temperature_layer_0 = =default_material_bed_temperature + 10
+
+speed_print = 60
+speed_travel = 75
+speed_layer_0 = 17
+speed_infill = 60
+speed_wall_0 = 50
+speed_wall_x = 60
+speed_topbottom = 60
diff --git a/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_fine.inst.cfg
new file mode 100644
index 0000000000..b26282ecb7
--- /dev/null
+++ b/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_fine.inst.cfg
@@ -0,0 +1,23 @@
+[general]
+version = 4
+name = Fine
+definition = dagoma_discoeasy200_bicolor
+
+[metadata]
+setting_version = 15
+type = quality
+quality_type = normal
+weight = 0
+material = chromatik_pla
+
+[values]
+layer_height = 0.1
+line_width = =machine_nozzle_size * 0.875
+
+speed_print = 35
+speed_travel = 50
+speed_layer_0 = 15
+speed_infill = 40
+speed_wall_0 = 25
+speed_wall_x = 35
+speed_topbottom = 35
diff --git a/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_standard.inst.cfg
new file mode 100644
index 0000000000..6bc4310ce4
--- /dev/null
+++ b/resources/quality/dagoma/dagoma_discoeasy200_bicolor_pla_standard.inst.cfg
@@ -0,0 +1,26 @@
+[general]
+version = 4
+name = Standard
+definition = dagoma_discoeasy200_bicolor
+
+[metadata]
+setting_version = 15
+type = quality
+quality_type = fast
+weight = -1
+material = chromatik_pla
+
+[values]
+layer_height = 0.15
+line_width = =machine_nozzle_size * 0.875
+
+material_print_temperature = =default_material_print_temperature + 5
+material_bed_temperature_layer_0 = =default_material_bed_temperature + 5
+
+speed_print = 50
+speed_travel = 60
+speed_layer_0 = 17
+speed_infill = 50
+speed_wall_0 = 40
+speed_wall_x = 45
+speed_topbottom = 50
diff --git a/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_fast.inst.cfg b/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_fast.inst.cfg
new file mode 100644
index 0000000000..c08bd89d1e
--- /dev/null
+++ b/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_fast.inst.cfg
@@ -0,0 +1,26 @@
+[general]
+version = 4
+name = Fast
+definition = dagoma_discoultimate_bicolor
+
+[metadata]
+setting_version = 15
+type = quality
+quality_type = draft
+weight = -2
+material = chromatik_pla
+
+[values]
+layer_height = 0.2
+line_width = =machine_nozzle_size * 0.875
+
+material_print_temperature = =default_material_print_temperature + 10
+material_bed_temperature_layer_0 = =default_material_bed_temperature + 10
+
+speed_print = 60
+speed_travel = 75
+speed_layer_0 = 17
+speed_infill = 60
+speed_wall_0 = 50
+speed_wall_x = 60
+speed_topbottom = 60
diff --git a/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_fine.inst.cfg b/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_fine.inst.cfg
new file mode 100644
index 0000000000..7795d6aaa9
--- /dev/null
+++ b/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_fine.inst.cfg
@@ -0,0 +1,23 @@
+[general]
+version = 4
+name = Fine
+definition = dagoma_discoultimate_bicolor
+
+[metadata]
+setting_version = 15
+type = quality
+quality_type = normal
+weight = 0
+material = chromatik_pla
+
+[values]
+layer_height = 0.1
+line_width = =machine_nozzle_size * 0.875
+
+speed_print = 35
+speed_travel = 50
+speed_layer_0 = 15
+speed_infill = 40
+speed_wall_0 = 25
+speed_wall_x = 35
+speed_topbottom = 35
diff --git a/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_standard.inst.cfg b/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_standard.inst.cfg
new file mode 100644
index 0000000000..7015261d3b
--- /dev/null
+++ b/resources/quality/dagoma/dagoma_discoultimate_bicolor_pla_standard.inst.cfg
@@ -0,0 +1,26 @@
+[general]
+version = 4
+name = Standard
+definition = dagoma_discoultimate_bicolor
+
+[metadata]
+setting_version = 15
+type = quality
+quality_type = fast
+weight = -1
+material = chromatik_pla
+
+[values]
+layer_height = 0.15
+line_width = =machine_nozzle_size * 0.875
+
+material_print_temperature = =default_material_print_temperature + 5
+material_bed_temperature_layer_0 = =default_material_bed_temperature + 5
+
+speed_print = 50
+speed_travel = 60
+speed_layer_0 = 17
+speed_infill = 50
+speed_wall_0 = 40
+speed_wall_x = 45
+speed_topbottom = 50