Merge branch 'master' into temp_CURA-5864

This commit is contained in:
Remco Burema 2019-02-06 16:23:30 +01:00
commit da6ff7c5a9
95 changed files with 2061 additions and 1277 deletions

View File

@ -17,6 +17,7 @@ if(CURA_DEBUGMODE)
set(_cura_debugmode "ON")
endif()
set(CURA_APP_NAME "cura" CACHE STRING "Short name of Cura, used for configuration folder")
set(CURA_APP_DISPLAY_NAME "Ultimaker Cura" CACHE STRING "Display name of Cura")
set(CURA_VERSION "master" CACHE STRING "Version name of Cura")
set(CURA_BUILDTYPE "" CACHE STRING "Build type of Cura, eg. 'PPA'")

View File

@ -2,14 +2,22 @@
# Cura is released under the terms of the LGPLv3 or higher.
# ---------
# Genearl constants used in Cura
# General constants used in Cura
# ---------
DEFAULT_CURA_APP_NAME = "cura"
DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura"
DEFAULT_CURA_VERSION = "master"
DEFAULT_CURA_BUILD_TYPE = ""
DEFAULT_CURA_DEBUG_MODE = False
DEFAULT_CURA_SDK_VERSION = "6.0.0"
try:
from cura.CuraVersion import CuraAppName # type: ignore
if CuraAppName == "":
CuraAppName = DEFAULT_CURA_APP_NAME
except ImportError:
CuraAppName = DEFAULT_CURA_APP_NAME
try:
from cura.CuraVersion import CuraAppDisplayName # type: ignore
if CuraAppDisplayName == "":

View File

@ -156,7 +156,7 @@ class CuraApplication(QtApplication):
Q_ENUMS(ResourceTypes)
def __init__(self, *args, **kwargs):
super().__init__(name = "cura",
super().__init__(name = ApplicationMetadata.CuraAppName,
app_display_name = ApplicationMetadata.CuraAppDisplayName,
version = ApplicationMetadata.CuraVersion,
api_version = ApplicationMetadata.CuraSDKVersion,

View File

@ -1,6 +1,7 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
CuraAppName = "@CURA_APP_NAME@"
CuraAppDisplayName = "@CURA_APP_DISPLAY_NAME@"
CuraVersion = "@CURA_VERSION@"
CuraBuildType = "@CURA_BUILDTYPE@"

View File

@ -1,12 +1,11 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtProperty, Qt
from PyQt5.QtCore import Qt
from UM.Qt.ListModel import ListModel
from UM.Settings.ContainerRegistry import ContainerRegistry
from cura.PrinterOutputDevice import ConnectionType
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
class GlobalStacksModel(ListModel):
@ -21,14 +20,13 @@ class GlobalStacksModel(ListModel):
self.addRoleName(self.NameRole, "name")
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
self.addRoleName(self.ConnectionTypeRole, "connectionType")
self.addRoleName(self.MetaDataRole, "metadata")
self._container_stacks = []
# Listen to changes
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
ContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
self._filter_dict = {}
self._update()
@ -43,19 +41,20 @@ class GlobalStacksModel(ListModel):
def _update(self) -> None:
items = []
container_stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine")
container_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine")
for container_stack in container_stacks:
connection_type = int(container_stack.getMetaDataEntry("connection_type", ConnectionType.NotConnected.value))
has_remote_connection = connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
has_remote_connection = False
for connection_type in container_stack.configuredConnectionTypes:
has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
if container_stack.getMetaDataEntry("hidden", False) in ["True", True]:
continue
# TODO: Remove reference to connect group name.
items.append({"name": container_stack.getMetaDataEntry("connect_group_name", container_stack.getName()),
items.append({"name": container_stack.getMetaDataEntry("group_name", container_stack.getName()),
"id": container_stack.getId(),
"hasRemoteConnection": has_remote_connection,
"connectionType": connection_type,
"metadata": container_stack.getMetaData().copy()})
items.sort(key=lambda i: not i["hasRemoteConnection"])
self.setItems(items)

View File

@ -7,43 +7,36 @@ from UM.Mesh.MeshBuilder import MeshBuilder
from .LayerData import LayerData
import numpy
from typing import Dict, Optional
## Builder class for constructing a LayerData object
class LayerDataBuilder(MeshBuilder):
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._layers = {}
self._element_counts = {}
self._layers = {} # type: Dict[int, Layer]
self._element_counts = {} # type: Dict[int, int]
def addLayer(self, layer):
def addLayer(self, layer: int) -> None:
if layer not in self._layers:
self._layers[layer] = Layer(layer)
def addPolygon(self, layer, polygon_type, data, line_width, line_thickness, line_feedrate):
if layer not in self._layers:
self.addLayer(layer)
def getLayer(self, layer: int) -> Optional[Layer]:
return self._layers.get(layer)
p = LayerPolygon(self, polygon_type, data, line_width, line_thickness, line_feedrate)
self._layers[layer].polygons.append(p)
def getLayer(self, layer):
if layer in self._layers:
return self._layers[layer]
def getLayers(self):
def getLayers(self) -> Dict[int, Layer]:
return self._layers
def getElementCounts(self):
def getElementCounts(self) -> Dict[int, int]:
return self._element_counts
def setLayerHeight(self, layer, height):
def setLayerHeight(self, layer: int, height: float) -> None:
if layer not in self._layers:
self.addLayer(layer)
self._layers[layer].setHeight(height)
def setLayerThickness(self, layer, thickness):
def setLayerThickness(self, layer: int, thickness: float) -> None:
if layer not in self._layers:
self.addLayer(layer)
@ -71,7 +64,7 @@ class LayerDataBuilder(MeshBuilder):
vertex_offset = 0
index_offset = 0
for layer, data in sorted(self._layers.items()):
( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices)
vertex_offset, index_offset = data.build(vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices)
self._element_counts[layer] = data.elementCount
self.addVertices(vertices)

View File

@ -1,13 +1,25 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
from cura.LayerData import LayerData
## Simple decorator to indicate a scene node holds layer data.
class LayerDataDecorator(SceneNodeDecorator):
def __init__(self):
super().__init__()
self._layer_data = None
self._layer_data = None # type: Optional[LayerData]
def getLayerData(self):
def getLayerData(self) -> Optional["LayerData"]:
return self._layer_data
def setLayerData(self, layer_data):
def setLayerData(self, layer_data: LayerData) -> None:
self._layer_data = layer_data
def __deepcopy__(self, memo) -> "LayerDataDecorator":
copied_decorator = LayerDataDecorator()
copied_decorator._layer_data = self._layer_data
return copied_decorator

View File

@ -2,7 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Application import Application
from typing import Any
from typing import Any, Optional
import numpy
from UM.Logger import Logger
@ -26,13 +26,13 @@ class LayerPolygon:
__jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(__number_of_types) == NoneType, numpy.arange(__number_of_types) == MoveCombingType), numpy.arange(__number_of_types) == MoveRetractionType)
## LayerPolygon, used in ProcessSlicedLayersJob
# \param extruder
# \param extruder The position of the extruder
# \param line_types array with line_types
# \param data new_points
# \param line_widths array with line widths
# \param line_thicknesses: array with type as index and thickness as value
# \param line_feedrates array with line feedrates
def __init__(self, extruder, line_types, data, line_widths, line_thicknesses, line_feedrates):
def __init__(self, extruder: int, line_types: numpy.ndarray, data: numpy.ndarray, line_widths: numpy.ndarray, line_thicknesses: numpy.ndarray, line_feedrates: numpy.ndarray) -> None:
self._extruder = extruder
self._types = line_types
for i in range(len(self._types)):
@ -57,16 +57,16 @@ class LayerPolygon:
# Buffering the colors shouldn't be necessary as it is not
# re-used and can save alot of memory usage.
self._color_map = LayerPolygon.getColorMap()
self._colors = self._color_map[self._types]
self._colors = self._color_map[self._types] # type: numpy.ndarray
# When type is used as index returns true if type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType
# Should be generated in better way, not hardcoded.
self._isInfillOrSkinTypeMap = numpy.array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1], dtype=numpy.bool)
self._build_cache_line_mesh_mask = None
self._build_cache_needed_points = None
self._build_cache_line_mesh_mask = None # type: Optional[numpy.ndarray]
self._build_cache_needed_points = None # type: Optional[numpy.ndarray]
def buildCache(self):
def buildCache(self) -> None:
# For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out.
self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype=bool)
mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask)
@ -94,10 +94,14 @@ class LayerPolygon:
# \param extruders : vertex numpy array to be filled
# \param line_types : vertex numpy array to be filled
# \param indices : index numpy array to be filled
def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices):
def build(self, vertex_offset: int, index_offset: int, vertices: numpy.ndarray, colors: numpy.ndarray, line_dimensions: numpy.ndarray, feedrates: numpy.ndarray, extruders: numpy.ndarray, line_types: numpy.ndarray, indices: numpy.ndarray) -> None:
if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None:
self.buildCache()
if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None:
Logger.log("w", "Failed to build cache for layer polygon")
return
line_mesh_mask = self._build_cache_line_mesh_mask
needed_points_list = self._build_cache_needed_points

View File

@ -52,14 +52,14 @@ class MachineManagementModel(ListModel):
"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("connect_group_name"))
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["connect_group_name"],
items.append({"name": metadata.get("group_name", ""),
"id": container.getId(),
"metadata": metadata,
"group": catalog.i18nc("@info:title", "Network enabled printers")})

View File

@ -81,8 +81,8 @@ class GenericOutputController(PrinterOutputController):
self._output_device.cancelPrint()
pass
def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int) -> None:
self._output_device.sendCommand("M140 S%s" % temperature)
def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: float) -> None:
self._output_device.sendCommand("M140 S%s" % round(temperature)) # The API doesn't allow floating point.
def _onTargetBedTemperatureChanged(self) -> None:
if self._preheat_bed_timer.isActive() and self._preheat_printer and self._preheat_printer.targetBedTemperature == 0:
@ -96,14 +96,14 @@ class GenericOutputController(PrinterOutputController):
except ValueError:
return # Got invalid values, can't pre-heat.
self.setTargetBedTemperature(printer, temperature=temperature)
self.setTargetBedTemperature(printer, temperature = temperature)
self._preheat_bed_timer.setInterval(duration * 1000)
self._preheat_bed_timer.start()
self._preheat_printer = printer
printer.updateIsPreheating(True)
def cancelPreheatBed(self, printer: "PrinterOutputModel") -> None:
self.setTargetBedTemperature(printer, temperature=0)
self.setTargetBedTemperature(printer, temperature = 0)
self._preheat_bed_timer.stop()
printer.updateIsPreheating(False)

View File

@ -132,8 +132,7 @@ class PrintJobOutputModel(QObject):
@pyqtProperty(float, notify = timeElapsedChanged)
def progress(self) -> float:
time_elapsed = max(float(self.timeElapsed), 1.0) # Prevent a division by zero exception
result = time_elapsed / self.timeTotal
result = float(self.timeElapsed) / max(self.timeTotal, 1.0) # Prevent a division by zero exception.
return min(result, 1.0) # Never get a progress past 1.0
@pyqtProperty(str, notify=stateChanged)

View File

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Logger import Logger
@ -25,10 +25,10 @@ class PrinterOutputController:
self.can_update_firmware = False
self._output_device = output_device
def setTargetHotendTemperature(self, printer: "PrinterOutputModel", position: int, temperature: Union[int, float]) -> None:
def setTargetHotendTemperature(self, printer: "PrinterOutputModel", position: int, temperature: float) -> None:
Logger.log("w", "Set target hotend temperature not implemented in controller")
def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int) -> None:
def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: float) -> None:
Logger.log("w", "Set target bed temperature not implemented in controller")
def setJobState(self, job: "PrintJobOutputModel", state: str) -> None:

View File

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot, QUrl
@ -30,8 +30,8 @@ class PrinterOutputModel(QObject):
def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = "") -> None:
super().__init__(parent)
self._bed_temperature = -1 # Use -1 for no heated bed.
self._target_bed_temperature = 0
self._bed_temperature = -1 # type: float # Use -1 for no heated bed.
self._target_bed_temperature = 0 # type: float
self._name = ""
self._key = "" # Unique identifier
self._controller = output_controller
@ -188,19 +188,19 @@ class PrinterOutputModel(QObject):
self.nameChanged.emit()
## Update the bed temperature. This only changes it locally.
def updateBedTemperature(self, temperature: int) -> None:
def updateBedTemperature(self, temperature: float) -> None:
if self._bed_temperature != temperature:
self._bed_temperature = temperature
self.bedTemperatureChanged.emit()
def updateTargetBedTemperature(self, temperature: int) -> None:
def updateTargetBedTemperature(self, temperature: float) -> None:
if self._target_bed_temperature != temperature:
self._target_bed_temperature = temperature
self.targetBedTemperatureChanged.emit()
## Set the target bed temperature. This ensures that it's actually sent to the remote.
@pyqtSlot(int)
def setTargetBedTemperature(self, temperature: int) -> None:
@pyqtSlot(float)
def setTargetBedTemperature(self, temperature: float) -> None:
self._controller.setTargetBedTemperature(self, temperature)
self.updateTargetBedTemperature(temperature)
@ -225,55 +225,55 @@ class PrinterOutputModel(QObject):
def activePrintJob(self) -> Optional["PrintJobOutputModel"]:
return self._active_print_job
@pyqtProperty(str, notify=stateChanged)
@pyqtProperty(str, notify = stateChanged)
def state(self) -> str:
return self._printer_state
@pyqtProperty(int, notify=bedTemperatureChanged)
def bedTemperature(self) -> int:
@pyqtProperty(float, notify = bedTemperatureChanged)
def bedTemperature(self) -> float:
return self._bed_temperature
@pyqtProperty(int, notify=targetBedTemperatureChanged)
def targetBedTemperature(self) -> int:
@pyqtProperty(float, notify = targetBedTemperatureChanged)
def targetBedTemperature(self) -> float:
return self._target_bed_temperature
# Does the printer support pre-heating the bed at all
@pyqtProperty(bool, constant=True)
@pyqtProperty(bool, constant = True)
def canPreHeatBed(self) -> bool:
if self._controller:
return self._controller.can_pre_heat_bed
return False
# Does the printer support pre-heating the bed at all
@pyqtProperty(bool, constant=True)
@pyqtProperty(bool, constant = True)
def canPreHeatHotends(self) -> bool:
if self._controller:
return self._controller.can_pre_heat_hotends
return False
# Does the printer support sending raw G-code at all
@pyqtProperty(bool, constant=True)
@pyqtProperty(bool, constant = True)
def canSendRawGcode(self) -> bool:
if self._controller:
return self._controller.can_send_raw_gcode
return False
# Does the printer support pause at all
@pyqtProperty(bool, constant=True)
@pyqtProperty(bool, constant = True)
def canPause(self) -> bool:
if self._controller:
return self._controller.can_pause
return False
# Does the printer support abort at all
@pyqtProperty(bool, constant=True)
@pyqtProperty(bool, constant = True)
def canAbort(self) -> bool:
if self._controller:
return self._controller.can_abort
return False
# Does the printer support manual control at all
@pyqtProperty(bool, constant=True)
@pyqtProperty(bool, constant = True)
def canControlManually(self) -> bool:
if self._controller:
return self._controller.can_control_manually

View File

@ -10,7 +10,7 @@ class GCodeListDecorator(SceneNodeDecorator):
def getGCodeList(self) -> List[str]:
return self._gcode_list
def setGCodeList(self, list: List[str]):
def setGCodeList(self, list: List[str]) -> None:
self._gcode_list = list
def __deepcopy__(self, memo) -> "GCodeListDecorator":

View File

@ -107,17 +107,19 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
# that signal. Application.globalContainerStackChanged doesn't fill this
# signal; it's assumed to be the current printer in that case.
def _extrudersChanged(self, machine_id = None):
machine_manager = Application.getInstance().getMachineManager()
if machine_id is not None:
if Application.getInstance().getGlobalContainerStack() is None:
if machine_manager.activeMachine is None:
# No machine, don't need to update the current machine's extruders
return
if machine_id != Application.getInstance().getGlobalContainerStack().getId():
if machine_id != machine_manager.activeMachine.getId():
# Not the current machine
return
# Unlink from old extruders
for extruder in self._active_machine_extruders:
extruder.containersChanged.disconnect(self._onExtruderStackContainersChanged)
extruder.enabledChanged.disconnect(self._updateExtruders)
# Link to new extruders
self._active_machine_extruders = []
@ -126,6 +128,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
if extruder is None: #This extruder wasn't loaded yet. This happens asynchronously while this model is constructed from QML.
continue
extruder.containersChanged.connect(self._onExtruderStackContainersChanged)
extruder.enabledChanged.connect(self._updateExtruders)
self._active_machine_extruders.append(extruder)
self._updateExtruders() # Since the new extruders may have different properties, update our own model.

View File

@ -42,7 +42,12 @@ class GlobalStack(CuraContainerStack):
# Per thread we have our own resolving_settings, or strange things sometimes occur.
self._resolving_settings = defaultdict(set) #type: Dict[str, Set[str]] # keys are thread names
# Since the metadatachanged is defined in container stack, we can't use it here as a notifier for pyqt
# properties. So we need to tie them together like this.
self.metaDataChanged.connect(self.configuredConnectionTypesChanged)
extrudersChanged = pyqtSignal()
configuredConnectionTypesChanged = pyqtSignal()
## Get the list of extruders of this stack.
#
@ -63,6 +68,37 @@ class GlobalStack(CuraContainerStack):
def getLoadingPriority(cls) -> int:
return 2
## The configured connection types can be used to find out if the global
# stack is configured to be connected with a printer, without having to
# know all the details as to how this is exactly done (and without
# actually setting the stack to be active).
#
# This data can then in turn also be used when the global stack is active;
# If we can't get a network connection, but it is configured to have one,
# we can display a different icon to indicate the difference.
@pyqtProperty("QVariantList", notify=configuredConnectionTypesChanged)
def configuredConnectionTypes(self) -> List[int]:
# 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 != ""]
## \sa configuredConnectionTypes
def addConfiguredConnectionType(self, connection_type: int) -> None:
configured_connection_types = self.configuredConnectionTypes
if connection_type not in configured_connection_types:
# Store the values as a string.
configured_connection_types.append(connection_type)
self.setMetaDataEntry("connection_type", ",".join([str(c_type) for c_type in configured_connection_types]))
## \sa configuredConnectionTypes
def removeConfiguredConnectionType(self, connection_type: int) -> None:
configured_connection_types = self.configuredConnectionTypes
if connection_type in self.configured_connection_types:
# Store the values as a string.
configured_connection_types.remove(connection_type)
self.setMetaDataEntry("connection_type", ",".join([str(c_type) for c_type in configured_connection_types]))
@classmethod
def getConfigurationTypeFromSerialized(cls, serialized: str) -> Optional[str]:
configuration_type = super().getConfigurationTypeFromSerialized(serialized)

View File

@ -115,10 +115,6 @@ class MachineManager(QObject):
self._application.callLater(self.setInitialActiveMachine)
self._material_incompatible_message = Message(catalog.i18nc("@info:status",
"The selected material is incompatible with the selected machine or configuration."),
title = catalog.i18nc("@info:title", "Incompatible Material")) # type: Message
containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = self.activeMaterialId) # type: List[InstanceContainer]
if containers:
containers[0].nameChanged.connect(self._onMaterialNameChanged)
@ -505,7 +501,7 @@ class MachineManager(QObject):
@pyqtProperty(str, notify = globalContainerChanged)
def activeMachineName(self) -> str:
if self._global_container_stack:
return self._global_container_stack.getName()
return self._global_container_stack.getMetaDataEntry("group_name", self._global_container_stack.getName())
return ""
@pyqtProperty(str, notify = globalContainerChanged)
@ -521,10 +517,20 @@ class MachineManager(QObject):
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineHasRemoteConnection(self) -> bool:
if self._global_container_stack:
connection_type = int(self._global_container_stack.getMetaDataEntry("connection_type", ConnectionType.NotConnected.value))
return connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
has_remote_connection = False
for connection_type in self._global_container_stack.configuredConnectionTypes:
has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value,
ConnectionType.CloudConnection.value]
return has_remote_connection
return False
@pyqtProperty("QVariantList", notify=globalContainerChanged)
def activeMachineConfiguredConnectionTypes(self):
if self._global_container_stack:
return self._global_container_stack.configuredConnectionTypes
return []
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineIsGroup(self) -> bool:
return bool(self._printer_output_devices) and len(self._printer_output_devices[0].printers) > 1
@ -547,7 +553,7 @@ class MachineManager(QObject):
@pyqtProperty(str, notify = printerConnectedStatusChanged)
def activeMachineNetworkGroupName(self) -> str:
if self._global_container_stack:
return self._global_container_stack.getMetaDataEntry("connect_group_name", "")
return self._global_container_stack.getMetaDataEntry("group_name", "")
return ""
@pyqtProperty(QObject, notify = globalContainerChanged)
@ -1339,7 +1345,7 @@ class MachineManager(QObject):
if not new_machine:
return
new_machine.setMetaDataEntry("um_network_key", self.activeMachineNetworkKey())
new_machine.setMetaDataEntry("connect_group_name", self.activeMachineNetworkGroupName)
new_machine.setMetaDataEntry("group_name", self.activeMachineNetworkGroupName)
new_machine.setMetaDataEntry("hidden", False)
new_machine.setMetaDataEntry("connection_type", self._global_container_stack.getMetaDataEntry("connection_type"))
else:
@ -1358,15 +1364,45 @@ class MachineManager(QObject):
self.blurSettings.emit()
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
self.switchPrinterType(configuration.printerType)
used_extruder_stack_list = ExtruderManager.getInstance().getUsedExtruderStacks()
disabled_used_extruder_position_set = set()
extruders_to_disable = set()
# If an extruder that's currently used to print a model gets disabled due to the syncing, we need to show
# a message explaining why.
need_to_show_message = False
for extruder_configuration in configuration.extruderConfigurations:
extruder_has_hotend = extruder_configuration.hotendID != ""
extruder_has_material = extruder_configuration.material.guid != ""
# If the machine doesn't have a hotend or material, disable this extruder
if not extruder_has_hotend or not extruder_has_material:
extruders_to_disable.add(extruder_configuration.position)
# If there's no material and/or nozzle on the printer, enable the first extruder and disable the rest.
if len(extruders_to_disable) == len(self._global_container_stack.extruders):
extruders_to_disable.remove(min(extruders_to_disable))
for extruder_configuration in configuration.extruderConfigurations:
position = str(extruder_configuration.position)
variant_container_node = self._variant_manager.getVariantNode(self._global_container_stack.definition.getId(), extruder_configuration.hotendID)
# If the machine doesn't have a hotend or material, disable this extruder
if int(position) in extruders_to_disable:
self._global_container_stack.extruders[position].setEnabled(False)
need_to_show_message = True
disabled_used_extruder_position_set.add(int(position))
else:
variant_container_node = self._variant_manager.getVariantNode(self._global_container_stack.definition.getId(),
extruder_configuration.hotendID)
material_container_node = self._material_manager.getMaterialNodeByType(self._global_container_stack,
position,
extruder_configuration.hotendID,
configuration.buildplateConfiguration,
extruder_configuration.material.guid)
if variant_container_node:
self._setVariantNode(position, variant_container_node)
else:
@ -1376,6 +1412,7 @@ class MachineManager(QObject):
self._setMaterial(position, material_container_node)
else:
self._global_container_stack.extruders[position].material = empty_material_container
self._global_container_stack.extruders[position].setEnabled(True)
self.updateMaterialWithVariant(position)
if configuration.buildplateConfiguration is not None:
@ -1388,6 +1425,21 @@ class MachineManager(QObject):
self._global_container_stack.variant = empty_variant_container
self._updateQualityWithMaterial()
if need_to_show_message:
msg_str = "{extruders} is disabled because there is no material loaded. Please load a material or use custom configurations."
# Show human-readable extruder names such as "Extruder Left", "Extruder Front" instead of "Extruder 1, 2, 3".
extruder_names = []
for position in sorted(disabled_used_extruder_position_set):
extruder_stack = self._global_container_stack.extruders[str(position)]
extruder_name = extruder_stack.definition.getName()
extruder_names.append(extruder_name)
extruders_str = ", ".join(extruder_names)
msg_str = msg_str.format(extruders = extruders_str)
message = Message(catalog.i18nc("@info:status", msg_str),
title = catalog.i18nc("@info:title", "Extruder(s) Disabled"))
message.show()
# See if we need to show the Discard or Keep changes screen
if self.hasUserSettings and self._application.getPreferences().getValue("cura/active_mode") == 1:
self._application.discardOrKeepProfileChanges()
@ -1404,12 +1456,12 @@ class MachineManager(QObject):
# then all the container stacks are updated, both the current and the hidden ones.
def checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
if self._global_container_stack and device_id == self.activeMachineNetworkKey():
# Check if the connect_group_name is correct. If not, update all the containers connected to the same printer
# Check if the group_name is correct. If not, update all the containers connected to the same printer
if self.activeMachineNetworkGroupName != group_name:
metadata_filter = {"um_network_key": self.activeMachineNetworkKey()}
containers = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
for container in containers:
container.setMetaDataEntry("connect_group_name", group_name)
container.setMetaDataEntry("group_name", group_name)
## This method checks if there is an instance connected to the given network_key
def existNetworkInstances(self, network_key: str) -> bool:

View File

@ -9,6 +9,7 @@ import os
import sys
from UM.Platform import Platform
from cura.ApplicationMetadata import CuraAppName
parser = argparse.ArgumentParser(prog = "cura",
add_help = False)
@ -22,11 +23,11 @@ known_args = vars(parser.parse_known_args()[0])
if not known_args["debug"]:
def get_cura_dir_path():
if Platform.isWindows():
return os.path.expanduser("~/AppData/Roaming/cura")
return os.path.expanduser("~/AppData/Roaming/" + CuraAppName)
elif Platform.isLinux():
return os.path.expanduser("~/.local/share/cura")
return os.path.expanduser("~/.local/share/" + CuraAppName)
elif Platform.isOSX():
return os.path.expanduser("~/Library/Logs/cura")
return os.path.expanduser("~/Library/Logs/" + CuraAppName)
if hasattr(sys, "frozen"):
dirpath = get_cura_dir_path()

View File

@ -500,7 +500,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
is_printer_group = False
if machine_conflict:
group_name = existing_global_stack.getMetaDataEntry("connect_group_name")
group_name = existing_global_stack.getMetaDataEntry("group_name")
if group_name is not None:
is_printer_group = True
machine_name = group_name

View File

@ -1,9 +1,9 @@
# 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
from datetime import datetime
from typing import Optional, List, Dict, Any
from typing import Any, cast, Dict, List, Optional
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
@ -68,7 +68,7 @@ class DrivePluginExtension(QObject, Extension):
def showDriveWindow(self) -> None:
if not self._drive_window:
plugin_dir_path = CuraApplication.getInstance().getPluginRegistry().getPluginPath("CuraDrive")
plugin_dir_path = cast(str, CuraApplication.getInstance().getPluginRegistry().getPluginPath(self.getPluginId())) # We know this plug-in exists because that's us, so this always returns str.
path = os.path.join(plugin_dir_path, "src", "qml", "main.qml")
self._drive_window = CuraApplication.getInstance().createQmlComponent(path, {"CuraDrive": self})
self.refreshBackups()

View File

@ -28,7 +28,7 @@ class FirmwareUpdateCheckerMessage(Message):
"[no_icon]",
"[no_description]",
button_style = Message.ActionButtonStyle.LINK,
button_align = Message.ActionButtonStyle.BUTTON_ALIGN_LEFT)
button_align = Message.ActionButtonAlignment.ALIGN_LEFT)
def getMachineId(self) -> int:
return self._machine_id

View File

@ -57,7 +57,7 @@ class FirmwareUpdaterMachineAction(MachineAction):
outputDeviceCanUpdateFirmwareChanged = pyqtSignal()
@pyqtProperty(QObject, notify = outputDeviceCanUpdateFirmwareChanged)
def firmwareUpdater(self) -> Optional["FirmwareUpdater"]:
if self._active_output_device and self._active_output_device.activePrinter and self._active_output_device.activePrinter.getController().can_update_firmware:
if self._active_output_device and self._active_output_device.activePrinter and self._active_output_device.activePrinter.getController() is not None and self._active_output_device.activePrinter.getController().can_update_firmware:
self._active_firmware_updater = self._active_output_device.getFirmwareUpdater()
return self._active_firmware_updater

View File

@ -107,6 +107,8 @@ class FlavorParser:
self._layer_data_builder.setLayerHeight(self._layer_number, path[0][2])
self._layer_data_builder.setLayerThickness(self._layer_number, layer_thickness)
this_layer = self._layer_data_builder.getLayer(self._layer_number)
if not this_layer:
return False
except ValueError:
return False
count = len(path)

View File

@ -2,20 +2,43 @@
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
import UM 1.3 as UM
import Cura 1.0 as Cura
// We show a nice overlay on the 3D viewer when the current output device has no monitor view
Rectangle
{
id: viewportOverlay
property bool isConnected: Cura.MachineManager.activeMachineHasActiveNetworkConnection || Cura.MachineManager.activeMachineHasActiveCloudConnection
property bool isNetworkConfigurable: ["Ultimaker 3", "Ultimaker 3 Extended", "Ultimaker S5"].indexOf(Cura.MachineManager.activeMachineDefinitionName) > -1
property bool isNetworkConfigured:
{
// Readability:
var connectedTypes = [2, 3];
var types = Cura.MachineManager.activeMachineConfiguredConnectionTypes
// Check if configured connection types includes either 2 or 3 (LAN or cloud)
for (var i = 0; i < types.length; i++)
{
if (connectedTypes.indexOf(types[i]) >= 0)
{
return true
}
}
return false
}
color: UM.Theme.getColor("viewport_overlay")
anchors.fill: parent
UM.I18nCatalog
{
id: catalog
name: "cura"
}
// This mouse area is to prevent mouse clicks to be passed onto the scene.
MouseArea
{
@ -29,6 +52,8 @@ Rectangle
{
anchors.fill: parent
}
// CASE 1: CAN MONITOR & CONNECTED
Loader
{
id: monitorViewComponent
@ -42,4 +67,118 @@ Rectangle
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem : null
}
// CASE 2 & 3: Empty states
Column
{
anchors
{
top: parent.top
topMargin: UM.Theme.getSize("monitor_empty_state_offset").height
horizontalCenter: parent.horizontalCenter
}
width: UM.Theme.getSize("monitor_empty_state_size").width
spacing: UM.Theme.getSize("default_margin").height
visible: monitorViewComponent.sourceComponent == null
// CASE 2: CAN MONITOR & NOT CONNECTED
Label
{
anchors
{
horizontalCenter: parent.horizontalCenter
}
visible: isNetworkConfigured && !isConnected
text: catalog.i18nc("@info", "Please make sure your printer has a connection:\n- Check if the printer is turned on.\n- Check if the printer is connected to the network.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("monitor_text_primary")
wrapMode: Text.WordWrap
lineHeight: UM.Theme.getSize("monitor_text_line_large").height
lineHeightMode: Text.FixedHeight
width: contentWidth
}
// CASE 3: CAN NOT MONITOR
Label
{
id: noNetworkLabel
anchors
{
horizontalCenter: parent.horizontalCenter
}
visible: !isNetworkConfigured
text: catalog.i18nc("@info", "Please select a network connected printer to monitor.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("monitor_text_primary")
wrapMode: Text.WordWrap
width: contentWidth
lineHeight: UM.Theme.getSize("monitor_text_line_large").height
lineHeightMode: Text.FixedHeight
}
Label
{
id: noNetworkUltimakerLabel
anchors
{
horizontalCenter: parent.horizontalCenter
}
visible: !isNetworkConfigured && isNetworkConfigurable
text: catalog.i18nc("@info", "Please connect your Ultimaker printer to your local network.")
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("monitor_text_primary")
wrapMode: Text.WordWrap
width: contentWidth
lineHeight: UM.Theme.getSize("monitor_text_line_large").height
lineHeightMode: Text.FixedHeight
}
Item
{
anchors
{
left: noNetworkUltimakerLabel.left
}
visible: !isNetworkConfigured && isNetworkConfigurable
height: UM.Theme.getSize("monitor_text_line").height
width: childrenRect.width
UM.RecolorImage
{
id: externalLinkIcon
anchors.verticalCenter: parent.verticalCenter
color: UM.Theme.getColor("monitor_text_link")
source: UM.Theme.getIcon("external_link")
width: UM.Theme.getSize("monitor_external_link_icon").width
height: UM.Theme.getSize("monitor_external_link_icon").height
}
Label
{
id: manageQueueText
anchors
{
left: externalLinkIcon.right
leftMargin: UM.Theme.getSize("narrow_margin").width
verticalCenter: externalLinkIcon.verticalCenter
}
color: UM.Theme.getColor("monitor_text_link")
font: UM.Theme.getFont("medium") // 14pt, regular
linkColor: UM.Theme.getColor("monitor_text_link")
text: catalog.i18nc("@label link to technical assistance", "View user manuals online")
renderType: Text.NativeRendering
}
MouseArea
{
anchors.fill: parent
hoverEnabled: true
onClicked: Qt.openUrlExternally("https://ultimaker.com/en/resources/manuals/ultimaker-3d-printers")
onEntered:
{
manageQueueText.font.underline = true
}
onExited:
{
manageQueueText.font.underline = false
}
}
}
}
}

View File

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
from typing import Optional, Tuple
@ -45,6 +45,22 @@ class FilamentChange(Script):
"unit": "mm",
"type": "float",
"default_value": 300.0
},
"x_position":
{
"label": "X Position",
"description": "Extruder X position. The print head will move here for filament change.",
"unit": "mm",
"type": "float",
"default_value": 0
},
"y_position":
{
"label": "Y Position",
"description": "Extruder Y position. The print head will move here for filament change.",
"unit": "mm",
"type": "float",
"default_value": 0
}
}
}"""
@ -55,6 +71,8 @@ class FilamentChange(Script):
layer_nums = self.getSettingValueByKey("layer_number")
initial_retract = self.getSettingValueByKey("initial_retract")
later_retract = self.getSettingValueByKey("later_retract")
x_pos = self.getSettingValueByKey("x_position")
y_pos = self.getSettingValueByKey("y_position")
color_change = "M600"
@ -64,6 +82,12 @@ class FilamentChange(Script):
if later_retract is not None and later_retract > 0.:
color_change = color_change + (" L%.2f" % later_retract)
if x_pos is not None:
color_change = color_change + (" X%.2f" % x_pos)
if y_pos is not None:
color_change = color_change + (" Y%.2f" % y_pos)
color_change = color_change + " ; Generated by FilamentChange plugin"
layer_targets = layer_nums.split(",")

View File

@ -0,0 +1,24 @@
//Copyright (c) 2019 Ultimaker B.V.
//Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import UM 1.0 as UM
import Cura 1.0 as Cura
Item
{
id: prepareMain
Cura.ActionPanelWidget
{
id: actionPanelWidget
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: UM.Theme.getSize("thick_margin").width
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
}
}

View File

@ -1,13 +1,11 @@
# 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 UM.Application import Application
from UM.PluginRegistry import PluginRegistry
from UM.Resources import Resources
from cura.Stages.CuraStage import CuraStage
## Stage for preparing model (slicing).
class PrepareStage(CuraStage):
def __init__(self, parent = None):
@ -16,4 +14,6 @@ class PrepareStage(CuraStage):
def _engineCreated(self):
menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml")
main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMain.qml")
self.addDisplayComponent("menu", menu_component_path)
self.addDisplayComponent("main", main_component_path)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.4
@ -9,10 +9,22 @@ import QtQuick.Controls.Styles 1.1
import UM 1.0 as UM
import Cura 1.0 as Cura
Loader
Item
{
Loader
{
id: previewMain
source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : ""
}
Cura.ActionPanelWidget
{
id: actionPanelWidget
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: UM.Theme.getSize("thick_margin").width
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
hasPreviewButton: false
}
}

View File

@ -49,6 +49,7 @@ Rectangle
wrapMode: Text.WordWrap
elide: Text.ElideRight
font: UM.Theme.getFont("medium_bold")
color: UM.Theme.getColor("text")
}
UM.RecolorImage
{

View File

@ -37,7 +37,7 @@ class Toolbox(QObject, Extension):
self._application = application # type: CuraApplication
self._sdk_version = ApplicationMetadata.CuraSDKVersion # type: Union[str, int]
self._cloud_api_version = UltimakerCloudAuthentication.CuraCloudAPIVersion # type: int
self._cloud_api_version = UltimakerCloudAuthentication.CuraCloudAPIVersion # type: str
self._cloud_api_root = UltimakerCloudAuthentication.CuraCloudAPIRoot # type: str
self._api_url = None # type: Optional[str]

View File

@ -95,10 +95,14 @@ class UFPWriter(MeshWriter):
added_materials = []
for extruder_stack in global_stack.extruders.values():
material = extruder_stack.material
try:
material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material"
except KeyError:
Logger.log("w", "Unable to get base_file for the material %s", material.getId())
continue
material_file_name = "/Materials/" + material_file_name
#Same material cannot be added
# The same material should not be added again.
if material_file_name in added_materials:
continue

View File

@ -9,12 +9,14 @@ import Cura 1.0 as Cura
Rectangle {
id: base
property var enabled: true
property var iconSource: null;
color: "#0a0850" // TODO: Theme!
color: UM.Theme.getColor("monitor_icon_primary")
height: width;
radius: Math.round(0.5 * width);
width: 24 * screenScaleFactor;
property var enabled: true
UM.RecolorImage {
id: icon;
@ -22,7 +24,7 @@ Rectangle {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
color: UM.Theme.getColor("primary_text");
color: UM.Theme.getColor("monitor_icon_accent");
height: width;
source: iconSource;
width: Math.round(parent.width / 2);

View File

@ -6,10 +6,11 @@ import QtQuick.Controls 2.0
import UM 1.3 as UM
import Cura 1.0 as Cura
// TODO: Theme & documentation!
// The expandable component has 3 major sub components:
// * The headerItem Always visible and should hold some info about what happens if the component is expanded
// * The popupItem The content that needs to be shown if the component is expanded.
/**
* The expandable component has 3 major sub components:
* - The headerItem Always visible and should hold some info about what happens if the component is expanded
* - The popupItem The content that needs to be shown if the component is expanded.
*/
Item
{
id: base
@ -17,10 +18,10 @@ Item
property bool expanded: false
property bool enabled: true
property var borderWidth: 1
property color borderColor: "#CCCCCC"
property color headerBackgroundColor: "white"
property color headerHoverColor: "#e8f2fc"
property color drawerBackgroundColor: "white"
property color borderColor: UM.Theme.getColor("monitor_card_border")
property color headerBackgroundColor: UM.Theme.getColor("monitor_icon_accent")
property color headerHoverColor: UM.Theme.getColor("monitor_card_hover")
property color drawerBackgroundColor: UM.Theme.getColor("monitor_icon_accent")
property alias headerItem: header.children
property alias drawerItem: drawer.children
@ -38,6 +39,7 @@ Item
color: base.enabled && headerMouseArea.containsMouse ? headerHoverColor : headerBackgroundColor
height: childrenRect.height
width: parent.width
radius: 2 * screenScaleFactor // TODO: Theme!
Behavior on color
{
ColorAnimation
@ -76,6 +78,7 @@ Item
color: headerBackgroundColor
height: base.expanded ? childrenRect.height : 0
width: parent.width
radius: 2 * screenScaleFactor // TODO: Theme!
Behavior on height
{
NumberAnimation

View File

@ -0,0 +1,227 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.1
import QtGraphicalEffects 1.0
import UM 1.3 as UM
/**
* This is a generic pop-up element which can be supplied with a target and a content item. The
* content item will appear to the left, right, above, or below the target depending on the value of
* the direction property
*/
Popup
{
id: base
/**
* The target item is what the pop-up is "tied" to, usually a button
*/
property var target
/**
* Which direction should the pop-up "point"?
* Possible values include:
* - "up"
* - "down"
* - "left"
* - "right"
*/
property string direction: "down"
/**
* We save the default direction so that if a pop-up was flipped but later has space (i.e. it
* moved), we can unflip it back to the default direction.
*/
property string originalDirection: ""
/**
* Should the popup close when you click outside it? For example, this is
* disabled by the InfoBlurb component since it's opened and closed using mouse
* hovers, not clicks.
*/
property bool closeOnClick: true
/**
* Use white for context menus, dark grey for info blurbs!
*/
property var color: "#ffffff" // TODO: Theme!
Component.onCompleted:
{
recalculatePosition()
// Set the direction here so it's only set once and never mutated
originalDirection = (' ' + direction).slice(1)
}
background: Item
{
anchors.fill: parent
DropShadow
{
anchors.fill: pointedRectangle
color: UM.Theme.getColor("monitor_shadow")
radius: UM.Theme.getSize("monitor_shadow_radius").width
source: pointedRectangle
transparentBorder: true
verticalOffset: 2 * screenScaleFactor
}
Item
{
id: pointedRectangle
anchors
{
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
height: parent.height - 10 * screenScaleFactor // Because of the shadow
width: parent.width - 10 * screenScaleFactor // Because of the shadow
Rectangle
{
id: point
anchors
{
horizontalCenter:
{
switch(direction)
{
case "left":
return bloop.left
case "right":
return bloop.right
default:
return bloop.horizontalCenter
}
}
verticalCenter:
{
switch(direction)
{
case "up":
return bloop.top
case "down":
return bloop.bottom
default:
return bloop.verticalCenter
}
}
}
color: base.color
height: 12 * screenScaleFactor
transform: Rotation
{
angle: 45
origin.x: point.width / 2
origin.y: point.height / 2
}
width: height
}
Rectangle
{
id: bloop
anchors
{
fill: parent
leftMargin: direction == "left" ? 8 * screenScaleFactor : 0
rightMargin: direction == "right" ? 8 * screenScaleFactor : 0
topMargin: direction == "up" ? 8 * screenScaleFactor : 0
bottomMargin: direction == "down" ? 8 * screenScaleFactor : 0
}
color: base.color
width: parent.width
}
}
}
visible: false
onClosed: visible = false
onOpened:
{
// Flip orientation if necessary
recalculateOrientation()
// Fix position if necessary
recalculatePosition()
// Show the pop up
visible = true
}
closePolicy: closeOnClick ? Popup.CloseOnPressOutside : Popup.NoAutoClose
clip: true
padding: UM.Theme.getSize("monitor_shadow_radius").width
topPadding: direction == "up" ? padding + 8 * screenScaleFactor : padding
bottomPadding: direction == "down" ? padding + 8 * screenScaleFactor : padding
leftPadding: direction == "left" ? padding + 8 * screenScaleFactor : padding
rightPadding: direction == "right" ? padding + 8 * screenScaleFactor : padding
function recalculatePosition() {
// Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
const realHeight = contentItem.implicitHeight + topPadding + bottomPadding
var centered = {
x: target.x + target.width / 2 - realWidth / 2,
y: target.y + target.height / 2 - realHeight / 2
}
switch(direction)
{
case "left":
x = target.x + target.width
y = centered.y
break
case "right":
x = target.x - realWidth
y = centered.y
break
case "up":
x = centered.x
y = target.y + target.height
break
case "down":
x = centered.x
y = target.y - realHeight
break
}
}
function recalculateOrientation() {
var availableSpace
var targetPosition = target.mapToItem(monitorFrame, 0, 0)
// Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
const realHeight = contentItem.implicitHeight + topPadding + bottomPadding
switch(originalDirection)
{
case "up":
availableSpace = monitorFrame.height - (targetPosition.y + target.height)
direction = availableSpace < realHeight ? "down" : originalDirection
break
case "down":
availableSpace = targetPosition.y
direction = availableSpace < realHeight ? "up" : originalDirection
break
case "right":
availableSpace = targetPosition.x
direction = availableSpace < realWidth ? "left" : originalDirection
break
case "left":
availableSpace = monitorFrame.width - (targetPosition.x + target.width)
direction = availableSpace < realWidth ? "right" : originalDirection
break
}
}
}

View File

@ -41,7 +41,7 @@ Item
anchors.centerIn: parent
height: parent.height
width: height
color: buildplateIcon.visible > 0 ? "transparent" : "#eeeeee" // TODO: Theme!
color: buildplateIcon.visible > 0 ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
radius: Math.floor(height / 2)
}
@ -49,7 +49,7 @@ Item
{
id: buildplateIcon
anchors.centerIn: parent
color: "#0a0850" // TODO: Theme! (Standard purple)
color: UM.Theme.getColor("monitor_icon_primary")
height: parent.height
source: "../svg/icons/buildplate.svg"
width: height
@ -60,7 +60,7 @@ Item
Label
{
id: buildplateLabel
color: "#191919" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("default") // 12pt, regular
text: buildplate ? buildplate : ""

View File

@ -49,12 +49,12 @@ Item
GradientStop
{
position: 0.0
color: "#fff6f6f6" // TODO: Theme!
color: UM.Theme.getColor("monitor_stage_background")
}
GradientStop
{
position: 1.0
color: "#66f6f6f6" // TODO: Theme!
color: UM.Theme.getColor("monitor_stage_background_fade")
}
}
}
@ -82,9 +82,9 @@ Item
onClicked: navigateTo(currentIndex - 1)
background: Rectangle
{
color: leftButton.hovered ? "#e8f2fc" : "#ffffff" // TODO: Theme!
color: leftButton.hovered ? UM.Theme.getColor("monitor_card_hover") : UM.Theme.getColor("monitor_card_background")
border.width: 1 * screenScaleFactor // TODO: Theme!
border.color: "#cccccc" // TODO: Theme!
border.color: UM.Theme.getColor("monitor_card_border")
radius: 2 * screenScaleFactor // TODO: Theme!
}
contentItem: Item
@ -97,7 +97,7 @@ Item
height: width // TODO: Theme!
sourceSize.width: width // TODO: Theme!
sourceSize.height: width // TODO: Theme!
color: "#152950" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
source: UM.Theme.getIcon("arrow_left")
}
}
@ -161,9 +161,9 @@ Item
hoverEnabled: true
background: Rectangle
{
color: rightButton.hovered ? "#e8f2fc" : "#ffffff" // TODO: Theme!
color: rightButton.hovered ? UM.Theme.getColor("monitor_card_hover") : UM.Theme.getColor("monitor_card_background")
border.width: 1 * screenScaleFactor // TODO: Theme!
border.color: "#cccccc" // TODO: Theme!
border.color: UM.Theme.getColor("monitor_card_border")
radius: 2 * screenScaleFactor // TODO: Theme!
}
contentItem: Item
@ -176,7 +176,7 @@ Item
height: width // TODO: Theme!
sourceSize.width: width // TODO: Theme!
sourceSize.height: width // TODO: Theme!
color: "#152950" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
source: UM.Theme.getIcon("arrow_right")
}
}
@ -204,12 +204,12 @@ Item
GradientStop
{
position: 0.0
color: "#66f6f6f6" // TODO: Theme!
color: UM.Theme.getColor("monitor_stage_background_fade")
}
GradientStop
{
position: 1.0
color: "#fff6f6f6" // TODO: Theme!
color: UM.Theme.getColor("monitor_stage_background")
}
}
}
@ -238,7 +238,7 @@ Item
{
background: Rectangle
{
color: model.index == currentIndex ? "#777777" : "#d8d8d8" // TODO: Theme!
color: model.index == currentIndex ? UM.Theme.getColor("monitor_carousel_dot_current") : UM.Theme.getColor("monitor_carousel_dot")
radius: Math.floor(width / 2)
width: 12 * screenScaleFactor // TODO: Theme!
height: width // TODO: Theme!

View File

@ -0,0 +1,182 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.1
import UM 1.3 as UM
/**
* A MonitorInfoBlurb is an extension of the GenericPopUp used to show static information (vs. interactive context
* menus). It accepts some text (text), an item to link to to (target), and a specification of which side of the target
* to appear on (direction). It also sets the GenericPopUp's color to black, to differentiate itself from a menu.
*/
Item
{
property alias target: popUp.target
property var printJob: null
GenericPopUp
{
id: popUp
// Which way should the pop-up point? Default is up, but will flip when required
direction: "up"
// Use dark grey for info blurbs and white for context menus
color: UM.Theme.getColor("monitor_context_menu")
contentItem: Item
{
id: contentWrapper
implicitWidth: childrenRect.width
implicitHeight: menuItems.height + UM.Theme.getSize("default_margin").height
Column
{
id: menuItems
width: 144 * screenScaleFactor
anchors
{
top: parent.top
topMargin: Math.floor(UM.Theme.getSize("default_margin").height / 2)
}
spacing: Math.floor(UM.Theme.getSize("default_margin").height / 2)
PrintJobContextMenuItem {
onClicked: {
sendToTopConfirmationDialog.visible = true;
popUp.close();
}
text: catalog.i18nc("@label", "Move to top");
visible: {
if (printJob && (printJob.state == "queued" || printJob.state == "error") && !isAssigned(printJob)) {
if (OutputDevice && OutputDevice.queuedPrintJobs[0]) {
return OutputDevice.queuedPrintJobs[0].key != printJob.key;
}
}
return false;
}
}
PrintJobContextMenuItem {
onClicked: {
deleteConfirmationDialog.visible = true;
popUp.close();
}
text: catalog.i18nc("@label", "Delete");
visible: {
if (!printJob) {
return false;
}
var states = ["queued", "error", "sent_to_printer"];
return states.indexOf(printJob.state) !== -1;
}
}
PrintJobContextMenuItem {
enabled: visible && !(printJob.state == "pausing" || printJob.state == "resuming");
onClicked: {
if (printJob.state == "paused") {
printJob.setState("print");
popUp.close();
return;
}
if (printJob.state == "printing") {
printJob.setState("pause");
popUp.close();
return;
}
}
text: {
if (!printJob) {
return "";
}
switch(printJob.state) {
case "paused":
return catalog.i18nc("@label", "Resume");
case "pausing":
return catalog.i18nc("@label", "Pausing...");
case "resuming":
return catalog.i18nc("@label", "Resuming...");
default:
catalog.i18nc("@label", "Pause");
}
}
visible: {
if (!printJob) {
return false;
}
var states = ["printing", "pausing", "paused", "resuming"];
return states.indexOf(printJob.state) !== -1;
}
}
PrintJobContextMenuItem {
enabled: visible && printJob.state !== "aborting";
onClicked: {
abortConfirmationDialog.visible = true;
popUp.close();
}
text: printJob && printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
visible: {
if (!printJob) {
return false;
}
var states = ["pre_print", "printing", "pausing", "paused", "resuming"];
return states.indexOf(printJob.state) !== -1;
}
}
}
}
}
MessageDialog {
id: sendToTopConfirmationDialog
Component.onCompleted: visible = false
icon: StandardIcon.Warning
onYes: OutputDevice.sendJobToTop(printJob.key)
standardButtons: StandardButton.Yes | StandardButton.No
text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to move %1 to the top of the queue?").arg(printJob.name) : ""
title: catalog.i18nc("@window:title", "Move print job to top")
}
MessageDialog {
id: deleteConfirmationDialog
Component.onCompleted: visible = false
icon: StandardIcon.Warning
onYes: OutputDevice.deleteJobFromQueue(printJob.key)
standardButtons: StandardButton.Yes | StandardButton.No
text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to delete %1?").arg(printJob.name) : ""
title: catalog.i18nc("@window:title", "Delete print job")
}
MessageDialog {
id: abortConfirmationDialog
Component.onCompleted: visible = false
icon: StandardIcon.Warning
onYes: printJob.setState("abort")
standardButtons: StandardButton.Yes | StandardButton.No
text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to abort %1?").arg(printJob.name) : ""
title: catalog.i18nc("@window:title", "Abort print")
}
function switchPopupState() {
popUp.visible ? popUp.close() : popUp.open()
}
function open() {
popUp.open()
}
function close() {
popUp.close()
}
function isAssigned(job) {
if (!job) {
return false;
}
return job.assignedPrinter ? true : false;
}
}

View File

@ -0,0 +1,31 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Controls 2.0
import UM 1.3 as UM
import Cura 1.0 as Cura
Button
{
id: base
background: Rectangle
{
color: UM.Theme.getColor("viewport_background") // TODO: Theme!
height: base.height
opacity: base.down || base.hovered ? 1 : 0
radius: Math.round(0.5 * width)
width: base.width
}
contentItem: Label {
color: UM.Theme.getColor("monitor_text_primary")
font.pixelSize: 32 * screenScaleFactor
horizontalAlignment: Text.AlignHCenter
text: base.text
verticalAlignment: Text.AlignVCenter
}
height: width
hoverEnabled: enabled
text: "\u22EE" //Unicode Three stacked points.
width: 36 * screenScaleFactor // TODO: Theme!
}

View File

@ -36,7 +36,7 @@ Item
MonitorIconExtruder
{
id: extruderIcon
color: "#eeeeee" // TODO: Theme!
color: UM.Theme.getColor("monitor_skeleton_loading")
position: 0
}
@ -48,7 +48,7 @@ Item
left: extruderIcon.right
leftMargin: 12 * screenScaleFactor // TODO: Theme!
}
color: materialLabel.visible > 0 ? "transparent" : "#eeeeee" // TODO: Theme!
color: materialLabel.visible > 0 ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
height: 18 * screenScaleFactor // TODO: Theme!
width: Math.max(materialLabel.contentWidth, 60 * screenScaleFactor) // TODO: Theme!
radius: 2 * screenScaleFactor // TODO: Theme!
@ -57,7 +57,7 @@ Item
{
id: materialLabel
color: "#191919" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("default") // 12pt, regular
text: ""
@ -77,7 +77,7 @@ Item
left: materialLabelWrapper.left
bottom: parent.bottom
}
color: printCoreLabel.visible > 0 ? "transparent" : "#eeeeee" // TODO: Theme!
color: printCoreLabel.visible > 0 ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
height: 18 * screenScaleFactor // TODO: Theme!
width: Math.max(printCoreLabel.contentWidth, 36 * screenScaleFactor) // TODO: Theme!
radius: 2 * screenScaleFactor // TODO: Theme!
@ -86,7 +86,7 @@ Item
{
id: printCoreLabel
color: "#191919" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("default_bold") // 12pt, bold
text: ""

View File

@ -39,6 +39,7 @@ Item
{
id: positionLabel
font: UM.Theme.getFont("small")
color: UM.Theme.getColor("monitor_text_primary")
height: Math.round(size / 2)
horizontalAlignment: Text.AlignHCenter
text: position + 1

View File

@ -0,0 +1,53 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.3
import QtQuick.Controls 2.0
import UM 1.3 as UM
/**
* A MonitorInfoBlurb is an extension of the GenericPopUp used to show static information (vs. interactive context
* menus). It accepts some text (text), an item to link to to (target), and a specification of which side of the target
* to appear on (direction). It also sets the GenericPopUp's color to black, to differentiate itself from a menu.
*/
Item
{
property alias text: innerLabel.text
property alias target: popUp.target
property alias direction: popUp.direction
GenericPopUp
{
id: popUp
// Which way should the pop-up point? Default is up, but will flip when required
direction: "up"
// Use dark grey for info blurbs and white for context menus
color: UM.Theme.getColor("monitor_tooltip")
contentItem: Item
{
id: contentWrapper
implicitWidth: childrenRect.width
implicitHeight: innerLabel.contentHeight + 2 * innerLabel.padding
Label
{
id: innerLabel
padding: 12 * screenScaleFactor // TODO: Theme!
text: ""
wrapMode: Text.WordWrap
width: 240 * screenScaleFactor // TODO: Theme!
color: UM.Theme.getColor("monitor_tooltip_text")
font: UM.Theme.getFont("default")
}
}
}
function open() {
popUp.open()
}
function close() {
popUp.close()
}
}

View File

@ -4,6 +4,7 @@
import QtQuick 2.2
import QtQuick.Controls 2.0
import UM 1.3 as UM
import Cura 1.0 as Cura
/**
* A Print Job Card is essentially just a filled-in Expandable Card item. All
@ -21,13 +22,17 @@ Item
// The print job which all other data is derived from
property var printJob: null
// If the printer is a cloud printer or not. Other items base their enabled state off of this boolean. In the future
// they might not need to though.
property bool cloudConnection: Cura.MachineManager.activeMachineHasActiveCloudConnection
width: parent.width
height: childrenRect.height
ExpandableCard
{
enabled: printJob != null
borderColor: printJob.configurationChanges.length !== 0 ? "#f5a623" : "#CCCCCC" // TODO: Theme!
borderColor: printJob && printJob.configurationChanges.length !== 0 ? UM.Theme.getColor("warning") : UM.Theme.getColor("monitor_card_border")
headerItem: Row
{
height: 48 * screenScaleFactor // TODO: Theme!
@ -49,15 +54,16 @@ Item
width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
Rectangle
{
color: "#eeeeee"
color: UM.Theme.getColor("monitor_skeleton_loading")
width: Math.round(parent.width / 2)
height: parent.height
visible: !printJob
radius: 2 * screenScaleFactor // TODO: Theme!
}
Label
{
text: printJob && printJob.name ? printJob.name : ""
color: "#374355"
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
visible: printJob
@ -75,15 +81,16 @@ Item
width: 216 * screenScaleFactor // TODO: Theme! (Should match column size)
Rectangle
{
color: "#eeeeee"
color: UM.Theme.getColor("monitor_skeleton_loading")
width: Math.round(parent.width / 3)
height: parent.height
visible: !printJob
radius: 2 * screenScaleFactor // TODO: Theme!
}
Label
{
text: printJob ? OutputDevice.formatDuration(printJob.timeTotal) : ""
color: "#374355"
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
visible: printJob
@ -102,17 +109,18 @@ Item
Rectangle
{
color: "#eeeeee"
color: UM.Theme.getColor("monitor_skeleton_loading")
width: 72 * screenScaleFactor // TODO: Theme!
height: parent.height
visible: !printJob
radius: 2 * screenScaleFactor // TODO: Theme!
}
Label
{
id: printerAssignmentLabel
anchors.verticalCenter: parent.verticalCenter
color: "#374355"
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
text: {
@ -176,7 +184,7 @@ Item
{
id: printerConfiguration
anchors.verticalCenter: parent.verticalCenter
buildplate: "Glass"
buildplate: catalog.i18nc("@label", "Glass")
configurations:
[
base.printJob.configuration.extruderConfigurations[0],
@ -186,7 +194,7 @@ Item
}
Label {
text: printJob && printJob.owner ? printJob.owner : ""
color: "#374355" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
anchors.top: printerConfiguration.top
@ -198,18 +206,52 @@ Item
}
}
PrintJobContextMenu
MonitorContextMenuButton
{
id: contextButton
id: contextMenuButton
anchors
{
right: parent.right;
right: parent.right
rightMargin: 8 * screenScaleFactor // TODO: Theme!
top: parent.top
topMargin: 8 * screenScaleFactor // TODO: Theme!
}
printJob: base.printJob
width: 32 * screenScaleFactor // TODO: Theme!
height: 32 * screenScaleFactor // TODO: Theme!
enabled: !cloudConnection
onClicked: enabled ? contextMenu.switchPopupState() : {}
visible:
{
if (!printJob) {
return false
}
var states = ["queued", "error", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]
return states.indexOf(printJob.state) !== -1
}
}
MonitorContextMenu
{
id: contextMenu
printJob: base.printJob ? base.printJob : null
target: contextMenuButton
}
// For cloud printing, add this mouse area over the disabled contextButton to indicate that it's not available
MouseArea
{
id: contextMenuDisabledButtonArea
anchors.fill: contextMenuButton
hoverEnabled: contextMenuButton.visible && !contextMenuButton.enabled
onEntered: contextMenuDisabledInfo.open()
onExited: contextMenuDisabledInfo.close()
enabled: !contextMenuButton.enabled
}
MonitorInfoBlurb
{
id: contextMenuDisabledInfo
text: catalog.i18nc("@info", "These options are not available because you are monitoring a cloud printer.")
target: contextMenuButton
}
}

View File

@ -19,7 +19,7 @@ Item
Rectangle
{
anchors.fill: parent
color: printJob ? "transparent" : "#eeeeee" // TODO: Theme!
color: printJob ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
radius: 8 // TODO: Theme!
Image
{

View File

@ -34,15 +34,15 @@ Item
{
background: Rectangle
{
color: "#f5f5f5" // TODO: Theme!
implicitHeight: visible ? 8 * screenScaleFactor : 0 // TODO: Theme!
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 ? "#3282ff" : "#CCCCCC" // TODO: Theme!
color: printJob && printJob.isActive ? UM.Theme.getColor("monitor_progress_bar_fill") : UM.Theme.getColor("monitor_progress_bar_deactive")
radius: 2 * screenScaleFactor // TODO: Theme!
}
}
@ -56,7 +56,7 @@ Item
leftMargin: 18 * screenScaleFactor // TODO: Theme!
}
text: printJob ? Math.round(printJob.progress * 100) + "%" : "0%"
color: printJob && printJob.isActive ? "#374355" : "#babac1" // TODO: Theme!
color: printJob && printJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
width: contentWidth
font: UM.Theme.getFont("medium") // 14pt, regular
@ -72,7 +72,7 @@ Item
left: percentLabel.right
leftMargin: 18 * screenScaleFactor // TODO: Theme!
}
color: "#374355" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
font: UM.Theme.getFont("medium") // 14pt, regular
text:
{

View File

@ -5,15 +5,14 @@ import QtQuick 2.3
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.1
import UM 1.3 as UM
import Cura 1.0 as Cura
/**
* A Printer Card is has two main components: the printer portion and the print
* job portion, the latter being paired in the UI when a print job is paired
* a printer in-cluster.
* A Printer Card is has two main components: the printer portion and the print job portion, the latter being paired in
* the UI when a print job is paired a printer in-cluster.
*
* NOTE: For most labels, a fixed height with vertical alignment is used to make
* layouts more deterministic (like the fixed-size textboxes used in original
* mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
* NOTE: For most labels, a fixed height with vertical alignment is used to make layouts more deterministic (like the
* fixed-size textboxes used in original mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
* with '// FIXED-LINE-HEIGHT:'.
*/
Item
@ -25,11 +24,14 @@ Item
property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here
// If the printer card's controls are enabled. This is used by the carousel
// to prevent opening the context menu or camera while the printer card is not
// "in focus"
// If the printer card's controls are enabled. This is used by the carousel to prevent opening the context menu or
// camera while the printer card is not "in focus"
property var enabled: true
// If the printer is a cloud printer or not. Other items base their enabled state off of this boolean. In the future
// they might not need to though.
property bool cloudConnection: Cura.MachineManager.activeMachineHasActiveCloudConnection
width: 834 * screenScaleFactor // TODO: Theme!
height: childrenRect.height
@ -37,10 +39,10 @@ Item
{
id: background
anchors.fill: parent
color: "#FFFFFF" // TODO: Theme!
color: UM.Theme.getColor("monitor_card_background")
border
{
color: "#CCCCCC" // TODO: Theme!
color: UM.Theme.getColor("monitor_card_border")
width: borderSize // TODO: Remove once themed
}
radius: 2 * screenScaleFactor // TODO: Theme!
@ -69,7 +71,7 @@ Item
id: printerImage
width: 108 * screenScaleFactor // TODO: Theme!
height: 108 * screenScaleFactor // TODO: Theme!
color: printer ? "transparent" : "#eeeeee" // TODO: Theme!
color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
radius: 8 // TODO: Theme!
Image
{
@ -93,8 +95,7 @@ Item
Rectangle
{
id: printerNameLabel
// color: "#414054" // TODO: Theme!
color: printer ? "transparent" : "#eeeeee" // TODO: Theme!
color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
height: 18 * screenScaleFactor // TODO: Theme!
width: parent.width
radius: 2 * screenScaleFactor // TODO: Theme!
@ -102,7 +103,7 @@ Item
Label
{
text: printer && printer.name ? printer.name : ""
color: "#414054" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("large") // 16pt, bold
width: parent.width
@ -116,7 +117,7 @@ Item
Rectangle
{
color: "#eeeeee" // TODO: Theme!
color: UM.Theme.getColor("monitor_skeleton_loading")
height: 18 * screenScaleFactor // TODO: Theme!
radius: 2 * screenScaleFactor // TODO: Theme!
visible: !printer
@ -156,16 +157,11 @@ Item
}
height: 72 * screenScaleFactor // TODO: Theme!te theRect's x property
}
// TODO: Make this work.
PropertyAnimation { target: printerConfiguration; property: "visible"; to: 0; loops: Animation.Infinite; duration: 500 }
}
PrintJobContextMenu
MonitorContextMenuButton
{
id: contextButton
id: contextMenuButton
anchors
{
right: parent.right
@ -173,15 +169,49 @@ Item
top: parent.top
topMargin: 12 * screenScaleFactor // TODO: Theme!
}
printJob: printer ? printer.activePrintJob : null
width: 36 * screenScaleFactor // TODO: Theme!
height: 36 * screenScaleFactor // TODO: Theme!
enabled: base.enabled
visible: printer
enabled: !cloudConnection
onClicked: enabled ? contextMenu.switchPopupState() : {}
visible:
{
if (!printer || !printer.activePrintJob) {
return false
}
var states = ["queued", "error", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]
return states.indexOf(printer.activePrintJob.state) !== -1
}
}
MonitorContextMenu
{
id: contextMenu
printJob: printer ? printer.activePrintJob : null
target: contextMenuButton
}
// For cloud printing, add this mouse area over the disabled contextButton to indicate that it's not available
MouseArea
{
id: contextMenuDisabledButtonArea
anchors.fill: contextMenuButton
hoverEnabled: contextMenuButton.visible && !contextMenuButton.enabled
onEntered: contextMenuDisabledInfo.open()
onExited: contextMenuDisabledInfo.close()
enabled: !contextMenuButton.enabled
}
MonitorInfoBlurb
{
id: contextMenuDisabledInfo
text: catalog.i18nc("@info", "These options are not available because you are monitoring a cloud printer.")
target: contextMenuButton
}
CameraButton
{
id: cameraButton;
id: cameraButton
anchors
{
right: parent.right
@ -190,9 +220,27 @@ Item
bottomMargin: 20 * screenScaleFactor // TODO: Theme!
}
iconSource: "../svg/icons/camera.svg"
enabled: base.enabled
enabled: !cloudConnection
visible: printer
}
// For cloud printing, add this mouse area over the disabled cameraButton to indicate that it's not available
MouseArea
{
id: cameraDisabledButtonArea
anchors.fill: cameraButton
hoverEnabled: cameraButton.visible && !cameraButton.enabled
onEntered: cameraDisabledInfo.open()
onExited: cameraDisabledInfo.close()
enabled: !cameraButton.enabled
}
MonitorInfoBlurb
{
id: cameraDisabledInfo
text: catalog.i18nc("@info", "The webcam is not available because you are monitoring a cloud printer.")
target: cameraButton
}
}
@ -220,7 +268,7 @@ Item
}
border
{
color: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? "#f5a623" : "transparent" // TODO: Theme!
color: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? UM.Theme.getColor("warning") : "transparent" // TODO: Theme!
width: borderSize // TODO: Remove once themed
}
color: "transparent" // TODO: Theme!
@ -246,7 +294,7 @@ Item
{
verticalCenter: parent.verticalCenter
}
color: printer ? "#414054" : "#aaaaaa" // TODO: Theme!
color: printer ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
font: UM.Theme.getFont("large_bold") // 16pt, bold
text: {
if (!printer) {
@ -258,7 +306,7 @@ Item
}
if (printer && printer.state == "unreachable")
{
return catalog.i18nc("@label:status", "Unavailable")
return catalog.i18nc("@label:status", "Unreachable")
}
if (printer && !printer.activePrintJob && printer.state == "idle")
{
@ -299,10 +347,10 @@ Item
Label
{
id: printerJobNameLabel
color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? "#414054" : "#babac1" // TODO: Theme!
color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
elide: Text.ElideRight
font: UM.Theme.getFont("large") // 16pt, bold
text: printer && printer.activePrintJob ? printer.activePrintJob.name : "Untitled" // TODO: I18N
text: printer && printer.activePrintJob ? printer.activePrintJob.name : catalog.i18nc("@label", "Untitled")
width: parent.width
// FIXED-LINE-HEIGHT:
@ -319,10 +367,10 @@ Item
topMargin: 6 * screenScaleFactor // TODO: Theme!
left: printerJobNameLabel.left
}
color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme!
color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
elide: Text.ElideRight
font: UM.Theme.getFont("default") // 12pt, regular
text: printer && printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
text: printer && printer.activePrintJob ? printer.activePrintJob.owner : catalog.i18nc("@label", "Anonymous")
width: parent.width
// FIXED-LINE-HEIGHT:
@ -348,8 +396,9 @@ Item
verticalCenter: parent.verticalCenter
}
font: UM.Theme.getFont("default")
text: "Requires configuration changes"
text: catalog.i18nc("@label:status", "Requires configuration changes")
visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 && !printerStatus.visible
color: UM.Theme.getColor("monitor_text_primary")
// FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme!
@ -368,13 +417,13 @@ Item
}
background: Rectangle
{
color: "#d8d8d8" // TODO: Theme!
color: UM.Theme.getColor("monitor_secondary_button_shadow")
radius: 2 * screenScaleFactor // Todo: Theme!
Rectangle
{
anchors.fill: parent
anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
color: detailsButton.hovered ? "#e4e4e4" : "#f0f0f0" // TODO: Theme!
color: detailsButton.hovered ? UM.Theme.getColor("monitor_secondary_button_hover") : UM.Theme.getColor("monitor_secondary_button")
radius: 2 * screenScaleFactor // Todo: Theme!
}
}
@ -382,9 +431,9 @@ Item
{
anchors.fill: parent
anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
color: "#1e66d7" // TODO: Theme!
color: UM.Theme.getColor("monitor_secondary_button_text")
font: UM.Theme.getFont("medium") // 14pt, regular
text: "Details" // TODO: I18NC!
text: catalog.i18nc("@action:button","Details");
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
height: 18 * screenScaleFactor // TODO: Theme!

View File

@ -37,7 +37,7 @@ Item
MonitorExtruderConfiguration
{
color: modelData && modelData.activeMaterial ? modelData.activeMaterial.color : "#eeeeee" // TODO: Theme!
color: modelData && modelData.activeMaterial ? modelData.activeMaterial.color : UM.Theme.getColor("monitor_skeleton_loading")
material: modelData && modelData.activeMaterial ? modelData.activeMaterial.name : ""
position: modelData && typeof(modelData.position) === "number" ? modelData.position : -1 // Use negative one to create empty extruder number
printCore: modelData ? modelData.hotendID : ""

View File

@ -32,14 +32,14 @@ Item
Rectangle {
id: background
anchors.fill: parent
color: printerNameLabel.visible ? "#e4e4f2" : "#eeeeee"// TODO: Theme!
color: printerNameLabel.visible ? UM.Theme.getColor("monitor_printer_family_tag") : UM.Theme.getColor("monitor_skeleton_loading")
radius: 2 * screenScaleFactor // TODO: Theme!
}
Label {
id: printerNameLabel
anchors.centerIn: parent
color: "#535369" // TODO: Theme!
color: UM.Theme.getColor("monitor_text_primary")
text: tagText
font.pointSize: 10 // TODO: Theme!
visible: text !== ""

View File

@ -22,7 +22,7 @@ Item
left: queuedPrintJobs.left
top: parent.top
}
color: UM.Theme.getColor("text")
color: UM.Theme.getColor("monitor_text_primary")
font: UM.Theme.getFont("large")
text: catalog.i18nc("@label", "Queued")
}
@ -42,7 +42,7 @@ Item
{
id: externalLinkIcon
anchors.verticalCenter: manageQueueLabel.verticalCenter
color: UM.Theme.getColor("text_link")
color: UM.Theme.getColor("monitor_text_link")
source: UM.Theme.getIcon("external_link")
width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
@ -56,10 +56,10 @@ Item
leftMargin: 6 * screenScaleFactor // TODO: Theme!
verticalCenter: externalLinkIcon.verticalCenter
}
color: UM.Theme.getColor("text_link")
font: UM.Theme.getFont("default") // 12pt, regular
linkColor: UM.Theme.getColor("text_link")
text: catalog.i18nc("@label link to connect manager", "Manage queue in Cura Connect")
color: UM.Theme.getColor("monitor_text_link")
font: UM.Theme.getFont("medium") // 14pt, regular
linkColor: UM.Theme.getColor("monitor_text_link")
text: catalog.i18nc("@label link to connect manager", "Go to Cura Connect")
renderType: Text.NativeRendering
}
}
@ -94,7 +94,7 @@ Item
Label
{
text: catalog.i18nc("@label", "Print jobs")
color: "#666666"
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
anchors.verticalCenter: parent.verticalCenter
@ -108,7 +108,7 @@ Item
Label
{
text: catalog.i18nc("@label", "Total print time")
color: "#666666"
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
anchors.verticalCenter: parent.verticalCenter
@ -122,7 +122,7 @@ Item
Label
{
text: catalog.i18nc("@label", "Waiting for")
color: "#666666"
color: UM.Theme.getColor("monitor_text_primary")
elide: Text.ElideRight
font: UM.Theme.getFont("medium") // 14pt, regular
anchors.verticalCenter: parent.verticalCenter
@ -160,8 +160,101 @@ Item
}
printJob: modelData
}
model: OutputDevice.receivedPrintJobs ? OutputDevice.queuedPrintJobs : [null,null]
model:
{
// When printing over the cloud we don't recieve print jobs until there is one, so
// unless there's at least one print job we'll be stuck with skeleton loading
// indefinitely.
if (Cura.MachineManager.activeMachineHasActiveCloudConnection)
{
return OutputDevice.queuedPrintJobs
}
return OutputDevice.receivedPrintJobs ? OutputDevice.queuedPrintJobs : [null,null]
}
spacing: 6 // TODO: Theme!
}
}
Rectangle
{
anchors
{
horizontalCenter: parent.horizontalCenter
top: printJobQueueHeadings.bottom
topMargin: 12 * screenScaleFactor // TODO: Theme!
}
height: 48 * screenScaleFactor // TODO: Theme!
width: parent.width
color: UM.Theme.getColor("monitor_card_background")
border.color: UM.Theme.getColor("monitor_card_border")
radius: 2 * screenScaleFactor // TODO: Theme!
visible: printJobList.model.length == 0
Row
{
anchors
{
left: parent.left
leftMargin: 18 * screenScaleFactor // TODO: Theme!
verticalCenter: parent.verticalCenter
}
spacing: 18 * screenScaleFactor // TODO: Theme!
height: 18 * screenScaleFactor // TODO: Theme!
Label
{
text: "All jobs are printed."
color: UM.Theme.getColor("monitor_text_primary")
font: UM.Theme.getFont("medium") // 14pt, regular
}
Item
{
id: viewPrintHistoryLabel
height: 18 * screenScaleFactor // TODO: Theme!
width: childrenRect.width
UM.RecolorImage
{
id: printHistoryIcon
anchors.verticalCenter: parent.verticalCenter
color: UM.Theme.getColor("monitor_text_link")
source: UM.Theme.getIcon("external_link")
width: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
height: 16 * screenScaleFactor // TODO: Theme! (Y U NO USE 18 LIKE ALL OTHER ICONS?!)
}
Label
{
id: viewPrintHistoryText
anchors
{
left: printHistoryIcon.right
leftMargin: 6 * screenScaleFactor // TODO: Theme!
verticalCenter: printHistoryIcon.verticalCenter
}
color: UM.Theme.getColor("monitor_text_link")
font: UM.Theme.getFont("medium") // 14pt, regular
linkColor: UM.Theme.getColor("monitor_text_link")
text: catalog.i18nc("@label link to connect manager", "View print history")
renderType: Text.NativeRendering
}
MouseArea
{
anchors.fill: parent
hoverEnabled: true
onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
onEntered:
{
viewPrintHistoryText.font.underline = true
}
onExited:
{
viewPrintHistoryText.font.underline = false
}
}
}
}
}
}

View File

@ -11,7 +11,7 @@ import QtGraphicalEffects 1.0
// This is the root component for the monitor stage.
Component
{
Item
Rectangle
{
id: monitorFrame
@ -24,6 +24,7 @@ Component
}
}
width: maximumWidth
color: UM.Theme.getColor("monitor_stage_background")
// Enable keyboard navigation. NOTE: This is done here so that we can also potentially
// forward to the queue items in the future. (Deleting selected print job, etc.)
@ -36,24 +37,6 @@ Component
name: "cura"
}
LinearGradient
{
anchors.fill: parent
gradient: Gradient
{
GradientStop
{
position: 0.0
color: "#f6f6f6" // TODO: Theme!
}
GradientStop
{
position: 1.0
color: "#ffffff" // TODO: Theme!
}
}
}
Item
{
id: printers

View File

@ -1,274 +0,0 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.1
import QtGraphicalEffects 1.0
import UM 1.3 as UM
Item {
id: root;
property var printJob: null;
property var started: isStarted(printJob);
property var assigned: isAssigned(printJob);
property var enabled: true
Button {
id: button;
background: Rectangle {
color: UM.Theme.getColor("viewport_background"); // TODO: Theme!
height: button.height;
opacity: button.down || button.hovered ? 1 : 0;
radius: Math.round(0.5 * width);
width: button.width;
}
contentItem: Label {
color: UM.Theme.getColor("monitor_context_menu_dots");
font.pixelSize: 32 * screenScaleFactor;
horizontalAlignment: Text.AlignHCenter;
text: button.text;
verticalAlignment: Text.AlignVCenter;
}
height: width;
hoverEnabled: base.enabled
onClicked: base.enabled ? parent.switchPopupState() : {}
text: "\u22EE"; //Unicode; Three stacked points.
visible: {
if (!printJob) {
return false;
}
var states = ["queued", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"];
return states.indexOf(printJob.state) !== -1;
}
width: 36 * screenScaleFactor; // TODO: Theme!
}
Popup {
id: popup;
background: Item {
anchors.fill: parent;
DropShadow {
anchors.fill: pointedRectangle;
color: UM.Theme.getColor("monitor_shadow");
radius: UM.Theme.getSize("monitor_shadow_radius").width;
source: pointedRectangle;
transparentBorder: true;
verticalOffset: 2 * screenScaleFactor;
}
Item {
id: pointedRectangle;
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
height: parent.height - 10 * screenScaleFactor; // Because of the shadow
width: parent.width - 10 * screenScaleFactor; // Because of the shadow
Rectangle {
id: point;
anchors {
right: bloop.right;
rightMargin: 24 * screenScaleFactor;
}
color: UM.Theme.getColor("monitor_context_menu_background");
height: 14 * screenScaleFactor;
transform: Rotation {
angle: 45;
}
width: 14 * screenScaleFactor;
y: 1 * screenScaleFactor;
}
Rectangle {
id: bloop;
anchors {
bottom: parent.bottom;
bottomMargin: 8 * screenScaleFactor; // Because of the shadow
top: parent.top;
topMargin: 8 * screenScaleFactor; // Because of the shadow + point
}
color: UM.Theme.getColor("monitor_context_menu_background");
width: parent.width;
}
}
}
clip: true;
closePolicy: Popup.CloseOnPressOutside;
contentItem: Column {
id: popupOptions;
anchors {
top: parent.top;
topMargin: UM.Theme.getSize("default_margin").height + 10 * screenScaleFactor; // Account for the point of the box
}
height: childrenRect.height + spacing * popupOptions.children.length + UM.Theme.getSize("default_margin").height;
spacing: Math.floor(UM.Theme.getSize("default_margin").height / 2);
width: parent.width;
PrintJobContextMenuItem {
onClicked: {
sendToTopConfirmationDialog.visible = true;
popup.close();
}
text: catalog.i18nc("@label", "Move to top");
visible: {
if (printJob && printJob.state == "queued" && !assigned) {
if (OutputDevice && OutputDevice.queuedPrintJobs[0]) {
return OutputDevice.queuedPrintJobs[0].key != printJob.key;
}
}
return false;
}
}
PrintJobContextMenuItem {
onClicked: {
deleteConfirmationDialog.visible = true;
popup.close();
}
text: catalog.i18nc("@label", "Delete");
visible: {
if (!printJob) {
return false;
}
var states = ["queued", "sent_to_printer"];
return states.indexOf(printJob.state) !== -1;
}
}
PrintJobContextMenuItem {
enabled: visible && !(printJob.state == "pausing" || printJob.state == "resuming");
onClicked: {
if (printJob.state == "paused") {
printJob.setState("print");
popup.close();
return;
}
if (printJob.state == "printing") {
printJob.setState("pause");
popup.close();
return;
}
}
text: {
if (!printJob) {
return "";
}
switch(printJob.state) {
case "paused":
return catalog.i18nc("@label", "Resume");
case "pausing":
return catalog.i18nc("@label", "Pausing...");
case "resuming":
return catalog.i18nc("@label", "Resuming...");
default:
catalog.i18nc("@label", "Pause");
}
}
visible: {
if (!printJob) {
return false;
}
var states = ["printing", "pausing", "paused", "resuming"];
return states.indexOf(printJob.state) !== -1;
}
}
PrintJobContextMenuItem {
enabled: visible && printJob.state !== "aborting";
onClicked: {
abortConfirmationDialog.visible = true;
popup.close();
}
text: printJob && printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
visible: {
if (!printJob) {
return false;
}
var states = ["pre_print", "printing", "pausing", "paused", "resuming"];
return states.indexOf(printJob.state) !== -1;
}
}
}
enter: Transition {
NumberAnimation {
duration: 75;
property: "visible";
}
}
exit: Transition {
NumberAnimation {
duration: 75;
property: "visible";
}
}
height: contentItem.height + 2 * padding;
onClosed: visible = false;
onOpened: visible = true;
padding: UM.Theme.getSize("monitor_shadow_radius").width;
transformOrigin: Popup.Top;
visible: false;
width: 182 * screenScaleFactor;
x: (button.width - width) + 26 * screenScaleFactor;
y: button.height + 5 * screenScaleFactor; // Because shadow
}
MessageDialog {
id: sendToTopConfirmationDialog;
Component.onCompleted: visible = false;
icon: StandardIcon.Warning;
onYes: OutputDevice.sendJobToTop(printJob.key);
standardButtons: StandardButton.Yes | StandardButton.No;
text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to move %1 to the top of the queue?").arg(printJob.name) : "";
title: catalog.i18nc("@window:title", "Move print job to top");
}
MessageDialog {
id: deleteConfirmationDialog;
Component.onCompleted: visible = false;
icon: StandardIcon.Warning;
onYes: OutputDevice.deleteJobFromQueue(printJob.key);
standardButtons: StandardButton.Yes | StandardButton.No;
text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to delete %1?").arg(printJob.name) : "";
title: catalog.i18nc("@window:title", "Delete print job");
}
MessageDialog {
id: abortConfirmationDialog;
Component.onCompleted: visible = false;
icon: StandardIcon.Warning;
onYes: printJob.setState("abort");
standardButtons: StandardButton.Yes | StandardButton.No;
text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to abort %1?").arg(printJob.name) : "";
title: catalog.i18nc("@window:title", "Abort print");
}
// Utils
function switchPopupState() {
popup.visible ? popup.close() : popup.open();
}
function isStarted(job) {
if (!job) {
return false;
}
return ["pre_print", "printing", "pausing", "paused", "resuming", "aborting"].indexOf(job.state) !== -1;
}
function isAssigned(job) {
if (!job) {
return false;
}
return job.assignedPrinter ? true : false;
}
function getMenuLength() {
var visible = 0;
for (var i = 0; i < popupOptions.children.length; i++) {
if (popupOptions.children[i].visible) {
visible++;
}
}
return visible;
}
}

View File

@ -9,10 +9,10 @@ import UM 1.3 as UM
Button {
background: Rectangle {
opacity: parent.down || parent.hovered ? 1 : 0;
color: UM.Theme.getColor("monitor_context_menu_highlight");
color: UM.Theme.getColor("monitor_context_menu_hover")
}
contentItem: Label {
color: enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("text_inactive");
color: enabled ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled");
text: parent.text
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;

View File

@ -111,7 +111,7 @@ class CloudOutputDeviceManager:
stored_cluster_id = active_machine.getMetaDataEntry(self.META_CLUSTER_ID)
if stored_cluster_id in self._remote_clusters:
device = self._remote_clusters[stored_cluster_id]
self._connectToOutputDevice(device)
self._connectToOutputDevice(device, active_machine)
Logger.log("d", "Device connected by metadata cluster ID %s", stored_cluster_id)
else:
self._connectByNetworkKey(active_machine)
@ -129,12 +129,13 @@ class CloudOutputDeviceManager:
Logger.log("i", "Found cluster %s with network key %s", device, local_network_key)
active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
self._connectToOutputDevice(device)
self._connectToOutputDevice(device, active_machine)
## Connects to an output device and makes sure it is registered in the output device manager.
def _connectToOutputDevice(self, device: CloudOutputDevice) -> None:
def _connectToOutputDevice(self, device: CloudOutputDevice, active_machine: GlobalStack) -> None:
device.connect()
self._output_device_manager.addOutputDevice(device)
active_machine.addConfiguredConnectionType(device.connectionType.value)
## Handles an API error received from the cloud.
# \param errors: The errors received

View File

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Any, cast, Tuple, Union, Optional, Dict, List
@ -13,6 +13,7 @@ from UM.FileHandler.WriteFileJob import WriteFileJob # To call the file writer
from UM.Logger import Logger
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from UM.Qt.Duration import Duration, DurationFormat
from UM.Message import Message
from UM.Scene.SceneNode import SceneNode # For typing.
@ -194,7 +195,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._progress_message = Message(i18n_catalog.i18nc("@info:status", "Sending data to printer"), lifetime = 0,
dismissable = False, progress = -1,
title = i18n_catalog.i18nc("@info:title", "Sending Data"))
self._progress_message.addAction("Abort", i18n_catalog.i18nc("@action:button", "Cancel"), icon = None,
self._progress_message.addAction("Abort", i18n_catalog.i18nc("@action:button", "Cancel"), icon = "",
description = "")
self._progress_message.actionTriggered.connect(self._progressMessageActionTriggered)
self._progress_message.show()
@ -255,7 +256,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
# Treat upload progress as response. Uploading can take more than 10 seconds, so if we don't, we can get
# timeout responses if this happens.
self._last_response_time = time()
if self._progress_message is not None and new_progress > self._progress_message.getProgress():
if self._progress_message is not None and new_progress != self._progress_message.getProgress():
self._progress_message.show() # Ensure that the message is visible.
self._progress_message.setProgress(bytes_sent / bytes_total * 100)
@ -267,7 +268,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
i18n_catalog.i18nc("@info:status", "Print job was successfully sent to the printer."),
lifetime=5, dismissable=True,
title=i18n_catalog.i18nc("@info:title", "Data Sent"))
self._success_message.addAction("View", i18n_catalog.i18nc("@action:button", "View in Monitor"), icon=None,
self._success_message.addAction("View", i18n_catalog.i18nc("@action:button", "View in Monitor"), icon = "",
description="")
self._success_message.actionTriggered.connect(self._successMessageActionTriggered)
self._success_message.show()
@ -346,12 +347,16 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def getDateCompleted(self, time_remaining: int) -> str:
return formatDateCompleted(time_remaining)
@pyqtSlot(int, result = str)
def formatDuration(self, seconds: int) -> str:
return Duration(seconds).getDisplayString(DurationFormat.Format.Short)
@pyqtSlot(str)
def sendJobToTop(self, print_job_uuid: str) -> None:
# This function is part of the output device (and not of the printjob output model) as this type of operation
# is a modification of the cluster queue and not of the actual job.
data = "{\"to_position\": 0}"
self.put("print_jobs/{uuid}/move_to_position".format(uuid = print_job_uuid), data, on_finished=None)
data = "{\"list\": \"queued\",\"to_position\": 0}"
self.post("print_jobs/{uuid}/action/move".format(uuid = print_job_uuid), data, on_finished=None)
@pyqtSlot(str)
def deleteJobFromQueue(self, print_job_uuid: str) -> None:

View File

@ -13,6 +13,7 @@ from UM.i18n import i18nCatalog
from cura.CuraApplication import CuraApplication
from cura.MachineAction import MachineAction
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from .UM3OutputDevicePlugin import UM3OutputDevicePlugin
@ -105,13 +106,13 @@ class DiscoverUM3Action(MachineAction):
global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
if global_container_stack:
meta_data = global_container_stack.getMetaData()
if "connect_group_name" in meta_data:
previous_connect_group_name = meta_data["connect_group_name"]
global_container_stack.setMetaDataEntry("connect_group_name", group_name)
if "group_name" in meta_data:
previous_connect_group_name = meta_data["group_name"]
global_container_stack.setMetaDataEntry("group_name", group_name)
# Find all the places where there is the same group name and change it accordingly
CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "connect_group_name", value = previous_connect_group_name, new_value = group_name)
CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "group_name", value = previous_connect_group_name, new_value = group_name)
else:
global_container_stack.setMetaDataEntry("connect_group_name", group_name)
global_container_stack.setMetaDataEntry("group_name", group_name)
# Set the default value for "hidden", which is used when you have a group with multiple types of printers
global_container_stack.setMetaDataEntry("hidden", False)
@ -133,23 +134,29 @@ class DiscoverUM3Action(MachineAction):
return
meta_data = global_container_stack.getMetaData()
if "um_network_key" in meta_data:
previous_network_key = meta_data["um_network_key"]
global_container_stack.setMetaDataEntry("um_network_key", printer_device.key)
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)
global_container_stack.removeMetaDataEntry("network_authentication_id")
global_container_stack.removeMetaDataEntry("network_authentication_key")
CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "um_network_key", value = previous_network_key, new_value = printer_device.key)
if "connection_type" in meta_data:
previous_connection_type = meta_data["connection_type"]
global_container_stack.setMetaDataEntry("connection_type", printer_device.connectionType.value)
CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "connection_type", value = previous_connection_type, new_value = printer_device.connectionType.value)
else:
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.setMetaDataEntry("connection_type", printer_device.connectionType.value)
global_container_stack.addConfiguredConnectionType(printer_device.connectionType.value)
if self._network_plugin:
# Ensure that the connection states are refreshed.

View File

@ -1,4 +1,4 @@
# Copyright (c) 2017 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
@ -33,9 +33,9 @@ class LegacyUM3PrinterOutputController(PrinterOutputController):
data = "{\"target\": \"%s\"}" % state
self._output_device.put("print_job/state", data, on_finished=None)
def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int):
def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: float):
data = str(temperature)
self._output_device.put("printer/bed/temperature/target", data, on_finished=self._onPutBedTemperatureCompleted)
self._output_device.put("printer/bed/temperature/target", data, on_finished = self._onPutBedTemperatureCompleted)
def _onPutBedTemperatureCompleted(self, reply):
if Version(self._preheat_printer.firmwareVersion) < Version("3.5.92"):

View File

@ -1,14 +1,14 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import json
import os
from typing import Dict, TYPE_CHECKING, Set, Optional
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
from UM.Application import Application
from UM.Job import Job
from UM.Logger import Logger
from cura.CuraApplication import CuraApplication
# Absolute imports don't work in plugins
from .Models import ClusterMaterial, LocalMaterial
@ -86,8 +86,8 @@ class SendMaterialJob(Job):
#
# \param materials_to_send A set with id's of materials that must be sent.
def _sendMaterials(self, materials_to_send: Set[str]) -> None:
container_registry = Application.getInstance().getContainerRegistry()
material_manager = Application.getInstance().getMaterialManager()
container_registry = CuraApplication.getInstance().getContainerRegistry()
material_manager = CuraApplication.getInstance().getMaterialManager()
material_group_dict = material_manager.getAllMaterialGroups()
for root_material_id in material_group_dict:
@ -166,7 +166,7 @@ class SendMaterialJob(Job):
# \return a dictionary of LocalMaterial objects by GUID
def _getLocalMaterials(self) -> Dict[str, LocalMaterial]:
result = {} # type: Dict[str, LocalMaterial]
material_manager = Application.getInstance().getMaterialManager()
material_manager = CuraApplication.getInstance().getMaterialManager()
material_group_dict = material_manager.getAllMaterialGroups()

View File

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import json
from queue import Queue
@ -9,7 +9,7 @@ from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager
from PyQt5.QtCore import QUrl
from UM.Application import Application
from cura.CuraApplication import CuraApplication
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from UM.Logger import Logger
from UM.Signal import Signal, signalemitter
@ -41,7 +41,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self.addDeviceSignal.connect(self._onAddDevice)
self.removeDeviceSignal.connect(self._onRemoveDevice)
Application.getInstance().globalContainerStackChanged.connect(self.reCheckConnections)
CuraApplication.getInstance().globalContainerStackChanged.connect(self.reCheckConnections)
self._discovered_devices = {}
@ -56,7 +56,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._cluster_api_prefix = "/cluster-api/v" + self._cluster_api_version + "/"
# Get list of manual instances from preferences
self._preferences = Application.getInstance().getPreferences()
self._preferences = CuraApplication.getInstance().getPreferences()
self._preferences.addPreference("um3networkprinting/manual_instances",
"") # A comma-separated list of ip adresses or hostnames
@ -108,7 +108,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self.resetLastManualDevice()
def reCheckConnections(self):
active_machine = Application.getInstance().getGlobalContainerStack()
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
if not active_machine:
return
@ -118,7 +118,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
if key == um_network_key:
if not self._discovered_devices[key].isConnected():
Logger.log("d", "Attempting to connect with [%s]" % key)
active_machine.setMetaDataEntry("connection_type", self._discovered_devices[key].connectionType.value)
# It should already be set, but if it actually connects we know for sure it's supported!
active_machine.addConfiguredConnectionType(self._discovered_devices[key].connectionType.value)
self._discovered_devices[key].connect()
self._discovered_devices[key].connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
else:
@ -134,7 +135,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
return
if self._discovered_devices[key].isConnected():
# Sometimes the status changes after changing the global container and maybe the device doesn't belong to this machine
um_network_key = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key")
um_network_key = CuraApplication.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key")
if key == um_network_key:
self.getOutputDeviceManager().addOutputDevice(self._discovered_devices[key])
else:
@ -244,7 +245,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
properties = device.getProperties().copy()
if b"incomplete" in properties:
del properties[b"incomplete"]
properties[b'cluster_size'] = len(cluster_printers_list)
properties[b"cluster_size"] = len(cluster_printers_list)
self._onRemoveDevice(instance_name)
self._onAddDevice(instance_name, address, properties)
@ -287,9 +288,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._discovered_devices[device.getId()] = device
self.discoveredDevicesChanged.emit()
global_container_stack = Application.getInstance().getGlobalContainerStack()
global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
if global_container_stack and device.getId() == global_container_stack.getMetaDataEntry("um_network_key"):
global_container_stack.setMetaDataEntry("connection_type", device.connectionType.value)
# Ensure that the configured connection type is set.
global_container_stack.addConfiguredConnectionType(device.connectionType.value)
device.connect()
device.connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
@ -306,7 +308,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._service_changed_request_event.wait(timeout = 5.0)
# Stop if the application is shutting down
if Application.getInstance().isShuttingDown():
if CuraApplication.getInstance().isShuttingDown():
return
self._service_changed_request_event.clear()

View File

@ -72,9 +72,9 @@ class AutoDetectBaudJob(Job):
while timeout_time > time():
line = serial.readline()
if b"ok " in line and b"T:" in line:
if b"ok" in line and b"T:" in line:
successful_responses += 1
if successful_responses >= 3:
if successful_responses >= 1:
self.setResult(baud_rate)
Logger.log("d", "Detected baud rate {baud_rate} on serial {serial} on retry {retry} with after {time_elapsed:0.2f} seconds.".format(
serial = self._serial_port, baud_rate = baud_rate, retry = retry, time_elapsed = time() - start_timeout_time))

View File

@ -55,6 +55,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._update_thread = Thread(target = self._update, daemon = True)
self._last_temperature_request = None # type: Optional[int]
self._firmware_idle_count = 0
self._is_printing = False # A print is being sent.
@ -114,7 +115,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs):
if self._is_printing:
return # Aleady printing
self.writeStarted.emit(self)
# cancel any ongoing preheat timer before starting a print
self._printers[0].getController().stopPreheatTimers()

View File

@ -1,9 +1,12 @@
import configparser
from typing import Tuple, List, Set
from typing import Tuple, List, Set, Dict
import io
from UM.VersionUpgrade import VersionUpgrade
from cura.PrinterOutputDevice import ConnectionType
deleted_settings = {"bridge_wall_max_overhang"} # type: Set[str]
renamed_configurations = {"connect_group_name": "group_name"} # type: Dict[str, str]
class VersionUpgrade35to40(VersionUpgrade):
@ -20,10 +23,16 @@ class VersionUpgrade35to40(VersionUpgrade):
# Set the connection type if um_network_key or the octoprint key is set.
parser["metadata"]["connection_type"] = str(ConnectionType.NetworkConnection.value)
if "metadata" in parser:
for old_name, new_name in renamed_configurations.items():
if old_name not in parser["metadata"]:
continue
parser["metadata"][new_name] = parser["metadata"][old_name]
del parser["metadata"][old_name]
result = io.StringIO()
parser.write(result)
return [filename], [result.getvalue()]
pass
def getCfgVersion(self, serialised: str) -> int:
parser = configparser.ConfigParser(interpolation = None)

View File

@ -0,0 +1,51 @@
{
"id": "CR-X",
"version": 2,
"name": "Creality CR-X",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "SRC",
"manufacturer": "Creality3D",
"category": "Other",
"file_formats": "text/x-gcode",
"platform": "cr-x.stl",
"has_variants": false,
"has_machine_quality": false,
"preferred_quality_type": "draft",
"machine_extruder_trains": {
"0": "cr-x_extruder_0",
"1": "cr-x_extruder_1"
}
},
"overrides": {
"machine_name": { "default_value": "Creality CR-X" },
"machine_extruder_count": { "default_value": 2 },
"machine_heated_bed": { "default_value": true },
"machine_width": { "default_value": 300 },
"machine_depth": { "default_value": 300 },
"machine_height": { "default_value": 400 },
"machine_center_is_zero": { "default_value": false },
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 70},
"adhesion_type": { "default_value": "skirt" },
"gantry_height": { "default_value": 30 },
"speed_print": { "default_value": 60 },
"speed_travel": { "default_value": 120 },
"machine_max_acceleration_x": { "default_value": 500 },
"machine_max_acceleration_y": { "default_value": 500 },
"machine_max_acceleration_z": { "default_value": 100 },
"machine_max_acceleration_e": { "default_value": 5000 },
"machine_max_jerk_xy": { "default_value": 5.0 },
"machine_max_jerk_z": { "default_value": 0.4 },
"machine_max_jerk_e": { "default_value": 5.0 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": { "default_value": "G21 ;metric values\nG28 ;home all\nG90 ;absolute positioning\nM107 ;start with the fan off\nG1 F2400 Z15.0 ;raise the nozzle 15mm\nM109 S{material_print_temperature} ;Set Extruder Temperature and Wait\nM190 S{material_bed_temperature}; Wait for bed temperature to reach target temp\nT0 ;Switch to Extruder 1\nG1 F3000 X5 Y10 Z0.2 ;move to prime start position\nG92 E0 ;reset extrusion distance\nG1 F600 X160 E15 ;prime nozzle in a line\nG1 F5000 X180 ;quick wipe\nG92 E0 ;reset extrusion distance" },
"machine_end_gcode": { "default_value": "M104 S0 ;hotend off\nM140 S0 ;bed off\nG92 E0\nG1 F2000 E-100 ;retract filament 100mm\nG92 E0\nG1 F3000 X0 Y270 ;move bed for easy part removal\nM84 ;disable steppers" },
"material_print_temperature": { "default_value": 200 },
"wall_thickness": { "default_value": 1 },
"top_bottom_thickness": { "default_value": 1 },
"bottom_thickness": { "default_value": 1 }
}
}

View File

@ -3395,7 +3395,7 @@
"infill": "Within Infill"
},
"default_value": "all",
"resolve": "'noskin' if 'noskin' in extruderValues('retraction_combing') else ('all' if 'all' in extruderValues('retraction_combing') else 'off')",
"resolve": "'noskin' if 'noskin' in extruderValues('retraction_combing') else ('infill' if 'infill' in extruderValues('retraction_combing') else ('all' if 'all' in extruderValues('retraction_combing') else 'off'))",
"settable_per_mesh": false,
"settable_per_extruder": false
},

View File

@ -15,6 +15,7 @@
"has_machine_materials": true,
"has_machine_quality": true,
"first_start_actions": [],
"supported_actions": [],
"machine_extruder_trains":
{
"0": "ultimaker2_plus_extruder_0"

View File

@ -0,0 +1,27 @@
{
"id": "cr-x_extruder_0",
"version": 2,
"name": "Left Extruder",
"inherits": "fdmextruder",
"metadata": {
"machine": "Creality CR-X",
"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 },
"material_diameter": { "default_value": 1.75 },
"machine_nozzle_size": { "default_value": 0.4 },
"machine_extruder_start_code": {
"default_value": "\nT0 ;switch to extruder 1\nG92 E0 ;reset extruder distance\nG1 F2000 E93 ;load filament\nG92 E0 ;reset extruder distance\nM104 S{material_print_temperature}"
},
"machine_extruder_end_code": {
"default_value": "\nG92 E0 ;reset extruder distance\nG1 F800 E-5 ;short retract\nG1 F2400 X295 Y265 ;move near prime tower\nG1 F2000 E-93 ;long retract for filament removal\nG92 E0 ;reset extruder distance\nG90"
}
}
}

View File

@ -0,0 +1,27 @@
{
"id": "cr-x_extruder_1",
"version": 2,
"name": "Right Extruder",
"inherits": "fdmextruder",
"metadata": {
"machine": "Creality CR-X",
"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 },
"material_diameter": { "default_value": 1.75 },
"machine_nozzle_size": { "default_value": 0.4 },
"machine_extruder_start_code": {
"default_value": "\nT1 ;switch to extruder 2\nG92 E0 ;reset extruder distance\nG1 F2000 E93 ;load filament\nG92 E0 ;reset extruder distance\nM104 S{material_print_temperature}"
},
"machine_extruder_end_code": {
"default_value": "\nG92 E0 ;reset extruder distance\nG1 F800 E-5 ;short retract\nG1 F2400 X295 Y265 ;move near prime tower\nG1 F2000 E-93 ;long retract for filament removal\nG92 E0 ;reset extruder distance\nG90"
}
}
}

BIN
resources/meshes/cr-x.stl Normal file

Binary file not shown.

View File

@ -1,8 +1,8 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.4 as UM
import Cura 1.1 as Cura
@ -16,38 +16,6 @@ Column
padding: UM.Theme.getSize("wide_margin").height
spacing: UM.Theme.getSize("wide_margin").height
AvatarImage
{
id: avatar
width: UM.Theme.getSize("avatar_image").width
height: UM.Theme.getSize("avatar_image").height
anchors.horizontalCenter: parent.horizontalCenter
source:
{
if(loggedIn)
{
if(profileImage)
{
return profileImage
}
return UM.Theme.getImage("avatar_no_user")
}
return UM.Theme.getImage("avatar_no_user")
}
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
}
Label
{
id: information
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
text: loggedIn ? profile["username"] : catalog.i18nc("@label", "Please log in or create an account to\nenjoy all features of Ultimaker Cura.")
font: loggedIn ? UM.Theme.getFont("large_bold") : UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
}
Loader
{
id: accountOperations

View File

@ -1,21 +1,69 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.4 as UM
import Cura 1.1 as Cura
Button
Item
{
id: accountWidget
property var profile: Cura.API.account.userProfile
property var loggedIn: Cura.API.account.isLoggedIn
height: signInButton.height > accountWidget.height ? signInButton.height : accountWidget.height
width: signInButton.width > accountWidget.width ? signInButton.width : accountWidget.width
Button
{
id: signInButton
anchors.verticalCenter: parent.verticalCenter
text: catalog.i18nc("@action:button", "Sign in")
height: Math.round(0.5 * UM.Theme.getSize("main_window_header").height)
onClicked: popup.opened ? popup.close() : popup.open()
visible: !loggedIn
hoverEnabled: true
background: Rectangle
{
radius: UM.Theme.getSize("action_button_radius").width
color: signInButton.hovered ? UM.Theme.getColor("primary_text") : UM.Theme.getColor("main_window_header_background")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("primary_text")
}
contentItem: Label
{
id: label
text: signInButton.text
font: UM.Theme.getFont("default")
color: signInButton.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text")
width: contentWidth
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
}
}
Button
{
id: accountWidget
anchors.verticalCenter: parent.verticalCenter
implicitHeight: UM.Theme.getSize("main_window_header").height
implicitWidth: UM.Theme.getSize("main_window_header").height
hoverEnabled: true
visible: loggedIn
text: (loggedIn && profile["profile_image_url"] == "") ? profile["username"].charAt(0).toUpperCase() : ""
background: AvatarImage
{
id: avatar
@ -25,22 +73,43 @@ Button
anchors.verticalCenter: accountWidget.verticalCenter
anchors.horizontalCenter: accountWidget.horizontalCenter
source:
{
if(loggedIn)
{
if(profile["profile_image_url"])
{
return profile["profile_image_url"]
}
return UM.Theme.getImage("avatar_no_user")
}
return UM.Theme.getImage("avatar_no_user")
}
source: (loggedIn && profile["profile_image_url"]) ? profile["profile_image_url"] : ""
outlineColor: loggedIn ? UM.Theme.getColor("account_widget_outline_active") : UM.Theme.getColor("lining")
}
contentItem: Item
{
anchors.verticalCenter: accountWidget.verticalCenter
anchors.horizontalCenter: accountWidget.horizontalCenter
visible: avatar.source == ""
Rectangle
{
id: initialCircle
anchors.centerIn: parent
width: Math.min(parent.width, parent.height)
height: width
radius: width
color: accountWidget.hovered ? UM.Theme.getColor("primary_text") : "transparent"
border.width: 1
border.color: UM.Theme.getColor("primary_text")
}
Label
{
id: initialLabel
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
text: accountWidget.text
font: UM.Theme.getFont("large_bold")
color: accountWidget.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
}
}
onClicked: popup.opened ? popup.close() : popup.open()
}
Popup
{

View File

@ -1,8 +1,8 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtGraphicalEffects 1.0
import UM 1.4 as UM
@ -16,6 +16,7 @@ Item
property alias source: profileImage.source
property alias outlineColor: profileImageOutline.color
property bool hasAvatar: source != ""
Image
{
@ -32,6 +33,7 @@ Item
id: profileImageMask
anchors.fill: parent
radius: width
color: hasAvatar ? "white" : "transparent"
}
OpacityMask
@ -39,6 +41,7 @@ Item
anchors.fill: parent
source: profileImage
maskSource: profileImageMask
visible: hasAvatar
cached: true
}
@ -49,6 +52,7 @@ Item
// Make it a bit bigger than it has to, otherwise it sometimes shows a white border.
width: parent.width + 2
height: parent.height + 2
visible: hasAvatar
source: UM.Theme.getIcon("circle_outline")
sourceSize: Qt.size(parent.width, parent.height)
color: UM.Theme.getColor("account_widget_ouline_active")

View File

@ -1,31 +1,82 @@
// Copyright (c) 2018 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 2.10
import QtQuick.Controls 2.3
import UM 1.4 as UM
import Cura 1.1 as Cura
Row
Column
{
spacing: UM.Theme.getSize("default_margin").width
Image
{
id: machinesImage
anchors.horizontalCenter: parent.horizontalCenter
source: UM.Theme.getIcon("sign_in_to_cloud")
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
}
Label
{
id: title
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
text: catalog.i18nc("@label", "Ultimaker Cloud")
font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
}
Label
{
id: generalInformation
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
text: catalog.i18nc("@label", "The next generation 3D printing workflow")
font: UM.Theme.getFont("default_bold")
color: UM.Theme.getColor("text")
}
Label
{
id: generalInformationPoints
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignLeft
renderType: Text.NativeRendering
text: catalog.i18nc("@text", "- Send print jobs to Ultimaker printers outside your local network\n- Store your Ultimaker Cura settings in the cloud for use anywhere\n- Get exclusive access to material profiles from leading brands")
lineHeight: 1.4
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
}
// placeholder
Label
{
text: " "
}
Cura.PrimaryButton
{
anchors.horizontalCenter: parent.horizontalCenter
width: UM.Theme.getSize("account_button").width
height: UM.Theme.getSize("account_button").height
text: catalog.i18nc("@button", "Sign in")
onClicked: Cura.API.account.login()
fixedWidthMode: true
}
Cura.SecondaryButton
{
anchors.horizontalCenter: parent.horizontalCenter
width: UM.Theme.getSize("account_button").width
height: UM.Theme.getSize("account_button").height
text: catalog.i18nc("@button", "Create account")
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl + "/app/create")
fixedWidthMode: true
}
Cura.PrimaryButton
{
width: UM.Theme.getSize("account_button").width
height: UM.Theme.getSize("account_button").height
text: catalog.i18nc("@button", "Login")
onClicked: Cura.API.account.login()
fixedWidthMode: true
}
}

View File

@ -1,31 +1,63 @@
// Copyright (c) 2018 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 2.10
import QtQuick.Controls 2.3
import UM 1.4 as UM
import Cura 1.1 as Cura
Row
Column
{
width: Math.max(title.width,
accountButton.width) * 1.5
spacing: UM.Theme.getSize("default_margin").width
Label
{
id: title
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering
text: catalog.i18nc("@label", "Hi " + profile.username)
font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
}
// placeholder
Label
{
text: " "
}
Cura.SecondaryButton
{
id: accountButton
anchors.horizontalCenter: parent.horizontalCenter
width: UM.Theme.getSize("account_button").width
height: UM.Theme.getSize("account_button").height
text: catalog.i18nc("@button", "Manage account")
text: catalog.i18nc("@button", "Ultimaker account")
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl)
fixedWidthMode: true
fixedWidthMode: false
}
Cura.PrimaryButton
Label
{
width: UM.Theme.getSize("account_button").width
height: UM.Theme.getSize("account_button").height
text: catalog.i18nc("@button", "Logout")
id: signOutButton
anchors.horizontalCenter: parent.horizontalCenter
text: catalog.i18nc("@button", "Sign out")
color: UM.Theme.getColor("secondary_button_text")
font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering
MouseArea
{
anchors.fill: parent
onClicked: Cura.API.account.logout()
fixedWidthMode: true
hoverEnabled: true
onEntered: signOutButton.font.underline = true
onExited: signOutButton.font.underline = false
}
}
}

View File

@ -48,12 +48,13 @@ Button
contentItem: Row
{
spacing: UM.Theme.getSize("narrow_margin").width
height: button.height
//Left side icon. Only displayed if !isIconOnRightSide.
UM.RecolorImage
{
id: buttonIconLeft
source: ""
height: UM.Theme.getSize("action_button_icon").height
height: visible ? UM.Theme.getSize("action_button_icon").height : 0
width: visible ? height : 0
sourceSize.width: width
sourceSize.height: height
@ -70,9 +71,11 @@ Button
font: UM.Theme.getFont("medium")
visible: text != ""
renderType: Text.NativeRendering
height: parent.height
anchors.verticalCenter: parent.verticalCenter
width: fixedWidthMode ? button.width - button.leftPadding - button.rightPadding : undefined
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
@ -81,7 +84,7 @@ Button
{
id: buttonIconRight
source: buttonIconLeft.source
height: UM.Theme.getSize("action_button_icon").height
height: visible ? UM.Theme.getSize("action_button_icon").height : 0
width: visible ? height : 0
sourceSize.width: width
sourceSize.height: height

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
@ -12,13 +12,22 @@ import Cura 1.0 as Cura
// This element hold all the elements needed for the user to trigger the slicing process, and later
// to get information about the printing times, material consumption and the output process (such as
// saving to a file, printing over network, ...
Rectangle
Item
{
id: base
width: childrenRect.width
height: childrenRect.height
visible: CuraApplication.platformActivity
property bool hasPreviewButton: true
Rectangle
{
id: actionPanelWidget
width: UM.Theme.getSize("action_panel_widget").width
height: childrenRect.height + 2 * UM.Theme.getSize("thick_margin").height
anchors. right: parent.right
color: UM.Theme.getColor("main_background")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
@ -39,7 +48,14 @@ Rectangle
right: parent.right
rightMargin: UM.Theme.getSize("thick_margin").width
}
sourceComponent: outputAvailable ? outputProcessWidget : sliceProcessWidget
sourceComponent: actionPanelWidget.outputAvailable ? outputProcessWidget : sliceProcessWidget
onLoaded:
{
if(actionPanelWidget.outputAvailable)
{
loader.item.hasPreviewButton = base.hasPreviewButton;
}
}
}
Component
@ -53,4 +69,38 @@ Rectangle
id: outputProcessWidget
OutputProcessWidget { }
}
}
Item
{
id: additionalComponents
width: childrenRect.width
anchors.right: actionPanelWidget.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.bottom: actionPanelWidget.bottom
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height * 2
visible: actionPanelWidget.visible
Row
{
id: additionalComponentsRow
anchors.verticalCenter: parent.verticalCenter
spacing: UM.Theme.getSize("default_margin").width
}
}
Component.onCompleted: base.addAdditionalComponents()
Connections
{
target: CuraApplication
onAdditionalComponentsChanged: base.addAdditionalComponents()
}
function addAdditionalComponents()
{
for (var component in CuraApplication.additionalComponents["saveButton"])
{
CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
@ -19,6 +19,7 @@ Column
spacing: UM.Theme.getSize("thin_margin").height
property bool preSlicedData: PrintInformation.preSliced
property alias hasPreviewButton: previewStageShortcut.visible
UM.I18nCatalog
{
@ -120,7 +121,6 @@ Column
toolTipContentAlignment: Cura.ToolTip.ContentAlignment.AlignLeft
onClicked: UM.Controller.setActiveStage("PreviewStage")
visible: UM.Controller.activeStage != null && UM.Controller.activeStage.stageId != "PreviewStage"
}
Cura.OutputDevicesActionButton

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7
@ -36,30 +36,63 @@ Column
Label
{
property var printDuration: PrintInformation.currentPrintTime
id: byLineType
text:
property var printDuration: PrintInformation.currentPrintTime
property var columnWidthMultipliers: [ 0.4, 0.3, 0.3 ]
property var columnHorizontalAligns: [ TextInput.AlignLeft, TextInput.AlignHCenter, TextInput.AlignHCenter ]
function getMaterialTable()
{
var result = []
// All the time information for the different features is achieved
var printTime = PrintInformation.getFeaturePrintTimes()
var totalSeconds = parseInt(printDuration.getDisplayString(UM.DurationFormat.Seconds))
// A message is created and displayed when the user hover the time label
var text = "<table width=\"100%\">"
for(var feature in printTime)
{
if(!printTime[feature].isTotalDurationZero)
{
text += "<tr><td>" + feature + ":</td>" +
"<td align=\"right\" valign=\"bottom\">&nbsp;&nbsp;%1</td>".arg(printTime[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)) +
"<td align=\"right\" valign=\"bottom\">&nbsp;&nbsp;%1%</td>".arg(Math.round(100 * parseInt(printTime[feature].getDisplayString(UM.DurationFormat.Seconds)) / totalSeconds)) +
"</tr>"
var row = []
row.push(feature + ": ")
row.push("%1".arg(printTime[feature].getDisplayString(UM.DurationFormat.ISO8601).slice(0,-3)))
row.push("%1%".arg(Math.round(100 * parseInt(printTime[feature].getDisplayString(UM.DurationFormat.Seconds)) / totalSeconds)))
result.push(row)
}
}
text += "</table>"
return text
return result
}
Column
{
Repeater
{
model: byLineType.getMaterialTable()
Row
{
Repeater
{
model: modelData
Label
{
width: Math.round(byLineType.width * byLineType.columnWidthMultipliers[index])
height: contentHeight
horizontalAlignment: byLineType.columnHorizontalAligns[index]
font: UM.Theme.getFont("default")
wrapMode: Text.WrapAnywhere
text: modelData
renderType: Text.NativeRendering
}
}
}
}
}
width: parent.width - 2 * UM.Theme.getSize("default_margin").width
height: childrenRect.height
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering
@ -85,31 +118,19 @@ Column
Label
{
id: byMaterialType
property var printMaterialLengths: PrintInformation.materialLengths
property var printMaterialWeights: PrintInformation.materialWeights
property var printMaterialCosts: PrintInformation.materialCosts
property var printMaterialNames: PrintInformation.materialNames
property var columnWidthMultipliers: [ 0.4, 0.2, 0.2, 0.2 ]
property var columnHorizontalAligns: [ TextInput.AlignLeft, TextInput.AlignHCenter, TextInput.AlignHCenter, TextInput.AlignHCenter ]
function formatRow(items)
function getMaterialTable()
{
var rowHTML = "<tr>"
for(var item = 0; item < items.length; item++)
{
if (item == 0)
{
rowHTML += "<td valign=\"bottom\">%1</td>".arg(items[item])
}
else
{
rowHTML += "<td align=\"right\" valign=\"bottom\">&nbsp;&nbsp;%1</td>".arg(items[item])
}
}
rowHTML += "</tr>"
return rowHTML
}
var result = []
text:
{
var lengths = []
var weights = []
var costs = []
@ -135,21 +156,46 @@ Column
costs = ["0.00"]
}
var text = "<table width=\"100%\">"
for(var index = 0; index < lengths.length; index++)
{
text += formatRow([
"%1:".arg(names[index]),
catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]),
catalog.i18nc("@label g for grams", "%1g").arg(weights[index]),
"%1&nbsp;%2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]),
])
var row = []
row.push("%1".arg(names[index]))
row.push(catalog.i18nc("@label m for meter", "%1m").arg(lengths[index]))
row.push(catalog.i18nc("@label g for grams", "%1g").arg(weights[index]))
row.push("%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(costs[index]))
result.push(row)
}
text += "</table>"
return text
return result
}
Column
{
Repeater
{
model: byMaterialType.getMaterialTable()
Row
{
Repeater
{
model: modelData
Label
{
width: Math.round(byMaterialType.width * byMaterialType.columnWidthMultipliers[index])
height: contentHeight
horizontalAlignment: byLineType.columnHorizontalAligns[index]
font: UM.Theme.getFont("default")
wrapMode: Text.WrapAnywhere
text: modelData
renderType: Text.NativeRendering
}
}
}
}
}
width: parent.width - 2 * UM.Theme.getSize("default_margin").width
height: childrenRect.height
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default")
renderType: Text.NativeRendering

View File

@ -246,63 +246,6 @@ UM.MainWindow
}
}
Cura.ActionPanelWidget
{
id: actionPanelWidget
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: UM.Theme.getSize("thick_margin").width
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
/*
Show this panel only if there is something on the build plate, and there is NOT an opaque item in front of the build plate.
This cannot be solved by Z indexing! If you want to try solving this, please increase this counter when you're done:
Number of people having tried to fix this by z-indexing: 2
The problem arises from the following render order requirements:
- The stage menu must be rendered above the stage main.
- The stage main must be rendered above the action panel (because the monitor page must be rendered above the action panel).
- The action panel must be rendered above the expandable components drop-down.
However since the expandable components drop-downs are child elements of the stage menu,
they can't be rendered lower than elements that are lower than the stage menu.
Therefore we opted to forego the second requirement and hide the action panel instead when something obscures it (except the expandable components).
We assume that QQuickRectangles are always opaque and any other item is not.
*/
visible: CuraApplication.platformActivity && (main.item == null || !qmlTypeOf(main.item, "QQuickRectangle"))
}
Item
{
id: additionalComponents
width: childrenRect.width
anchors.right: actionPanelWidget.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.bottom: actionPanelWidget.bottom
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height * 2
visible: actionPanelWidget.visible
Row
{
id: additionalComponentsRow
anchors.verticalCenter: parent.verticalCenter
spacing: UM.Theme.getSize("default_margin").width
}
}
Component.onCompleted: contentItem.addAdditionalComponents()
Connections
{
target: CuraApplication
onAdditionalComponentsChanged: contentItem.addAdditionalComponents("saveButton")
}
function addAdditionalComponents()
{
for (var component in CuraApplication.additionalComponents["saveButton"])
{
CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow
}
}
Loader
{
// A stage can control this area. If nothing is set, it will therefore show the 3D view.
@ -373,6 +316,24 @@ UM.MainWindow
bottom: parent.bottom
bottomMargin: UM.Theme.getSize("default_margin").height
}
primaryButton: Component
{
Cura.PrimaryButton
{
text: model.name
height: UM.Theme.getSize("message_action_button").height
}
}
secondaryButton: Component
{
Cura.SecondaryButton
{
text: model.name
height: UM.Theme.getSize("message_action_button").height
}
}
}
}

View File

@ -35,9 +35,9 @@ UM.Dialog
{
id: logo
width: (base.minimumWidth * 0.85) | 0
height: (width * (UM.Theme.getSize("logo").height / UM.Theme.getSize("logo").width)) | 0
source: UM.Theme.getImage("logo_about")
source: UM.Theme.getImage("logo")
sourceSize.width: width
sourceSize.height: height
anchors.top: parent.top
anchors.topMargin: ((base.minimumWidth - width) / 2) | 0

View File

@ -29,7 +29,7 @@ Item
source: UM.Theme.getImage("logo")
width: UM.Theme.getSize("logo").width
height: UM.Theme.getSize("logo").height
fillMode: Image.PreserveAspectFit
sourceSize.width: width
sourceSize.height: height
}
@ -122,6 +122,7 @@ Item
id: accountWidget
anchors
{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
}

View File

@ -218,7 +218,8 @@ Button
{
if(isValidMaterial)
{
Cura.MachineManager.applyRemoteConfiguration(configuration);
toggleContent()
Cura.MachineManager.applyRemoteConfiguration(configuration)
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 Ultimaker B.V.
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.6
@ -288,6 +288,58 @@ Item
menu: Cura.NozzleMenu { extruderIndex: Cura.ExtruderManager.activeExtruderIndex }
}
}
Row
{
id: warnings
height: UM.Theme.getSize("print_setup_big_item").height
visible: buildplateCompatibilityError || buildplateCompatibilityWarning
property bool buildplateCompatibilityError: !Cura.MachineManager.variantBuildplateCompatible && !Cura.MachineManager.variantBuildplateUsable
property bool buildplateCompatibilityWarning: Cura.MachineManager.variantBuildplateUsable
// This is a space holder aligning the warning messages.
Label
{
text: ""
width: selectors.textWidth
renderType: Text.NativeRendering
}
Item
{
width: selectors.controlWidth
height: parent.height
UM.RecolorImage
{
id: warningImage
anchors.left: parent.left
source: UM.Theme.getIcon("warning")
width: UM.Theme.getSize("section_icon").width
height: UM.Theme.getSize("section_icon").height
sourceSize.width: width
sourceSize.height: height
color: UM.Theme.getColor("material_compatibility_warning")
visible: !Cura.MachineManager.isCurrentSetupSupported || warnings.buildplateCompatibilityError || warnings.buildplateCompatibilityWarning
}
Label
{
id: materialCompatibilityLabel
anchors.left: warningImage.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width
verticalAlignment: Text.AlignVCenter
width: selectors.controlWidth - warningImage.width - UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@label", "Use glue for better adhesion with this material combination.")
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
visible: CuraSDKVersion == "dev" ? false : warnings.buildplateCompatibilityError || warnings.buildplateCompatibilityWarning
wrapMode: Text.WordWrap
renderType: Text.NativeRendering
}
}
}
}
}
}

View File

@ -14,9 +14,9 @@ Instantiator
{
property string connectGroupName:
{
if("connect_group_name" in model.metadata)
if("group_name" in model.metadata)
{
return model.metadata["connect_group_name"]
return model.metadata["group_name"]
}
return ""
}

View File

@ -56,7 +56,7 @@ UM.ManagementPage
{
text: catalog.i18nc("@action:button", "Rename");
iconName: "edit-rename";
enabled: base.currentItem != null && base.currentItem.metadata.connect_group_name == null
enabled: base.currentItem != null && base.currentItem.metadata.group_name == null
onClicked: renameDialog.open();
}
]

View File

@ -173,6 +173,7 @@ Item
id: createQualityDialog
title: catalog.i18nc("@title:window", "Create Profile")
object: "<new name>"
explanation: catalog.i18nc("@info", "Please provide a name for this profile.")
onAccepted:
{
base.newQualityNameToSelect = newName; // We want to switch to the new profile once it's created

View File

@ -38,7 +38,7 @@ ListView
var result = Cura.MachineManager.activeMachineId == model.id
if (Cura.MachineManager.activeMachineHasRemoteConnection)
{
result |= Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"]
result |= Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["group_name"]
}
return result
}

View File

@ -4,7 +4,7 @@ name = Best Quality
definition = nwa3d_a5
[metadata]
setting_version = 6
setting_version = 7
type = quality
quality_type = best
weight = 1

View File

@ -4,7 +4,7 @@ name = Fast Quality
definition = nwa3d_a5
[metadata]
setting_version = 6
setting_version = 7
type = quality
quality_type = fast
weight = -1

View File

@ -4,7 +4,7 @@ name = Normal Quality
definition = nwa3d_a5
[metadata]
setting_version = 6
setting_version = 7
type = quality
quality_type = normal
weight = 0

View File

@ -6,10 +6,11 @@
"colors": {
"main_background": [39, 44, 48, 255],
"message_background": [39, 44, 48, 255],
"wide_lining": [31, 36, 39, 255],
"thick_lining": [255, 255, 255, 30],
"lining": [64, 69, 72, 255],
"viewport_overlay": [0, 6, 9, 222],
"viewport_overlay": [30, 36, 39, 255],
"primary": [12, 169, 227, 255],
"primary_hover": [48, 182, 231, 255],
@ -215,24 +216,40 @@
"toolbox_header_button_text_inactive": [128, 128, 128, 255],
"toolbox_header_button_text_hovered": [255, 255, 255, 255],
"monitor_card_background_inactive": [43, 48, 52, 255],
"monitor_card_background": [43, 48, 52, 255],
"monitor_context_menu_background": [80, 84, 87, 255],
"monitor_context_menu_dots": [0, 167, 233, 255],
"monitor_context_menu_highlight": [0, 167, 233, 255],
"monitor_image_overlay": [255, 255, 255, 255],
"monitor_lining_heavy": [255, 255, 255, 255],
"monitor_lining_light": [102, 102, 102, 255],
"monitor_pill_background": [102, 102, 102, 255],
"monitor_printer_family_tag": [86, 86, 106, 255],
"monitor_text_primary": [229, 229, 229, 255],
"monitor_text_disabled": [102, 102, 102, 255],
"monitor_text_link": [103, 160, 252, 255],
"monitor_icon_primary": [229, 229, 229, 255],
"monitor_icon_accent": [51, 53, 54, 255],
"monitor_secondary_button_hover": [80, 80, 80, 255],
"monitor_secondary_button": [92, 92, 92, 255],
"monitor_secondary_button_text": [250, 250, 250, 255],
"monitor_secondary_button_shadow": [74, 74, 74, 255],
"monitor_card_border": [102, 102, 102, 255],
"monitor_card_background": [51, 53, 54, 255],
"monitor_card_hover": [84, 89, 95, 255],
"monitor_stage_background": [30, 36, 39, 255],
"monitor_stage_background_fade": [30, 36, 39, 102],
"monitor_progress_bar_fill": [50, 130, 255, 255],
"monitor_progress_bar_deactive": [102, 102, 102, 255],
"monitor_progress_bar_empty": [67, 67, 67, 255],
"monitor_tooltip": [25, 25, 25, 255],
"monitor_tooltip_text": [229, 229, 229, 255],
"monitor_context_menu": [67, 67, 67, 255],
"monitor_context_menu_hover": [30, 102, 215, 255],
"monitor_skeleton_loading": [102, 102, 102, 255],
"monitor_placeholder_image": [102, 102, 102, 255],
"monitor_printer_icon": [255, 255, 255, 255],
"monitor_progress_background_text": [102, 102, 102, 255],
"monitor_progress_background": [80, 84, 87, 255],
"monitor_progress_fill_inactive": [216, 216, 216, 255],
"monitor_progress_fill_text": [0, 0, 0, 255],
"monitor_progress_fill": [216, 216, 216, 255],
"monotir_printer_icon_inactive": [154, 154, 154, 255],
"monitor_skeleton_fill": [31, 36, 39, 255],
"monitor_skeleton_fill_dark": [31, 36, 39, 255]
"monitor_image_overlay": [0, 0, 0, 255],
"monitor_shadow": [4, 10, 13, 255],
"monitor_carousel_dot": [119, 119, 119, 255],
"monitor_carousel_dot_current": [216, 216, 216, 255]
}
}

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="78px" height="58px" viewBox="0 0 78 58" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>Group-cloud</title>
<desc>Created with Sketch.</desc>
<g id="Sign-in-/Message-restyle" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Sign-in-open" transform="translate(-1013.000000, -128.000000)">
<g id="Group-cloud" transform="translate(1013.000000, 128.000000)">
<g id="Icon/-group-printer/-connected">
<g id="printer-group">
<g id="Group-Copy" transform="translate(0.000000, 2.122786)" fill="#08073F" fill-rule="nonzero">
<g id="UM3">
<path d="M34.2044094,0.202170085 L0.287432013,0.202170085 C0.164246864,0.202170085 0.0410617159,0.323472136 0.0410617159,0.444774187 L0.0410617159,38.5740521 C0.0410617159,38.6953542 0.164246864,38.8166563 0.287432013,38.8166563 L2.50476467,38.8166563 C2.99750527,38.8166563 3.49024586,38.7357883 3.73661615,38.3314482 L3.98298644,38.088844 C4.31148018,37.8058059 4.76315904,37.6440697 5.21483793,37.6036358 L29.2770035,37.6036358 C29.7697441,37.6036358 30.2624847,37.6845038 30.508855,38.088844 L30.7552253,38.3314482 C31.0837189,38.6144862 31.5353978,38.7762222 31.9870768,38.8166563 L34.2044094,38.8166563 C34.3275946,38.8166563 34.4507797,38.6953542 34.4507797,38.5740521 L34.4507797,0.444774187 C34.4507797,0.323472136 34.3275946,0.202170085 34.2044094,0.202170085 Z M30.6731017,29.4763984 C30.6731017,30.6085509 29.7286825,31.5385333 28.5789543,31.5385333 L5.83076366,31.5385333 C4.68103562,31.5385333 3.73661615,30.6085509 3.73661615,29.4763984 L3.73661615,4.44774187 C3.73661615,4.0434017 4.06510989,3.67949555 4.51678875,3.67949555 L29.9339908,3.67949555 C30.3446081,3.67949555 30.7141636,4.00296768 30.7141636,4.44774187 L30.7141636,29.4763984 L30.6731017,29.4763984 Z" id="Shape"></path>
</g>
</g>
<g id="Group-Copy-4" transform="translate(43.114802, 2.122786)" fill="#08073F" fill-rule="nonzero">
<g id="UM3">
<path d="M34.2044094,0.202170085 L0.287432013,0.202170085 C0.164246864,0.202170085 0.0410617159,0.323472136 0.0410617159,0.444774187 L0.0410617159,38.5740521 C0.0410617159,38.6953542 0.164246864,38.8166563 0.287432013,38.8166563 L2.50476467,38.8166563 C2.99750527,38.8166563 3.49024586,38.7357883 3.73661615,38.3314482 L3.98298644,38.088844 C4.31148018,37.8058059 4.76315904,37.6440697 5.21483793,37.6036358 L29.2770035,37.6036358 C29.7697441,37.6036358 30.2624847,37.6845038 30.508855,38.088844 L30.7552253,38.3314482 C31.0837189,38.6144862 31.5353978,38.7762222 31.9870768,38.8166563 L34.2044094,38.8166563 C34.3275946,38.8166563 34.4507797,38.6953542 34.4507797,38.5740521 L34.4507797,0.444774187 C34.4507797,0.323472136 34.3275946,0.202170085 34.2044094,0.202170085 Z M30.6731017,29.4763984 C30.6731017,30.6085509 29.7286825,31.5385333 28.5789543,31.5385333 L5.83076366,31.5385333 C4.68103562,31.5385333 3.73661615,30.6085509 3.73661615,29.4763984 L3.73661615,4.44774187 C3.73661615,4.0434017 4.06510989,3.67949555 4.51678875,3.67949555 L29.9339908,3.67949555 C30.3446081,3.67949555 30.7141636,4.00296768 30.7141636,4.44774187 L30.7141636,29.4763984 L30.6731017,29.4763984 Z" id="Shape"></path>
</g>
</g>
<g id="Group-Copy-2" transform="translate(19.401661, 0.000000)">
<rect id="Rectangle" fill="#FFFFFF" x="4.31148018" y="0" width="30.1803611" height="36.0873602"></rect>
<g id="UM3" fill="#08073F" fill-rule="nonzero">
<path d="M38.4799606,0.227441345 L0.323361012,0.227441345 C0.184777722,0.227441345 0.0461944303,0.363906153 0.0461944303,0.50037096 L0.0461944303,43.3958088 C0.0461944303,43.5322734 0.184777722,43.6687383 0.323361012,43.6687383 L2.81786025,43.6687383 C3.37219342,43.6687383 3.92652659,43.5777618 4.20369316,43.122879 L4.48085976,42.8499495 C4.8504152,42.5315316 5.35855393,42.3495785 5.86669267,42.3040902 L32.936629,42.3040902 C33.4909621,42.3040902 34.0452952,42.3950669 34.3224619,42.8499495 L34.5996285,43.122879 C34.9691838,43.4412969 35.4773225,43.62325 35.9854612,43.6687383 L38.4799606,43.6687383 C38.6185438,43.6687383 38.7571272,43.5322734 38.7571272,43.3958088 L38.7571272,0.50037096 C38.7571272,0.363906153 38.6185438,0.227441345 38.4799606,0.227441345 Z M34.5072395,33.1609482 C34.5072395,34.4346197 33.4447677,35.4808499 32.1513237,35.4808499 L6.55960911,35.4808499 C5.26616507,35.4808499 4.20369316,34.4346197 4.20369316,33.1609482 L4.20369316,5.0037096 C4.20369316,4.54882691 4.57324863,4.13943248 5.08138736,4.13943248 L33.6757398,4.13943248 C34.1376842,4.13943248 34.5534339,4.50333865 34.5534339,5.0037096 L34.5534339,33.1609482 L34.5072395,33.1609482 Z" id="Shape"></path>
</g>
</g>
</g>
</g>
<g id="Group" transform="translate(40.578299, 25.035294)">
<ellipse id="Oval-Copy" stroke="#FFFFFF" stroke-width="3.5636363" fill="#3282FF" cx="15.6684507" cy="15.5040369" rx="15.5251417" ry="15.3630911"></ellipse>
<path d="M22.3562041,13.3374471 C22.1651254,11.6632641 20.7320354,10.3830065 19.0123274,10.3830065 C18.5346308,10.3830065 18.1524734,10.4814879 17.7703161,10.6784506 C16.9104621,9.29971165 15.3818327,8.41337947 13.7576641,8.41337947 C11.0825627,8.41337947 8.98069738,10.5799693 8.98069738,13.3374471 C8.98069738,13.3374471 8.98069738,13.3374471 8.98069738,13.4359285 C7.3565287,13.6328912 6.11451736,15.1101115 6.11451736,16.7842945 C6.11451736,18.6554402 7.64314671,20.2311419 9.45839405,20.2311419 C10.8914841,20.2311419 20.1587994,20.2311419 21.8785074,20.2311419 C23.6937548,20.2311419 25.2223841,18.6554402 25.2223841,16.7842945 C25.2223841,15.0116302 23.9803728,13.6328912 22.3562041,13.3374471 Z" id="Path" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="500"
height="500"
viewBox="0 0 132.29167 132.29167"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="avatar_no_user.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="264.32988"
inkscape:cy="275.53798"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1137"
inkscape:window-x="2872"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-164.70834)">
<g
id="g819"
transform="matrix(2.4332992,0,0,2.4332992,27.213046,191.79972)"
style="fill:#afafaf;fill-opacity:1">
<path
id="path815"
d="m 16,15.7 c 3.6,0 6.4,-3.5 6.4,-7.8 C 22.4,3.6 21.5,0 16,0 10.5,0 9.6,3.5 9.6,7.8 c 0,4.4 2.8,7.9 6.4,7.9 z"
inkscape:connector-curvature="0"
style="fill:#afafaf;fill-opacity:1" />
<path
id="path817"
d="m 28.2,27.3 c -0.1,-7.5 -1.1,-9.7 -8.6,-11 -0.9,0.9 -2.2,1.4 -3.5,1.3 -1.3,0.1 -2.6,-0.4 -3.5,-1.3 C 5,17.6 4,19.7 3.8,27 c 0,0.2 0,0.4 0,0.6 v 0.8 c 0,0 1.8,3.7 12.2,3.7 10.4,0 12.2,-3.6 12.2,-3.6 v -0.6 c 0,-0.3 -0.1,-0.4 0,-0.6 z"
inkscape:connector-curvature="0"
style="fill:#afafaf;fill-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
@ -9,164 +7,31 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="110mm"
height="33mm"
viewBox="0 0 110 33"
width="82px"
height="18px"
viewBox="0 0 82 18"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="logo.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="97.165681"
inkscape:cy="69.313647"
inkscape:document-units="mm"
inkscape:current-layer="g4570"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1137"
inkscape:window-x="2872"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-264)">
<g
id="g4570"
transform="matrix(0.1443759,0,0,0.14575971,-5.7750359,237.12191)">
id="svg12"
sodipodi:docname="logo2.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<polygon
id="polygon4506"
points="741.8,410.8 781.7,410.8 801.9,390.6 801.9,350.7 762,350.7 741.8,370.9 "
class="st0"
style="fill:#3282ff;fill-opacity:1" />
fill="#20A6DB"
points="82 10.3797468 77.8757345 10.3797468 75.7721519 12.4764557 75.7721519 16.6075949 79.9067798 16.6075949 82 14.5108861"
id="polygon2" />
<path
id="path4508"
d="m 40,334.7 c 0,44.3 28.1,76.1 74.4,76.1 h 70.3 V 371 H 114.4 C 91,370.9 79.5,354.4 79.5,334.7 79.5,315 91,298.8 114.4,298.6 h 70.3 V 258.9 H 114.4 C 68.1,258.9 40,290.4 40,334.7 Z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
fill="white"
d="M0,9.32538529 C0,14.168804 3.22511,17.6455696 8.53908129,17.6455696 L16.6075949,17.6455696 L16.6075949,13.294146 L8.53908129,13.294146 C5.8534025,13.2832128 4.53351762,11.4792306 4.53351762,9.32538529 C4.53351762,7.17153994 5.8534025,5.40035747 8.53908129,5.37849102 L16.6075949,5.37849102 L16.6075949,1.03800064 L8.53908129,1.03800064 C3.21363275,1.02706742 0,4.47103333 0,9.32538529 Z"
id="path4"/>
<path
id="path4510"
d="m 336.7,338.8 c 0,22.6 -16.5,34.7 -36.2,34.7 -19.7,0 -35.9,-12.1 -35.9,-34.7 v -79.9 h -39.9 v 79.9 c 0,44.7 31.5,71.9 75.8,71.9 44.3,0 76.1,-27.1 76.1,-71.9 v -79.9 h -39.9 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
fill="white"
d="M33.004725,9.78605176 C33.004725,12.2613239 31.20074,13.5835846 29.0468913,13.5835846 C26.8930426,13.5835846 25.1218573,12.2613239 25.1218573,9.78605176 L25.1218573,1.03797468 L20.7594937,1.03797468 L20.7594937,9.78605176 C20.7594937,14.6837056 24.203465,17.6455696 29.0468913,17.6455696 C33.8903176,17.6455696 37.3670886,14.6731275 37.3670886,9.78605176 L37.3670886,1.03797468 L33.004725,1.03797468 L33.004725,9.78605176 L33.004725,9.78605176 Z"
id="path6"/>
<path
id="path4512"
d="m 624.1,258.9 c -46.3,0 -74.4,31.5 -74.4,75.8 0,44.3 28.1,76.1 74.4,76.1 h 16.4 V 371 h -16.4 c -23.4,-0.1 -34.9,-16.6 -34.9,-36.3 0,-19.7 11.5,-35.9 34.9,-36.1 h 37.3 v 52 20.4 39.8 h 39.9 v -2.3 -37.5 -72.4 -32.8 -7 h -77.2 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
fill="white"
d="M62.1251127,1.03797468 C57.0530042,1.03797468 53.9746835,4.47968021 53.9746835,9.31992005 C53.9746835,14.1601599 57.0530042,17.6346436 62.1251127,17.6346436 L63.9217127,17.6346436 L63.9217127,13.297002 L62.1251127,13.297002 C59.5616713,13.2860759 58.3018603,11.4832778 58.3018603,9.3308461 C58.3018603,7.17841439 59.5616713,5.4083944 62.1251127,5.38654231 L66.2112822,5.38654231 L66.2112822,11.0680879 L66.2112822,13.297002 L66.2112822,17.6455696 L70.5822785,17.6455696 L70.5822785,17.3942705 L70.5822785,13.297002 L70.5822785,5.38654231 L70.5822785,1.80279813 L70.5822785,1.03797468 L62.1251127,1.03797468 Z"
id="path8"/>
<path
id="path4514"
d="m 416.6,333 v 77.8 H 456 V 333 c 0,-19.3 11.5,-35.1 34.9,-35.3 h 28.8 V 258.8 H 491 c -46.3,0.1 -74.4,30.9 -74.4,74.2 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<g
id="g4542">
<path
id="path4518"
d="m 456.3,198.8 c -3.1,0 -5.3,1.8 -5.3,5.3 v 29.4 c 0,3.5 2.1,5.3 5.3,5.3 3.2,0 5.3,-1.8 5.3,-5.3 v -29.4 c -0.1,-3.5 -2.2,-5.3 -5.3,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4520"
d="m 456.3,184.4 c -2.9,0 -5.3,2.4 -5.3,5.4 0,0 0,0.1 0,0.1 0,3 2.5,5.3 5.5,5.3 3,0 5.3,-2.5 5.3,-5.5 -0.1,-3 -2.6,-5.3 -5.5,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4522"
d="m 408.8,184.6 v 0 l -9.4,-0.1 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 h 3.6 v 43 c 0,3.5 2.1,5.3 5.3,5.3 3.1,0 5.3,-1.8 5.3,-5.3 v -43.6 c -0.2,-3.4 -2,-5.1 -4.8,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4524"
d="m 521.3,204.9 c -1.1,-2.9 -3.8,-4.8 -6.8,-4.7 -0.4,0 -0.7,0.1 -1.1,0.1 -2.6,0.3 -4.8,2 -5.7,4.5 l -6.4,15.2 -6.4,-15.3 c -1.1,-2.8 -3.8,-4.6 -6.8,-4.6 -0.2,0 -0.3,0 -0.5,0 h -8.9 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 h 2.2 l -9.2,25.8 c -1,2.7 0.4,5.7 3.1,6.7 0.6,0.2 1.1,0.3 1.7,0.3 2.2,0 4.1,-1.4 4.9,-3.5 l 6.9,-19.2 7.9,18.8 c 0.5,1.7 1.8,3 3.5,3.5 0,0 0.1,0 0.1,0 0.2,0.1 0.4,0.1 0.6,0.1 0.3,0 0.5,0.1 0.8,0.1 0,0 0,0 0.1,0 0,0 0,0 0,0 v 0 0.1 c 2.1,0 4,-1.3 4.8,-3.2 l 8.1,-19.5 6.9,19.3 c 0.7,2.1 2.7,3.4 4.9,3.5 h 0.1 c 0.6,0 1.2,-0.1 1.7,-0.3 0,0 0,0 0,0 2.7,-1 4.1,-3.9 3.1,-6.6 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4526"
d="m 476.5,238.8 c 0,0 0,0 0,0 0,0 0,0 0,0 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4528"
d="m 608.9,215.4 7.8,-8.1 c 1.1,-0.8 1.6,-2.1 1.6,-3.5 -0.2,-2.6 -2.3,-4.7 -5,-4.8 -1.6,0.1 -3,0.8 -4,2 l -9.1,10.2 c -1.1,1.3 -1.7,2.9 -1.7,4.6 v 0 c 0,3.2 2.8,6.3 2.8,6.3 l 10,14.1 c 1,1.6 2.8,2.5 4.7,2.5 2.8,-0.1 5,-2.3 5,-5.1 0,-1.2 -0.4,-2.4 -1.1,-3.4 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4530"
d="m 590.9,184.6 v 0 l -9.4,-0.1 c -1.6,0 -3,1.3 -3,3 0,1.7 1.3,3 3,3 h 3.6 v 42.9 c 0,3.5 2.1,5.3 5.3,5.3 3.2,0 5.3,-1.8 5.3,-5.3 v -8 -35.5 c -0.1,-3.4 -1.9,-5.1 -4.8,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4532"
d="m 440.7,200.2 h -3.3 v -6.7 c 0,-3.5 -2.1,-5.3 -5.3,-5.3 -3.1,0 -5.3,1.8 -5.3,5.3 v 6.7 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 v 27.4 c 0,3.5 2.2,5.3 5.3,5.3 3.1,0 5.3,-1.8 5.3,-5.3 V 228 206.2 h 3.3 c 1.6,0 3,-1.3 3,-3 0,-1.7 -1.3,-3 -3,-3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4534"
d="m 573.4,227.7 v -18.6 c 0,-7.6 -7.7,-11.2 -21.5,-10.1 -2.3,0.2 -9.2,1.5 -9.2,1.5 -2.1,0.5 -4.2,1.6 -4.2,4.2 -0.1,2 1.4,3.7 3.4,3.8 0,0 0,0 0,0 0.3,0 0.6,0 0.8,0 0,0 7.4,-1.4 10,-1.6 1.3,-0.1 2.7,-0.1 4,-0.1 3.5,0.1 6.2,0.5 6.2,3.6 v 13.8 c 0,3.9 -3.5,7.6 -9.3,7.6 -3.6,0 -5.8,-1.9 -5.8,-4.3 0,-3.2 2.4,-4.5 6.8,-5.2 1.6,-0.3 2.6,-1.8 2.3,-3.4 0,0 0,0 0,0 0,-0.1 -0.1,-0.3 -0.1,-0.4 -0.8,-3.1 -4.7,-2.7 -4.7,-2.7 -8.1,0.9 -14.7,3.4 -14.7,12.1 0,6.6 5.9,10.7 11.9,10.7 5.5,0 10.3,-1.6 14.4,-6.1 0.2,3.2 1.7,6.1 6.2,6.1 2.5,0 4.8,-1.7 4.8,-4 -0.2,-1.4 -1.3,-2.5 -1.3,-6.9 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4536"
d="m 387.8,213 -0.1,0.1 v -22.7 c -0.2,-3 -2.6,-5.4 -5.5,-5.5 -3.3,-0.2 -6.1,2.3 -6.3,5.5 v 28.5 c 0,7 -4,10.2 -10.7,10.2 -6.8,0 -10.7,-3.2 -10.7,-10.2 v -28.5 c 0,-0.2 0,-0.5 0,-0.7 0,0 0,0 0,0 -0.2,-3.1 -2.8,-5.4 -5.9,-5.2 v 0 0 h -0.7 -8.7 c -1.6,0 -3,1.3 -3,3 0,1.7 1.3,3 3,3 h 3.5 c 0,0 0,0 0,0 l 0.1,27.5 c 0,14.3 8.8,20.7 22.5,20.7 5.3,0 9.9,-1 13.5,-3 0.9,1.7 2.5,2.9 5.4,2.9 2.5,0 4.8,-1.7 4.8,-4 0,-1.7 -1.1,-2.7 -1.1,-7.1 V 213 Z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4538"
d="m 645.5,199 c -12.5,0 -19.9,8.2 -19.9,20.5 0,9.2 5.4,19.1 20.3,19.1 2.9,0 12.5,-2.2 12.5,-2.2 2.5,-0.5 4.3,-1.7 3.7,-5 -0.5,-2.3 -2.3,-3.3 -5,-2.9 0,0 -8.3,1.6 -11.2,1.8 -6.1,0.5 -9.7,-4 -9.7,-9.6 0,0 -1.7,-14.4 9.6,-14.4 4.6,0 8.2,3.7 8.9,8.4 h -11.1 c -1.6,0 -3,1.3 -3,3 0,1.7 1.3,3 3,3 v 0 0 H 660 c 3.5,0 4.6,-0.9 4.6,-4.5 -0.1,-8.6 -7,-17.2 -19.1,-17.2 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
id="path4540"
d="m 696.9,198.9 c -0.3,0 -0.6,0 -0.9,0 h -5.5 c -2.9,0 -4.9,1.5 -5.2,4.4 -0.3,-2.9 -2.3,-4.3 -5.2,-4.3 h -9.4 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 h 4.2 v 28.6 c 0,3.5 2.1,5.3 5.3,5.3 3.1,0 5.3,-1.8 5.3,-5.3 v -21.1 c 0,-1.6 1.3,-3 3,-3 h 7.7 c 3.5,0 5.3,-2.1 5.3,-5.3 0,-2.8 -1.9,-5.1 -4.6,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
</g>
</g>
</g>
<style
id="style4504"
type="text/css">
.st0{fill:#333333;}
.st1{fill:#FFFFFF;}
</style>
fill="white"
d="M 41.518987,9.13915 V 17.646 h 4.36332 V 9.13915 c 0,-2.1053391 1.273557,-3.8366328 3.86497,-3.8580068 h 3.189432 V 1.038405 h -3.189432 c -5.127454,0 -8.22829,3.3664044 -8.22829,8.100745 z"
id="path10" />
</svg>

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,172 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="110mm"
height="33mm"
viewBox="0 0 110 33"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="logo.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="97.165681"
inkscape:cy="69.313647"
inkscape:document-units="mm"
inkscape:current-layer="g4570"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1137"
inkscape:window-x="2872"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-264)">
<g
id="g4570"
transform="matrix(0.1443759,0,0,0.14575971,-5.7750359,237.12191)">
<polygon
id="polygon4506"
points="741.8,410.8 781.7,410.8 801.9,390.6 801.9,350.7 762,350.7 741.8,370.9 "
class="st0"
style="fill:#3282ff;fill-opacity:1" />
<path
id="path4508"
d="m 40,334.7 c 0,44.3 28.1,76.1 74.4,76.1 h 70.3 V 371 H 114.4 C 91,370.9 79.5,354.4 79.5,334.7 79.5,315 91,298.8 114.4,298.6 h 70.3 V 258.9 H 114.4 C 68.1,258.9 40,290.4 40,334.7 Z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4510"
d="m 336.7,338.8 c 0,22.6 -16.5,34.7 -36.2,34.7 -19.7,0 -35.9,-12.1 -35.9,-34.7 v -79.9 h -39.9 v 79.9 c 0,44.7 31.5,71.9 75.8,71.9 44.3,0 76.1,-27.1 76.1,-71.9 v -79.9 h -39.9 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4512"
d="m 624.1,258.9 c -46.3,0 -74.4,31.5 -74.4,75.8 0,44.3 28.1,76.1 74.4,76.1 h 16.4 V 371 h -16.4 c -23.4,-0.1 -34.9,-16.6 -34.9,-36.3 0,-19.7 11.5,-35.9 34.9,-36.1 h 37.3 v 52 20.4 39.8 h 39.9 v -2.3 -37.5 -72.4 -32.8 -7 h -77.2 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4514"
d="m 416.6,333 v 77.8 H 456 V 333 c 0,-19.3 11.5,-35.1 34.9,-35.3 h 28.8 V 258.8 H 491 c -46.3,0.1 -74.4,30.9 -74.4,74.2 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<g
id="g4542">
<path
id="path4518"
d="m 456.3,198.8 c -3.1,0 -5.3,1.8 -5.3,5.3 v 29.4 c 0,3.5 2.1,5.3 5.3,5.3 3.2,0 5.3,-1.8 5.3,-5.3 v -29.4 c -0.1,-3.5 -2.2,-5.3 -5.3,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4520"
d="m 456.3,184.4 c -2.9,0 -5.3,2.4 -5.3,5.4 0,0 0,0.1 0,0.1 0,3 2.5,5.3 5.5,5.3 3,0 5.3,-2.5 5.3,-5.5 -0.1,-3 -2.6,-5.3 -5.5,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4522"
d="m 408.8,184.6 v 0 l -9.4,-0.1 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 h 3.6 v 43 c 0,3.5 2.1,5.3 5.3,5.3 3.1,0 5.3,-1.8 5.3,-5.3 v -43.6 c -0.2,-3.4 -2,-5.1 -4.8,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4524"
d="m 521.3,204.9 c -1.1,-2.9 -3.8,-4.8 -6.8,-4.7 -0.4,0 -0.7,0.1 -1.1,0.1 -2.6,0.3 -4.8,2 -5.7,4.5 l -6.4,15.2 -6.4,-15.3 c -1.1,-2.8 -3.8,-4.6 -6.8,-4.6 -0.2,0 -0.3,0 -0.5,0 h -8.9 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 h 2.2 l -9.2,25.8 c -1,2.7 0.4,5.7 3.1,6.7 0.6,0.2 1.1,0.3 1.7,0.3 2.2,0 4.1,-1.4 4.9,-3.5 l 6.9,-19.2 7.9,18.8 c 0.5,1.7 1.8,3 3.5,3.5 0,0 0.1,0 0.1,0 0.2,0.1 0.4,0.1 0.6,0.1 0.3,0 0.5,0.1 0.8,0.1 0,0 0,0 0.1,0 0,0 0,0 0,0 v 0 0.1 c 2.1,0 4,-1.3 4.8,-3.2 l 8.1,-19.5 6.9,19.3 c 0.7,2.1 2.7,3.4 4.9,3.5 h 0.1 c 0.6,0 1.2,-0.1 1.7,-0.3 0,0 0,0 0,0 2.7,-1 4.1,-3.9 3.1,-6.6 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4526"
d="m 476.5,238.8 c 0,0 0,0 0,0 0,0 0,0 0,0 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4528"
d="m 608.9,215.4 7.8,-8.1 c 1.1,-0.8 1.6,-2.1 1.6,-3.5 -0.2,-2.6 -2.3,-4.7 -5,-4.8 -1.6,0.1 -3,0.8 -4,2 l -9.1,10.2 c -1.1,1.3 -1.7,2.9 -1.7,4.6 v 0 c 0,3.2 2.8,6.3 2.8,6.3 l 10,14.1 c 1,1.6 2.8,2.5 4.7,2.5 2.8,-0.1 5,-2.3 5,-5.1 0,-1.2 -0.4,-2.4 -1.1,-3.4 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4530"
d="m 590.9,184.6 v 0 l -9.4,-0.1 c -1.6,0 -3,1.3 -3,3 0,1.7 1.3,3 3,3 h 3.6 v 42.9 c 0,3.5 2.1,5.3 5.3,5.3 3.2,0 5.3,-1.8 5.3,-5.3 v -8 -35.5 c -0.1,-3.4 -1.9,-5.1 -4.8,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4532"
d="m 440.7,200.2 h -3.3 v -6.7 c 0,-3.5 -2.1,-5.3 -5.3,-5.3 -3.1,0 -5.3,1.8 -5.3,5.3 v 6.7 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 v 27.4 c 0,3.5 2.2,5.3 5.3,5.3 3.1,0 5.3,-1.8 5.3,-5.3 V 228 206.2 h 3.3 c 1.6,0 3,-1.3 3,-3 0,-1.7 -1.3,-3 -3,-3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4534"
d="m 573.4,227.7 v -18.6 c 0,-7.6 -7.7,-11.2 -21.5,-10.1 -2.3,0.2 -9.2,1.5 -9.2,1.5 -2.1,0.5 -4.2,1.6 -4.2,4.2 -0.1,2 1.4,3.7 3.4,3.8 0,0 0,0 0,0 0.3,0 0.6,0 0.8,0 0,0 7.4,-1.4 10,-1.6 1.3,-0.1 2.7,-0.1 4,-0.1 3.5,0.1 6.2,0.5 6.2,3.6 v 13.8 c 0,3.9 -3.5,7.6 -9.3,7.6 -3.6,0 -5.8,-1.9 -5.8,-4.3 0,-3.2 2.4,-4.5 6.8,-5.2 1.6,-0.3 2.6,-1.8 2.3,-3.4 0,0 0,0 0,0 0,-0.1 -0.1,-0.3 -0.1,-0.4 -0.8,-3.1 -4.7,-2.7 -4.7,-2.7 -8.1,0.9 -14.7,3.4 -14.7,12.1 0,6.6 5.9,10.7 11.9,10.7 5.5,0 10.3,-1.6 14.4,-6.1 0.2,3.2 1.7,6.1 6.2,6.1 2.5,0 4.8,-1.7 4.8,-4 -0.2,-1.4 -1.3,-2.5 -1.3,-6.9 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4536"
d="m 387.8,213 -0.1,0.1 v -22.7 c -0.2,-3 -2.6,-5.4 -5.5,-5.5 -3.3,-0.2 -6.1,2.3 -6.3,5.5 v 28.5 c 0,7 -4,10.2 -10.7,10.2 -6.8,0 -10.7,-3.2 -10.7,-10.2 v -28.5 c 0,-0.2 0,-0.5 0,-0.7 0,0 0,0 0,0 -0.2,-3.1 -2.8,-5.4 -5.9,-5.2 v 0 0 h -0.7 -8.7 c -1.6,0 -3,1.3 -3,3 0,1.7 1.3,3 3,3 h 3.5 c 0,0 0,0 0,0 l 0.1,27.5 c 0,14.3 8.8,20.7 22.5,20.7 5.3,0 9.9,-1 13.5,-3 0.9,1.7 2.5,2.9 5.4,2.9 2.5,0 4.8,-1.7 4.8,-4 0,-1.7 -1.1,-2.7 -1.1,-7.1 V 213 Z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4538"
d="m 645.5,199 c -12.5,0 -19.9,8.2 -19.9,20.5 0,9.2 5.4,19.1 20.3,19.1 2.9,0 12.5,-2.2 12.5,-2.2 2.5,-0.5 4.3,-1.7 3.7,-5 -0.5,-2.3 -2.3,-3.3 -5,-2.9 0,0 -8.3,1.6 -11.2,1.8 -6.1,0.5 -9.7,-4 -9.7,-9.6 0,0 -1.7,-14.4 9.6,-14.4 4.6,0 8.2,3.7 8.9,8.4 h -11.1 c -1.6,0 -3,1.3 -3,3 0,1.7 1.3,3 3,3 v 0 0 H 660 c 3.5,0 4.6,-0.9 4.6,-4.5 -0.1,-8.6 -7,-17.2 -19.1,-17.2 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
<path
id="path4540"
d="m 696.9,198.9 c -0.3,0 -0.6,0 -0.9,0 h -5.5 c -2.9,0 -4.9,1.5 -5.2,4.4 -0.3,-2.9 -2.3,-4.3 -5.2,-4.3 h -9.4 c -1.6,0 -3,1.3 -3,3 0,1.6 1.3,3 3,3 h 4.2 v 28.6 c 0,3.5 2.1,5.3 5.3,5.3 3.1,0 5.3,-1.8 5.3,-5.3 v -21.1 c 0,-1.6 1.3,-3 3,-3 h 7.7 c 3.5,0 5.3,-2.1 5.3,-5.3 0,-2.8 -1.9,-5.1 -4.6,-5.3 z"
class="st1"
inkscape:connector-curvature="0"
style="fill:#000000" />
</g>
</g>
</g>
<style
id="style4504"
type="text/css">
.st0{fill:#333333;}
.st1{fill:#000000;}
</style>
</svg>

Before

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -146,7 +146,7 @@
"wide_lining": [245, 245, 245, 255],
"thick_lining": [127, 127, 127, 255],
"lining": [192, 193, 194, 255],
"viewport_overlay": [0, 0, 0, 192],
"viewport_overlay": [246, 246, 246, 255],
"primary": [50, 130, 255, 255],
"primary_shadow": [64, 47, 205, 255],
@ -294,7 +294,7 @@
"setting_validation_ok": [255, 255, 255, 255],
"setting_filter_field" : [153, 153, 153, 255],
"material_compatibility_warning": [0, 0, 0, 255],
"material_compatibility_warning": [243, 166, 59, 255],
"progressbar_background": [245, 245, 245, 255],
"progressbar_control": [50, 130, 255, 255],
@ -320,17 +320,9 @@
"tooltip_text": [255, 255, 255, 255],
"message_background": [255, 255, 255, 255],
"message_shadow": [0, 0, 0, 120],
"message_border": [192, 193, 194, 255],
"message_text": [0, 0, 0, 255],
"message_close": [102, 102, 102, 255],
"message_close_hover": [8, 7, 63, 255],
"message_button": [38, 113, 231, 255],
"message_button_hover": [81, 145, 247, 255],
"message_button_active": [38, 113, 231, 255],
"message_button_text": [255, 255, 255, 255],
"message_button_text_hover": [255, 255, 255, 255],
"message_button_text_active": [255, 255, 255, 255],
"message_progressbar_background": [245, 245, 245, 255],
"message_progressbar_control": [50, 130, 255, 255],
@ -400,27 +392,41 @@
"favorites_header_text_hover": [31, 36, 39, 255],
"favorites_row_selected": [196, 239, 255, 255],
"monitor_card_background_inactive": [240, 240, 240, 255],
"monitor_printer_family_tag": [228, 228, 242, 255],
"monitor_text_primary": [65, 64, 84, 255],
"monitor_text_disabled": [238, 238, 238, 255],
"monitor_text_link": [50, 130, 255, 255],
"monitor_icon_primary": [10, 8, 80, 255],
"monitor_icon_accent": [255, 255, 255, 255],
"monitor_secondary_button_hover": [228, 228, 228, 255],
"monitor_secondary_button": [240, 240, 240, 255],
"monitor_secondary_button_text": [30, 102, 215, 255],
"monitor_secondary_button_shadow": [216, 216, 216, 255],
"monitor_card_border": [192, 193, 194, 255],
"monitor_card_background": [255, 255, 255, 255],
"monitor_context_menu_background": [255, 255, 255, 255],
"monitor_context_menu_dots": [154, 154, 154, 255],
"monitor_context_menu_highlight": [245, 245, 245, 255],
"monitor_image_overlay": [0, 0, 0, 255],
"monitor_lining_heavy": [0, 0, 0, 255],
"monitor_lining_light": [230, 230, 230, 255],
"monitor_pill_background": [245, 245, 245, 255],
"monitor_card_hover": [232, 242, 252, 255],
"monitor_stage_background": [246, 246, 246, 255],
"monitor_stage_background_fade": [246, 246, 246, 102],
"monitor_progress_bar_fill": [50, 130, 255, 255],
"monitor_progress_bar_deactive": [192, 193, 194, 255],
"monitor_progress_bar_empty": [245, 245, 245, 255],
"monitor_tooltip": [25, 25, 25, 255],
"monitor_tooltip_text": [255, 255, 255, 255],
"monitor_context_menu": [255, 255, 255, 255],
"monitor_context_menu_hover": [245, 245, 245, 255],
"monitor_skeleton_loading": [238, 238, 238, 255],
"monitor_placeholder_image": [230, 230, 230, 255],
"monitor_printer_icon_inactive": [154, 154, 154, 255],
"monitor_printer_icon": [50, 130, 255, 255],
"monitor_progress_background_text": [0,0,0,255],
"monitor_progress_background": [245, 245, 245, 255],
"monitor_progress_fill_inactive": [154, 154, 154, 255],
"monitor_progress_fill_text": [255,255,255,255],
"monitor_progress_fill": [50, 130, 255, 255],
"monitor_shadow": [0, 0, 0, 63],
"monitor_skeleton_fill": [245, 245, 245, 255],
"monitor_skeleton_fill_dark": [216, 216, 216, 255],
"monitor_text_inactive": [154, 154, 154, 255]
"monitor_image_overlay": [0, 0, 0, 255],
"monitor_shadow": [220, 220, 220, 255],
"monitor_carousel_dot": [216, 216, 216, 255],
"monitor_carousel_dot_current": [119, 119, 119, 255]
},
"sizes": {
@ -432,7 +438,7 @@
"stage_menu": [0.0, 4.0],
"account_button": [12, 3],
"account_button": [12, 2.5],
"print_setup_widget": [38.0, 30.0],
"print_setup_mode_toggle": [0.0, 2.0],
@ -499,7 +505,7 @@
"button_icon": [2.5, 2.5],
"button_lining": [0, 0],
"action_button": [15.0, 3.0],
"action_button": [15.0, 2.5],
"action_button_icon": [1.0, 1.0],
"action_button_radius": [0.15, 0.15],
@ -555,12 +561,8 @@
"message": [30.0, 5.0],
"message_close": [1, 1],
"message_button": [6.0, 1.8],
"message_shadow": [0, 0],
"message_margin": [0, 1.0],
"message_inner_margin": [1.5, 1.5],
"message_radius": [0.25, 0.25],
"message_button_radius": [0.15, 0.15],
"message_action_button": [0, 2.0],
"infill_button_margin": [0.5, 0.5],
@ -596,10 +598,14 @@
"monitor_config_override_box": [1.0, 14.0],
"monitor_extruder_circle": [2.75, 2.75],
"monitor_text_line": [1.16, 1.16],
"monitor_text_line": [1.5, 1.5],
"monitor_text_line_large": [2.33, 2.33],
"monitor_thick_lining": [0.16, 0.16],
"monitor_corner_radius": [0.3, 0.3],
"monitor_shadow_radius": [0.4, 0.4],
"monitor_shadow_offset": [0.15, 0.15]
"monitor_shadow_offset": [0.15, 0.15],
"monitor_empty_state_offset": [5.6, 5.6],
"monitor_empty_state_size": [35.0, 25.0],
"monitor_external_link_icon": [1.16, 1.16]
}
}

View File

@ -0,0 +1,16 @@
from cura.Scene.GCodeListDecorator import GCodeListDecorator
def test_setAndGetList():
decorator = GCodeListDecorator()
decorator.setGCodeList(["Test"])
assert decorator.getGCodeList() == ["Test"]
def test_copyGCodeDecorator():
decorator = GCodeListDecorator()
decorator.setGCodeList(["Test"])
import copy
copied_decorator = copy.deepcopy(decorator)
assert decorator.getGCodeList() == copied_decorator.getGCodeList()

View File

@ -104,3 +104,18 @@ def test_addMachineAction(machine_action_manager):
machine_action_manager.addFirstStartAction(test_machine, "test_action")
machine_action_manager.addFirstStartAction(test_machine, "test_action")
assert machine_action_manager.getFirstStartActions(test_machine) == [test_action, test_action]
# Adding unknown action should not crash.
machine_action_manager.addFirstStartAction(test_machine, "key_that_doesnt_exists")
def test_removeMachineAction(machine_action_manager):
test_action = MachineAction(key="test_action")
test_machine = Machine("test_machine")
machine_action_manager.addMachineAction(test_action)
# Remove the machine action
machine_action_manager.removeMachineAction(test_action)
assert machine_action_manager.getMachineAction("test_action") is None
# Attempting to remove it again should not crash.
machine_action_manager.removeMachineAction(test_action)