Merge branch 'master' into CURA-6440_exclude_support_blocks_in_used_extruders

This commit is contained in:
Ghostkeeper 2019-04-04 16:41:00 +02:00
commit 93ef8f6c98
No known key found for this signature in database
GPG key ID: 86BEF881AE2CF276
169 changed files with 5231 additions and 4137 deletions

View file

@ -116,12 +116,13 @@ class Backup:
current_version = self._application.getVersion()
version_to_restore = self.meta_data.get("cura_release", "master")
if current_version != version_to_restore:
# Cannot restore version older or newer than current because settings might have changed.
# Restoring this will cause a lot of issues so we don't allow this for now.
if current_version < version_to_restore:
# Cannot restore version newer than current because settings might have changed.
Logger.log("d", "Tried to restore a Cura backup of version {version_to_restore} with cura version {current_version}".format(version_to_restore = version_to_restore, current_version = current_version))
self._showMessage(
self.catalog.i18nc("@info:backup_failed",
"Tried to restore a Cura backup that does not match your current version."))
"Tried to restore a Cura backup that is higher than the current version."))
return False
version_data_dir = Resources.getDataStoragePath()

View file

@ -13,113 +13,117 @@ from PyQt5.QtGui import QColor, QIcon
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType
from UM.i18n import i18nCatalog
from UM.Application import Application
from UM.Decorators import override
from UM.FlameProfiler import pyqtSlot
from UM.Logger import Logger
from UM.Message import Message
from UM.Platform import Platform
from UM.PluginError import PluginNotFoundError
from UM.Scene.SceneNode import SceneNode
from UM.Scene.Camera import Camera
from UM.Math.Vector import Vector
from UM.Math.Quaternion import Quaternion
from UM.Resources import Resources
from UM.Preferences import Preferences
from UM.Qt.QtApplication import QtApplication # The class we're inheriting from.
import UM.Util
from UM.View.SelectionPass import SelectionPass # For typing.
from UM.Math.AxisAlignedBox import AxisAlignedBox
from UM.Math.Matrix import Matrix
from UM.Platform import Platform
from UM.Resources import Resources
from UM.Scene.ToolHandle import ToolHandle
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Math.Quaternion import Quaternion
from UM.Math.Vector import Vector
from UM.Mesh.ReadMeshJob import ReadMeshJob
from UM.Logger import Logger
from UM.Preferences import Preferences
from UM.Qt.QtApplication import QtApplication #The class we're inheriting from.
from UM.View.SelectionPass import SelectionPass #For typing.
from UM.Scene.Selection import Selection
from UM.Scene.GroupDecorator import GroupDecorator
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.Validator import Validator
from UM.Message import Message
from UM.i18n import i18nCatalog
from UM.Workspace.WorkspaceReader import WorkspaceReader
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
from UM.Operations.GroupedOperation import GroupedOperation
from UM.Operations.SetTransformOperation import SetTransformOperation
from UM.Scene.Camera import Camera
from UM.Scene.GroupDecorator import GroupDecorator
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Scene.SceneNode import SceneNode
from UM.Scene.Selection import Selection
from UM.Scene.ToolHandle import ToolHandle
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType
from UM.Settings.SettingFunction import SettingFunction
from UM.Settings.Validator import Validator
from UM.Workspace.WorkspaceReader import WorkspaceReader
from cura.API import CuraAPI
from cura.Arranging.Arrange import Arrange
from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob
from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob
from cura.Arranging.ShapeArray import ShapeArray
from cura.MultiplyObjectsJob import MultiplyObjectsJob
from cura.GlobalStacksModel import GlobalStacksModel
from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
from cura.Operations.SetParentOperation import SetParentOperation
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
from cura.Scene.BlockSlicingDecorator import BlockSlicingDecorator
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
from cura.Scene.CuraSceneController import CuraSceneController
from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.SettingFunction import SettingFunction
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.MachineNameValidator import MachineNameValidator
from cura.Machines.Models.BuildPlateModel import BuildPlateModel
from cura.Machines.Models.NozzleModel import NozzleModel
from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel
from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel
from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel
from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel
from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel
from cura.Machines.Models.QualityManagementModel import QualityManagementModel
from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel
from cura.Machines.Models.MachineManagementModel import MachineManagementModel
from cura.Machines.Models.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
from cura.Scene import ZOffsetDecorator
from cura.Machines.MachineErrorChecker import MachineErrorChecker
from cura.Machines.VariantManager import VariantManager
from cura.Machines.Models.BuildPlateModel import BuildPlateModel
from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel
from cura.Machines.Models.DiscoveredPrintersModel import DiscoveredPrintersModel
from cura.Machines.Models.ExtrudersModel import ExtrudersModel
from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel
from cura.Machines.Models.FirstStartMachineActionsModel import FirstStartMachineActionsModel
from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel
from cura.Machines.Models.GlobalStacksModel import GlobalStacksModel
from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel
from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from cura.Machines.Models.NozzleModel import NozzleModel
from cura.Machines.Models.QualityManagementModel import QualityManagementModel
from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel
from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel
from cura.Machines.Models.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel
from cura.Machines.Models.UserChangesModel import UserChangesModel
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
import cura.Settings.cura_empty_instance_containers
from cura.Settings.ContainerManager import ContainerManager
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.MachineManager import MachineManager
from cura.Settings.MachineNameValidator import MachineNameValidator
from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
from cura.Settings.SettingInheritanceManager import SettingInheritanceManager
from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel
from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager
from cura.Machines.VariantManager import VariantManager
from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager
from cura.UI import CuraSplashScreen, MachineActionManager, PrintInformation
from cura.UI.MachineSettingsManager import MachineSettingsManager
from cura.UI.ObjectsModel import ObjectsModel
from cura.UI.TextManager import TextManager
from cura.UI.WelcomePagesModel import WelcomePagesModel
from .SingleInstance import SingleInstance
from .AutoSave import AutoSave
from . import PlatformPhysics
from . import BuildVolume
from . import CameraAnimation
from . import PrintInformation
from . import CuraActions
from cura.Scene import ZOffsetDecorator
from . import CuraSplashScreen
from . import PrintJobPreviewImageProvider
from . import MachineActionManager
from cura.TaskManagement.OnExitCallbackManager import OnExitCallbackManager
from cura.Settings.MachineManager import MachineManager
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.UserChangesModel import UserChangesModel
from cura.Settings.ExtrudersModel import ExtrudersModel
from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
from cura.Settings.ContainerManager import ContainerManager
from cura.Settings.SidebarCustomMenuItemsModel import SidebarCustomMenuItemsModel
import cura.Settings.cura_empty_instance_containers
from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions
from cura.ObjectsModel import ObjectsModel
from cura.PrinterOutputDevice import PrinterOutputDevice
from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
from cura import ApplicationMetadata, UltimakerCloudAuthentication
from UM.FlameProfiler import pyqtSlot
from UM.Decorators import override
if TYPE_CHECKING:
from cura.Machines.MaterialManager import MaterialManager
from cura.Machines.QualityManager import QualityManager
@ -208,6 +212,13 @@ class CuraApplication(QtApplication):
self._cura_scene_controller = None
self._machine_error_checker = None
self._machine_settings_manager = MachineSettingsManager(self)
self._discovered_printer_model = DiscoveredPrintersModel(self)
self._first_start_machine_actions_model = FirstStartMachineActionsModel(self)
self._welcome_pages_model = WelcomePagesModel(self)
self._text_manager = TextManager(self)
self._quality_profile_drop_down_menu_model = None
self._custom_quality_profile_drop_down_menu_model = None
self._cura_API = CuraAPI(self)
@ -237,8 +248,6 @@ class CuraApplication(QtApplication):
self._update_platform_activity_timer = None
self._need_to_show_user_agreement = True
self._sidebar_custom_menu_items = [] # type: list # Keeps list of custom menu items for the side bar
self._plugins_loaded = False
@ -450,7 +459,6 @@ class CuraApplication(QtApplication):
# Misc.:
"ConsoleLogger", #You want to be able to read the log if something goes wrong.
"CuraEngineBackend", #Cura is useless without this one since you can't slice.
"UserAgreement", #Our lawyers want every user to see this at least once.
"FileLogger", #You want to be able to read the log if something goes wrong.
"XmlMaterialProfile", #Cura crashes without this one.
"Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back.
@ -522,7 +530,7 @@ class CuraApplication(QtApplication):
preferences.addPreference("cura/expanded_brands", "")
preferences.addPreference("cura/expanded_types", "")
self._need_to_show_user_agreement = not preferences.getValue("general/accepted_user_agreement")
preferences.addPreference("general/accepted_user_agreement", False)
for key in [
"dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin
@ -545,13 +553,20 @@ class CuraApplication(QtApplication):
@pyqtProperty(bool)
def needToShowUserAgreement(self) -> bool:
return self._need_to_show_user_agreement
return not UM.Util.parseBool(self.getPreferences().getValue("general/accepted_user_agreement"))
def setNeedToShowUserAgreement(self, set_value = True) -> None:
self._need_to_show_user_agreement = set_value
@pyqtSlot(bool)
def setNeedToShowUserAgreement(self, set_value: bool = True) -> None:
self.getPreferences().setValue("general/accepted_user_agreement", str(not set_value))
@pyqtSlot(str, str)
def writeToLog(self, severity: str, message: str) -> None:
Logger.log(severity, message)
# DO NOT call this function to close the application, use checkAndExitApplication() instead which will perform
# pre-exit checks such as checking for in-progress USB printing, etc.
# Except for the 'Decline and close' in the 'User Agreement'-step in the Welcome-pages, that should be a hard exit.
@pyqtSlot()
def closeApplication(self) -> None:
Logger.log("i", "Close application")
main_window = self.getMainWindow()
@ -745,6 +760,9 @@ class CuraApplication(QtApplication):
# Initialize Cura API
self._cura_API.initialize()
self._output_device_manager.start()
self._welcome_pages_model.initialize()
# Detect in which mode to run and execute that mode
if self._is_headless:
self.runWithoutGUI()
@ -839,10 +857,30 @@ class CuraApplication(QtApplication):
# Hide the splash screen
self.closeSplash()
@pyqtSlot(result = QObject)
def getDiscoveredPrintersModel(self, *args) -> "DiscoveredPrintersModel":
return self._discovered_printer_model
@pyqtSlot(result = QObject)
def getFirstStartMachineActionsModel(self, *args) -> "FirstStartMachineActionsModel":
return self._first_start_machine_actions_model
@pyqtSlot(result = QObject)
def getSettingVisibilityPresetsModel(self, *args) -> SettingVisibilityPresetsModel:
return self._setting_visibility_presets_model
@pyqtSlot(result = QObject)
def getWelcomePagesModel(self, *args) -> "WelcomePagesModel":
return self._welcome_pages_model
@pyqtSlot(result = QObject)
def getMachineSettingsManager(self, *args) -> "MachineSettingsManager":
return self._machine_settings_manager
@pyqtSlot(result = QObject)
def getTextManager(self, *args) -> "TextManager":
return self._text_manager
def getCuraFormulaFunctions(self, *args) -> "CuraFormulaFunctions":
if self._cura_formula_functions is None:
self._cura_formula_functions = CuraFormulaFunctions(self)
@ -975,6 +1013,9 @@ class CuraApplication(QtApplication):
qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager)
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
qmlRegisterType(WelcomePagesModel, "Cura", 1, 0, "WelcomePagesModel")
qmlRegisterType(TextManager, "Cura", 1, 0, "TextManager")
qmlRegisterType(NetworkMJPGImage, "Cura", 1, 0, "NetworkMJPGImage")
qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel)
@ -988,7 +1029,8 @@ class CuraApplication(QtApplication):
qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")
qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel")
qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel")
qmlRegisterType(DiscoveredPrintersModel, "Cura", 1, 0, "DiscoveredPrintersModel")
qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
"QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel)
@ -999,6 +1041,7 @@ class CuraApplication(QtApplication):
qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler")
qmlRegisterType(SettingVisibilityPresetsModel, "Cura", 1, 0, "SettingVisibilityPresetsModel")
qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel")
qmlRegisterType(FirstStartMachineActionsModel, "Cura", 1, 0, "FirstStartMachineActionsModel")
qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")
qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel")
qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.getInstance)

View file

@ -33,6 +33,12 @@ class MachineAction(QObject, PluginObject):
def getKey(self) -> str:
return self._key
## Whether this action needs to ask the user anything.
# If not, we shouldn't present the user with certain screens which otherwise show up.
# Defaults to true to be in line with the old behaviour.
def needsUserInteraction(self) -> bool:
return True
@pyqtProperty(str, notify = labelChanged)
def label(self) -> str:
return self._label

View file

@ -0,0 +1,140 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Callable, Dict, List, Optional, TYPE_CHECKING
from PyQt5.QtCore import pyqtSlot, pyqtProperty, pyqtSignal, QObject
from UM.i18n import i18nCatalog
from UM.Logger import Logger
if TYPE_CHECKING:
from PyQt5.QtCore import QObject
from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice
catalog = i18nCatalog("cura")
class DiscoveredPrinter(QObject):
def __init__(self, ip_address: str, key: str, name: str, create_callback: Callable[[str], None], machine_type: str,
device: "NetworkedPrinterOutputDevice", parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
self._ip_address = ip_address
self._key = key
self._name = name
self.create_callback = create_callback
self._machine_type = machine_type
self._device = device
nameChanged = pyqtSignal()
def getKey(self) -> str:
return self._key
@pyqtProperty(str, notify = nameChanged)
def name(self) -> str:
return self._name
def setName(self, name: str) -> None:
if self._name != name:
self._name = name
self.nameChanged.emit()
machineTypeChanged = pyqtSignal()
@pyqtProperty(str, notify = machineTypeChanged)
def machineType(self) -> str:
return self._machine_type
def setMachineType(self, machine_type: str) -> None:
if self._machine_type != machine_type:
self._machine_type = machine_type
self.machineTypeChanged.emit()
# Human readable machine type string
@pyqtProperty(str, notify = machineTypeChanged)
def readableMachineType(self) -> str:
from cura.CuraApplication import CuraApplication
readable_type = CuraApplication.getInstance().getMachineManager().getMachineTypeNameFromId(self._machine_type)
if not readable_type:
readable_type = catalog.i18nc("@label", "Unknown")
return readable_type
@pyqtProperty(bool, notify = machineTypeChanged)
def isUnknownMachineType(self) -> bool:
return self.readableMachineType.lower() == "unknown"
@pyqtProperty(QObject, constant = True)
def device(self) -> "NetworkedPrinterOutputDevice":
return self._device
#
# Discovered printers are all the printers that were found on the network, which provide a more convenient way
# to add networked printers (Plugin finds a bunch of printers, user can select one from the list, plugin can then
# add that printer to Cura as the active one).
#
class DiscoveredPrintersModel(QObject):
def __init__(self, parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
self._discovered_printer_by_ip_dict = dict() # type: Dict[str, DiscoveredPrinter]
discoveredPrintersChanged = pyqtSignal()
@pyqtProperty(list, notify = discoveredPrintersChanged)
def discoveredPrinters(self) -> List["DiscoveredPrinter"]:
item_list = list(x for x in self._discovered_printer_by_ip_dict.values())
item_list.sort(key = lambda x: x.device.name)
return item_list
def addDiscoveredPrinter(self, ip_address: str, key: str, name: str, create_callback: Callable[[str], None],
machine_type: str, device: "NetworkedPrinterOutputDevice") -> None:
if ip_address in self._discovered_printer_by_ip_dict:
Logger.log("e", "Printer with ip [%s] has already been added", ip_address)
return
discovered_printer = DiscoveredPrinter(ip_address, key, name, create_callback, machine_type, device, parent = self)
self._discovered_printer_by_ip_dict[ip_address] = discovered_printer
self.discoveredPrintersChanged.emit()
def updateDiscoveredPrinter(self, ip_address: str,
name: Optional[str] = None,
machine_type: Optional[str] = None) -> None:
if ip_address not in self._discovered_printer_by_ip_dict:
Logger.log("w", "Printer with ip [%s] is not known", ip_address)
return
item = self._discovered_printer_by_ip_dict[ip_address]
if name is not None:
item.setName(name)
if machine_type is not None:
item.setMachineType(machine_type)
def removeDiscoveredPrinter(self, ip_address: str) -> None:
if ip_address not in self._discovered_printer_by_ip_dict:
Logger.log("w", "Key [%s] does not exist in the discovered printers list.", ip_address)
return
del self._discovered_printer_by_ip_dict[ip_address]
self.discoveredPrintersChanged.emit()
# A convenience function for QML to create a machine (GlobalStack) out of the given discovered printer.
# This function invokes the given discovered printer's "create_callback" to do this.
@pyqtSlot("QVariant")
def createMachineFromDiscoveredPrinter(self, discovered_printer: "DiscoveredPrinter") -> None:
discovered_printer.create_callback(discovered_printer.getKey())
@pyqtSlot(str)
def createMachineFromDiscoveredPrinterAddress(self, ip_address: str) -> None:
if ip_address not in self._discovered_printer_by_ip_dict:
Logger.log("i", "Key [%s] does not exist in the discovered printers list.", ip_address)
return
self.createMachineFromDiscoveredPrinter(self._discovered_printer_by_ip_dict[ip_address])

View file

@ -2,23 +2,25 @@
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
from typing import Iterable
from typing import Iterable, TYPE_CHECKING
from UM.i18n import i18nCatalog
import UM.Qt.ListModel
from UM.Qt.ListModel import ListModel
from UM.Application import Application
import UM.FlameProfiler
from cura.Settings.ExtruderStack import ExtruderStack # To listen to changes on the extruders.
if TYPE_CHECKING:
from cura.Settings.ExtruderStack import ExtruderStack # To listen to changes on the extruders.
catalog = i18nCatalog("cura")
## Model that holds extruders.
#
# This model is designed for use by any list of extruders, but specifically
# intended for drop-down lists of the current machine's extruders in place of
# settings.
class ExtrudersModel(UM.Qt.ListModel.ListModel):
class ExtrudersModel(ListModel):
# The ID of the container stack for the extruder.
IdRole = Qt.UserRole + 1

View file

@ -0,0 +1,104 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional, Dict, Any, TYPE_CHECKING
from PyQt5.QtCore import QObject, Qt, pyqtProperty, pyqtSignal, pyqtSlot
from UM.Qt.ListModel import ListModel
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
#
# This model holds all first-start machine actions for the currently active machine. It has 2 roles:
# - title : the title/name of the action
# - content : the QObject of the QML content of the action
# - action : the MachineAction object itself
#
class FirstStartMachineActionsModel(ListModel):
TitleRole = Qt.UserRole + 1
ContentRole = Qt.UserRole + 2
ActionRole = Qt.UserRole + 3
def __init__(self, application: "CuraApplication", parent: Optional[QObject] = None) -> None:
super().__init__(parent)
self.addRoleName(self.TitleRole, "title")
self.addRoleName(self.ContentRole, "content")
self.addRoleName(self.ActionRole, "action")
self._current_action_index = 0
self._application = application
self._application.initializationFinished.connect(self._initialize)
def _initialize(self) -> None:
self._application.getMachineManager().globalContainerChanged.connect(self._update)
self._update()
currentActionIndexChanged = pyqtSignal()
allFinished = pyqtSignal() # Emitted when all actions have been finished.
@pyqtProperty(int, notify = currentActionIndexChanged)
def currentActionIndex(self) -> int:
return self._current_action_index
@pyqtProperty("QVariantMap", notify = currentActionIndexChanged)
def currentItem(self) -> Optional[Dict[str, Any]]:
if self._current_action_index >= self.count:
return dict()
else:
return self.getItem(self._current_action_index)
@pyqtProperty(bool, notify = currentActionIndexChanged)
def hasMoreActions(self) -> bool:
return self._current_action_index < self.count - 1
@pyqtSlot()
def goToNextAction(self) -> None:
# finish the current item
if "action" in self.currentItem:
self.currentItem["action"].setFinished()
if not self.hasMoreActions:
self.allFinished.emit()
self.reset()
return
self._current_action_index += 1
self.currentActionIndexChanged.emit()
# Resets the current action index to 0 so the wizard panel can show actions from the beginning.
@pyqtSlot()
def reset(self) -> None:
self._current_action_index = 0
self.currentActionIndexChanged.emit()
if self.count == 0:
self.allFinished.emit()
def _update(self) -> None:
global_stack = self._application.getMachineManager().activeMachine
if global_stack is None:
self.setItems([])
return
definition_id = global_stack.definition.getId()
first_start_actions = self._application.getMachineActionManager().getFirstStartActions(definition_id)
item_list = []
for item in first_start_actions:
item_list.append({"title": item.label,
"content": item.displayItem,
"action": item,
})
item.reset()
self.setItems(item_list)
self.reset()
__all__ = ["FirstStartMachineActionsModel"]

View file

@ -1,7 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Logger import Logger
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
class GenericMaterialsModel(BaseMaterialsModel):

View file

@ -1,14 +1,13 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, QTimer
from UM.Qt.ListModel import ListModel
from UM.i18n import i18nCatalog
from PyQt5.QtCore import pyqtProperty, Qt, QTimer
from cura.PrinterOutputDevice import ConnectionType
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.GlobalStack import GlobalStack
@ -18,14 +17,18 @@ class GlobalStacksModel(ListModel):
HasRemoteConnectionRole = Qt.UserRole + 3
ConnectionTypeRole = Qt.UserRole + 4
MetaDataRole = Qt.UserRole + 5
DiscoverySourceRole = Qt.UserRole + 6 # For separating local and remote printers in the machine management page
def __init__(self, parent = None):
def __init__(self, parent = None) -> None:
super().__init__(parent)
self._catalog = i18nCatalog("cura")
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
self.addRoleName(self.MetaDataRole, "metadata")
self._container_stacks = []
self.addRoleName(self.DiscoverySourceRole, "discoverySource")
self._change_timer = QTimer()
self._change_timer.setInterval(200)
@ -36,16 +39,15 @@ class GlobalStacksModel(ListModel):
CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
self._filter_dict = {}
self._updateDelayed()
## Handler for container added/removed events from registry
def _onContainerChanged(self, container):
def _onContainerChanged(self, container) -> None:
# We only need to update when the added / removed container GlobalStack
if isinstance(container, GlobalStack):
self._updateDelayed()
def _updateDelayed(self):
def _updateDelayed(self) -> None:
self._change_timer.start()
def _update(self) -> None:
@ -57,14 +59,19 @@ class GlobalStacksModel(ListModel):
has_remote_connection = False
for connection_type in container_stack.configuredConnectionTypes:
has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value,
ConnectionType.CloudConnection.value]
if container_stack.getMetaDataEntry("hidden", False) in ["True", True]:
continue
section_name = "Network enabled printers" if has_remote_connection else "Local printers"
section_name = self._catalog.i18nc("@info:title", section_name)
items.append({"name": container_stack.getMetaDataEntry("group_name", container_stack.getName()),
"id": container_stack.getId(),
"hasRemoteConnection": has_remote_connection,
"metadata": container_stack.getMetaData().copy()})
items.sort(key=lambda i: not i["hasRemoteConnection"])
"metadata": container_stack.getMetaData().copy(),
"discoverySource": section_name})
items.sort(key = lambda i: not i["hasRemoteConnection"])
self.setItems(items)

View file

@ -1,82 +0,0 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Qt.ListModel import ListModel
from PyQt5.QtCore import Qt
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.ContainerStack import ContainerStack
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
#
# This the QML model for the quality management page.
#
class MachineManagementModel(ListModel):
NameRole = Qt.UserRole + 1
IdRole = Qt.UserRole + 2
MetaDataRole = Qt.UserRole + 3
GroupRole = Qt.UserRole + 4
def __init__(self, parent = None):
super().__init__(parent)
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.MetaDataRole, "metadata")
self.addRoleName(self.GroupRole, "group")
self._local_container_stacks = []
self._network_container_stacks = []
# Listen to changes
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
ContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
self._filter_dict = {}
self._update()
## Handler for container added/removed events from registry
def _onContainerChanged(self, container):
# We only need to update when the added / removed container is a stack.
if isinstance(container, ContainerStack) and container.getMetaDataEntry("type") == "machine":
self._update()
## Private convenience function to reset & repopulate the model.
def _update(self):
items = []
# Get first the network enabled printers
network_filter_printers = {"type": "machine",
"um_network_key": "*",
"hidden": "False"}
self._network_container_stacks = ContainerRegistry.getInstance().findContainerStacks(**network_filter_printers)
self._network_container_stacks.sort(key = lambda i: i.getMetaDataEntry("group_name", ""))
for container in self._network_container_stacks:
metadata = container.getMetaData().copy()
if container.getBottom():
metadata["definition_name"] = container.getBottom().getName()
items.append({"name": metadata.get("group_name", ""),
"id": container.getId(),
"metadata": metadata,
"group": catalog.i18nc("@info:title", "Network enabled printers")})
# Get now the local printers
local_filter_printers = {"type": "machine", "um_network_key": None}
self._local_container_stacks = ContainerRegistry.getInstance().findContainerStacks(**local_filter_printers)
self._local_container_stacks.sort(key = lambda i: i.getName())
for container in self._local_container_stacks:
metadata = container.getMetaData().copy()
if container.getBottom():
metadata["definition_name"] = container.getBottom().getName()
items.append({"name": container.getName(),
"id": container.getId(),
"metadata": metadata,
"group": catalog.i18nc("@info:title", "Local printers")})
self.setItems(items)

View file

@ -1,9 +1,8 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from PyQt5.QtCore import Qt, pyqtSignal
from UM.Qt.ListModel import ListModel
from UM.Logger import Logger
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
class MaterialTypesModel(ListModel):

View file

@ -10,7 +10,6 @@ from UM.Application import Application
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from UM.Settings.SettingFunction import SettingFunction
from UM.Qt.ListModel import ListModel

View file

@ -9,7 +9,7 @@ from typing import Union
MYPY = False
if MYPY:
from cura.PrinterOutputDevice import PrinterOutputDevice
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
class FirmwareUpdater(QObject):
firmwareProgressChanged = pyqtSignal()

View file

@ -3,14 +3,15 @@
from typing import TYPE_CHECKING, Set, Union, Optional
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
from PyQt5.QtCore import QTimer
from .PrinterOutputController import PrinterOutputController
if TYPE_CHECKING:
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
from .Models.PrintJobOutputModel import PrintJobOutputModel
from .Models.PrinterOutputModel import PrinterOutputModel
from .PrinterOutputDevice import PrinterOutputDevice
from .Models.ExtruderOutputModel import ExtruderOutputModel
class GenericOutputController(PrinterOutputController):

View file

@ -1,34 +0,0 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot
class MaterialOutputModel(QObject):
def __init__(self, guid, type, color, brand, name, parent = None):
super().__init__(parent)
self._guid = guid
self._type = type
self._color = color
self._brand = brand
self._name = name
@pyqtProperty(str, constant = True)
def guid(self):
return self._guid
@pyqtProperty(str, constant=True)
def type(self):
return self._type
@pyqtProperty(str, constant=True)
def brand(self):
return self._brand
@pyqtProperty(str, constant=True)
def color(self):
return self._color
@pyqtProperty(str, constant=True)
def name(self):
return self._name

View file

@ -4,7 +4,7 @@ from typing import Optional
from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from .MaterialOutputModel import MaterialOutputModel
class ExtruderConfigurationModel(QObject):
@ -67,4 +67,4 @@ class ExtruderConfigurationModel(QObject):
# Calculating a hash function using the position of the extruder, the material GUID and the hotend id to check if is
# unique within a set
def __hash__(self):
return hash(self._position) ^ (hash(self._material.guid) if self._material is not None else hash(0)) ^ hash(self._hotend_id)
return hash(self._position) ^ (hash(self._material.guid) if self._material is not None else hash(0)) ^ hash(self._hotend_id)

View file

@ -1,14 +1,15 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
from .ExtruderConfigurationModel import ExtruderConfigurationModel
if TYPE_CHECKING:
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from .MaterialOutputModel import MaterialOutputModel
from .PrinterOutputModel import PrinterOutputModel
class ExtruderOutputModel(QObject):

View file

@ -0,0 +1,36 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
from PyQt5.QtCore import pyqtProperty, QObject
class MaterialOutputModel(QObject):
def __init__(self, guid: Optional[str], type: str, color: str, brand: str, name: str, parent = None) -> None:
super().__init__(parent)
self._guid = guid
self._type = type
self._color = color
self._brand = brand
self._name = name
@pyqtProperty(str, constant = True)
def guid(self) -> str:
return self._guid if self._guid else ""
@pyqtProperty(str, constant = True)
def type(self) -> str:
return self._type
@pyqtProperty(str, constant = True)
def brand(self) -> str:
return self._brand
@pyqtProperty(str, constant = True)
def color(self) -> str:
return self._color
@pyqtProperty(str, constant = True)
def name(self) -> str:
return self._name

View file

@ -1,16 +1,15 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
from typing import Optional, TYPE_CHECKING, List
from PyQt5.QtCore import QUrl
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot, QUrl
from PyQt5.QtGui import QImage
if TYPE_CHECKING:
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
class PrintJobOutputModel(QObject):
@ -25,7 +24,7 @@ class PrintJobOutputModel(QObject):
previewImageChanged = pyqtSignal()
compatibleMachineFamiliesChanged = pyqtSignal()
def __init__(self, output_controller: "PrinterOutputController", key: str = "", name: str = "", parent=None) -> None:
def __init__(self, output_controller: "PrinterOutputController", key: str = "", name: str = "", parent = None) -> None:
super().__init__(parent)
self._output_controller = output_controller
self._state = ""
@ -36,7 +35,7 @@ class PrintJobOutputModel(QObject):
self._assigned_printer = None # type: Optional[PrinterOutputModel]
self._owner = "" # Who started/owns the print job?
self._configuration = None # type: Optional[ConfigurationModel]
self._configuration = None # type: Optional[PrinterConfigurationModel]
self._compatible_machine_families = [] # type: List[str]
self._preview_image_id = 0
@ -70,10 +69,10 @@ class PrintJobOutputModel(QObject):
self.previewImageChanged.emit()
@pyqtProperty(QObject, notify=configurationChanged)
def configuration(self) -> Optional["ConfigurationModel"]:
def configuration(self) -> Optional["PrinterConfigurationModel"]:
return self._configuration
def updateConfiguration(self, configuration: Optional["ConfigurationModel"]) -> None:
def updateConfiguration(self, configuration: Optional["PrinterConfigurationModel"]) -> None:
if self._configuration != configuration:
self._configuration = configuration
self.configurationChanged.emit()
@ -142,13 +141,13 @@ class PrintJobOutputModel(QObject):
@pyqtProperty(bool, notify=stateChanged)
def isActive(self) -> bool:
inactiveStates = [
inactive_states = [
"pausing",
"paused",
"resuming",
"wait_cleanup"
]
if self.state in inactiveStates and self.timeRemaining > 0:
if self.state in inactive_states and self.timeRemaining > 0:
return False
return True

View file

@ -6,10 +6,10 @@ from typing import List
MYPY = False
if MYPY:
from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
class ConfigurationModel(QObject):
class PrinterConfigurationModel(QObject):
configurationChanged = pyqtSignal()
@ -19,14 +19,14 @@ class ConfigurationModel(QObject):
self._extruder_configurations = [] # type: List[ExtruderConfigurationModel]
self._buildplate_configuration = ""
def setPrinterType(self, printer_type):
def setPrinterType(self, printer_type: str) -> None:
self._printer_type = printer_type
@pyqtProperty(str, fset = setPrinterType, notify = configurationChanged)
def printerType(self) -> str:
return self._printer_type
def setExtruderConfigurations(self, extruder_configurations: List["ExtruderConfigurationModel"]):
def setExtruderConfigurations(self, extruder_configurations: List["ExtruderConfigurationModel"]) -> None:
if self._extruder_configurations != extruder_configurations:
self._extruder_configurations = extruder_configurations
@ -40,7 +40,7 @@ class ConfigurationModel(QObject):
return self._extruder_configurations
def setBuildplateConfiguration(self, buildplate_configuration: str) -> None:
if self._buildplate_configuration != buildplate_configuration:
if self._buildplate_configuration != buildplate_configuration:
self._buildplate_configuration = buildplate_configuration
self.configurationChanged.emit()
@ -86,4 +86,4 @@ class ConfigurationModel(QObject):
if first_extruder:
extruder_hash &= hash(first_extruder)
return hash(self._printer_type) ^ extruder_hash ^ hash(self._buildplate_configuration)
return hash(self._printer_type) ^ extruder_hash ^ hash(self._buildplate_configuration)

View file

@ -4,12 +4,12 @@
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot, QUrl
from typing import List, Dict, Optional
from UM.Math.Vector import Vector
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from cura.PrinterOutput.Models.ExtruderOutputModel import ExtruderOutputModel
MYPY = False
if MYPY:
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
@ -37,7 +37,7 @@ class PrinterOutputModel(QObject):
self._controller = output_controller
self._controller.canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged)
self._extruders = [ExtruderOutputModel(printer = self, position = i) for i in range(number_of_extruders)]
self._printer_configuration = ConfigurationModel() # Indicates the current configuration setup in this printer
self._printer_configuration = PrinterConfigurationModel() # Indicates the current configuration setup in this printer
self._head_position = Vector(0, 0, 0)
self._active_print_job = None # type: Optional[PrintJobOutputModel]
self._firmware_version = firmware_version
@ -291,7 +291,7 @@ class PrinterOutputModel(QObject):
# Returns the configuration (material, variant and buildplate) of the current printer
@pyqtProperty(QObject, notify = configurationChanged)
def printerConfiguration(self) -> Optional[ConfigurationModel]:
def printerConfiguration(self) -> Optional[PrinterConfigurationModel]:
if self._printer_configuration.isValid():
return self._printer_configuration
return None

View file

View file

@ -7,7 +7,7 @@ from UM.Scene.SceneNode import SceneNode #For typing.
from cura.API import Account
from cura.CuraApplication import CuraApplication
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
from PyQt5.QtNetwork import QHttpMultiPart, QHttpPart, QNetworkRequest, QNetworkAccessManager, QNetworkReply, QAuthenticator
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl, QCoreApplication

View file

@ -4,14 +4,12 @@
from UM.Logger import Logger
from UM.Signal import Signal
from typing import Union
MYPY = False
if MYPY:
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
from .Models.PrintJobOutputModel import PrintJobOutputModel
from .Models.ExtruderOutputModel import ExtruderOutputModel
from .Models.PrinterOutputModel import PrinterOutputModel
from .PrinterOutputDevice import PrinterOutputDevice
class PrinterOutputController:

View file

@ -3,9 +3,6 @@
from enum import IntEnum
from typing import Callable, List, Optional, Union
from UM.Decorators import deprecated
from UM.i18n import i18nCatalog
from UM.OutputDevice.OutputDevice import OutputDevice
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QTimer, QUrl
from PyQt5.QtWidgets import QMessageBox
@ -13,14 +10,17 @@ from UM.Logger import Logger
from UM.Signal import signalemitter
from UM.Qt.QtApplication import QtApplication
from UM.FlameProfiler import pyqtSlot
from UM.Decorators import deprecated
from UM.i18n import i18nCatalog
from UM.OutputDevice.OutputDevice import OutputDevice
MYPY = False
if MYPY:
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater
from UM.FileHandler.FileHandler import FileHandler
from UM.Scene.SceneNode import SceneNode
from .Models.PrinterOutputModel import PrinterOutputModel
from .Models.PrinterConfigurationModel import PrinterConfigurationModel
from .FirmwareUpdater import FirmwareUpdater
i18n_catalog = i18nCatalog("cura")
@ -73,7 +73,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
super().__init__(device_id = device_id, parent = parent) # type: ignore # MyPy complains with the multiple inheritance
self._printers = [] # type: List[PrinterOutputModel]
self._unique_configurations = [] # type: List[ConfigurationModel]
self._unique_configurations = [] # type: List[PrinterConfigurationModel]
self._monitor_view_qml_path = "" # type: str
self._monitor_component = None # type: Optional[QObject]
@ -216,7 +216,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
# Returns the unique configurations of the printers within this output device
@pyqtProperty("QVariantList", notify = uniqueConfigurationsChanged)
def uniqueConfigurations(self) -> List["ConfigurationModel"]:
def uniqueConfigurations(self) -> List["PrinterConfigurationModel"]:
return self._unique_configurations
def _updateUniqueConfigurations(self) -> None:

View file

@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt, pyqtSlot, QObject
from PyQt5.QtWidgets import QApplication
from UM.Scene.Camera import Camera
from cura.ObjectsModel import ObjectsModel
from cura.UI.ObjectsModel import ObjectsModel
from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from UM.Application import Application

View file

@ -42,7 +42,14 @@ class CuraFormulaFunctions:
try:
extruder_stack = global_stack.extruders[str(extruder_position)]
except KeyError:
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available" % (property_key, extruder_position))
if extruder_position != 0:
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. Returning the result form extruder 0 instead" % (property_key, extruder_position))
# This fixes a very specific fringe case; If a profile was created for a custom printer and one of the
# extruder settings has been set to non zero and the profile is loaded for a machine that has only a single extruder
# it would cause all kinds of issues (and eventually a crash).
# See https://github.com/Ultimaker/Cura/issues/5535
return self.getValueInExtruder(0, property_key, context)
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. " % (property_key, extruder_position))
return None
value = extruder_stack.getRawProperty(property_key, "value", context = context)

View file

@ -64,6 +64,10 @@ class GlobalStack(CuraContainerStack):
machine_extruder_count = self.getProperty("machine_extruder_count", "value")
return result_list[:machine_extruder_count]
@pyqtProperty(int, constant = True)
def maxExtruderCount(self):
return len(self.getMetaDataEntry("machine_extruder_trains"))
@classmethod
def getLoadingPriority(cls) -> int:
return 2
@ -81,7 +85,15 @@ class GlobalStack(CuraContainerStack):
# Requesting it from the metadata actually gets them as strings (as that's what you get from serializing).
# But we do want them returned as a list of ints (so the rest of the code can directly compare)
connection_types = self.getMetaDataEntry("connection_type", "").split(",")
return [int(connection_type) for connection_type in connection_types if connection_type != ""]
result = []
for connection_type in connection_types:
if connection_type != "":
try:
result.append(int(connection_type))
except ValueError:
# We got invalid data, probably a None.
pass
return result
## \sa configuredConnectionTypes
def addConfiguredConnectionType(self, connection_type: int) -> None:

View file

@ -6,13 +6,13 @@ import re
import unicodedata
from typing import Any, List, Dict, TYPE_CHECKING, Optional, cast
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.Interfaces import ContainerInterface
from UM.Signal import Signal
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer
from UM.FlameProfiler import pyqtSlot
from UM import Util
from UM.Logger import Logger
@ -22,10 +22,10 @@ from UM.Settings.SettingFunction import SettingFunction
from UM.Signal import postponeSignals, CompressTechnique
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionType
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionType
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.ExtruderStack import ExtruderStack
@ -106,7 +106,7 @@ class MachineManager(QObject):
# There might already be some output devices by the time the signal is connected
self._onOutputDevicesChanged()
self._current_printer_configuration = ConfigurationModel() # Indicates the current configuration setup in this printer
self._current_printer_configuration = PrinterConfigurationModel() # Indicates the current configuration setup in this printer
self.activeMaterialChanged.connect(self._onCurrentConfigurationChanged)
self.activeVariantChanged.connect(self._onCurrentConfigurationChanged)
# Force to compute the current configuration
@ -157,6 +157,7 @@ class MachineManager(QObject):
printerConnectedStatusChanged = pyqtSignal() # Emitted every time the active machine change or the outputdevices change
rootMaterialChanged = pyqtSignal()
discoveredPrintersChanged = pyqtSignal()
def setInitialActiveMachine(self) -> None:
active_machine_id = self._application.getPreferences().getValue("cura/active_machine")
@ -171,10 +172,9 @@ class MachineManager(QObject):
self._printer_output_devices.append(printer_output_device)
self.outputDevicesChanged.emit()
self.printerConnectedStatusChanged.emit()
@pyqtProperty(QObject, notify = currentConfigurationChanged)
def currentConfiguration(self) -> ConfigurationModel:
def currentConfiguration(self) -> PrinterConfigurationModel:
return self._current_printer_configuration
def _onCurrentConfigurationChanged(self) -> None:
@ -205,7 +205,7 @@ class MachineManager(QObject):
self.currentConfigurationChanged.emit()
@pyqtSlot(QObject, result = bool)
def matchesConfiguration(self, configuration: ConfigurationModel) -> bool:
def matchesConfiguration(self, configuration: PrinterConfigurationModel) -> bool:
return self._current_printer_configuration == configuration
@pyqtProperty("QVariantList", notify = outputDevicesChanged)
@ -386,9 +386,17 @@ class MachineManager(QObject):
return machine
return None
@pyqtSlot(str)
@pyqtSlot(str, str)
def addMachine(self, name: str, definition_id: str) -> None:
new_stack = CuraStackBuilder.createMachine(name, definition_id)
def addMachine(self, definition_id: str, name: Optional[str] = None) -> None:
if name is None:
definitions = CuraContainerRegistry.getInstance().findDefinitionContainers(id = definition_id)
if definitions:
name = definitions[0].getName()
else:
name = definition_id
new_stack = CuraStackBuilder.createMachine(cast(str, name), definition_id)
if new_stack:
# Instead of setting the global container stack here, we set the active machine and so the signals are emitted
self.setActiveMachine(new_stack.getId())
@ -1367,7 +1375,7 @@ class MachineManager(QObject):
self.setActiveMachine(new_machine.getId())
@pyqtSlot(QObject)
def applyRemoteConfiguration(self, configuration: ConfigurationModel) -> None:
def applyRemoteConfiguration(self, configuration: PrinterConfigurationModel) -> None:
if self._global_container_stack is None:
return
self.blurSettings.emit()
@ -1650,3 +1658,10 @@ class MachineManager(QObject):
abbr_machine += stripped_word
return abbr_machine
def getMachineTypeNameFromId(self, machine_type_id: str) -> str:
machine_type_name = ""
results = self._container_registry.findDefinitionContainersMetadata(id = machine_type_id)
if results:
machine_type_name = results[0]["name"]
return machine_type_name

View file

@ -34,7 +34,7 @@ class PerObjectContainerStack(CuraContainerStack):
if limit_to_extruder is not None:
limit_to_extruder = str(limit_to_extruder)
# if this stack has the limit_to_extruder "not overriden", use the original limit_to_extruder as the current
# if this stack has the limit_to_extruder "not overridden", use the original limit_to_extruder as the current
# limit_to_extruder, so the values retrieved will be from the perspective of the original limit_to_extruder
# stack.
if limit_to_extruder == "-1":
@ -42,7 +42,7 @@ class PerObjectContainerStack(CuraContainerStack):
limit_to_extruder = context.context["original_limit_to_extruder"]
if limit_to_extruder is not None and limit_to_extruder != "-1" and limit_to_extruder in global_stack.extruders:
# set the original limit_to_extruder if this is the first stack that has a non-overriden limit_to_extruder
# set the original limit_to_extruder if this is the first stack that has a non-overridden limit_to_extruder
if "original_limit_to_extruder" not in context.context:
context.context["original_limit_to_extruder"] = limit_to_extruder

View file

@ -41,6 +41,22 @@ empty_quality_changes_container.setMetaDataEntry("type", "quality_changes")
empty_quality_changes_container.setMetaDataEntry("quality_type", "not_supported")
# All empty container IDs set
ALL_EMPTY_CONTAINER_ID_SET = {
EMPTY_CONTAINER_ID,
EMPTY_DEFINITION_CHANGES_CONTAINER_ID,
EMPTY_VARIANT_CONTAINER_ID,
EMPTY_MATERIAL_CONTAINER_ID,
EMPTY_QUALITY_CONTAINER_ID,
EMPTY_QUALITY_CHANGES_CONTAINER_ID,
}
# Convenience function to check if a container ID represents an empty container.
def isEmptyContainer(container_id: str) -> bool:
return container_id in ALL_EMPTY_CONTAINER_ID_SET
__all__ = ["EMPTY_CONTAINER_ID",
"empty_container", # For convenience
"EMPTY_DEFINITION_CHANGES_CONTAINER_ID",
@ -52,5 +68,7 @@ __all__ = ["EMPTY_CONTAINER_ID",
"EMPTY_QUALITY_CHANGES_CONTAINER_ID",
"empty_quality_changes_container",
"EMPTY_QUALITY_CONTAINER_ID",
"empty_quality_container"
"empty_quality_container",
"ALL_EMPTY_CONTAINER_ID_SET",
"isEmptyContainer",
]

View file

@ -1,29 +1,32 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtProperty, QUrl
from UM.Stage import Stage
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
# to indicate this.
# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific
# buttons and elements. This component will be drawn over the bar & main component.
# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest
# of the screen.
class CuraStage(Stage):
def __init__(self, parent = None) -> None:
super().__init__(parent)
@pyqtProperty(str, constant = True)
def stageId(self) -> str:
return self.getPluginId()
@pyqtProperty(QUrl, constant = True)
def mainComponent(self) -> QUrl:
return self.getDisplayComponent("main")
@pyqtProperty(QUrl, constant = True)
def stageMenuComponent(self) -> QUrl:
return self.getDisplayComponent("menu")
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtProperty, QUrl
from UM.Stage import Stage
# Since Cura has a few pre-defined "space claims" for the locations of certain components, we've provided some structure
# to indicate this.
# * The StageMenuComponent is the horizontal area below the stage bar. This should be used to show stage specific
# buttons and elements. This component will be drawn over the bar & main component.
# * The MainComponent is the component that will be drawn starting from the bottom of the stageBar and fills the rest
# of the screen.
class CuraStage(Stage):
def __init__(self, parent = None) -> None:
super().__init__(parent)
@pyqtProperty(str, constant = True)
def stageId(self) -> str:
return self.getPluginId()
@pyqtProperty(QUrl, constant = True)
def mainComponent(self) -> QUrl:
return self.getDisplayComponent("main")
@pyqtProperty(QUrl, constant = True)
def stageMenuComponent(self) -> QUrl:
return self.getDisplayComponent("menu")
__all__ = ["CuraStage"]

View file

@ -1,2 +0,0 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.

View file

@ -12,7 +12,7 @@ from UM.PluginRegistry import PluginRegistry # So MachineAction can be added as
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
from cura.Settings.GlobalStack import GlobalStack
from .MachineAction import MachineAction
from cura.MachineAction import MachineAction
## Raised when trying to add an unknown machine action as a required action
@ -136,7 +136,7 @@ class MachineActionManager(QObject):
# action multiple times).
# \param definition_id The ID of the definition that you want to get the "on added" actions for.
# \returns List of actions.
@pyqtSlot(str, result="QVariantList")
@pyqtSlot(str, result = "QVariantList")
def getFirstStartActions(self, definition_id: str) -> List["MachineAction"]:
if definition_id in self._first_start_actions:
return self._first_start_actions[definition_id]

View file

@ -0,0 +1,82 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import QObject, pyqtSlot
from UM.i18n import i18nCatalog
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
#
# This manager provides (convenience) functions to the Machine Settings Dialog QML to update certain machine settings.
#
class MachineSettingsManager(QObject):
def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
self._i18n_catalog = i18nCatalog("cura")
self._application = application
# Force rebuilding the build volume by reloading the global container stack. This is a bit of a hack, but it seems
# quite enough.
@pyqtSlot()
def forceUpdate(self) -> None:
self._application.getMachineManager().globalContainerChanged.emit()
# Function for the Machine Settings panel (QML) to update the compatible material diameter after a user has changed
# an extruder's compatible material diameter. This ensures that after the modification, changes can be notified
# and updated right away.
@pyqtSlot(int)
def updateMaterialForDiameter(self, extruder_position: int) -> None:
# Updates the material container to a material that matches the material diameter set for the printer
self._application.getMachineManager().updateMaterialWithVariant(str(extruder_position))
@pyqtSlot(int)
def setMachineExtruderCount(self, extruder_count: int) -> None:
# Note: this method was in this class before, but since it's quite generic and other plugins also need it
# it was moved to the machine manager instead. Now this method just calls the machine manager.
self._application.getMachineManager().setActiveMachineExtruderCount(extruder_count)
# Function for the Machine Settings panel (QML) to update after the usre changes "Number of Extruders".
#
# fieldOfView: The Ultimaker 2 family (not 2+) does not have materials in Cura by default, because the material is
# to be set on the printer. But when switching to Marlin flavor, the printer firmware can not change/insert material
# settings on the fly so they need to be configured in Cura. So when switching between gcode flavors, materials may
# need to be enabled/disabled.
@pyqtSlot()
def updateHasMaterialsMetadata(self):
machine_manager = self._application.getMachineManager()
material_manager = self._application.getMaterialManager()
global_stack = machine_manager.activeMachine
definition = global_stack.definition
if definition.getProperty("machine_gcode_flavor", "value") != "UltiGCode" or definition.getMetaDataEntry(
"has_materials", False):
# In other words: only continue for the UM2 (extended), but not for the UM2+
return
extruder_positions = list(global_stack.extruders.keys())
has_materials = global_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
material_node = None
if has_materials:
global_stack.setMetaDataEntry("has_materials", True)
else:
# The metadata entry is stored in an ini, and ini files are parsed as strings only.
# Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
if "has_materials" in global_stack.getMetaData():
global_stack.removeMetaDataEntry("has_materials")
# set materials
for position in extruder_positions:
if has_materials:
material_node = material_manager.getDefaultMaterial(global_stack, position, None)
machine_manager.setMaterial(position, material_node)
self.forceUpdate()

View file

@ -1,6 +1,9 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from collections import defaultdict
from typing import Dict
from PyQt5.QtCore import QTimer
from UM.Application import Application
@ -10,14 +13,13 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Scene.SceneNode import SceneNode
from UM.Scene.Selection import Selection
from UM.i18n import i18nCatalog
from collections import defaultdict
catalog = i18nCatalog("cura")
## Keep track of all objects in the project
class ObjectsModel(ListModel):
def __init__(self):
def __init__(self) -> None:
super().__init__()
Application.getInstance().getController().getScene().sceneChanged.connect(self._updateSceneDelayed)
@ -30,31 +32,33 @@ class ObjectsModel(ListModel):
self._build_plate_number = -1
def setActiveBuildPlate(self, nr):
def setActiveBuildPlate(self, nr: int) -> None:
if self._build_plate_number != nr:
self._build_plate_number = nr
self._update()
def _updateSceneDelayed(self, source):
def _updateSceneDelayed(self, source) -> None:
if not isinstance(source, Camera):
self._update_timer.start()
def _updateDelayed(self, *args):
def _updateDelayed(self, *args) -> None:
self._update_timer.start()
def _update(self, *args):
def _update(self, *args) -> None:
nodes = []
filter_current_build_plate = Application.getInstance().getPreferences().getValue("view/filter_current_build_plate")
active_build_plate_number = self._build_plate_number
group_nr = 1
name_count_dict = defaultdict(int)
name_count_dict = defaultdict(int) # type: Dict[str, int]
for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()): # type: ignore
if not isinstance(node, SceneNode):
continue
if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
continue
if node.getParent() and node.getParent().callDecoration("isGroup"):
parent = node.getParent()
if parent and parent.callDecoration("isGroup"):
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
if not node.callDecoration("isSliceable") and not node.callDecoration("isGroup"):
continue
@ -70,7 +74,7 @@ class ObjectsModel(ListModel):
group_nr += 1
if hasattr(node, "isOutsideBuildArea"):
is_outside_build_area = node.isOutsideBuildArea()
is_outside_build_area = node.isOutsideBuildArea() # type: ignore
else:
is_outside_build_area = False

View file

@ -5,8 +5,7 @@ import json
import math
import os
import unicodedata
import re # To create abbreviations for printer names.
from typing import Dict, List, Optional
from typing import Dict, List, Optional, TYPE_CHECKING
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
@ -16,8 +15,6 @@ from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication

69
cura/UI/TextManager.py Normal file
View file

@ -0,0 +1,69 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import collections
from typing import Optional, Dict, List, cast
from PyQt5.QtCore import QObject, pyqtSlot
from UM.Resources import Resources
from UM.Version import Version
#
# This manager provides means to load texts to QML.
#
class TextManager(QObject):
def __init__(self, parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
self._change_log_text = ""
@pyqtSlot(result = str)
def getChangeLogText(self) -> str:
if not self._change_log_text:
self._change_log_text = self._loadChangeLogText()
return self._change_log_text
def _loadChangeLogText(self) -> str:
# Load change log texts and organize them with a dict
file_path = Resources.getPath(Resources.Texts, "change_log.txt")
change_logs_dict = {} # type: Dict[Version, Dict[str, List[str]]]
with open(file_path, "r", encoding = "utf-8") as f:
open_version = None # type: Optional[Version]
open_header = "" # Initialise to an empty header in case there is no "*" in the first line of the changelog
for line in f:
line = line.replace("\n", "")
if "[" in line and "]" in line:
line = line.replace("[", "")
line = line.replace("]", "")
open_version = Version(line)
if open_version > Version([14, 99, 99]): # Bit of a hack: We released the 15.x.x versions before 2.x
open_version = Version([0, open_version.getMinor(), open_version.getRevision(), open_version.getPostfixVersion()])
open_header = ""
change_logs_dict[open_version] = collections.OrderedDict()
elif line.startswith("*"):
open_header = line.replace("*", "")
change_logs_dict[cast(Version, open_version)][open_header] = []
elif line != "":
if open_header not in change_logs_dict[cast(Version, open_version)]:
change_logs_dict[cast(Version, open_version)][open_header] = []
change_logs_dict[cast(Version, open_version)][open_header].append(line)
# Format changelog text
content = ""
for version in sorted(change_logs_dict.keys(), reverse = True):
text_version = version
if version < Version([1, 0, 0]): # Bit of a hack: We released the 15.x.x versions before 2.x
text_version = Version([15, version.getMinor(), version.getRevision(), version.getPostfixVersion()])
content += "<h1>" + str(text_version) + "</h1><br>"
content += ""
for change in change_logs_dict[version]:
if str(change) != "":
content += "<b>" + str(change) + "</b><br>"
for line in change_logs_dict[version][change]:
content += str(line) + "<br>"
content += "<br>"
return content

View file

@ -0,0 +1,230 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from collections import deque
import os
from typing import TYPE_CHECKING, Optional, List, Dict, Any
from PyQt5.QtCore import QUrl, Qt, pyqtSlot, pyqtProperty, pyqtSignal
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel
from UM.Resources import Resources
if TYPE_CHECKING:
from PyQt5.QtCore import QObject
from cura.CuraApplication import CuraApplication
#
# This is the Qt ListModel that contains all welcome pages data. Each page is a page that can be shown as a step in the
# welcome wizard dialog. Each item in this ListModel represents a page, which contains the following fields:
#
# - id : A unique page_id which can be used in function goToPage(page_id)
# - page_url : The QUrl to the QML file that contains the content of this page
# - next_page_id : (OPTIONAL) The next page ID to go to when this page finished. This is optional. If this is not
# provided, it will go to the page with the current index + 1
# - should_show_function : (OPTIONAL) An optional function that returns True/False indicating if this page should be
# shown. By default all pages should be shown. If a function returns False, that page will
# be skipped and its next page will be shown.
#
# Note that in any case, a page that has its "should_show_function" == False will ALWAYS be skipped.
#
class WelcomePagesModel(ListModel):
IdRole = Qt.UserRole + 1 # Page ID
PageUrlRole = Qt.UserRole + 2 # URL to the page's QML file
NextPageIdRole = Qt.UserRole + 3 # The next page ID it should go to
def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.PageUrlRole, "page_url")
self.addRoleName(self.NextPageIdRole, "next_page_id")
self._application = application
self._pages = [] # type: List[Dict[str, Any]]
self._current_page_index = 0
# Store all the previous page indices so it can go back.
self._previous_page_indices_stack = deque() # type: deque
allFinished = pyqtSignal() # emitted when all steps have been finished
currentPageIndexChanged = pyqtSignal()
@pyqtProperty(int, notify = currentPageIndexChanged)
def currentPageIndex(self) -> int:
return self._current_page_index
# Returns a float number in [0, 1] which indicates the current progress.
@pyqtProperty(float, notify = currentPageIndexChanged)
def currentProgress(self) -> float:
if len(self._items) == 0:
return 0
else:
return self._current_page_index / len(self._items)
# Indicates if the current page is the last page.
@pyqtProperty(bool, notify = currentPageIndexChanged)
def isCurrentPageLast(self) -> bool:
return self._current_page_index == len(self._items) - 1
def _setCurrentPageIndex(self, page_index: int) -> None:
if page_index != self._current_page_index:
self._previous_page_indices_stack.append(self._current_page_index)
self._current_page_index = page_index
self.currentPageIndexChanged.emit()
# Ends the Welcome-Pages. Put as a separate function for cases like the 'decline' in the User-Agreement.
@pyqtSlot()
def atEnd(self) -> None:
self.allFinished.emit()
self.resetState()
# Goes to the next page.
# If "from_index" is given, it will look for the next page to show starting from the "from_index" page instead of
# the "self._current_page_index".
@pyqtSlot()
def goToNextPage(self, from_index: Optional[int] = None) -> None:
# Look for the next page that should be shown
current_index = self._current_page_index if from_index is None else from_index
while True:
page_item = self._items[current_index]
# Check if there's a "next_page_id" assigned. If so, go to that page. Otherwise, go to the page with the
# current index + 1.
next_page_id = page_item.get("next_page_id")
next_page_index = current_index + 1
if next_page_id:
idx = self.getPageIndexById(next_page_id)
if idx is None:
# FIXME: If we cannot find the next page, we cannot do anything here.
Logger.log("e", "Cannot find page with ID [%s]", next_page_id)
return
next_page_index = idx
# If we have reached the last page, emit allFinished signal and reset.
if next_page_index == len(self._items):
self.atEnd()
return
# Check if the this page should be shown (default yes), if not, keep looking for the next one.
next_page_item = self.getItem(next_page_index)
if self._shouldPageBeShown(next_page_index):
break
Logger.log("d", "Page [%s] should not be displayed, look for the next page.", next_page_item["id"])
current_index = next_page_index
# Move to the next page
self._setCurrentPageIndex(next_page_index)
# Goes to the previous page. If there's no previous page, do nothing.
@pyqtSlot()
def goToPreviousPage(self) -> None:
if len(self._previous_page_indices_stack) == 0:
Logger.log("i", "No previous page, do nothing")
return
previous_page_index = self._previous_page_indices_stack.pop()
self._current_page_index = previous_page_index
self.currentPageIndexChanged.emit()
# Sets the current page to the given page ID. If the page ID is not found, do nothing.
@pyqtSlot(str)
def goToPage(self, page_id: str) -> None:
page_index = self.getPageIndexById(page_id)
if page_index is None:
# FIXME: If we cannot find the next page, we cannot do anything here.
Logger.log("e", "Cannot find page with ID [%s]", page_index)
return
if self._shouldPageBeShown(page_index):
# Move to that page if it should be shown
self._setCurrentPageIndex(page_index)
else:
# Find the next page to show starting from the "page_index"
self.goToNextPage(from_index = page_index)
# Checks if the page with the given index should be shown by calling the "should_show_function" associated with it.
# If the function is not present, returns True (show page by default).
def _shouldPageBeShown(self, page_index: int) -> bool:
next_page_item = self.getItem(page_index)
should_show_function = next_page_item.get("should_show_function", lambda: True)
return should_show_function()
# Resets the state of the WelcomePagesModel. This functions does the following:
# - Resets current_page_index to 0
# - Clears the previous page indices stack
@pyqtSlot()
def resetState(self) -> None:
self._current_page_index = 0
self._previous_page_indices_stack.clear()
self.currentPageIndexChanged.emit()
# Gets the page index with the given page ID. If the page ID doesn't exist, returns None.
def getPageIndexById(self, page_id: str) -> Optional[int]:
page_idx = None
for idx, page_item in enumerate(self._items):
if page_item["id"] == page_id:
page_idx = idx
break
return page_idx
# Convenience function to get QUrl path to pages that's located in "resources/qml/WelcomePages".
def _getBuiltinWelcomePagePath(self, page_filename: str) -> "QUrl":
from cura.CuraApplication import CuraApplication
return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles,
os.path.join("WelcomePages", page_filename)))
def initialize(self) -> None:
# Add default welcome pages
self._pages.append({"id": "welcome",
"page_url": self._getBuiltinWelcomePagePath("WelcomeContent.qml"),
})
self._pages.append({"id": "user_agreement",
"page_url": self._getBuiltinWelcomePagePath("UserAgreementContent.qml"),
})
self._pages.append({"id": "whats_new",
"page_url": self._getBuiltinWelcomePagePath("WhatsNewContent.qml"),
})
self._pages.append({"id": "data_collections",
"page_url": self._getBuiltinWelcomePagePath("DataCollectionsContent.qml"),
})
self._pages.append({"id": "add_network_or_local_printer",
"page_url": self._getBuiltinWelcomePagePath("AddNetworkOrLocalPrinterContent.qml"),
"next_page_id": "machine_actions",
})
self._pages.append({"id": "add_printer_by_ip",
"page_url": self._getBuiltinWelcomePagePath("AddPrinterByIpContent.qml"),
"next_page_id": "machine_actions",
})
self._pages.append({"id": "machine_actions",
"page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"),
"next_page_id": "cloud",
"should_show_function": self.shouldShowMachineActions,
})
self._pages.append({"id": "cloud",
"page_url": self._getBuiltinWelcomePagePath("CloudContent.qml"),
})
self.setItems(self._pages)
# Indicates if the machine action panel should be shown by checking if there's any first start machine actions
# available.
def shouldShowMachineActions(self) -> bool:
global_stack = self._application.getMachineManager().activeMachine
if global_stack is None:
return False
definition_id = global_stack.definition.getId()
first_start_actions = self._application.getMachineActionManager().getFirstStartActions(definition_id)
return len([action for action in first_start_actions if action.needsUserInteraction()]) > 0
def addPage(self) -> None:
pass
__all__ = ["WelcomePagesModel"]

0
cura/UI/__init__.py Normal file
View file

View file

@ -259,7 +259,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
quality_name = ""
custom_quality_name = ""
num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
num_settings_overridden_by_quality_changes = 0 # How many settings are changed by the quality changes
num_user_settings = 0
quality_changes_conflict = False
@ -297,7 +297,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
custom_quality_name = parser["general"]["name"]
values = parser["values"] if parser.has_section("values") else dict()
num_settings_overriden_by_quality_changes += len(values)
num_settings_overridden_by_quality_changes += len(values)
# Check if quality changes already exists.
quality_changes = self._container_registry.findInstanceContainers(name = custom_quality_name,
type = "quality_changes")
@ -515,7 +515,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._dialog.setNumVisibleSettings(num_visible_settings)
self._dialog.setQualityName(quality_name)
self._dialog.setQualityType(quality_type)
self._dialog.setNumSettingsOverridenByQualityChanges(num_settings_overriden_by_quality_changes)
self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes)
self._dialog.setNumUserSettings(num_user_settings)
self._dialog.setActiveMode(active_mode)
self._dialog.setMachineName(machine_name)
@ -820,6 +820,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
global_stack, extruder_stack)
container_info.container = container
container.setDirty(True)
self._container_registry.addContainer(container)
for key, value in container_info.parser["values"].items():
container_info.container.setProperty(key, "value", value)

View file

@ -41,7 +41,7 @@ class WorkspaceDialog(QObject):
self._num_user_settings = 0
self._active_mode = ""
self._quality_name = ""
self._num_settings_overriden_by_quality_changes = 0
self._num_settings_overridden_by_quality_changes = 0
self._quality_type = ""
self._machine_name = ""
self._machine_type = ""
@ -151,11 +151,11 @@ class WorkspaceDialog(QObject):
@pyqtProperty(int, notify=numSettingsOverridenByQualityChangesChanged)
def numSettingsOverridenByQualityChanges(self):
return self._num_settings_overriden_by_quality_changes
return self._num_settings_overridden_by_quality_changes
def setNumSettingsOverridenByQualityChanges(self, num_settings_overriden_by_quality_changes):
self._num_settings_overriden_by_quality_changes = num_settings_overriden_by_quality_changes
self.numSettingsOverridenByQualityChangesChanged.emit()
def setNumSettingsOverriddenByQualityChanges(self, num_settings_overridden_by_quality_changes):
self._num_settings_overridden_by_quality_changes = num_settings_overridden_by_quality_changes
self.numSettingsOverriddenByQualityChangesChanged.emit()
@pyqtProperty(str, notify=qualityNameChanged)
def qualityName(self):

View file

@ -1,20 +1,20 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os.path
from PyQt5.QtCore import QObject
from UM.i18n import i18nCatalog
from UM.Extension import Extension
from UM.Application import Application
from UM.PluginRegistry import PluginRegistry
from UM.Version import Version
from PyQt5.QtCore import pyqtSlot, QObject
import os.path
import collections
catalog = i18nCatalog("cura")
class ChangeLog(Extension, QObject,):
class ChangeLog(Extension, QObject):
def __init__(self, parent = None):
QObject.__init__(self, parent)
Extension.__init__(self)
@ -26,55 +26,11 @@ class ChangeLog(Extension, QObject,):
else:
self._current_app_version = None
self._change_logs = None
Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
Application.getInstance().getPreferences().addPreference("general/latest_version_changelog_shown", "2.0.0") #First version of CURA with uranium
self.setMenuName(catalog.i18nc("@item:inmenu", "Changelog"))
self.addMenuItem(catalog.i18nc("@item:inmenu", "Show Changelog"), self.showChangelog)
def getChangeLogs(self):
if not self._change_logs:
self.loadChangeLogs()
return self._change_logs
@pyqtSlot(result = str)
def getChangeLogString(self):
logs = self.getChangeLogs()
result = ""
for version in logs:
result += "<h1>" + str(version) + "</h1><br>"
result += ""
for change in logs[version]:
if str(change) != "":
result += "<b>" + str(change) + "</b><br>"
for line in logs[version][change]:
result += str(line) + "<br>"
result += "<br>"
pass
return result
def loadChangeLogs(self):
self._change_logs = collections.OrderedDict()
with open(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.txt"), "r", encoding = "utf-8") as f:
open_version = None
open_header = "" # Initialise to an empty header in case there is no "*" in the first line of the changelog
for line in f:
line = line.replace("\n","")
if "[" in line and "]" in line:
line = line.replace("[","")
line = line.replace("]","")
open_version = Version(line)
open_header = ""
self._change_logs[open_version] = collections.OrderedDict()
elif line.startswith("*"):
open_header = line.replace("*","")
self._change_logs[open_version][open_header] = []
elif line != "":
if open_header not in self._change_logs[open_version]:
self._change_logs[open_version][open_header] = []
self._change_logs[open_version][open_header].append(line)
def _onEngineCreated(self):
if not self._current_app_version:
return #We're on dev branch.

View file

@ -6,7 +6,9 @@ import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
import UM 1.1 as UM
import UM 1.3 as UM
import Cura 1.0 as Cura
UM.Dialog
{
@ -20,7 +22,7 @@ UM.Dialog
TextArea
{
anchors.fill: parent
text: manager.getChangeLogString()
text: CuraApplication.getTextManager().getChangeLogText()
readOnly: true;
textFormat: TextEdit.RichText
}

View file

@ -10,20 +10,17 @@ from time import time
from typing import Any, cast, Dict, List, Optional, Set, TYPE_CHECKING
from UM.Backend.Backend import Backend, BackendState
from UM.Scene.Camera import Camera
from UM.Scene.SceneNode import SceneNode
from UM.Signal import Signal
from UM.Logger import Logger
from UM.Message import Message
from UM.PluginRegistry import PluginRegistry
from UM.Resources import Resources
from UM.Platform import Platform
from UM.Qt.Duration import DurationFormat
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Settings.Interfaces import DefinitionContainerInterface
from UM.Settings.SettingInstance import SettingInstance #For typing.
from UM.Tool import Tool #For typing.
from UM.Mesh.MeshData import MeshData #For typing.
from cura.CuraApplication import CuraApplication
from cura.Settings.ExtruderManager import ExtruderManager

View file

@ -24,7 +24,7 @@ from cura import LayerPolygon
import numpy
from time import time
from cura.Settings.ExtrudersModel import ExtrudersModel
from cura.Machines.Models.ExtrudersModel import ExtrudersModel
catalog = i18nCatalog("cura")

View file

@ -1,16 +1,21 @@
# Copyright (c) 2017 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtProperty, pyqtSignal
from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import pyqtProperty
import UM.i18n
from UM.FlameProfiler import pyqtSlot
from UM.Application import Application
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.DefinitionContainer import DefinitionContainer
from cura.MachineAction import MachineAction
from cura.Settings.CuraStackBuilder import CuraStackBuilder
from cura.Settings.cura_empty_instance_containers import isEmptyContainer
if TYPE_CHECKING:
from PyQt5.QtCore import QObject
catalog = UM.i18n.i18nCatalog("cura")
@ -18,139 +23,102 @@ catalog = UM.i18n.i18nCatalog("cura")
## This action allows for certain settings that are "machine only") to be modified.
# It automatically detects machine definitions that it knows how to change and attaches itself to those.
class MachineSettingsAction(MachineAction):
def __init__(self, parent = None):
def __init__(self, parent: Optional["QObject"] = None) -> None:
super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings"))
self._qml_url = "MachineSettingsAction.qml"
self._application = Application.getInstance()
self._global_container_stack = None
from cura.CuraApplication import CuraApplication
self._application = CuraApplication.getInstance()
from cura.Settings.CuraContainerStack import _ContainerIndexes
self._container_index = _ContainerIndexes.DefinitionChanges
self._store_container_index = _ContainerIndexes.DefinitionChanges
self._container_registry = ContainerRegistry.getInstance()
self._container_registry.containerAdded.connect(self._onContainerAdded)
self._container_registry.containerRemoved.connect(self._onContainerRemoved)
self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
# The machine settings dialog blocks auto-slicing when it's shown, and re-enables it when it's finished.
self._backend = self._application.getBackend()
self.onFinished.connect(self._onFinished)
self._empty_definition_container_id_list = []
def _isEmptyDefinitionChanges(self, container_id: str):
if not self._empty_definition_container_id_list:
self._empty_definition_container_id_list = [self._application.empty_container.getId(),
self._application.empty_definition_changes_container.getId()]
return container_id in self._empty_definition_container_id_list
# Which container index in a stack to store machine setting changes.
@pyqtProperty(int, constant = True)
def storeContainerIndex(self) -> int:
return self._store_container_index
def _onContainerAdded(self, container):
# Add this action as a supported action to all machine definitions
if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine":
self._application.getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
def _onContainerRemoved(self, container):
# Remove definition_changes containers when a stack is removed
if container.getMetaDataEntry("type") in ["machine", "extruder_train"]:
definition_changes_id = container.definitionChanges.getId()
if self._isEmptyDefinitionChanges(definition_changes_id):
return
def _reset(self):
if not self._global_container_stack:
global_stack = self._application.getMachineManager().activeMachine
if not global_stack:
return
# Make sure there is a definition_changes container to store the machine settings
definition_changes_id = self._global_container_stack.definitionChanges.getId()
if self._isEmptyDefinitionChanges(definition_changes_id):
CuraStackBuilder.createDefinitionChangesContainer(self._global_container_stack,
self._global_container_stack.getName() + "_settings")
# Notify the UI in which container to store the machine settings data
from cura.Settings.CuraContainerStack import _ContainerIndexes
container_index = _ContainerIndexes.DefinitionChanges
if container_index != self._container_index:
self._container_index = container_index
self.containerIndexChanged.emit()
definition_changes_id = global_stack.definitionChanges.getId()
if isEmptyContainer(definition_changes_id):
CuraStackBuilder.createDefinitionChangesContainer(global_stack,
global_stack.getName() + "_settings")
# Disable auto-slicing while the MachineAction is showing
if self._backend: # This sometimes triggers before backend is loaded.
self._backend.disableTimer()
@pyqtSlot()
def onFinishAction(self):
# Restore autoslicing when the machineaction is dismissed
def _onFinished(self):
# Restore auto-slicing when the machine action is dismissed
if self._backend and self._backend.determineAutoSlicing():
self._backend.enableTimer()
self._backend.tickle()
containerIndexChanged = pyqtSignal()
@pyqtProperty(int, notify = containerIndexChanged)
def containerIndex(self):
return self._container_index
def _onGlobalContainerChanged(self):
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
# This additional emit is needed because we cannot connect a UM.Signal directly to a pyqtSignal
self.globalContainerChanged.emit()
globalContainerChanged = pyqtSignal()
@pyqtProperty(int, notify = globalContainerChanged)
def definedExtruderCount(self):
if not self._global_container_stack:
return 0
return len(self._global_container_stack.getMetaDataEntry("machine_extruder_trains"))
@pyqtSlot(int)
def setMachineExtruderCount(self, extruder_count):
def setMachineExtruderCount(self, extruder_count: int) -> None:
# Note: this method was in this class before, but since it's quite generic and other plugins also need it
# it was moved to the machine manager instead. Now this method just calls the machine manager.
self._application.getMachineManager().setActiveMachineExtruderCount(extruder_count)
@pyqtSlot()
def forceUpdate(self):
def forceUpdate(self) -> None:
# Force rebuilding the build volume by reloading the global container stack.
# This is a bit of a hack, but it seems quick enough.
self._application.globalContainerStackChanged.emit()
self._application.getMachineManager().globalContainerChanged.emit()
@pyqtSlot()
def updateHasMaterialsMetadata(self):
def updateHasMaterialsMetadata(self) -> None:
global_stack = self._application.getMachineManager().activeMachine
# Updates the has_materials metadata flag after switching gcode flavor
if not self._global_container_stack:
if not global_stack:
return
definition = self._global_container_stack.getBottom()
definition = global_stack.getDefinition()
if definition.getProperty("machine_gcode_flavor", "value") != "UltiGCode" or definition.getMetaDataEntry("has_materials", False):
# In other words: only continue for the UM2 (extended), but not for the UM2+
return
machine_manager = self._application.getMachineManager()
material_manager = self._application.getMaterialManager()
extruder_positions = list(self._global_container_stack.extruders.keys())
has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
extruder_positions = list(global_stack.extruders.keys())
has_materials = global_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
material_node = None
if has_materials:
self._global_container_stack.setMetaDataEntry("has_materials", True)
global_stack.setMetaDataEntry("has_materials", True)
else:
# The metadata entry is stored in an ini, and ini files are parsed as strings only.
# Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
if "has_materials" in self._global_container_stack.getMetaData():
self._global_container_stack.removeMetaDataEntry("has_materials")
if "has_materials" in global_stack.getMetaData():
global_stack.removeMetaDataEntry("has_materials")
# set materials
for position in extruder_positions:
if has_materials:
material_node = material_manager.getDefaultMaterial(self._global_container_stack, position, None)
material_node = material_manager.getDefaultMaterial(global_stack, position, None)
machine_manager.setMaterial(position, material_node)
self._application.globalContainerStackChanged.emit()
@pyqtSlot(int)
def updateMaterialForDiameter(self, extruder_position: int):
def updateMaterialForDiameter(self, extruder_position: int) -> None:
# Updates the material container to a material that matches the material diameter set for the printer
self._application.getMachineManager().updateMaterialWithVariant(str(extruder_position))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,180 @@
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.3 as UM
import Cura 1.1 as Cura
//
// This component contains the content for the "Welcome" page of the welcome on-boarding process.
//
Item
{
id: base
UM.I18nCatalog { id: catalog; name: "cura" }
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
property int labelWidth: 180
property int controlWidth: UM.Theme.getSize("setting_control").width * 3 / 4
property var labelFont: UM.Theme.getFont("medium")
property int columnWidth: (parent.width - 2 * UM.Theme.getSize("default_margin").width) / 2
property int columnSpacing: 3
property int propertyStoreIndex: manager.storeContainerIndex // definition_changes
property string extruderStackId: ""
property int extruderPosition: 0
property var forceUpdateFunction: manager.forceUpdate
function updateMaterialDiameter()
{
manager.updateMaterialForDiameter(extruderPosition)
}
Item
{
id: upperBlock
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: UM.Theme.getSize("default_margin").width
height: childrenRect.height
// =======================================
// Left-side column "Nozzle Settings"
// =======================================
Column
{
anchors.top: parent.top
anchors.left: parent.left
width: parent.width * 2 / 3
spacing: base.columnSpacing
Label // Title Label
{
text: catalog.i18nc("@title:label", "Nozzle Settings")
font: UM.Theme.getFont("medium_bold")
renderType: Text.NativeRendering
}
Cura.NumericTextFieldWithUnit // "Nozzle size"
{
id: extruderNozzleSizeField
visible: !Cura.MachineManager.hasVariants
containerStackId: base.extruderStackId
settingKey: "machine_nozzle_size"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Nozzle size")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.NumericTextFieldWithUnit // "Compatible material diameter"
{
id: extruderCompatibleMaterialDiameterField
containerStackId: base.extruderStackId
settingKey: "material_diameter"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Compatible material diameter")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
// Other modules won't automatically respond after the user changes the value, so we need to force it.
afterOnEditingFinishedFunction: updateMaterialDiameter
}
Cura.NumericTextFieldWithUnit // "Nozzle offset X"
{
id: extruderNozzleOffsetXField
containerStackId: base.extruderStackId
settingKey: "machine_nozzle_offset_x"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Nozzle offset X")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.NumericTextFieldWithUnit // "Nozzle offset Y"
{
id: extruderNozzleOffsetYField
containerStackId: base.extruderStackId
settingKey: "machine_nozzle_offset_y"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Nozzle offset Y")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.NumericTextFieldWithUnit // "Cooling Fan Number"
{
id: extruderNozzleCoolingFanNumberField
containerStackId: base.extruderStackId
settingKey: "machine_extruder_cooling_fan_number"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Cooling Fan Number")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: ""
forceUpdateOnChangeFunction: forceUpdateFunction
}
}
}
Item // Extruder Start and End G-code
{
id: lowerBlock
anchors.top: upperBlock.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: UM.Theme.getSize("default_margin").width
Cura.GcodeTextArea // "Extruder Start G-code"
{
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
width: base.columnWidth - UM.Theme.getSize("default_margin").width
labelText: catalog.i18nc("@title:label", "Extruder Start G-code")
containerStackId: base.extruderStackId
settingKey: "machine_extruder_start_code"
settingStoreIndex: propertyStoreIndex
}
Cura.GcodeTextArea // "Extruder End G-code"
{
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
anchors.right: parent.right
width: base.columnWidth - UM.Theme.getSize("default_margin").width
labelText: catalog.i18nc("@title:label", "Extruder End G-code")
containerStackId: base.extruderStackId
settingKey: "machine_extruder_end_code"
settingStoreIndex: propertyStoreIndex
}
}
}

View file

@ -0,0 +1,339 @@
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.3 as UM
import Cura 1.1 as Cura
//
// This the content in the "Printer" tab in the Machine Settings dialog.
//
Item
{
id: base
UM.I18nCatalog { id: catalog; name: "cura" }
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
property int labelWidth: 130
property int controlWidth: UM.Theme.getSize("setting_control").width * 3 / 4
property var labelFont: UM.Theme.getFont("default")
property int columnWidth: (parent.width - 2 * UM.Theme.getSize("default_margin").width) / 2
property int columnSpacing: 3
property int propertyStoreIndex: manager.storeContainerIndex // definition_changes
property string machineStackId: Cura.MachineManager.activeMachineId
property var forceUpdateFunction: manager.forceUpdate
Item
{
id: upperBlock
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: UM.Theme.getSize("default_margin").width
height: childrenRect.height
// =======================================
// Left-side column for "Printer Settings"
// =======================================
Column
{
anchors.top: parent.top
anchors.left: parent.left
width: base.columnWidth
spacing: base.columnSpacing
Label // Title Label
{
text: catalog.i18nc("@title:label", "Printer Settings")
font: UM.Theme.getFont("medium_bold")
renderType: Text.NativeRendering
}
Cura.NumericTextFieldWithUnit // "X (Width)"
{
id: machineXWidthField
containerStackId: machineStackId
settingKey: "machine_width"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "X (Width)")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.NumericTextFieldWithUnit // "Y (Depth)"
{
id: machineYDepthField
containerStackId: machineStackId
settingKey: "machine_depth"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Y (Depth)")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.NumericTextFieldWithUnit // "Z (Height)"
{
id: machineZHeightField
containerStackId: machineStackId
settingKey: "machine_height"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Z (Height)")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.ComboBoxWithOptions // "Build plate shape"
{
id: buildPlateShapeComboBox
containerStackId: machineStackId
settingKey: "machine_shape"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Build plate shape")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.SimpleCheckBox // "Origin at center"
{
id: originAtCenterCheckBox
containerStackId: machineStackId
settingKey: "machine_center_is_zero"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Origin at center")
labelFont: base.labelFont
labelWidth: base.labelWidth
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.SimpleCheckBox // "Heated bed"
{
id: heatedBedCheckBox
containerStackId: machineStackId
settingKey: "machine_heated_bed"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Heated bed")
labelFont: base.labelFont
labelWidth: base.labelWidth
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.ComboBoxWithOptions // "G-code flavor"
{
id: gcodeFlavorComboBox
containerStackId: machineStackId
settingKey: "machine_gcode_flavor"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "G-code flavor")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
forceUpdateOnChangeFunction: forceUpdateFunction
// FIXME(Lipu): better document this.
// This has something to do with UM2 and UM2+ regarding "has_material" and the gcode flavor settings.
// I don't remember exactly what.
afterOnEditingFinishedFunction: manager.updateHasMaterialsMetadata
}
}
// =======================================
// Right-side column for "Printhead Settings"
// =======================================
Column
{
anchors.top: parent.top
anchors.right: parent.right
width: base.columnWidth
spacing: base.columnSpacing
Label // Title Label
{
text: catalog.i18nc("@title:label", "Printhead Settings")
font: UM.Theme.getFont("medium_bold")
renderType: Text.NativeRendering
}
Cura.PrintHeadMinMaxTextField // "X min"
{
id: machineXMinField
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "X min")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
axisName: "x"
axisMinOrMax: "min"
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.PrintHeadMinMaxTextField // "Y min"
{
id: machineYMinField
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Y min")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
axisName: "y"
axisMinOrMax: "min"
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.PrintHeadMinMaxTextField // "X max"
{
id: machineXMaxField
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "X max")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
axisName: "x"
axisMinOrMax: "max"
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.PrintHeadMinMaxTextField // "Y max"
{
id: machineYMaxField
containerStackId: machineStackId
settingKey: "machine_head_with_fans_polygon"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Y max")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
axisName: "y"
axisMinOrMax: "max"
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.NumericTextFieldWithUnit // "Gantry Height"
{
id: machineGantryHeightField
containerStackId: machineStackId
settingKey: "gantry_height"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Gantry Height")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
unitText: catalog.i18nc("@label", "mm")
forceUpdateOnChangeFunction: forceUpdateFunction
}
Cura.ComboBoxWithOptions // "Number of Extruders"
{
id: numberOfExtrudersComboBox
containerStackId: machineStackId
settingKey: "machine_extruder_count"
settingStoreIndex: propertyStoreIndex
labelText: catalog.i18nc("@label", "Number of Extruders")
labelFont: base.labelFont
labelWidth: base.labelWidth
controlWidth: base.controlWidth
forceUpdateOnChangeFunction: forceUpdateFunction
// FIXME(Lipu): better document this.
// This has something to do with UM2 and UM2+ regarding "has_material" and the gcode flavor settings.
// I don't remember exactly what.
afterOnEditingFinishedFunction: manager.updateHasMaterialsMetadata
setValueFunction: manager.setMachineExtruderCount
optionModel: ListModel
{
id: extruderCountModel
Component.onCompleted:
{
extruderCountModel.clear()
for (var i = 1; i <= Cura.MachineManager.activeMachine.maxExtruderCount; i++)
{
// Use String as value. JavaScript only has Number. PropertyProvider.setPropertyValue()
// takes a QVariant as value, and Number gets translated into a float. This will cause problem
// for integer settings such as "Number of Extruders".
extruderCountModel.append({ text: String(i), value: String(i) })
}
}
}
}
}
}
Item // Start and End G-code
{
id: lowerBlock
anchors.top: upperBlock.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: UM.Theme.getSize("default_margin").width
Cura.GcodeTextArea // "Start G-code"
{
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
width: base.columnWidth - UM.Theme.getSize("default_margin").width
labelText: catalog.i18nc("@title:label", "Start G-code")
containerStackId: machineStackId
settingKey: "machine_start_gcode"
settingStoreIndex: propertyStoreIndex
}
Cura.GcodeTextArea // "End G-code"
{
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
anchors.right: parent.right
width: base.columnWidth - UM.Theme.getSize("default_margin").width
labelText: catalog.i18nc("@title:label", "End G-code")
containerStackId: machineStackId
settingKey: "machine_end_gcode"
settingStoreIndex: propertyStoreIndex
}
}
}

View file

@ -2,8 +2,6 @@
# Cura is released under the terms of the LGPLv3 or higher.
import os.path
from UM.Application import Application
from UM.PluginRegistry import PluginRegistry
from UM.Resources import Resources
from cura.Stages.CuraStage import CuraStage

View file

@ -48,20 +48,6 @@ class SliceInfo(QObject, Extension):
def _onAppInitialized(self):
# DO NOT read any preferences values in the constructor because at the time plugins are created, no version
# upgrade has been performed yet because version upgrades are plugins too!
if not self._application.getPreferences().getValue("info/asked_send_slice_info"):
self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymized usage statistics."),
lifetime = 0,
dismissable = False,
title = catalog.i18nc("@info:title", "Collecting Data"))
self.send_slice_info_message.addAction("MoreInfo", name = catalog.i18nc("@action:button", "More info"), icon = None,
description = catalog.i18nc("@action:tooltip", "See more information on what data Cura sends."), button_style = Message.ActionButtonStyle.LINK)
self.send_slice_info_message.addAction("Dismiss", name = catalog.i18nc("@action:button", "Allow"), icon = None,
description = catalog.i18nc("@action:tooltip", "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."))
self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered)
self.send_slice_info_message.show()
if self._more_info_dialog is None:
self._more_info_dialog = self._createDialog("MoreInfoWindow.qml")

View file

@ -50,7 +50,6 @@ class Toolbox(QObject, Extension):
self._request_headers = [] # type: List[Tuple[bytes, bytes]]
self._updateRequestHeader()
self._request_urls = {} # type: Dict[str, QUrl]
self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated
self._old_plugin_ids = set() # type: Set[str]

View file

@ -371,7 +371,7 @@ Cura.MachineAction
Label
{
text: catalog.i18nc("@alabel", "Enter the IP address or hostname of your printer on the network.")
text: catalog.i18nc("@label", "Enter the IP address or hostname of your printer on the network.")
width: parent.width
wrapMode: Text.WordWrap
renderType: Text.NativeRendering

View file

@ -22,7 +22,7 @@ Item
width: childrenRect.width
height: 18 * screenScaleFactor // TODO: Theme!
ProgressBar
UM.ProgressBar
{
id: progressBar
anchors
@ -30,22 +30,6 @@ Item
verticalCenter: parent.verticalCenter
}
value: printJob ? printJob.progress : 0
style: ProgressBarStyle
{
background: Rectangle
{
color: UM.Theme.getColor("monitor_progress_bar_empty")
implicitHeight: visible ? 12 * screenScaleFactor : 0 // TODO: Theme!
implicitWidth: 180 * screenScaleFactor // TODO: Theme!
radius: 2 * screenScaleFactor // TODO: Theme!
}
progress: Rectangle
{
id: progressItem;
color: printJob && printJob.isActive ? UM.Theme.getColor("monitor_progress_bar_fill") : UM.Theme.getColor("monitor_progress_bar_deactive")
radius: 2 * screenScaleFactor // TODO: Theme!
}
}
}
Label
{

View file

@ -18,8 +18,8 @@ from UM.Scene.SceneNode import SceneNode
from cura.CuraApplication import CuraApplication
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutputDevice import ConnectionType
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from .CloudOutputController import CloudOutputController
from ..MeshFormatHandler import MeshFormatHandler

View file

@ -32,8 +32,8 @@ class CloudOutputDeviceManager:
# The translation catalog for this device.
I18N_CATALOG = i18nCatalog("cura")
addedCloudCluster = Signal()
removedCloudCluster = Signal()
addedCloudCluster = Signal(CloudOutputDevice)
removedCloudCluster = Signal(CloudOutputDevice)
def __init__(self) -> None:
# Persistent dict containing the remote clusters for the authenticated user.
@ -86,7 +86,7 @@ class CloudOutputDeviceManager:
removed_cluster.disconnect()
removed_cluster.close()
self._output_device_manager.removeOutputDevice(removed_cluster.key)
self.removedCloudCluster.emit()
self.removedCloudCluster.emit(removed_cluster)
del self._remote_clusters[removed_cluster.key]
# Add an output device for each new remote cluster.
@ -94,7 +94,7 @@ class CloudOutputDeviceManager:
for added_cluster in added_clusters:
device = CloudOutputDevice(self._api, added_cluster)
self._remote_clusters[added_cluster.cluster_id] = device
self.addedCloudCluster.emit()
self.addedCloudCluster.emit(added_cluster)
for device, cluster in updates:
device.clusterData = cluster

View file

@ -2,8 +2,8 @@
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Union, Dict, Optional, Any
from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
from cura.PrinterOutput.Models.ExtruderOutputModel import ExtruderOutputModel
from .CloudClusterPrinterConfigurationMaterial import CloudClusterPrinterConfigurationMaterial
from .BaseCloudModel import BaseCloudModel

View file

@ -2,7 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher.
from typing import List, Optional, Union, Dict, Any
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from ...UM3PrintJobOutputModel import UM3PrintJobOutputModel
from ...ConfigurationChangeModel import ConfigurationChangeModel
from ..CloudOutputController import CloudOutputController
@ -95,9 +95,9 @@ class CloudClusterPrintJobStatus(BaseCloudModel):
return model
## Creates a new configuration model
def _createConfigurationModel(self) -> ConfigurationModel:
def _createConfigurationModel(self) -> PrinterConfigurationModel:
extruders = [extruder.createConfigurationModel() for extruder in self.configuration or ()]
configuration = ConfigurationModel()
configuration = PrinterConfigurationModel()
configuration.setExtruderConfigurations(extruders)
return configuration

View file

@ -2,7 +2,7 @@ from typing import Optional
from UM.Logger import Logger
from cura.CuraApplication import CuraApplication
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
from .BaseCloudModel import BaseCloudModel

View file

@ -3,7 +3,7 @@
from typing import List, Union, Dict, Optional, Any
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from .CloudClusterBuildPlate import CloudClusterBuildPlate
from .CloudClusterPrintCoreConfiguration import CloudClusterPrintCoreConfiguration
from .BaseCloudModel import BaseCloudModel

View file

@ -19,12 +19,12 @@ from UM.Scene.SceneNode import SceneNode # For typing.
from UM.Settings.ContainerRegistry import ContainerRegistry
from cura.CuraApplication import CuraApplication
from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
from cura.PrinterOutput.Models.PrinterConfigurationModel import PrinterConfigurationModel
from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutputDevice import ConnectionType
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from .Cloud.Utils import formatTimeCompleted, formatDateCompleted
from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController
@ -522,7 +522,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
print_job = UM3PrintJobOutputModel(output_controller=ClusterUM3PrinterOutputController(self),
key=data["uuid"], name= data["name"])
configuration = ConfigurationModel()
configuration = PrinterConfigurationModel()
extruders = [ExtruderConfigurationModel(position = idx) for idx in range(0, self._number_of_extruders)]
for index in range(0, self._number_of_extruders):
try:
@ -633,6 +633,11 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
printer.updateKey(data["uuid"])
printer.updateType(data["machine_variant"])
if data["status"] != "unreachable":
self._application.getDiscoveredPrintersModel().updateDiscoveredPrinter(data["ip_address"],
name = data["friendly_name"],
machine_type = data["machine_variant"])
# Do not store the build plate information that comes from connect if the current printer has not build plate information
if "build_plate" in data and machine_definition.getMetaDataEntry("has_variant_buildplates", False):
printer.updateBuildplate(data["build_plate"]["type"])

View file

@ -5,7 +5,7 @@ from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
MYPY = False
if MYPY:
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
class ClusterUM3PrinterOutputController(PrinterOutputController):
def __init__(self, output_device):

View file

@ -18,7 +18,7 @@ from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from .UM3OutputDevicePlugin import UM3OutputDevicePlugin
if TYPE_CHECKING:
from cura.PrinterOutputDevice import PrinterOutputDevice
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
catalog = i18nCatalog("cura")
@ -41,6 +41,11 @@ class DiscoverUM3Action(MachineAction):
# Time to wait after a zero-conf service change before allowing a zeroconf reset
self._zero_conf_change_grace_period = 0.25 #type: float
# Overrides the one in MachineAction.
# This requires not attention from the user (any more), so we don't need to show any 'upgrade screens'.
def needsUserInteraction(self) -> bool:
return False
@pyqtSlot()
def startDiscovery(self):
if not self._network_plugin:
@ -118,49 +123,14 @@ class DiscoverUM3Action(MachineAction):
if self._network_plugin:
# Ensure that the connection states are refreshed.
self._network_plugin.reCheckConnections()
self._network_plugin.refreshConnections()
# Associates the currently active machine with the given printer device. The network connection information will be
# stored into the metadata of the currently active machine.
@pyqtSlot(QObject)
def associateActiveMachineWithPrinterDevice(self, printer_device: Optional["PrinterOutputDevice"]) -> None:
if not printer_device:
return
Logger.log("d", "Attempting to set the network key of the active machine to %s", printer_device.key)
global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
if not global_container_stack:
return
meta_data = global_container_stack.getMetaData()
if "um_network_key" in meta_data: # Global stack already had a connection, but it's changed.
old_network_key = meta_data["um_network_key"]
# Since we might have a bunch of hidden stacks, we also need to change it there.
metadata_filter = {"um_network_key": old_network_key}
containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine", **metadata_filter)
for container in containers:
container.setMetaDataEntry("um_network_key", printer_device.key)
# Delete old authentication data.
Logger.log("d", "Removing old authentication id %s for device %s",
global_container_stack.getMetaDataEntry("network_authentication_id", None), printer_device.key)
container.removeMetaDataEntry("network_authentication_id")
container.removeMetaDataEntry("network_authentication_key")
# Ensure that these containers do know that they are configured for network connection
container.addConfiguredConnectionType(printer_device.connectionType.value)
else: # Global stack didn't have a connection yet, configure it.
global_container_stack.setMetaDataEntry("um_network_key", printer_device.key)
global_container_stack.addConfiguredConnectionType(printer_device.connectionType.value)
if self._network_plugin:
# Ensure that the connection states are refreshed.
self._network_plugin.reCheckConnections()
self._network_plugin.associateActiveMachineWithPrinterDevice(printer_device)
@pyqtSlot(result = str)
def getStoredKey(self) -> str:

View file

@ -2,10 +2,10 @@ from typing import List, Optional
from cura.CuraApplication import CuraApplication
from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice, AuthState
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutputDevice import ConnectionType
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from cura.Settings.ContainerManager import ContainerManager
from cura.Settings.ExtruderManager import ExtruderManager

View file

@ -7,8 +7,8 @@ from UM.Version import Version
MYPY = False
if MYPY:
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
class LegacyUM3PrinterOutputController(PrinterOutputController):

View file

@ -1,23 +1,25 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import json
import os
from queue import Queue
from threading import Event, Thread
from time import time
import os
from typing import Optional, TYPE_CHECKING, Dict
from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager
from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices
from cura.CuraApplication import CuraApplication
from cura.PrinterOutputDevice import ConnectionType
from cura.Settings.GlobalStack import GlobalStack # typing
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from UM.i18n import i18nCatalog
from UM.Logger import Logger
from UM.Message import Message
from UM.OutputDevice.OutputDeviceManager import ManualDeviceAdditionAttempt
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from UM.PluginRegistry import PluginRegistry
from UM.Signal import Signal, signalemitter
@ -26,17 +28,23 @@ from UM.Version import Version
from . import ClusterUM3OutputDevice, LegacyUM3OutputDevice
from .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
from typing import Optional
if TYPE_CHECKING:
from PyQt5.QtNetwork import QNetworkReply
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
from cura.Settings.GlobalStack import GlobalStack
i18n_catalog = i18nCatalog("cura")
## This plugin handles the connection detection & creation of output device objects for the UM3 printer.
# Zero-Conf is used to detect printers, which are saved in a dict.
# If we discover a printer that has the same key as the active machine instance a connection is made.
@signalemitter
class UM3OutputDevicePlugin(OutputDevicePlugin):
addDeviceSignal = Signal()
removeDeviceSignal = Signal()
addDeviceSignal = Signal() # Called '...Signal' to avoid confusion with function-names.
removeDeviceSignal = Signal() # Ditto ^^^.
discoveredDevicesChanged = Signal()
cloudFlowIsPossible = Signal()
@ -55,7 +63,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self.addDeviceSignal.connect(self._onAddDevice)
self.removeDeviceSignal.connect(self._onRemoveDevice)
self._application.globalContainerStackChanged.connect(self.reCheckConnections)
self._application.globalContainerStackChanged.connect(self.refreshConnections)
self._discovered_devices = {}
@ -142,7 +150,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self.addManualDevice(address)
self.resetLastManualDevice()
def reCheckConnections(self):
def refreshConnections(self):
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
if not active_machine:
return
@ -176,6 +184,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self.checkCloudFlowIsPossible()
else:
self.getOutputDeviceManager().removeOutputDevice(key)
if key.startswith("manual:"):
self.removeManualDeviceSignal.emit(self.getPluginId(), key, self._discovered_devices[key].address)
def stop(self):
if self._zero_conf is not None:
@ -183,6 +193,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._zero_conf.close()
self._cloud_output_device_manager.stop()
def canAddManualDevice(self, address: str = "") -> ManualDeviceAdditionAttempt:
# This plugin should always be the fallback option (at least try it):
return ManualDeviceAdditionAttempt.POSSIBLE
def removeManualDevice(self, key, address = None):
if key in self._discovered_devices:
if not address:
@ -194,6 +208,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._manual_instances.remove(address)
self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances))
self.removeManualDeviceSignal.emit(self.getPluginId(), key, address)
def addManualDevice(self, address):
if address not in self._manual_instances:
self._manual_instances.append(address)
@ -215,6 +231,61 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._checkManualDevice(address)
def _createMachineFromDiscoveredPrinter(self, key: str) -> None:
discovered_device = self._discovered_devices.get(key)
if discovered_device is None:
Logger.log("e", "Could not find discovered device with key [%s]", key)
return
group_name = discovered_device.getProperty("name")
machine_type_id = discovered_device.getProperty("printer_type")
Logger.log("i", "Creating machine from network device with key = [%s], group name = [%s], printer type = [%s]",
key, group_name, machine_type_id)
self._application.getMachineManager().addMachine(machine_type_id, group_name)
# connect the new machine to that network printer
self.associateActiveMachineWithPrinterDevice(discovered_device)
# ensure that the connection states are refreshed.
self.refreshConnections()
def associateActiveMachineWithPrinterDevice(self, printer_device: Optional["PrinterOutputDevice"]) -> None:
if not printer_device:
return
Logger.log("d", "Attempting to set the network key of the active machine to %s", printer_device.key)
global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
if not global_container_stack:
return
meta_data = global_container_stack.getMetaData()
if "um_network_key" in meta_data: # Global stack already had a connection, but it's changed.
old_network_key = meta_data["um_network_key"]
# Since we might have a bunch of hidden stacks, we also need to change it there.
metadata_filter = {"um_network_key": old_network_key}
containers = self._application.getContainerRegistry().findContainerStacks(type = "machine", **metadata_filter)
for container in containers:
container.setMetaDataEntry("um_network_key", printer_device.key)
# Delete old authentication data.
Logger.log("d", "Removing old authentication id %s for device %s",
global_container_stack.getMetaDataEntry("network_authentication_id", None), printer_device.key)
container.removeMetaDataEntry("network_authentication_id")
container.removeMetaDataEntry("network_authentication_key")
# Ensure that these containers do know that they are configured for network connection
container.addConfiguredConnectionType(printer_device.connectionType.value)
else: # Global stack didn't have a connection yet, configure it.
global_container_stack.setMetaDataEntry("um_network_key", printer_device.key)
global_container_stack.addConfiguredConnectionType(printer_device.connectionType.value)
self.refreshConnections()
def _checkManualDevice(self, address):
# Check if a UM3 family device exists at this address.
# If a printer responds, it will replace the preliminary printer created above
@ -223,21 +294,29 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
name_request = QNetworkRequest(url)
self._network_manager.get(name_request)
def _onNetworkRequestFinished(self, reply):
def _onNetworkRequestFinished(self, reply: "QNetworkReply") -> None:
reply_url = reply.url().toString()
if "system" in reply_url:
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
# Something went wrong with checking the firmware version!
return
address = reply.url().host()
device = None
properties = {} # type: Dict[bytes, bytes]
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
# Either:
# - Something went wrong with checking the firmware version!
# - Something went wrong with checking the amount of printers the cluster has!
# - Couldn't find printer at the address when trying to add it manually.
if address in self._manual_instances:
self.removeManualDeviceSignal.emit(self.getPluginId(), "", address)
return
if "system" in reply_url:
try:
system_info = json.loads(bytes(reply.readAll()).decode("utf-8"))
except:
Logger.log("e", "Something went wrong converting the JSON.")
return
address = reply.url().host()
has_cluster_capable_firmware = Version(system_info["firmware"]) > self._min_cluster_version
instance_name = "manual:%s" % address
properties = {
@ -265,16 +344,12 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._network_manager.get(cluster_request)
elif "printers" in reply_url:
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
# Something went wrong with checking the amount of printers the cluster has!
return
# So we confirmed that the device is in fact a cluster printer, and we should now know how big it is.
try:
cluster_printers_list = json.loads(bytes(reply.readAll()).decode("utf-8"))
except:
Logger.log("e", "Something went wrong converting the JSON.")
return
address = reply.url().host()
instance_name = "manual:%s" % address
if instance_name in self._discovered_devices:
device = self._discovered_devices[instance_name]
@ -285,7 +360,11 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._onRemoveDevice(instance_name)
self._onAddDevice(instance_name, address, properties)
def _onRemoveDevice(self, device_id):
if device and address in self._manual_instances:
self.getOutputDeviceManager().addOutputDevice(device)
self.addManualDeviceSignal.emit(self.getPluginId(), device.getId(), address, properties)
def _onRemoveDevice(self, device_id: str) -> None:
device = self._discovered_devices.pop(device_id, None)
if device:
if device.isConnected():
@ -295,7 +374,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
except TypeError:
# Disconnect already happened.
pass
self._application.getDiscoveredPrintersModel().removeDiscoveredPrinter(device.address)
self.discoveredDevicesChanged.emit()
def _onAddDevice(self, name, address, properties):
@ -320,7 +399,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
device = ClusterUM3OutputDevice.ClusterUM3OutputDevice(name, address, properties)
else:
device = LegacyUM3OutputDevice.LegacyUM3OutputDevice(name, address, properties)
self._application.getDiscoveredPrintersModel().addDiscoveredPrinter(address, device.getId(), name, self._createMachineFromDiscoveredPrinter, properties[b"printer_type"].decode("utf-8"), device)
self._discovered_devices[device.getId()] = device
self.discoveredDevicesChanged.emit()
@ -412,9 +491,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
Logger.log("d", "Checking if cloud connection is possible...")
# Pre-Check: Skip if active machine already has been cloud connected or you said don't ask again
active_machine = self._application.getMachineManager().activeMachine # type: Optional["GlobalStack"]
active_machine = self._application.getMachineManager().activeMachine # type: Optional[GlobalStack]
if active_machine:
# Check 1A: Printer isn't already configured for cloud
if ConnectionType.CloudConnection.value in active_machine.configuredConnectionTypes:
Logger.log("d", "Active machine was already configured for cloud.")
@ -458,7 +536,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
if self._start_cloud_flow_message and not self._start_cloud_flow_message.visible:
self._start_cloud_flow_message.show()
def _onCloudPrintingConfigured(self) -> None:
def _onCloudPrintingConfigured(self, device) -> None:
# Hide the cloud flow start message if it was hanging around already
# For example: if the user already had the browser openen and made the association themselves
if self._start_cloud_flow_message and self._start_cloud_flow_message.visible:
@ -473,11 +551,20 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
# Set the machine's cloud flow as complete so we don't ask the user again and again for cloud connected printers
active_machine = self._application.getMachineManager().activeMachine
if active_machine:
active_machine.setMetaDataEntry("do_not_show_cloud_message", True)
# The active machine _might_ not be the machine that was in the added cloud cluster and
# then this will hide the cloud message for the wrong machine. So we only set it if the
# host names match between the active machine and the newly added cluster
saved_host_name = active_machine.getMetaDataEntry("um_network_key", "").split('.')[0]
added_host_name = device.toDict()["host_name"]
if added_host_name == saved_host_name:
active_machine.setMetaDataEntry("do_not_show_cloud_message", True)
return
def _onDontAskMeAgain(self, checked: bool) -> None:
active_machine = self._application.getMachineManager().activeMachine # type: Optional["GlobalStack"]
active_machine = self._application.getMachineManager().activeMachine # type: Optional[GlobalStack]
if active_machine:
active_machine.setMetaDataEntry("do_not_show_cloud_message", checked)
if checked:

View file

@ -5,7 +5,7 @@ from typing import List
from PyQt5.QtCore import pyqtProperty, pyqtSignal
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
from .ConfigurationChangeModel import ConfigurationChangeModel

View file

@ -6,7 +6,7 @@ from unittest.mock import patch, MagicMock
from UM.Scene.SceneNode import SceneNode
from cura.UltimakerCloudAuthentication import CuraCloudAPIRoot
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from ...src.Cloud import CloudApiClient
from ...src.Cloud.CloudOutputDevice import CloudOutputDevice
from ...src.Cloud.Models.CloudClusterResponse import CloudClusterResponse

View file

@ -13,7 +13,7 @@ from time import sleep
MYPY = False
if MYPY:
from cura.PrinterOutputDevice import PrinterOutputDevice
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
class AvrFirmwareUpdater(FirmwareUpdater):

View file

@ -10,9 +10,9 @@ from UM.PluginRegistry import PluginRegistry #To get the g-code output.
from UM.Qt.Duration import DurationFormat
from cura.CuraApplication import CuraApplication
from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice, ConnectionState, ConnectionType
from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
from cura.PrinterOutput.GenericOutputController import GenericOutputController
from .AutoDetectBaudJob import AutoDetectBaudJob

View file

@ -5,15 +5,13 @@ import threading
import time
import serial.tools.list_ports
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
from PyQt5.QtCore import QObject, pyqtSignal
from UM.Logger import Logger
from UM.Signal import Signal, signalemitter
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from UM.i18n import i18nCatalog
from cura.PrinterOutputDevice import ConnectionState
from cura.CuraApplication import CuraApplication
from cura.PrinterOutput.PrinterOutputDevice import ConnectionState
from . import USBPrinterOutputDevice

View file

@ -4,7 +4,7 @@
from typing import List
from cura.MachineAction import MachineAction
from cura.PrinterOutputDevice import PrinterOutputDevice
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
from UM.FlameProfiler import pyqtSlot

View file

@ -1,24 +1,27 @@
// Copyright (c) 2016 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import UM 1.2 as UM
import Cura 1.0 as Cura
import UM 1.3 as UM
import Cura 1.1 as Cura
Cura.MachineAction
{
anchors.fill: parent;
UM.I18nCatalog { id: catalog; name: "cura"; }
anchors.fill: parent
Item
{
id: bedLevelMachineAction
anchors.fill: parent;
UM.I18nCatalog { id: catalog; name: "cura"; }
anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("default_margin").height * 3
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width * 3 / 4
Label
{
@ -26,17 +29,21 @@ Cura.MachineAction
width: parent.width
text: catalog.i18nc("@title", "Build Plate Leveling")
wrapMode: Text.WordWrap
font.pointSize: 18;
font.pointSize: 18
renderType: Text.NativeRendering
}
Label
{
id: pageDescription
anchors.top: pageTitle.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.topMargin: UM.Theme.getSize("default_margin").height * 3
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "To make sure your prints will come out great, you can now adjust your buildplate. When you click 'Move to Next Position' the nozzle will move to the different positions that can be adjusted.")
renderType: Text.NativeRendering
}
Label
{
id: bedlevelingText
@ -45,37 +52,38 @@ Cura.MachineAction
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "For every position; insert a piece of paper under the nozzle and adjust the print build plate height. The print build plate height is right when the paper is slightly gripped by the tip of the nozzle.")
renderType: Text.NativeRendering
}
Row
{
id: bedlevelingWrapper
anchors.top: bedlevelingText.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.topMargin: UM.Theme.getSize("default_margin").height * 3
anchors.horizontalCenter: parent.horizontalCenter
width: childrenRect.width
spacing: UM.Theme.getSize("default_margin").width
Button
Cura.ActionButton
{
id: startBedLevelingButton
text: catalog.i18nc("@action:button","Start Build Plate Leveling")
text: catalog.i18nc("@action:button", "Start Build Plate Leveling")
onClicked:
{
startBedLevelingButton.visible = false;
bedlevelingButton.visible = true;
manager.startBedLeveling();
startBedLevelingButton.visible = false
bedlevelingButton.visible = true
manager.startBedLeveling()
}
}
Button
Cura.ActionButton
{
id: bedlevelingButton
text: catalog.i18nc("@action:button","Move to Next Position")
text: catalog.i18nc("@action:button", "Move to Next Position")
visible: false
onClicked:
{
manager.moveToNextLevelPosition();
manager.moveToNextLevelPosition()
}
}
}

View file

@ -1,13 +1,15 @@
# Copyright (c) 2018 Ultimaker B.V.
# Uranium is released under the terms of the LGPLv3 or higher.
from UM.Settings.ContainerRegistry import ContainerRegistry
from cura.MachineAction import MachineAction
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
from PyQt5.QtCore import pyqtSignal, pyqtProperty
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from UM.Application import Application
from UM.Util import parseBool
from cura.MachineAction import MachineAction
catalog = i18nCatalog("cura")

View file

@ -1,32 +1,24 @@
// Copyright (c) 2016 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.2 as UM
import Cura 1.0 as Cura
import UM 1.3 as UM
import Cura 1.1 as Cura
Cura.MachineAction
{
anchors.fill: parent;
UM.I18nCatalog { id: catalog; name: "cura"; }
anchors.fill: parent
Item
{
id: upgradeSelectionMachineAction
anchors.fill: parent
Label
{
id: pageTitle
width: parent.width
text: catalog.i18nc("@title", "Select Printer Upgrades")
wrapMode: Text.WordWrap
font.pointSize: 18;
}
anchors.topMargin: UM.Theme.getSize("default_margin").width * 5
anchors.leftMargin: UM.Theme.getSize("default_margin").width * 4
Label
{
@ -35,15 +27,19 @@ Cura.MachineAction
anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker 2.");
text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker 2.")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
CheckBox
Cura.CheckBox
{
id: olssonBlockCheckBox
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
height: UM.Theme.getSize("setting_control").height
text: catalog.i18nc("@label", "Olsson Block")
checked: manager.hasVariants
onClicked: manager.hasVariants = checked
@ -54,7 +50,5 @@ Cura.MachineAction
onHasVariantsChanged: olssonBlockCheckBox.checked = manager.hasVariants
}
}
UM.I18nCatalog { id: catalog; name: "cura"; }
}
}
}

View file

@ -1,193 +0,0 @@
from cura.MachineAction import MachineAction
from cura.PrinterOutputDevice import PrinterOutputDevice
from UM.Application import Application
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
from UM.Logger import Logger
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
## Action to check up if the self-built UMO was done correctly.
class UMOCheckupMachineAction(MachineAction):
def __init__(self):
super().__init__("UMOCheckup", catalog.i18nc("@action", "Checkup"))
self._qml_url = "UMOCheckupMachineAction.qml"
self._hotend_target_temp = 180
self._bed_target_temp = 60
self._output_device = None
self._bed_test_completed = False
self._hotend_test_completed = False
# Endstop tests
self._x_min_endstop_test_completed = False
self._y_min_endstop_test_completed = False
self._z_min_endstop_test_completed = False
self._check_started = False
Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
onBedTestCompleted = pyqtSignal()
onHotendTestCompleted = pyqtSignal()
onXMinEndstopTestCompleted = pyqtSignal()
onYMinEndstopTestCompleted = pyqtSignal()
onZMinEndstopTestCompleted = pyqtSignal()
bedTemperatureChanged = pyqtSignal()
hotendTemperatureChanged = pyqtSignal()
def _onOutputDevicesChanged(self):
# Check if this action was started, but no output device was found the first time.
# If so, re-try now that an output device has been added/removed.
if self._output_device is None and self._check_started:
self.startCheck()
def _getPrinterOutputDevices(self):
return [printer_output_device for printer_output_device in
Application.getInstance().getOutputDeviceManager().getOutputDevices() if
isinstance(printer_output_device, PrinterOutputDevice)]
def _reset(self):
if self._output_device:
self._output_device.bedTemperatureChanged.disconnect(self.bedTemperatureChanged)
self._output_device.hotendTemperaturesChanged.disconnect(self.hotendTemperatureChanged)
self._output_device.bedTemperatureChanged.disconnect(self._onBedTemperatureChanged)
self._output_device.hotendTemperaturesChanged.disconnect(self._onHotendTemperatureChanged)
self._output_device.endstopStateChanged.disconnect(self._onEndstopStateChanged)
try:
self._output_device.stopPollEndstop()
except AttributeError as e: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
Logger.log("e", "An exception occurred while stopping end stop polling: %s" % str(e))
self._output_device = None
self._check_started = False
self.checkStartedChanged.emit()
# Ensure everything is reset (and right signals are emitted again)
self._bed_test_completed = False
self.onBedTestCompleted.emit()
self._hotend_test_completed = False
self.onHotendTestCompleted.emit()
self._x_min_endstop_test_completed = False
self.onXMinEndstopTestCompleted.emit()
self._y_min_endstop_test_completed = False
self.onYMinEndstopTestCompleted.emit()
self._z_min_endstop_test_completed = False
self.onZMinEndstopTestCompleted.emit()
self.heatedBedChanged.emit()
@pyqtProperty(bool, notify = onBedTestCompleted)
def bedTestCompleted(self):
return self._bed_test_completed
@pyqtProperty(bool, notify = onHotendTestCompleted)
def hotendTestCompleted(self):
return self._hotend_test_completed
@pyqtProperty(bool, notify = onXMinEndstopTestCompleted)
def xMinEndstopTestCompleted(self):
return self._x_min_endstop_test_completed
@pyqtProperty(bool, notify=onYMinEndstopTestCompleted)
def yMinEndstopTestCompleted(self):
return self._y_min_endstop_test_completed
@pyqtProperty(bool, notify=onZMinEndstopTestCompleted)
def zMinEndstopTestCompleted(self):
return self._z_min_endstop_test_completed
@pyqtProperty(float, notify = bedTemperatureChanged)
def bedTemperature(self):
if not self._output_device:
return 0
return self._output_device.bedTemperature
@pyqtProperty(float, notify=hotendTemperatureChanged)
def hotendTemperature(self):
if not self._output_device:
return 0
return self._output_device.hotendTemperatures[0]
def _onHotendTemperatureChanged(self):
if not self._output_device:
return
if not self._hotend_test_completed:
if self._output_device.hotendTemperatures[0] + 10 > self._hotend_target_temp and self._output_device.hotendTemperatures[0] - 10 < self._hotend_target_temp:
self._hotend_test_completed = True
self.onHotendTestCompleted.emit()
def _onBedTemperatureChanged(self):
if not self._output_device:
return
if not self._bed_test_completed:
if self._output_device.bedTemperature + 5 > self._bed_target_temp and self._output_device.bedTemperature - 5 < self._bed_target_temp:
self._bed_test_completed = True
self.onBedTestCompleted.emit()
def _onEndstopStateChanged(self, switch_type, state):
if state:
if switch_type == "x_min":
self._x_min_endstop_test_completed = True
self.onXMinEndstopTestCompleted.emit()
elif switch_type == "y_min":
self._y_min_endstop_test_completed = True
self.onYMinEndstopTestCompleted.emit()
elif switch_type == "z_min":
self._z_min_endstop_test_completed = True
self.onZMinEndstopTestCompleted.emit()
checkStartedChanged = pyqtSignal()
@pyqtProperty(bool, notify = checkStartedChanged)
def checkStarted(self):
return self._check_started
@pyqtSlot()
def startCheck(self):
self._check_started = True
self.checkStartedChanged.emit()
output_devices = self._getPrinterOutputDevices()
if output_devices:
self._output_device = output_devices[0]
try:
self._output_device.sendCommand("M18") # Turn off all motors so the user can move the axes
self._output_device.startPollEndstop()
self._output_device.bedTemperatureChanged.connect(self.bedTemperatureChanged)
self._output_device.hotendTemperaturesChanged.connect(self.hotendTemperatureChanged)
self._output_device.bedTemperatureChanged.connect(self._onBedTemperatureChanged)
self._output_device.hotendTemperaturesChanged.connect(self._onHotendTemperatureChanged)
self._output_device.endstopStateChanged.connect(self._onEndstopStateChanged)
except AttributeError as e: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
Logger.log("e", "An exception occurred while starting end stop polling: %s" % str(e))
@pyqtSlot()
def cooldownHotend(self):
if self._output_device is not None:
self._output_device.setTargetHotendTemperature(0, 0)
@pyqtSlot()
def cooldownBed(self):
if self._output_device is not None:
self._output_device.setTargetBedTemperature(0)
@pyqtSlot()
def heatupHotend(self):
if self._output_device is not None:
self._output_device.setTargetHotendTemperature(0, self._hotend_target_temp)
@pyqtSlot()
def heatupBed(self):
if self._output_device is not None:
self._output_device.setTargetBedTemperature(self._bed_target_temp)
heatedBedChanged = pyqtSignal()
@pyqtProperty(bool, notify = heatedBedChanged)
def hasHeatedBed(self):
global_container_stack = Application.getInstance().getGlobalContainerStack()
return global_container_stack.getProperty("machine_heated_bed", "value")

View file

@ -1,288 +0,0 @@
import UM 1.2 as UM
import Cura 1.0 as Cura
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
Cura.MachineAction
{
anchors.fill: parent;
Item
{
id: checkupMachineAction
anchors.fill: parent;
property int leftRow: (checkupMachineAction.width * 0.40) | 0
property int rightRow: (checkupMachineAction.width * 0.60) | 0
property bool heatupHotendStarted: false
property bool heatupBedStarted: false
property bool printerConnected: Cura.MachineManager.printerConnected
UM.I18nCatalog { id: catalog; name: "cura"}
Label
{
id: pageTitle
width: parent.width
text: catalog.i18nc("@title", "Check Printer")
wrapMode: Text.WordWrap
font.pointSize: 18;
}
Label
{
id: pageDescription
anchors.top: pageTitle.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional");
}
Row
{
id: startStopButtons
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.horizontalCenter: parent.horizontalCenter
width: childrenRect.width
spacing: UM.Theme.getSize("default_margin").width
Button
{
id: startCheckButton
text: catalog.i18nc("@action:button","Start Printer Check");
onClicked:
{
checkupMachineAction.heatupHotendStarted = false;
checkupMachineAction.heatupBedStarted = false;
manager.startCheck();
startCheckButton.visible = false;
}
}
}
Item
{
id: checkupContent
anchors.top: startStopButtons.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
visible: manager.checkStarted
width: parent.width
height: 250
//////////////////////////////////////////////////////////
Label
{
id: connectionLabel
width: checkupMachineAction.leftRow
anchors.left: parent.left
anchors.top: parent.top
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Connection: ")
}
Label
{
id: connectionStatus
width: checkupMachineAction.rightRow
anchors.left: connectionLabel.right
anchors.top: parent.top
wrapMode: Text.WordWrap
text: checkupMachineAction.printerConnected ? catalog.i18nc("@info:status","Connected"): catalog.i18nc("@info:status","Not connected")
}
//////////////////////////////////////////////////////////
Label
{
id: endstopXLabel
width: checkupMachineAction.leftRow
anchors.left: parent.left
anchors.top: connectionLabel.bottom
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Min endstop X: ")
visible: checkupMachineAction.printerConnected
}
Label
{
id: endstopXStatus
width: checkupMachineAction.rightRow
anchors.left: endstopXLabel.right
anchors.top: connectionLabel.bottom
wrapMode: Text.WordWrap
text: manager.xMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
visible: checkupMachineAction.printerConnected
}
//////////////////////////////////////////////////////////////
Label
{
id: endstopYLabel
width: checkupMachineAction.leftRow
anchors.left: parent.left
anchors.top: endstopXLabel.bottom
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Min endstop Y: ")
visible: checkupMachineAction.printerConnected
}
Label
{
id: endstopYStatus
width: checkupMachineAction.rightRow
anchors.left: endstopYLabel.right
anchors.top: endstopXLabel.bottom
wrapMode: Text.WordWrap
text: manager.yMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
visible: checkupMachineAction.printerConnected
}
/////////////////////////////////////////////////////////////////////
Label
{
id: endstopZLabel
width: checkupMachineAction.leftRow
anchors.left: parent.left
anchors.top: endstopYLabel.bottom
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Min endstop Z: ")
visible: checkupMachineAction.printerConnected
}
Label
{
id: endstopZStatus
width: checkupMachineAction.rightRow
anchors.left: endstopZLabel.right
anchors.top: endstopYLabel.bottom
wrapMode: Text.WordWrap
text: manager.zMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked")
visible: checkupMachineAction.printerConnected
}
////////////////////////////////////////////////////////////
Label
{
id: nozzleTempLabel
width: checkupMachineAction.leftRow
height: nozzleTempButton.height
anchors.left: parent.left
anchors.top: endstopZLabel.bottom
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Nozzle temperature check: ")
visible: checkupMachineAction.printerConnected
}
Label
{
id: nozzleTempStatus
width: (checkupMachineAction.rightRow * 0.4) | 0
anchors.top: nozzleTempLabel.top
anchors.left: nozzleTempLabel.right
wrapMode: Text.WordWrap
text: catalog.i18nc("@info:status","Not checked")
visible: checkupMachineAction.printerConnected
}
Item
{
id: nozzleTempButton
width: (checkupMachineAction.rightRow * 0.3) | 0
height: childrenRect.height
anchors.top: nozzleTempLabel.top
anchors.left: bedTempStatus.right
anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").width/2)
visible: checkupMachineAction.printerConnected
Button
{
text: checkupMachineAction.heatupHotendStarted ? catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating")
onClicked:
{
if (checkupMachineAction.heatupHotendStarted)
{
manager.cooldownHotend()
checkupMachineAction.heatupHotendStarted = false
} else
{
manager.heatupHotend()
checkupMachineAction.heatupHotendStarted = true
}
}
}
}
Label
{
id: nozzleTemp
anchors.top: nozzleTempLabel.top
anchors.left: nozzleTempButton.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width
width: (checkupMachineAction.rightRow * 0.2) | 0
wrapMode: Text.WordWrap
text: manager.hotendTemperature + "°C"
font.bold: true
visible: checkupMachineAction.printerConnected
}
/////////////////////////////////////////////////////////////////////////////
Label
{
id: bedTempLabel
width: checkupMachineAction.leftRow
height: bedTempButton.height
anchors.left: parent.left
anchors.top: nozzleTempLabel.bottom
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Build plate temperature check:")
visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
}
Label
{
id: bedTempStatus
width: (checkupMachineAction.rightRow * 0.4) | 0
anchors.top: bedTempLabel.top
anchors.left: bedTempLabel.right
wrapMode: Text.WordWrap
text: manager.bedTestCompleted ? catalog.i18nc("@info:status","Not checked"): catalog.i18nc("@info:status","Checked")
visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
}
Item
{
id: bedTempButton
width: (checkupMachineAction.rightRow * 0.3) | 0
height: childrenRect.height
anchors.top: bedTempLabel.top
anchors.left: bedTempStatus.right
anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").width/2)
visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
Button
{
text: checkupMachineAction.heatupBedStarted ?catalog.i18nc("@action:button","Stop Heating") : catalog.i18nc("@action:button","Start Heating")
onClicked:
{
if (checkupMachineAction.heatupBedStarted)
{
manager.cooldownBed()
checkupMachineAction.heatupBedStarted = false
} else
{
manager.heatupBed()
checkupMachineAction.heatupBedStarted = true
}
}
}
}
Label
{
id: bedTemp
width: (checkupMachineAction.rightRow * 0.2) | 0
anchors.top: bedTempLabel.top
anchors.left: bedTempButton.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width
wrapMode: Text.WordWrap
text: manager.bedTemperature + "°C"
font.bold: true
visible: checkupMachineAction.printerConnected && manager.hasHeatedBed
}
Label
{
id: resultText
visible: false
anchors.top: bedTemp.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Everything is in order! You're done with your CheckUp.")
}
}
}
}

View file

@ -1,43 +1,38 @@
// Copyright (c) 2016 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.2 as UM
import Cura 1.0 as Cura
import UM 1.3 as UM
import Cura 1.1 as Cura
Cura.MachineAction
{
anchors.fill: parent;
UM.I18nCatalog { id: catalog; name: "cura"; }
anchors.fill: parent
Item
{
id: upgradeSelectionMachineAction
anchors.fill: parent
Label
{
id: pageTitle
width: parent.width
text: catalog.i18nc("@title", "Select Printer Upgrades")
wrapMode: Text.WordWrap
font.pointSize: 18;
}
anchors.topMargin: UM.Theme.getSize("default_margin").width * 5
anchors.leftMargin: UM.Theme.getSize("default_margin").width * 4
Label
{
id: pageDescription
anchors.top: pageTitle.bottom
anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
wrapMode: Text.WordWrap
text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker Original");
text: catalog.i18nc("@label","Please select any upgrades made to this Ultimaker Original")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
}
CheckBox
Cura.CheckBox
{
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
@ -46,7 +41,5 @@ Cura.MachineAction
checked: manager.hasHeatedBed
onClicked: manager.setHeatedBed(checked)
}
UM.I18nCatalog { id: catalog; name: "cura"; }
}
}
}

View file

@ -1,46 +0,0 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os
from PyQt5.QtCore import QObject, pyqtSlot
from UM.Extension import Extension
from UM.Logger import Logger
class UserAgreement(QObject, Extension):
def __init__(self, application):
super(UserAgreement, self).__init__()
self._application = application
self._user_agreement_window = None
self._user_agreement_context = None
self._application.engineCreatedSignal.connect(self._onEngineCreated)
self._application.getPreferences().addPreference("general/accepted_user_agreement", False)
def _onEngineCreated(self):
if not self._application.getPreferences().getValue("general/accepted_user_agreement"):
self.showUserAgreement()
def showUserAgreement(self):
if not self._user_agreement_window:
self.createUserAgreementWindow()
self._user_agreement_window.show()
@pyqtSlot(bool)
def didAgree(self, user_choice):
if user_choice:
Logger.log("i", "User agreed to the user agreement")
self._application.getPreferences().setValue("general/accepted_user_agreement", True)
self._user_agreement_window.hide()
else:
Logger.log("i", "User did NOT agree to the user agreement")
self._application.getPreferences().setValue("general/accepted_user_agreement", False)
self._application.quit()
self._application.setNeedToShowUserAgreement(False)
def createUserAgreementWindow(self):
path = os.path.join(self._application.getPluginRegistry().getPluginPath(self.getPluginId()), "UserAgreement.qml")
self._user_agreement_window = self._application.createQmlComponent(path, {"manager": self})

View file

@ -1,63 +0,0 @@
// Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.4
import UM 1.3 as UM
UM.Dialog
{
id: baseDialog
minimumWidth: Math.round(UM.Theme.getSize("modal_window_minimum").width * 0.75)
minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height * 0.5)
width: minimumWidth
height: minimumHeight
title: catalog.i18nc("@title:window", "User Agreement")
TextArea
{
anchors.top: parent.top
width: parent.width
anchors.bottom: buttonRow.top
text: ' <center><h3>DISCLAIMER BY ULTIMAKER</h3></center>
<p>PLEASE READ THIS DISCLAIMER CAREFULLY.</p>
<p>EXCEPT WHEN OTHERWISE STATED IN WRITING, ULTIMAKER PROVIDES ANY ULTIMAKER SOFTWARE OR THIRD PARTY SOFTWARE AS IS WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF ULTIMAKER SOFTWARE IS WITH YOU.</p>
<p>UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, IN NO EVENT WILL ULTIMAKER BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE ANY ULTIMAKER SOFTWARE OR THIRD PARTY SOFTWARE.</p>
'
readOnly: true;
textFormat: TextEdit.RichText
}
Item
{
id: buttonRow
anchors.bottom: parent.bottom
width: parent.width
anchors.bottomMargin: UM.Theme.getSize("default_margin").height
UM.I18nCatalog { id: catalog; name: "cura" }
Button
{
anchors.right: parent.right
text: catalog.i18nc("@action:button", "I understand and agree")
onClicked: {
baseDialog.accepted()
}
}
Button
{
anchors.left: parent.left
text: catalog.i18nc("@action:button", "I don't agree")
onClicked: {
baseDialog.rejected()
}
}
}
onAccepted: manager.didAgree(true)
onRejected: manager.didAgree(false)
onClosing: manager.didAgree(false)
}

View file

@ -1,10 +0,0 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from . import UserAgreement
def getMetaData():
return {}
def register(app):
return {"extension": UserAgreement.UserAgreement(app)}

View file

@ -1,8 +0,0 @@
{
"name": "UserAgreement",
"author": "Ultimaker B.V.",
"version": "1.0.1",
"description": "Ask the user once if he/she agrees with our license.",
"api": "6.0",
"i18n-catalog": "cura"
}

View file

@ -3,7 +3,7 @@ from typing import Tuple, List, Set, Dict
import io
from UM.VersionUpgrade import VersionUpgrade
from cura.PrinterOutputDevice import ConnectionType
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
deleted_settings = {"bridge_wall_max_overhang"} # type: Set[str]
renamed_configurations = {"connect_group_name": "group_name"} # type: Dict[str, str]

View file

@ -577,23 +577,6 @@
}
}
},
"UserAgreement": {
"package_info": {
"package_id": "UserAgreement",
"package_type": "plugin",
"display_name": "User Agreement",
"description": "Ask the user once if he/she agrees with our license.",
"package_version": "1.0.1",
"sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
}
}
},
"VersionUpgrade21to22": {
"package_info": {
"package_id": "VersionUpgrade21to22",

View file

@ -0,0 +1,235 @@
{
"id": "Mark2_for_Ultimaker2",
"version": 2,
"name": "Mark2 for Ultimaker2",
"inherits": "ultimaker2_plus",
"metadata": {
"visible": true,
"author": "TheUltimakerCommunity",
"manufacturer": "Foehnsturm",
"category": "Other",
"has_variants": true,
"has_materials": true,
"has_machine_materials": false,
"has_machine_quality": false,
"has_variant_materials": false,
"weight": 2,
"file_formats": "text/x-gcode",
"icon": "icon_ultimaker.png",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Mark2_for_Ultimaker2_backplate.png",
"machine_extruder_trains":
{
"0": "Mark2_extruder1",
"1": "Mark2_extruder2"
},
"supported_actions": ["MachineSettingsAction", "UpgradeFirmware"]
},
"overrides": {
"machine_name": { "default_value": "Mark2_for_Ultimaker2" },
"machine_width": {
"default_value": 223
},
"machine_depth": {
"default_value": 223
},
"machine_height": {
"default_value": 203
},
"gantry_height": {
"default_value": 52
},
"machine_center_is_zero": {
"default_value": false
},
"machine_nozzle_size": {
"default_value": 0.4
},
"machine_nozzle_heat_up_speed": {
"default_value": 3.5
},
"machine_nozzle_cool_down_speed": {
"default_value": 1.5
},
"machine_min_cool_heat_time_window":
{
"default_value": 15.0
},
"machine_show_variants": {
"default_value": true
},
"machine_nozzle_head_distance": {
"default_value": 5
},
"machine_nozzle_expansion_angle": {
"default_value": 45
},
"machine_heat_zone_length": {
"default_value": 20
},
"machine_heated_bed": {
"default_value": true
},
"speed_infill": {
"value": "speed_print"
},
"speed_wall_x": {
"value": "speed_wall"
},
"layer_height_0": {
"value": "round(machine_nozzle_size / 1.5, 2)"
},
"line_width": {
"value": "round(machine_nozzle_size * 0.875, 2)"
},
"speed_layer_0": {
"default_value": 20
},
"speed_support": {
"value": "speed_wall_0"
},
"machine_max_feedrate_x": {
"default_value": 250
},
"machine_max_feedrate_y": {
"default_value": 250
},
"machine_max_feedrate_z": {
"default_value": 40
},
"machine_max_feedrate_e": {
"default_value": 45
},
"machine_acceleration": {
"default_value": 3000
},
"retraction_amount": {
"default_value": 5.1
},
"retraction_speed": {
"default_value": 25
},
"switch_extruder_retraction_amount": {
"default_value": 0,
"value": "retraction_amount",
"enabled": false
},
"switch_extruder_retraction_speeds": {
"default_value": 25,
"value": "retraction_speed",
"enabled": false
},
"switch_extruder_retraction_speed": {
"default_value": 25,
"value": "retraction_retract_speed",
"enabled": false
},
"switch_extruder_prime_speed": {
"default_value": 25,
"value": "retraction_prime_speed",
"enabled": false
},
"machine_head_with_fans_polygon":
{
"default_value": [
[ -44, 14 ],
[ -44, -34 ],
[ 64, 14 ],
[ 64, -34 ]
]
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": false
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode" : {
"default_value": "",
"value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"G21 ;metric values\\nG90 ;absolute positioning\\nM82 ;set extruder to absolute mode\\nM107 ;start with the fan off\\nM200 D0 T0 ;reset filament diameter\\nM200 D0 T1\\nG28 Z0; home all\\nG28 X0 Y0\\nG0 Z20 F2400 ;move the platform to 20mm\\nG92 E0\\nM190 S{material_bed_temperature_layer_0}\\nM109 T0 S{material_standby_temperature, 0}\\nM109 T1 S{material_print_temperature_layer_0, 1}\\nM104 T0 S{material_print_temperature_layer_0, 0}\\nT1 ; move to the 2th head\\nG0 Z20 F2400\\nG92 E-7.0 ;prime distance\\nG1 E0 F45 ;purge nozzle\\nG1 E-5.1 F1500 ; retract\\nG1 X90 Z0.01 F5000 ; move away from the prime poop\\nG1 X50 F9000\\nG0 Z20 F2400\\nT0 ; move to the first head\\nM104 T1 S{material_standby_temperature, 1}\\nG0 Z20 F2400\\nM104 T{initial_extruder_nr} S{material_print_temperature_layer_0, initial_extruder_nr}\\nG92 E-7.0\\nG1 E0 F45 ;purge nozzle\\nG1 X60 Z0.01 F5000 ; move away from the prime poop\\nG1 X20 F9000\\nM400 ;finish all moves\\nG92 E0\\n;end of startup sequence\\n\""
},
"machine_end_gcode" : {
"default_value": "",
"value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"G90 ;absolute positioning\\nM104 S0 T0 ;extruder heater off\\nM104 S0 T1\\nM140 S0 ;turn off bed\\nT0 ; move to the first head\\nM107 ;fan off\""
},
"machine_extruder_count": {
"default_value": 2
},
"acceleration_enabled":
{
"default_value": true
},
"acceleration_print":
{
"default_value": 2000,
"value": "2000"
},
"acceleration_travel":
{
"default_value": 3000,
"value": "acceleration_print if magic_spiralize else 3000"
},
"acceleration_layer_0": { "value": "acceleration_topbottom" },
"acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
"acceleration_support": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
"acceleration_support_interface": { "value": "acceleration_topbottom" },
"acceleration_topbottom": { "value": "math.ceil(acceleration_print * 500 / 4000)" },
"acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 4000)" },
"acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 500 / 1000)" },
"jerk_enabled":
{
"default_value": true
},
"jerk_print":
{
"default_value": 12
},
"jerk_travel":
{
"default_value": 20,
"value": "jerk_print if magic_spiralize else 20"
},
"jerk_layer_0": { "value": "jerk_topbottom" },
"jerk_prime_tower": { "value": "10 if jerk_print < 16 else math.ceil(jerk_print * 15 / 25)" },
"jerk_support": { "value": "10 if jerk_print < 16 else math.ceil(jerk_print * 15 / 25)" },
"jerk_support_interface": { "value": "jerk_topbottom" },
"jerk_topbottom": { "value": "10 if jerk_print < 25 else math.ceil(jerk_print * 10 / 25)" },
"jerk_wall": { "value": "10 if jerk_print < 16 else math.ceil(jerk_print * 15 / 25)" },
"jerk_wall_0": { "value": "10 if jerk_wall < 16 else math.ceil(jerk_wall * 6 / 10)" },
"jerk_travel_layer_0": { "value": "math.ceil(jerk_layer_0 * jerk_travel / jerk_print)" },
"extruder_prime_pos_abs": { "default_value": false },
"extruder_prime_pos_x": { "default_value": 0.0, "enabled": false },
"extruder_prime_pos_y": { "default_value": 0.0, "enabled": false },
"extruder_prime_pos_z": { "default_value": 0.0, "enabled": false },
"start_layers_at_same_position":
{
"default_value": false,
"enabled": false,
"value": false
},
"layer_start_x":
{
"default_value": 105.0,
"enabled": false
},
"layer_start_y":
{
"default_value": 27.0,
"enabled": false
},
"prime_tower_position_x": {
"default_value": 185
},
"prime_tower_position_y": {
"default_value": 160
},
"machine_disallowed_areas": {
"default_value": [
[[-115, 112.5], [ -10, 112.5], [ -10, 72.5], [-115, 72.5]],
[[ 115, 112.5], [ 115, 72.5], [ 15, 72.5], [ 15, 112.5]],
[[-115, -112.5], [-115, -87.5], [ 115, -87.5], [ 115, -112.5]],
[[-115, 72.5], [-97, 72.5], [-97, -112.5], [-115, -112.5]]
]
}
}
}

View file

@ -4092,7 +4092,7 @@
"description": "Amount of offset applied to all support polygons in each layer. Positive values can smooth out the support areas and result in more sturdy support.",
"unit": "mm",
"type": "float",
"default_value": 0.2,
"default_value": 0,
"limit_to_extruder": "support_infill_extruder_nr",
"minimum_value_warning": "-1 * machine_nozzle_size",
"maximum_value_warning": "10 * machine_nozzle_size",
@ -6955,6 +6955,203 @@
"type": "float",
"enabled": "bridge_settings_enabled and bridge_enable_more_layers",
"settable_per_mesh": true
},
"clean_between_layers":
{
"label": "Wipe Nozzle Between Layers",
"description": "Whether to include nozzle wipe G-Code between layers. Enabling this setting could influence behavior of retract at layer change. Please use Wipe Retraction settings to control retraction at layers where the wipe script will be working.",
"default_value": false,
"type": "bool",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"max_extrusion_before_wipe":
{
"label": "Material Volume Between Wipes",
"description": "Maximum material, that can be extruded before another nozzle wipe is initiated.",
"default_value": 10,
"type": "float",
"unit": "mm³",
"enabled": "clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_retraction_enable":
{
"label": "Wipe Retraction Enable",
"description": "Retract the filament when the nozzle is moving over a non-printed area.",
"type": "bool",
"default_value": true,
"enabled": "clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_retraction_amount":
{
"label": "Wipe Retraction Distance",
"description": "Amount to retract the filament so it does not ooze during the wipe sequence.",
"unit": "mm",
"type": "float",
"default_value": 1,
"minimum_value_warning": "-0.0001",
"maximum_value_warning": "10.0",
"enabled": "wipe_retraction_enable and clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_retraction_extra_prime_amount":
{
"label": "Wipe Retraction Extra Prime Amount",
"description": "Some material can ooze away during a wipe travel moves, which can be compensated for here.",
"unit": "mm³",
"type": "float",
"default_value": 0,
"minimum_value_warning": "-0.0001",
"maximum_value_warning": "10.0",
"enabled": "wipe_retraction_enable and clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"wipe_retraction_speed":
{
"label": "Wipe Retraction Speed",
"description": "The speed at which the filament is retracted and primed during a wipe retraction move.",
"unit": "mm/s",
"type": "float",
"default_value": 5,
"minimum_value": "0",
"minimum_value_warning": "1",
"maximum_value": "machine_max_feedrate_e",
"maximum_value_warning": "70",
"enabled": "wipe_retraction_enable and clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"wipe_retraction_retract_speed":
{
"label": "Wipe Retraction Retract Speed",
"description": "The speed at which the filament is retracted during a wipe retraction move.",
"unit": "mm/s",
"type": "float",
"default_value": 3,
"minimum_value": "0",
"maximum_value": "machine_max_feedrate_e",
"minimum_value_warning": "1",
"maximum_value_warning": "70",
"enabled": "wipe_retraction_enable and clean_between_layers",
"value": "retraction_speed",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"wipe_retraction_prime_speed":
{
"label": "Retraction Prime Speed",
"description": "The speed at which the filament is primed during a wipe retraction move.",
"unit": "mm/s",
"type": "float",
"default_value": 2,
"minimum_value": "0",
"maximum_value": "machine_max_feedrate_e",
"minimum_value_warning": "1",
"maximum_value_warning": "70",
"enabled": "wipe_retraction_enable and clean_between_layers",
"value": "retraction_speed",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
},
"wipe_pause":
{
"label": "Wipe Pause",
"description": "Pause after the unretract.",
"unit": "s",
"type": "float",
"default_value": 0,
"minimum_value": "0",
"enabled": "clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_hop_enable":
{
"label": "Wipe Z Hop When Retracted",
"description": "Whenever a retraction is done, the build plate is lowered to create clearance between the nozzle and the print. It prevents the nozzle from hitting the print during travel moves, reducing the chance to knock the print from the build plate.",
"type": "bool",
"default_value": true,
"enabled": "clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_hop_amount":
{
"label": "Wipe Z Hop Height",
"description": "The height difference when performing a Z Hop.",
"unit": "mm",
"type": "float",
"default_value": 1,
"enabled": "wipe_hop_enable and clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_hop_speed":
{
"label": "Wipe Hop Speed",
"description": "Speed to move the z-axis during the hop.",
"unit": "mm/s",
"type": "float",
"default_value": 100,
"minimum_value": "0",
"minimum_value_warning": "1",
"enabled": "wipe_hop_enable and clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_brush_pos_x":
{
"label": "Wipe Brush X Position",
"description": "X location where wipe script will start.",
"type": "float",
"unit": "mm",
"default_value": 100,
"minimum_value_warning": "0",
"enabled": "clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_repeat_count":
{
"label": "Wipe Repeat Count",
"description": "Number of times to move the nozzle across the brush.",
"type": "int",
"minimum_value": "0",
"default_value": 5,
"enabled": "clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
},
"wipe_move_distance":
{
"label": "Wipe Move Distance",
"description": "The distance to move the head back and forth across the brush.",
"unit": "mm",
"type": "float",
"default_value": 20,
"enabled": "clean_between_layers",
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false
}
}
},

View file

@ -121,7 +121,7 @@
"retraction_hop_enabled": {"value": false},
"retraction_hop": {"value": 1},
"retraction_combing": {"value": "off"},
"retraction_combing": {"value": "'off'"},
"cool_fan_speed": {"value": 0},
"cool_fan_enabled": {"value": true},

View file

@ -12,8 +12,8 @@
"has_materials": true,
"has_machine_quality": true,
"exclude_materials": ["generic_hips", "generic_petg", "generic_bam", "ultimaker_bam", "generic_pva", "ultimaker_pva", "generic_tough_pla", "ultimaker_tough_pla_black", "ultimaker_tough_pla_green", "ultimaker_tough_pla_red", "ultimaker_tough_pla_white", "generic_cffcpe", "generic_cffpa", "generic_gffcpe", "generic_gffpa", "structur3d_dap100silicone" ],
"first_start_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"],
"supported_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"],
"first_start_actions": ["UMOUpgradeSelection", "BedLevel"],
"supported_actions": ["UMOUpgradeSelection", "BedLevel"],
"machine_extruder_trains":
{
"0": "ultimaker_original_extruder_0"

View file

@ -20,8 +20,8 @@
},
"firmware_file": "MarlinUltimaker-{baudrate}-dual.hex",
"firmware_hbk_file": "MarlinUltimaker-HBK-{baudrate}-dual.hex",
"first_start_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"],
"supported_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"]
"first_start_actions": ["UMOUpgradeSelection", "BedLevel"],
"supported_actions": ["UMOUpgradeSelection", "BedLevel"]
},
"overrides": {

View file

@ -10,8 +10,8 @@
"platform": "ultimaker2_platform.obj",
"platform_texture": "UltimakerPlusbackplate.png",
"quality_definition": "ultimaker_original",
"first_start_actions": ["UMOCheckup", "BedLevel"],
"supported_actions": ["UMOCheckup", "BedLevel"],
"first_start_actions": ["BedLevel"],
"supported_actions": ["BedLevel"],
"machine_extruder_trains":
{
"0": "ultimaker_original_plus_extruder_0"

View file

@ -0,0 +1,19 @@
{
"id": "Mark2_extruder1",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
"machine": "Mark2_for_Ultimaker2",
"position": "0"
},
"overrides": {
"extruder_nr": {
"default_value": 0,
"maximum_value": "1"
},
"machine_nozzle_offset_x": { "default_value": 0.0 },
"machine_nozzle_offset_y": { "default_value": 0.0 }
}
}

View file

@ -0,0 +1,19 @@
{
"id": "Mark2_extruder2",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
"metadata": {
"machine": "Mark2_for_Ultimaker2",
"position": "1"
},
"overrides": {
"extruder_nr": {
"default_value": 1,
"maximum_value": "1"
},
"machine_nozzle_offset_x": { "default_value": 0.0 },
"machine_nozzle_offset_y": { "default_value": 0.0 }
}
}

View file

@ -966,11 +966,6 @@ msgctxt "@action"
msgid "Select upgrades"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
@ -3085,101 +3080,6 @@ msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
msgctxt "@title"
msgid "Check Printer"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
msgctxt "@label"
msgid ""
"It's a good idea to do a few sanity checks on your Ultimaker. You can skip "
"this step if you know your machine is functional"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
msgctxt "@action:button"
msgid "Start Printer Check"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
msgctxt "@label"
msgid "Connection: "
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Connected"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Not connected"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
msgctxt "@label"
msgid "Min endstop X: "
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
msgctxt "@info:status"
msgid "Works"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Not checked"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
msgctxt "@label"
msgid "Min endstop Y: "
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
msgctxt "@label"
msgid "Min endstop Z: "
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
msgctxt "@label"
msgid "Nozzle temperature check: "
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Stop Heating"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Start Heating"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
msgctxt "@label"
msgid "Build plate temperature check:"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Checked"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
msgctxt "@label"
msgid "Everything is in order! You're done with your CheckUp."
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"

View file

@ -923,11 +923,6 @@ msgctxt "@action"
msgid "Select upgrades"
msgstr "Upgrades wählen"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
msgstr "Check-up"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
@ -2956,99 +2951,6 @@ msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Beheizte Druckplatte (offizielles Kit oder Eigenbau)"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
msgctxt "@title"
msgid "Check Printer"
msgstr "Drucker prüfen"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
msgctxt "@label"
msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
msgstr "Sie sollten einige Sanity Checks bei Ihrem Ultimaker durchführen. Sie können diesen Schritt überspringen, wenn Sie wissen, dass Ihr Gerät funktionsfähig ist"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
msgctxt "@action:button"
msgid "Start Printer Check"
msgstr "Überprüfung des Druckers starten"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
msgctxt "@label"
msgid "Connection: "
msgstr "Verbindung: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Connected"
msgstr "Verbunden"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Not connected"
msgstr "Nicht verbunden"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
msgctxt "@label"
msgid "Min endstop X: "
msgstr "Min. Endstopp X: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
msgctxt "@info:status"
msgid "Works"
msgstr "Funktionsfähig"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Not checked"
msgstr "Nicht überprüft"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
msgctxt "@label"
msgid "Min endstop Y: "
msgstr "Min. Endstopp Y: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
msgctxt "@label"
msgid "Min endstop Z: "
msgstr "Min. Endstopp Z: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
msgctxt "@label"
msgid "Nozzle temperature check: "
msgstr "Temperaturprüfung der Düse: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Stop Heating"
msgstr "Aufheizen stoppen"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Start Heating"
msgstr "Aufheizen starten"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
msgctxt "@label"
msgid "Build plate temperature check:"
msgstr "Temperaturprüfung der Druckplatte:"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Checked"
msgstr "Geprüft"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
msgctxt "@label"
msgid "Everything is in order! You're done with your CheckUp."
msgstr "Alles ist in Ordnung! Der Check-up ist abgeschlossen."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"

View file

@ -923,11 +923,6 @@ msgctxt "@action"
msgid "Select upgrades"
msgstr "Seleccionar actualizaciones"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
msgstr "Comprobación"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
@ -2956,99 +2951,6 @@ msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Placa de impresión caliente (kit oficial o construida por usted mismo)"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
msgctxt "@title"
msgid "Check Printer"
msgstr "Comprobar impresora"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
msgctxt "@label"
msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
msgstr "Es una buena idea hacer un par de comprobaciones en su Ultimaker. Puede omitir este paso si usted sabe que su máquina funciona correctamente"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
msgctxt "@action:button"
msgid "Start Printer Check"
msgstr "Iniciar comprobación de impresora"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
msgctxt "@label"
msgid "Connection: "
msgstr "Conexión: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Connected"
msgstr "Conectado"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Not connected"
msgstr "Sin conexión"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
msgctxt "@label"
msgid "Min endstop X: "
msgstr "Parada final mín. en X: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
msgctxt "@info:status"
msgid "Works"
msgstr "Funciona"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Not checked"
msgstr "Sin comprobar"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
msgctxt "@label"
msgid "Min endstop Y: "
msgstr "Parada final mín. en Y: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
msgctxt "@label"
msgid "Min endstop Z: "
msgstr "Parada final mín. en Z: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
msgctxt "@label"
msgid "Nozzle temperature check: "
msgstr "Comprobación de la temperatura de la tobera: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Stop Heating"
msgstr "Detener calentamiento"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Start Heating"
msgstr "Iniciar calentamiento"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
msgctxt "@label"
msgid "Build plate temperature check:"
msgstr "Comprobación de la temperatura de la placa de impresión:"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Checked"
msgstr "Comprobada"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
msgctxt "@label"
msgid "Everything is in order! You're done with your CheckUp."
msgstr "¡Todo correcto! Ha terminado con la comprobación."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"

View file

@ -921,11 +921,6 @@ msgctxt "@action"
msgid "Select upgrades"
msgstr "Valitse päivitykset"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
msgstr "Tarkastus"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
@ -2957,99 +2952,6 @@ msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Lämmitettävä alusta (virallinen sarja tai itse rakennettu)"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
msgctxt "@title"
msgid "Check Printer"
msgstr "Tarkista tulostin"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
msgctxt "@label"
msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
msgstr "Ultimakerille on hyvä tehdä muutamia toimintatarkastuksia. Voit jättää tämän vaiheen väliin, jos tiedät laitteesi olevan toimintakunnossa"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
msgctxt "@action:button"
msgid "Start Printer Check"
msgstr "Aloita tulostintarkistus"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
msgctxt "@label"
msgid "Connection: "
msgstr "Yhteys: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Connected"
msgstr "Yhdistetty"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Not connected"
msgstr "Ei yhteyttä"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
msgctxt "@label"
msgid "Min endstop X: "
msgstr "Min. päätyraja X: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
msgctxt "@info:status"
msgid "Works"
msgstr "Toimii"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Not checked"
msgstr "Ei tarkistettu"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
msgctxt "@label"
msgid "Min endstop Y: "
msgstr "Min. päätyraja Y: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
msgctxt "@label"
msgid "Min endstop Z: "
msgstr "Min. päätyraja Z: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
msgctxt "@label"
msgid "Nozzle temperature check: "
msgstr "Suuttimen lämpötilatarkistus: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Stop Heating"
msgstr "Lopeta lämmitys"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Start Heating"
msgstr "Aloita lämmitys"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
msgctxt "@label"
msgid "Build plate temperature check:"
msgstr "Alustan lämpötilan tarkistus:"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Checked"
msgstr "Tarkistettu"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
msgctxt "@label"
msgid "Everything is in order! You're done with your CheckUp."
msgstr "Kaikki on kunnossa! CheckUp on valmis."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"

View file

@ -923,11 +923,6 @@ msgctxt "@action"
msgid "Select upgrades"
msgstr "Sélectionner les mises à niveau"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
msgstr "Check-up"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
@ -2956,99 +2951,6 @@ msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Plateau chauffant (kit officiel ou fabriqué soi-même)"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
msgctxt "@title"
msgid "Check Printer"
msgstr "Tester l'imprimante"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
msgctxt "@label"
msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
msgstr "Il est préférable de procéder à quelques tests de fonctionnement sur votre Ultimaker. Vous pouvez passer cette étape si vous savez que votre machine est fonctionnelle"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
msgctxt "@action:button"
msgid "Start Printer Check"
msgstr "Démarrer le test de l'imprimante"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
msgctxt "@label"
msgid "Connection: "
msgstr "Connexion : "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Connected"
msgstr "Connecté"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Not connected"
msgstr "Non connecté"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
msgctxt "@label"
msgid "Min endstop X: "
msgstr "Fin de course X : "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
msgctxt "@info:status"
msgid "Works"
msgstr "Fonctionne"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Not checked"
msgstr "Non testé"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
msgctxt "@label"
msgid "Min endstop Y: "
msgstr "Fin de course Y : "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
msgctxt "@label"
msgid "Min endstop Z: "
msgstr "Fin de course Z : "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
msgctxt "@label"
msgid "Nozzle temperature check: "
msgstr "Test de la température de la buse : "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Stop Heating"
msgstr "Arrêter le chauffage"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Start Heating"
msgstr "Démarrer le chauffage"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
msgctxt "@label"
msgid "Build plate temperature check:"
msgstr "Contrôle de la température du plateau :"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Checked"
msgstr "Contrôlée"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
msgctxt "@label"
msgid "Everything is in order! You're done with your CheckUp."
msgstr "Tout est en ordre ! Vous avez terminé votre check-up."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"

View file

@ -927,11 +927,6 @@ msgctxt "@action"
msgid "Select upgrades"
msgstr "Seleziona aggiornamenti"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
msgstr "Controllo"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
@ -2977,99 +2972,6 @@ msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "Piano di stampa riscaldato (kit ufficiale o integrato)"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
msgctxt "@title"
msgid "Check Printer"
msgstr "Controllo stampante"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
msgctxt "@label"
msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
msgstr "È consigliabile eseguire alcuni controlli di integrità sulla Ultimaker. È possibile saltare questo passaggio se si è certi che la macchina funziona correttamente"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
msgctxt "@action:button"
msgid "Start Printer Check"
msgstr "Avvia controllo stampante"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
msgctxt "@label"
msgid "Connection: "
msgstr "Collegamento: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Connected"
msgstr "Collegato"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Not connected"
msgstr "Non collegato"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
msgctxt "@label"
msgid "Min endstop X: "
msgstr "Endstop min. asse X: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
msgctxt "@info:status"
msgid "Works"
msgstr "Funziona"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Not checked"
msgstr "Controllo non selezionato"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
msgctxt "@label"
msgid "Min endstop Y: "
msgstr "Endstop min. asse Y: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
msgctxt "@label"
msgid "Min endstop Z: "
msgstr "Endstop min. asse Z: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
msgctxt "@label"
msgid "Nozzle temperature check: "
msgstr "Controllo temperatura ugello: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Stop Heating"
msgstr "Arresto riscaldamento"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Start Heating"
msgstr "Avvio riscaldamento"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
msgctxt "@label"
msgid "Build plate temperature check:"
msgstr "Controllo temperatura piano di stampa:"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Checked"
msgstr "Controllo eseguito"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
msgctxt "@label"
msgid "Everything is in order! You're done with your CheckUp."
msgstr "È tutto in ordine! Controllo terminato."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"

View file

@ -928,11 +928,6 @@ msgctxt "@action"
msgid "Select upgrades"
msgstr "アップグレードを選択する"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
msgstr "チェックアップ"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action"
msgid "Level build plate"
@ -2976,99 +2971,6 @@ msgctxt "@label"
msgid "Heated Build Plate (official kit or self-built)"
msgstr "ヒーティッドビルドプレート(オフィシャルキットまたはセルフビルド)"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:27
msgctxt "@title"
msgid "Check Printer"
msgstr "プリンターチェック"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:39
msgctxt "@label"
msgid "It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"
msgstr "お持ちのUltimkaerにてサニティーチェックを数回行うことは推奨します。もしプリンター機能に問題ない場合はこの項目をスキップしてください"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:53
msgctxt "@action:button"
msgid "Start Printer Check"
msgstr "プリンターチェックを開始する"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:80
msgctxt "@label"
msgid "Connection: "
msgstr "コネクション: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Connected"
msgstr "接続済"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:89
msgctxt "@info:status"
msgid "Not connected"
msgstr "プリンターにつながっていません"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:99
msgctxt "@label"
msgid "Min endstop X: "
msgstr "エンドストップ X: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
msgctxt "@info:status"
msgid "Works"
msgstr "作品"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:109
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:130
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:151
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:173
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Not checked"
msgstr "チェックされていません"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:120
msgctxt "@label"
msgid "Min endstop Y: "
msgstr "エンドストップ Y: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:141
msgctxt "@label"
msgid "Min endstop Z: "
msgstr "エンドストップ Z: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:163
msgctxt "@label"
msgid "Nozzle temperature check: "
msgstr "ノズル温度チェック: "
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Stop Heating"
msgstr "ヒーティングストップ"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:187
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:248
msgctxt "@action:button"
msgid "Start Heating"
msgstr "ヒーティング開始"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:223
msgctxt "@label"
msgid "Build plate temperature check:"
msgstr "ビルドプレートの温度チェック:"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:234
msgctxt "@info:status"
msgid "Checked"
msgstr "チェック済"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml:284
msgctxt "@label"
msgid "Everything is in order! You're done with your CheckUp."
msgstr "すべてに異常はありません。チェックアップを終了しました。"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:119
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"

Some files were not shown because too many files have changed in this diff Show more