Merge branch 'master' of github.com:Ultimaker/Cura into CURA-7418-update-profile-window

This commit is contained in:
Jaime van Kessel 2020-06-15 14:10:20 +02:00
commit f6e9bc7c3c
No known key found for this signature in database
GPG Key ID: 3710727397403C91
51 changed files with 697 additions and 296 deletions

View File

@ -10,7 +10,7 @@ from UM.Message import Message
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from cura.OAuth2.AuthorizationService import AuthorizationService from cura.OAuth2.AuthorizationService import AuthorizationService
from cura.OAuth2.Models import OAuth2Settings from cura.OAuth2.Models import OAuth2Settings
from cura.UltimakerCloud import UltimakerCloudAuthentication from cura.UltimakerCloud import UltimakerCloudConstants
if TYPE_CHECKING: if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
@ -69,7 +69,7 @@ class Account(QObject):
self._last_sync_str = "-" self._last_sync_str = "-"
self._callback_port = 32118 self._callback_port = 32118
self._oauth_root = UltimakerCloudAuthentication.CuraCloudAccountAPIRoot self._oauth_root = UltimakerCloudConstants.CuraCloudAccountAPIRoot
self._oauth_settings = OAuth2Settings( self._oauth_settings = OAuth2Settings(
OAUTH_SERVER_URL= self._oauth_root, OAUTH_SERVER_URL= self._oauth_root,

View File

@ -4,14 +4,14 @@ from PyQt5.QtCore import QObject, pyqtSignal, QTimer, pyqtProperty
from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtNetwork import QNetworkReply
from UM.TaskManagement.HttpRequestManager import HttpRequestManager from UM.TaskManagement.HttpRequestManager import HttpRequestManager
from cura.UltimakerCloud import UltimakerCloudAuthentication from cura.UltimakerCloud import UltimakerCloudConstants
class ConnectionStatus(QObject): class ConnectionStatus(QObject):
"""Status info for some web services""" """Status info for some web services"""
UPDATE_INTERVAL = 10.0 # seconds 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] __instance = None # type: Optional[ConnectionStatus]

View File

@ -106,7 +106,7 @@ from cura.UI.RecommendedMode import RecommendedMode
from cura.UI.TextManager import TextManager from cura.UI.TextManager import TextManager
from cura.UI.WelcomePagesModel import WelcomePagesModel from cura.UI.WelcomePagesModel import WelcomePagesModel
from cura.UI.WhatsNewPagesModel import WhatsNewPagesModel from cura.UI.WhatsNewPagesModel import WhatsNewPagesModel
from cura.UltimakerCloud import UltimakerCloudAuthentication from cura.UltimakerCloud import UltimakerCloudConstants
from cura.Utils.NetworkingUtil import NetworkingUtil from cura.Utils.NetworkingUtil import NetworkingUtil
from . import BuildVolume from . import BuildVolume
from . import CameraAnimation from . import CameraAnimation
@ -207,6 +207,7 @@ class CuraApplication(QtApplication):
self._first_start_machine_actions_model = None self._first_start_machine_actions_model = None
self._welcome_pages_model = WelcomePagesModel(self, parent = self) self._welcome_pages_model = WelcomePagesModel(self, parent = self)
self._add_printer_pages_model = AddPrinterPagesModel(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._whats_new_pages_model = WhatsNewPagesModel(self, parent = self)
self._text_manager = TextManager(parent = self) self._text_manager = TextManager(parent = self)
@ -255,11 +256,11 @@ class CuraApplication(QtApplication):
@pyqtProperty(str, constant=True) @pyqtProperty(str, constant=True)
def ultimakerCloudApiRootUrl(self) -> str: def ultimakerCloudApiRootUrl(self) -> str:
return UltimakerCloudAuthentication.CuraCloudAPIRoot return UltimakerCloudConstants.CuraCloudAPIRoot
@pyqtProperty(str, constant = True) @pyqtProperty(str, constant = True)
def ultimakerCloudAccountRootUrl(self) -> str: def ultimakerCloudAccountRootUrl(self) -> str:
return UltimakerCloudAuthentication.CuraCloudAccountAPIRoot return UltimakerCloudConstants.CuraCloudAccountAPIRoot
@pyqtProperty(str, constant=True) @pyqtProperty(str, constant=True)
def ultimakerDigitalFactoryUrl(self) -> str: def ultimakerDigitalFactoryUrl(self) -> str:
@ -651,7 +652,7 @@ class CuraApplication(QtApplication):
return self._global_container_stack return self._global_container_stack
@override(Application) @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...")) self._setLoadingHint(self._i18n_catalog.i18nc("@info:progress", "Initializing Active Machine..."))
super().setGlobalContainerStack(stack) super().setGlobalContainerStack(stack)
@ -816,6 +817,7 @@ class CuraApplication(QtApplication):
self._output_device_manager.start() self._output_device_manager.start()
self._welcome_pages_model.initialize() self._welcome_pages_model.initialize()
self._add_printer_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() self._whats_new_pages_model.initialize()
# Detect in which mode to run and execute that mode # Detect in which mode to run and execute that mode
@ -853,6 +855,7 @@ class CuraApplication(QtApplication):
self.callLater(self._openFile, file_name) self.callLater(self._openFile, file_name)
initializationFinished = pyqtSignal() initializationFinished = pyqtSignal()
showAddPrintersUncancellableDialog = pyqtSignal() # Used to show the add printers dialog with a greyed background
def runWithoutGUI(self): def runWithoutGUI(self):
"""Run Cura without GUI elements and interaction (server mode).""" """Run Cura without GUI elements and interaction (server mode)."""
@ -943,6 +946,10 @@ class CuraApplication(QtApplication):
def getAddPrinterPagesModel(self, *args) -> "AddPrinterPagesModel": def getAddPrinterPagesModel(self, *args) -> "AddPrinterPagesModel":
return self._add_printer_pages_model 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) @pyqtSlot(result = QObject)
def getWhatsNewPagesModel(self, *args) -> "WhatsNewPagesModel": def getWhatsNewPagesModel(self, *args) -> "WhatsNewPagesModel":
return self._whats_new_pages_model return self._whats_new_pages_model

View File

@ -154,7 +154,7 @@ class BaseMaterialsModel(ListModel):
# Update the available materials (ContainerNode) for the current active machine and extruder setup. # Update the available materials (ContainerNode) for the current active machine and extruder setup.
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack() 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. return # There are no materials for this machine, so nothing to do.
extruder_list = global_stack.extruderList extruder_list = global_stack.extruderList
if self._extruder_position > len(extruder_list): if self._extruder_position > len(extruder_list):

View File

@ -2,6 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from http.server import HTTPServer from http.server import HTTPServer
from socketserver import ThreadingMixIn
from typing import Callable, Any, TYPE_CHECKING from typing import Callable, Any, TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
@ -9,7 +10,7 @@ if TYPE_CHECKING:
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers
class AuthorizationRequestServer(HTTPServer): class AuthorizationRequestServer(ThreadingMixIn, HTTPServer):
"""The authorization request callback handler server. """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 This subclass is needed to be able to pass some data to the request handler. This cannot be done on the request

View File

@ -81,7 +81,7 @@ class LocalAuthorizationServer:
if self._web_server: if self._web_server:
try: try:
self._web_server.server_close() self._web_server.shutdown()
except OSError: except OSError:
# OS error can happen if the socket was already closed. We really don't care about that case. # OS error can happen if the socket was already closed. We really don't care about that case.
pass pass

View File

@ -22,6 +22,7 @@ from UM.Settings.SettingFunction import SettingFunction
from UM.Signal import postponeSignals, CompressTechnique from UM.Signal import postponeSignals, CompressTechnique
import cura.CuraApplication # Imported like this to prevent circular references. import cura.CuraApplication # Imported like this to prevent circular references.
from UM.Util import parseBool
from cura.Machines.ContainerNode import ContainerNode from cura.Machines.ContainerNode import ContainerNode
from cura.Machines.ContainerTree import ContainerTree 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, from cura.Settings.cura_empty_instance_containers import (empty_definition_changes_container, empty_variant_container,
empty_material_container, empty_quality_container, empty_material_container, empty_quality_container,
empty_quality_changes_container, empty_intent_container) empty_quality_changes_container, empty_intent_container)
from cura.UltimakerCloud.UltimakerCloudConstants import META_UM_LINKED_TO_ACCOUNT
from .CuraStackBuilder import CuraStackBuilder from .CuraStackBuilder import CuraStackBuilder
@ -288,9 +290,15 @@ class MachineManager(QObject):
self.activeStackValueChanged.emit() self.activeStackValueChanged.emit()
@pyqtSlot(str) @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. 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() container_registry = CuraContainerRegistry.getInstance()
containers = container_registry.findContainerStacks(id = stack_id) containers = container_registry.findContainerStacks(id = stack_id)
if not containers: if not containers:
@ -494,6 +502,10 @@ class MachineManager(QObject):
group_size = int(self.activeMachine.getMetaDataEntry("group_size", "-1")) group_size = int(self.activeMachine.getMetaDataEntry("group_size", "-1"))
return 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) @pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineHasNetworkConnection(self) -> bool: def activeMachineHasNetworkConnection(self) -> bool:
# A network connection is only available if any output device is actually a network connected device. # 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] other_machine_stacks = [s for s in machine_stacks if s["id"] != machine_id]
if other_machine_stacks: if other_machine_stacks:
self.setActiveMachine(other_machine_stacks[0]["id"]) self.setActiveMachine(other_machine_stacks[0]["id"])
else:
self.setActiveMachine(None)
metadatas = CuraContainerRegistry.getInstance().findContainerStacksMetadata(id = machine_id) metadatas = CuraContainerRegistry.getInstance().findContainerStacksMetadata(id = machine_id)
if not metadatas: if not metadatas:

View File

@ -10,12 +10,11 @@ from .WelcomePagesModel import WelcomePagesModel
# #
class AddPrinterPagesModel(WelcomePagesModel): class AddPrinterPagesModel(WelcomePagesModel):
def initialize(self) -> None: def initialize(self, cancellable: bool = True) -> None:
self._pages.append({"id": "add_network_or_local_printer", self._pages.append({"id": "add_network_or_local_printer",
"page_url": self._getBuiltinWelcomePagePath("AddNetworkOrLocalPrinterContent.qml"), "page_url": self._getBuiltinWelcomePagePath("AddNetworkOrLocalPrinterContent.qml"),
"next_page_id": "machine_actions", "next_page_id": "machine_actions",
"next_page_button_text": self._catalog.i18nc("@action:button", "Add"), "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", self._pages.append({"id": "add_printer_by_ip",
"page_url": self._getBuiltinWelcomePagePath("AddPrinterByIpContent.qml"), "page_url": self._getBuiltinWelcomePagePath("AddPrinterByIpContent.qml"),
@ -30,6 +29,9 @@ class AddPrinterPagesModel(WelcomePagesModel):
"page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"), "page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"),
"should_show_function": self.shouldShowMachineActions, "should_show_function": self.shouldShowMachineActions,
}) })
if cancellable:
self._pages[0]["previous_page_button_text"] = self._catalog.i18nc("@action:button", "Cancel")
self.setItems(self._pages) self.setItems(self._pages)

View File

@ -9,6 +9,10 @@ DEFAULT_CLOUD_API_VERSION = "1" # type: str
DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str
DEFAULT_DIGITAL_FACTORY_URL = "https://digitalfactory.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: try:
from cura.CuraVersion import CuraCloudAPIRoot # type: ignore from cura.CuraVersion import CuraCloudAPIRoot # type: ignore
if CuraCloudAPIRoot == "": if CuraCloudAPIRoot == "":

View File

@ -1,13 +1,13 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from cura.UltimakerCloud import UltimakerCloudAuthentication from cura.UltimakerCloud import UltimakerCloudConstants
class Settings: class Settings:
# Keeps the plugin settings. # Keeps the plugin settings.
DRIVE_API_VERSION = 1 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_ENABLED_PREFERENCE_KEY = "cura_drive/auto_backup_enabled"
AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date" AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date"

View File

@ -289,6 +289,13 @@ class Stretcher:
self.layergcode = self.layergcode + sout + "\n" self.layergcode = self.layergcode + sout + "\n"
ipos = ipos + 1 ipos = ipos + 1
else: 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" self.layergcode = self.layergcode + layer_steps[i].comment + "\n"
def workOnSequence(self, orig_seq, modif_seq): def workOnSequence(self, orig_seq, modif_seq):

View File

@ -1,13 +1,13 @@
from typing import Union from typing import Union
from cura import ApplicationMetadata from cura import ApplicationMetadata
from cura.UltimakerCloud import UltimakerCloudAuthentication from cura.UltimakerCloud import UltimakerCloudConstants
class CloudApiModel: class CloudApiModel:
sdk_version = ApplicationMetadata.CuraSDKVersion # type: Union[str, int] sdk_version = ApplicationMetadata.CuraSDKVersion # type: Union[str, int]
cloud_api_version = UltimakerCloudAuthentication.CuraCloudAPIVersion # type: str cloud_api_version = UltimakerCloudConstants.CuraCloudAPIVersion # type: str
cloud_api_root = UltimakerCloudAuthentication.CuraCloudAPIRoot # 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( api_url = "{cloud_api_root}/cura-packages/v{cloud_api_version}/cura/v{sdk_version}".format(
cloud_api_root = cloud_api_root, cloud_api_root = cloud_api_root,
cloud_api_version = cloud_api_version, cloud_api_version = cloud_api_version,

View File

@ -13,7 +13,7 @@ from UM.TaskManagement.HttpRequestManager import HttpRequestManager
from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope
from cura.API import Account from cura.API import Account
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.UltimakerCloud import UltimakerCloudAuthentication from cura.UltimakerCloud import UltimakerCloudConstants
from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope
from .ToolPathUploader import ToolPathUploader from .ToolPathUploader import ToolPathUploader
from ..Models.BaseModel import BaseModel from ..Models.BaseModel import BaseModel
@ -35,7 +35,7 @@ class CloudApiClient:
""" """
# The cloud URL to use for this remote cluster. # 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) CLUSTER_API_ROOT = "{}/connect/v1".format(ROOT_PATH)
CURA_API_ROOT = "{}/cura/v1".format(ROOT_PATH) CURA_API_ROOT = "{}/cura/v1".format(ROOT_PATH)

View File

@ -1,21 +1,23 @@
# Copyright (c) 2019 Ultimaker B.V. # Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import os 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.QtNetwork import QNetworkReply
from PyQt5.QtWidgets import QMessageBox
from UM import i18nCatalog from UM import i18nCatalog
from UM.Logger import Logger # To log errors talking to the API. from UM.Logger import Logger # To log errors talking to the API.
from UM.Message import Message from UM.Message import Message
from UM.Settings.Interfaces import ContainerInterface from UM.Settings.Interfaces import ContainerInterface
from UM.Signal import Signal from UM.Signal import Signal
from UM.Util import parseBool
from cura.API import Account from cura.API import Account
from cura.API.Account import SyncState from cura.API.Account import SyncState
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.Settings.CuraStackBuilder import CuraStackBuilder from cura.Settings.CuraStackBuilder import CuraStackBuilder
from cura.Settings.GlobalStack import GlobalStack from cura.Settings.GlobalStack import GlobalStack
from cura.UltimakerCloud.UltimakerCloudConstants import META_UM_LINKED_TO_ACCOUNT
from .CloudApiClient import CloudApiClient from .CloudApiClient import CloudApiClient
from .CloudOutputDevice import CloudOutputDevice from .CloudOutputDevice import CloudOutputDevice
from ..Models.Http.CloudClusterResponse import CloudClusterResponse from ..Models.Http.CloudClusterResponse import CloudClusterResponse
@ -30,6 +32,7 @@ class CloudOutputDeviceManager:
META_CLUSTER_ID = "um_cloud_cluster_id" META_CLUSTER_ID = "um_cloud_cluster_id"
META_NETWORK_KEY = "um_network_key" META_NETWORK_KEY = "um_network_key"
SYNC_SERVICE_NAME = "CloudOutputDeviceManager" SYNC_SERVICE_NAME = "CloudOutputDeviceManager"
# The translation catalog for this device. # The translation catalog for this device.
@ -41,9 +44,14 @@ class CloudOutputDeviceManager:
def __init__(self) -> None: def __init__(self) -> None:
# Persistent dict containing the remote clusters for the authenticated user. # Persistent dict containing the remote clusters for the authenticated user.
self._remote_clusters = {} # type: Dict[str, CloudOutputDevice] 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._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
self._api = CloudApiClient(CuraApplication.getInstance(), on_error = lambda error: Logger.log("e", str(error))) self._api = CloudApiClient(CuraApplication.getInstance(), on_error = lambda error: Logger.log("e", str(error)))
self._account.loginStateChanged.connect(self._onLoginStateChanged) self._account.loginStateChanged.connect(self._onLoginStateChanged)
self._removed_printers_message = None # type: Optional[Message]
# Ensure we don't start twice. # Ensure we don't start twice.
self._running = False self._running = False
@ -98,23 +106,41 @@ class CloudOutputDeviceManager:
def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None: def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None:
"""Callback for when the request for getting the clusters is finished.""" """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 = [] new_clusters = []
all_clusters = {c.cluster_id: c for c in clusters} # type: Dict[str, CloudClusterResponse] 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] 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(): for device_id, cluster_data in all_clusters.items():
if device_id not in self._remote_clusters: if device_id not in self._remote_clusters:
new_clusters.append(cluster_data) 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) self._onDevicesDiscovered(new_clusters)
removed_device_keys = set(self._remote_clusters.keys()) - set(online_clusters.keys()) # Hide the current removed_printers_message, if there is any
for device_id in removed_device_keys: 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) self._onDiscoveredDeviceRemoved(device_id)
if new_clusters or removed_device_keys: # Handle devices that were previously added in Cura but do not exist in the account anymore (i.e. they were
self.discoveredDevicesChanged.emit() # removed from the account)
removed_device_keys = set(self._um_cloud_printers.keys()) - set(all_clusters.keys())
if removed_device_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 # If the removed device was active we should connect to the new active device
self._connectToActiveMachine() self._connectToActiveMachine()
@ -144,10 +170,13 @@ class CloudOutputDeviceManager:
if machine_manager.getMachine(device.printerType, {self.META_CLUSTER_ID: device.key}) is None \ 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. 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) new_devices.append(device)
elif device.getId() not in self._remote_clusters: elif device.getId() not in self._remote_clusters:
self._remote_clusters[device.getId()] = device self._remote_clusters[device.getId()] = device
remote_clusters_added = True 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. # Inform the Cloud printers model about new devices.
new_devices_list_of_dicts = [{ new_devices_list_of_dicts = [{
@ -163,7 +192,11 @@ class CloudOutputDeviceManager:
self._connectToActiveMachine() self._connectToActiveMachine()
return 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( image_path = os.path.join(
CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "", CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "",
@ -204,19 +237,97 @@ class CloudOutputDeviceManager:
max_disp_devices = 3 max_disp_devices = 3
if len(new_devices) > max_disp_devices: if len(new_devices) > max_disp_devices:
num_hidden = len(new_devices) - max_disp_devices + 1 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 = ["<li>{} ({})</li>".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.append(self.I18N_CATALOG.i18nc("info:hidden list items", "<li>... and {} others</li>", num_hidden))
device_names = "\n".join(device_name_list) device_names = "\n".join(device_name_list)
else: else:
device_names = "\n".join(["- {} ({})".format(device.name, device.printerTypeName) for device in new_devices]) device_names = "\n".join(["<li>{} ({})</li>".format(device.name, device.printerTypeName) for device in new_devices])
message_text = self.I18N_CATALOG.i18nc( message_text = self.I18N_CATALOG.i18nc(
"info:status", "info:status",
"Cloud printers added from your account:\n{}", "Cloud printers added from your account:\n<ul>{}</ul>",
device_names device_names
) )
message.setText(message_text) 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(["<li>{} ({})</li>".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",
"<ul>{}</ul>\nTo establish a connection, please visit the "
"<a href='https://mycloud.ultimaker.com/'>Ultimaker Digital Factory</a>.",
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: def _onDiscoveredDeviceRemoved(self, device_id: str) -> None:
device = self._remote_clusters.pop(device_id, None) # type: Optional[CloudOutputDevice] device = self._remote_clusters.pop(device_id, None) # type: Optional[CloudOutputDevice]
if not device: if not device:
@ -302,3 +413,24 @@ class CloudOutputDeviceManager:
container_cluster_id = container.getMetaDataEntry(self.META_CLUSTER_ID, None) container_cluster_id = container.getMetaDataEntry(self.META_CLUSTER_ID, None)
if container_cluster_id in self._remote_clusters.keys(): if container_cluster_id in self._remote_clusters.keys():
del self._remote_clusters[container_cluster_id] 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()

View File

@ -465,7 +465,7 @@ class XmlMaterialProfile(InstanceContainer):
return "materials" return "materials"
@classmethod @classmethod
def getVersionFromSerialized(cls, serialized: str) -> Optional[int]: def getVersionFromSerialized(cls, serialized: str) -> int:
data = ET.fromstring(serialized) data = ET.fromstring(serialized)
version = XmlMaterialProfile.Version version = XmlMaterialProfile.Version

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -1,82 +1,34 @@
{ {
"name": "Dagoma DiscoEasy200", "name": "Dagoma DiscoEasy200",
"version": 2, "version": 2,
"inherits": "fdmprinter", "inherits": "dagoma_disco",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Dagoma", "author": "Dagoma",
"manufacturer": "Dagoma", "manufacturer": "Dagoma",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform": "dagoma_discoeasy200.3mf", "platform": "dagoma_discoeasy200.3mf",
"platform_offset": [0, -57.3, -11], "platform_offset": [0, -57, -39],
"has_machine_quality": true, "has_machine_quality": true,
"has_materials": true, "has_materials": true,
"preferred_material": "chromatik_pla", "preferred_material": "chromatik_pla",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "dagoma_discoeasy200_extruder_0", "0": "dagoma_discoeasy200_extruder"
"1": "dagoma_discoeasy200_extruder_1"
} }
}, },
"overrides": { "overrides": {
"machine_name": {
"default_value": "Dagoma DiscoEasy200"
},
"machine_extruder_count": { "machine_extruder_count": {
"default_value": 2 "default_value": 1
},
"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"
}, },
"machine_start_gcode": { "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": { "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_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"
},
"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
} }
} }
} }

View File

@ -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"
}
}
}

View File

@ -1,82 +1,34 @@
{ {
"name": "Dagoma DiscoUltimate", "name": "Dagoma DiscoUltimate",
"version": 2, "version": 2,
"inherits": "fdmprinter", "inherits": "dagoma_disco",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Dagoma", "author": "Dagoma",
"manufacturer": "Dagoma", "manufacturer": "Dagoma",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform": "dagoma_discoultimate.3mf", "platform": "dagoma_discoultimate.3mf",
"platform_offset": [0, -58.5, -11], "platform_offset": [0, -58.5, -39.5],
"has_machine_quality": true, "has_machine_quality": true,
"has_materials": true, "has_materials": true,
"preferred_material": "chromatik_pla", "preferred_material": "chromatik_pla",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "dagoma_discoultimate_extruder_0", "0": "dagoma_discoultimate_extruder"
"1": "dagoma_discoultimate_extruder_1"
} }
}, },
"overrides": { "overrides": {
"machine_name": {
"default_value": "Dagoma DiscoUltimate"
},
"machine_extruder_count": { "machine_extruder_count": {
"default_value": 2 "default_value": 1
},
"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"
}, },
"machine_start_gcode": { "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": { "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_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"
},
"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
} }
} }
} }

View File

@ -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"
}
}
}

View File

@ -1,7 +1,7 @@
{ {
"name": "Dagoma Magis", "name": "Dagoma Magis",
"version": 2, "version": 2,
"inherits": "fdmprinter", "inherits": "dagoma_delta",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Dagoma", "author": "Dagoma",
@ -14,65 +14,12 @@
"preferred_material": "chromatik_pla", "preferred_material": "chromatik_pla",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "dagoma_magis_extruder_0" "0": "dagoma_magis_extruder"
} }
}, },
"overrides": { "overrides": {
"machine_width": { "machine_name": {
"default_value": 195.55 "default_value": "Dagoma Magis"
},
"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
} }
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "Dagoma NEVA", "name": "Dagoma Neva",
"version": 2, "version": 2,
"inherits": "fdmprinter", "inherits": "dagoma_delta",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Dagoma", "author": "Dagoma",
@ -14,65 +14,12 @@
"preferred_material": "chromatik_pla", "preferred_material": "chromatik_pla",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "dagoma_neva_extruder_0" "0": "dagoma_neva_extruder"
} }
}, },
"overrides": { "overrides": {
"machine_width": { "machine_name": {
"default_value": 195.55 "default_value": "Dagoma Neva"
},
"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
} }
} }
} }

View File

@ -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.", "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", "unit": "mm",
"type": "float", "type": "float",
"default_value": 2.24, "default_value": 0,
"value": "top_layers * layer_height / math.tan(math.radians(max_skin_angle_for_expansion))", "value": "top_layers * layer_height / math.tan(math.radians(max_skin_angle_for_expansion))",
"minimum_value": "0", "minimum_value": "0",
"enabled": "(top_layers > 0 or bottom_layers > 0) and (top_skin_expand_distance > 0 or bottom_skin_expand_distance > 0)", "enabled": "(top_layers > 0 or bottom_layers > 0) and (top_skin_expand_distance > 0 or bottom_skin_expand_distance > 0)",

View File

@ -55,7 +55,7 @@
"default_value": "RepRap (Marlin/Sprinter)" "default_value": "RepRap (Marlin/Sprinter)"
}, },
"machine_start_gcode": { "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": { "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'" "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'"

View File

@ -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
}
}
}

View File

@ -3,7 +3,7 @@
"name": "Extruder 1", "name": "Extruder 1",
"inherits": "fdmextruder", "inherits": "fdmextruder",
"metadata": { "metadata": {
"machine": "dagoma_discoeasy200", "machine": "dagoma_discoeasy200_bicolor",
"position": "0" "position": "0"
}, },
@ -18,10 +18,10 @@
"default_value": 1.75 "default_value": 1.75
}, },
"machine_extruder_start_code": { "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": { "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"
} }
} }
} }

View File

@ -3,7 +3,7 @@
"name": "Extruder 2", "name": "Extruder 2",
"inherits": "fdmextruder", "inherits": "fdmextruder",
"metadata": { "metadata": {
"machine": "dagoma_discoeasy200", "machine": "dagoma_discoeasy200_bicolor",
"position": "1" "position": "1"
}, },
@ -18,10 +18,10 @@
"default_value": 1.75 "default_value": 1.75
}, },
"machine_extruder_start_code": { "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": { "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"
} }
} }
} }

View File

@ -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
}
}
}

View File

@ -3,7 +3,7 @@
"name": "Extruder 1", "name": "Extruder 1",
"inherits": "fdmextruder", "inherits": "fdmextruder",
"metadata": { "metadata": {
"machine": "dagoma_discoultimate", "machine": "dagoma_discoultimate_bicolor",
"position": "0" "position": "0"
}, },
@ -18,10 +18,10 @@
"default_value": 1.75 "default_value": 1.75
}, },
"machine_extruder_start_code": { "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": { "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"
} }
} }
} }

View File

@ -3,7 +3,7 @@
"name": "Extruder 2", "name": "Extruder 2",
"inherits": "fdmextruder", "inherits": "fdmextruder",
"metadata": { "metadata": {
"machine": "dagoma_discoultimate", "machine": "dagoma_discoultimate_bicolor",
"position": "1" "position": "1"
}, },
@ -18,10 +18,10 @@
"default_value": 1.75 "default_value": 1.75
}, },
"machine_extruder_start_code": { "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": { "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"
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"version": 2, "version": 2,
"name": "Extruder 1", "name": "Extruder",
"inherits": "fdmextruder", "inherits": "fdmextruder",
"metadata": { "metadata": {
"machine": "dagoma_magis", "machine": "dagoma_magis",

View File

@ -1,6 +1,6 @@
{ {
"version": 2, "version": 2,
"name": "Extruder 1", "name": "Extruder",
"inherits": "fdmextruder", "inherits": "fdmextruder",
"metadata": { "metadata": {
"machine": "dagoma_neva", "machine": "dagoma_neva",

Binary file not shown.

Binary file not shown.

View File

@ -84,6 +84,21 @@ UM.MainWindow
CuraApplication.purgeWindows() 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 Connections
{ {
target: CuraApplication target: CuraApplication
@ -117,6 +132,15 @@ UM.MainWindow
welcomeDialogItem.progressBarVisible = false welcomeDialogItem.progressBarVisible = false
welcomeDialogItem.visible = true 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
}
} }
} }

View File

@ -14,8 +14,8 @@ UM.Dialog
id: base id: base
title: catalog.i18nc("@title:window", "Discard or Keep changes") title: catalog.i18nc("@title:window", "Discard or Keep changes")
width: UM.Theme.getSize("popup_dialog").width minimumWidth: UM.Theme.getSize("popup_dialog").width
height: UM.Theme.getSize("popup_dialog").height minimumHeight: UM.Theme.getSize("popup_dialog").height
property var changesModel: Cura.UserChangesModel{ id: userChangesModel} property var changesModel: Cura.UserChangesModel{ id: userChangesModel}
onVisibilityChanged: onVisibilityChanged:
{ {
@ -80,6 +80,8 @@ UM.Dialog
property var extruder_name: userChangesModel.getItem(styleData.row).extruder property var extruder_name: userChangesModel.getItem(styleData.row).extruder
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: parent.right
elide: Text.ElideRight
font: UM.Theme.getFont("system") font: UM.Theme.getFont("system")
text: text:
{ {

View File

@ -143,7 +143,7 @@ UM.Dialog
{ {
width: parent.width width: parent.width
height: childrenRect.height height: childrenRect.height
model: Cura.MachineManager.activeMachine.extruderList model: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.extruderList : null
delegate: Column delegate: Column
{ {
height: childrenRect.height height: childrenRect.height

View File

@ -33,7 +33,7 @@ Cura.ExpandablePopup
} }
contentPadding: UM.Theme.getSize("default_lining").width 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 headerItem: Item
{ {
@ -46,7 +46,7 @@ Cura.ExpandablePopup
model: extrudersModel model: extrudersModel
delegate: Item delegate: Item
{ {
Layout.fillWidth: true Layout.preferredWidth: Math.round(parent.width / extrudersModel.count)
Layout.fillHeight: true Layout.fillHeight: true
// Extruder icon. Shows extruder index and has the same color as the active material. // Extruder icon. Shows extruder index and has the same color as the active material.
@ -84,7 +84,7 @@ Cura.ExpandablePopup
{ {
id: variantLabel id: variantLabel
visible: Cura.MachineManager.activeMachine.hasVariants visible: Cura.MachineManager.activeMachine ? Cura.MachineManager.activeMachine.hasVariants : false
text: model.variant text: model.variant
elide: Text.ElideRight elide: Text.ElideRight
@ -114,7 +114,7 @@ Cura.ExpandablePopup
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
renderType: Text.NativeRendering 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 anchors
{ {

View File

@ -244,7 +244,7 @@ Item
Row Row
{ {
height: visible ? UM.Theme.getSize("print_setup_big_item").height : 0 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 Label
{ {
@ -305,7 +305,7 @@ Item
Row Row
{ {
height: visible ? UM.Theme.getSize("print_setup_big_item").height : 0 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 Label
{ {

View File

@ -130,7 +130,11 @@ Item
target: extruderModel target: extruderModel
onModelChanged: onModelChanged:
{ {
supportExtruderCombobox.color = supportExtruderCombobox.model.getItem(supportExtruderCombobox.currentIndex).color var maybeColor = supportExtruderCombobox.model.getItem(supportExtruderCombobox.currentIndex).color
if (maybeColor)
{
supportExtruderCombobox.color = maybeColor
}
} }
} }
onCurrentIndexChanged: onCurrentIndexChanged:

View File

@ -35,16 +35,23 @@ Cura.ExpandablePopup
} }
} }
readonly property string connectionStatusMessage: { function getConnectionStatusMessage() {
if (connectionStatus == "printer_cloud_not_available") if (connectionStatus == "printer_cloud_not_available")
{ {
if(Cura.API.connectionStatus.isInternetReachable) if(Cura.API.connectionStatus.isInternetReachable)
{ {
if (Cura.API.account.isLoggedIn) if (Cura.API.account.isLoggedIn)
{
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.") return catalog.i18nc("@status", "The cloud printer is offline. Please check if the printer is turned on and connected to the internet.")
} }
else else
{
return catalog.i18nc("@status", "This printer is not linked to your account. Please visit the Ultimaker Digital Factory to establish a connection.")
}
}
else
{ {
return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please sign in to connect to the cloud printer.") return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please sign in to connect to the cloud printer.")
} }
@ -139,12 +146,13 @@ Cura.ExpandablePopup
{ {
id: connectionStatusTooltipHoverArea id: connectionStatusTooltipHoverArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: connectionStatusMessage !== "" hoverEnabled: getConnectionStatusMessage() !== ""
acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks
onEntered: onEntered:
{ {
machineSelector.mouseArea.entered() // we want both this and the outer area to be entered machineSelector.mouseArea.entered() // we want both this and the outer area to be entered
tooltip.tooltipText = getConnectionStatusMessage()
tooltip.show() tooltip.show()
} }
onExited: { tooltip.hide() } onExited: { tooltip.hide() }
@ -155,7 +163,7 @@ Cura.ExpandablePopup
id: tooltip id: tooltip
width: 250 * screenScaleFactor width: 250 * screenScaleFactor
tooltipText: connectionStatusMessage tooltipText: getConnectionStatusMessage()
arrowSize: UM.Theme.getSize("button_tooltip_arrow").width arrowSize: UM.Theme.getSize("button_tooltip_arrow").width
x: connectionStatusImage.x - UM.Theme.getSize("narrow_margin").width x: connectionStatusImage.x - UM.Theme.getSize("narrow_margin").width
y: connectionStatusImage.y + connectionStatusImage.height + UM.Theme.getSize("narrow_margin").height y: connectionStatusImage.y + connectionStatusImage.height + UM.Theme.getSize("narrow_margin").height

View File

@ -28,11 +28,11 @@ ListView
delegate: MachineSelectorButton delegate: MachineSelectorButton
{ {
text: model.name text: model.name ? model.name : ""
width: listView.width width: listView.width
outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null 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: onClicked:
{ {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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