Fix merge conflicts with 4.0

This commit is contained in:
ChrisTerBeke 2019-01-08 11:49:36 +01:00
commit a6114d39e4
78 changed files with 595 additions and 474 deletions

View file

@ -51,7 +51,7 @@ from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob
from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob
from cura.Arranging.ShapeArray import ShapeArray from cura.Arranging.ShapeArray import ShapeArray
from cura.MultiplyObjectsJob import MultiplyObjectsJob from cura.MultiplyObjectsJob import MultiplyObjectsJob
from cura.PrintersModel import PrintersModel from cura.GlobalStacksModel import GlobalStacksModel
from cura.Scene.ConvexHullDecorator import ConvexHullDecorator from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
from cura.Operations.SetParentOperation import SetParentOperation from cura.Operations.SetParentOperation import SetParentOperation
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
@ -502,7 +502,8 @@ class CuraApplication(QtApplication):
preferences.addPreference("cura/choice_on_profile_override", "always_ask") preferences.addPreference("cura/choice_on_profile_override", "always_ask")
preferences.addPreference("cura/choice_on_open_project", "always_ask") preferences.addPreference("cura/choice_on_open_project", "always_ask")
preferences.addPreference("cura/use_multi_build_plate", False) preferences.addPreference("cura/use_multi_build_plate", False)
preferences.addPreference("view/settings_list_height", 400)
preferences.addPreference("view/settings_visible", False)
preferences.addPreference("cura/currency", "") preferences.addPreference("cura/currency", "")
preferences.addPreference("cura/material_settings", "{}") preferences.addPreference("cura/material_settings", "{}")
@ -974,7 +975,7 @@ class CuraApplication(QtApplication):
qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel") qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel")
qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer")
qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
qmlRegisterType(PrintersModel, "Cura", 1, 0, "PrintersModel") qmlRegisterType(GlobalStacksModel, "Cura", 1, 0, "GlobalStacksModel")
qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel") qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel")
qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")

View file

@ -12,7 +12,8 @@ from cura.PrinterOutputDevice import ConnectionType
from cura.Settings.GlobalStack import GlobalStack from cura.Settings.GlobalStack import GlobalStack
class PrintersModel(ListModel):
class GlobalStacksModel(ListModel):
NameRole = Qt.UserRole + 1 NameRole = Qt.UserRole + 1
IdRole = Qt.UserRole + 2 IdRole = Qt.UserRole + 2
HasRemoteConnectionRole = Qt.UserRole + 3 HasRemoteConnectionRole = Qt.UserRole + 3
@ -41,20 +42,14 @@ class PrintersModel(ListModel):
if isinstance(container, GlobalStack): if isinstance(container, GlobalStack):
self._update() self._update()
## Handler for container name change events.
def _onContainerNameChanged(self):
self._update()
def _update(self) -> None: def _update(self) -> None:
items = [] items = []
for container in self._container_stacks:
container.nameChanged.disconnect(self._onContainerNameChanged)
container_stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine") container_stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine")
for container_stack in container_stacks: for container_stack in container_stacks:
connection_type = container_stack.getMetaDataEntry("connection_type", 0) connection_type = int(container_stack.getMetaDataEntry("connection_type", ConnectionType.NotConnected.value))
has_remote_connection = int(connection_type) in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value] has_remote_connection = connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value]
if container_stack.getMetaDataEntry("hidden", False) in ["True", True]: if container_stack.getMetaDataEntry("hidden", False) in ["True", True]:
continue continue

View file

@ -302,6 +302,10 @@ class MaterialManager(QObject):
def getMaterialGroupListByGUID(self, guid: str) -> Optional[List[MaterialGroup]]: def getMaterialGroupListByGUID(self, guid: str) -> Optional[List[MaterialGroup]]:
return self._guid_material_groups_map.get(guid) return self._guid_material_groups_map.get(guid)
# Returns a dict of all material groups organized by root_material_id.
def getAllMaterialGroups(self) -> Dict[str, "MaterialGroup"]:
return self._material_group_map
# #
# Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup. # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup.
# #

View file

@ -1,7 +1,7 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt, QTimer
from UM.Application import Application from UM.Application import Application
from UM.Logger import Logger from UM.Logger import Logger
@ -39,15 +39,23 @@ class QualityProfilesDropDownMenuModel(ListModel):
self._machine_manager = self._application.getMachineManager() self._machine_manager = self._application.getMachineManager()
self._quality_manager = Application.getInstance().getQualityManager() self._quality_manager = Application.getInstance().getQualityManager()
self._application.globalContainerStackChanged.connect(self._update) self._application.globalContainerStackChanged.connect(self._onChange)
self._machine_manager.activeQualityGroupChanged.connect(self._update) self._machine_manager.activeQualityGroupChanged.connect(self._onChange)
self._machine_manager.extruderChanged.connect(self._update) self._machine_manager.extruderChanged.connect(self._onChange)
self._quality_manager.qualitiesUpdated.connect(self._update) self._quality_manager.qualitiesUpdated.connect(self._onChange)
self._layer_height_unit = "" # This is cached self._layer_height_unit = "" # This is cached
self._update_timer = QTimer() # type: QTimer
self._update_timer.setInterval(100)
self._update_timer.setSingleShot(True)
self._update_timer.timeout.connect(self._update)
self._update() self._update()
def _onChange(self) -> None:
self._update_timer.start()
def _update(self): def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))

View file

@ -35,7 +35,7 @@ class ConnectionState(IntEnum):
class ConnectionType(IntEnum): class ConnectionType(IntEnum):
Unknown = 0 NotConnected = 0
UsbConnection = 1 UsbConnection = 1
NetworkConnection = 2 NetworkConnection = 2
CloudConnection = 3 CloudConnection = 3
@ -69,7 +69,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
# Signal to indicate that the configuration of one of the printers has changed. # Signal to indicate that the configuration of one of the printers has changed.
uniqueConfigurationsChanged = pyqtSignal() uniqueConfigurationsChanged = pyqtSignal()
def __init__(self, device_id: str, connection_type: "ConnectionType" = ConnectionType.Unknown, parent: QObject = None) -> None: def __init__(self, device_id: str, connection_type: "ConnectionType" = ConnectionType.NotConnected, parent: QObject = None) -> None:
super().__init__(device_id = device_id, parent = parent) # type: ignore # MyPy complains with the multiple inheritance super().__init__(device_id = device_id, parent = parent) # type: ignore # MyPy complains with the multiple inheritance
self._printers = [] # type: List[PrinterOutputModel] self._printers = [] # type: List[PrinterOutputModel]

View file

@ -527,7 +527,10 @@ class MachineManager(QObject):
@pyqtProperty(bool, notify = printerConnectedStatusChanged) @pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineHasRemoteConnection(self) -> bool: def activeMachineHasRemoteConnection(self) -> bool:
return self.activeMachineHasActiveNetworkConnection or self.activeMachineHasActiveCloudConnection 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]
return False
@pyqtProperty(bool, notify = printerConnectedStatusChanged) @pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineIsGroup(self) -> bool: def activeMachineIsGroup(self) -> bool:

View file

@ -1,4 +1,5 @@
// Copyright (c) 2017 Ultimaker B.V. // Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10 import QtQuick 2.10
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
@ -7,31 +8,27 @@ import UM 1.3 as UM
import Cura 1.0 as Cura import Cura 1.0 as Cura
Item // We show a nice overlay on the 3D viewer when the current output device has no monitor view
Rectangle
{ {
// We show a nice overlay on the 3D viewer when the current output device has no monitor view id: viewportOverlay
Rectangle
color: UM.Theme.getColor("viewport_overlay")
anchors.fill: parent
// This mouse area is to prevent mouse clicks to be passed onto the scene.
MouseArea
{ {
id: viewportOverlay
color: UM.Theme.getColor("viewport_overlay")
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.AllButtons
// This mouse area is to prevent mouse clicks to be passed onto the scene. onWheel: wheel.accepted = true
MouseArea
{
anchors.fill: parent
acceptedButtons: Qt.AllButtons
onWheel: wheel.accepted = true
}
// Disable dropping files into Cura when the monitor page is active
DropArea
{
anchors.fill: parent
}
} }
// Disable dropping files into Cura when the monitor page is active
DropArea
{
anchors.fill: parent
}
Loader Loader
{ {
id: monitorViewComponent id: monitorViewComponent
@ -45,4 +42,4 @@ Item
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem : null sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem : null
} }
} }

View file

@ -61,7 +61,7 @@ UM.Dialog
anchors.leftMargin: base.textMargin anchors.leftMargin: base.textMargin
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: base.textMargin anchors.rightMargin: base.textMargin
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
elide: Text.ElideRight elide: Text.ElideRight
} }
ListView ListView
@ -289,7 +289,7 @@ UM.Dialog
elide: Text.ElideRight elide: Text.ElideRight
height: 20 * screenScaleFactor height: 20 * screenScaleFactor
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
} }
@ -484,7 +484,7 @@ UM.Dialog
onClicked: dialog.accept() onClicked: dialog.accept()
} }
Button Cura.SecondaryButton
{ {
objectName: "postProcessingSaveAreaButton" objectName: "postProcessingSaveAreaButton"
visible: activeScriptsList.count > 0 visible: activeScriptsList.count > 0
@ -492,41 +492,7 @@ UM.Dialog
width: height width: height
tooltip: catalog.i18nc("@info:tooltip", "Change active post-processing scripts") tooltip: catalog.i18nc("@info:tooltip", "Change active post-processing scripts")
onClicked: dialog.show() onClicked: dialog.show()
iconSource: "postprocessing.svg"
style: ButtonStyle fixedWidthMode: true
{
background: Rectangle
{
id: deviceSelectionIcon
border.width: UM.Theme.getSize("default_lining").width
border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") :
control.pressed ? UM.Theme.getColor("action_button_active_border") :
control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border")
color: !control.enabled ? UM.Theme.getColor("action_button_disabled") :
control.pressed ? UM.Theme.getColor("action_button_active") :
control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
Behavior on color { ColorAnimation { duration: 50; } }
anchors.left: parent.left
anchors.leftMargin: Math.round(UM.Theme.getSize("save_button_text_margin").width / 2)
width: parent.height
height: parent.height
UM.RecolorImage
{
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
width: Math.round(parent.width / 2)
height: Math.round(parent.height / 2)
sourceSize.height: height
color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
control.pressed ? UM.Theme.getColor("action_button_active_text") :
control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text")
source: "postprocessing.svg"
}
}
label: Label { }
}
} }
} }

View file

@ -163,9 +163,9 @@ Item
id: rangleHandleLabel id: rangleHandleLabel
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
x: parent.x + parent.width + UM.Theme.getSize("default_margin").width x: parent.x - width - UM.Theme.getSize("default_margin").width
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
target: Qt.point(sliderRoot.width + width, y + height / 2) target: Qt.point(sliderRoot.width, y + height / 2)
visible: sliderRoot.activeHandle == parent visible: sliderRoot.activeHandle == parent
// custom properties // custom properties

View file

@ -43,7 +43,7 @@ Cura.ExpandableComponent
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
height: parent.height height: parent.height
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text_medium") color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -60,7 +60,7 @@ Cura.ExpandableComponent
} }
height: parent.height height: parent.height
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View file

@ -30,7 +30,7 @@ Row
width: contentWidth width: contentWidth
anchors.verticalCenter: starIcon.verticalCenter anchors.verticalCenter: starIcon.verticalCenter
color: starIcon.color color: starIcon.color
font: UM.Theme.getFont("small") font: UM.Theme.getFont("default")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }

View file

@ -38,7 +38,7 @@ Window
{ {
id: mainView id: mainView
width: parent.width width: parent.width
z: -1 z: parent.z - 1
anchors anchors
{ {
top: header.bottom top: header.bottom

View file

@ -55,7 +55,7 @@ Item
bottomMargin: UM.Theme.getSize("default_margin").height bottomMargin: UM.Theme.getSize("default_margin").height
} }
text: details.name || "" text: details.name || ""
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: parent.width width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height height: UM.Theme.getSize("toolbox_property_label").height

View file

@ -61,8 +61,13 @@ Item
id: labelStyle id: labelStyle
text: control.text text: control.text
color: control.enabled ? (control.hovered ? UM.Theme.getColor("primary") : UM.Theme.getColor("text")) : UM.Theme.getColor("text_inactive") color: control.enabled ? (control.hovered ? UM.Theme.getColor("primary") : UM.Theme.getColor("text")) : UM.Theme.getColor("text_inactive")
font: UM.Theme.getFont("default_bold") font: UM.Theme.getFont("medium_bold")
horizontalAlignment: Text.AlignRight horizontalAlignment: Text.AlignLeft
anchors
{
left: parent.left
leftMargin: UM.Theme.getSize("default_margin").width
}
width: control.width width: control.width
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View file

@ -59,7 +59,7 @@ Item
leftMargin: UM.Theme.getSize("default_margin").width leftMargin: UM.Theme.getSize("default_margin").width
} }
text: details === null ? "" : (details.name || "") text: details === null ? "" : (details.name || "")
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
width: contentWidth width: contentWidth
height: contentHeight height: contentHeight

View file

@ -22,7 +22,7 @@ Column
text: gridArea.heading text: gridArea.heading
width: parent.width width: parent.width
color: UM.Theme.getColor("text_medium") color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("large")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
Grid Grid

View file

@ -112,7 +112,7 @@ Item
elide: Text.ElideRight elide: Text.ElideRight
width: parent.width width: parent.width
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
color: UM.Theme.getColor("text_medium") color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
anchors.top: name.bottom anchors.top: name.bottom
anchors.bottom: rating.top anchors.bottom: rating.top

View file

@ -23,7 +23,7 @@ Rectangle
text: catalog.i18nc("@label", "Featured") text: catalog.i18nc("@label", "Featured")
width: parent.width width: parent.width
color: UM.Theme.getColor("text_medium") color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("large")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
Grid Grid

View file

@ -37,7 +37,7 @@ ScrollView
width: page.width width: page.width
text: catalog.i18nc("@title:tab", "Plugins") text: catalog.i18nc("@title:tab", "Plugins")
color: UM.Theme.getColor("text_medium") color: UM.Theme.getColor("text_medium")
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("large")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
Rectangle Rectangle

View file

@ -49,13 +49,14 @@ Item
width: parent.width width: parent.width
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height) height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font: UM.Theme.getFont("default_bold") font: UM.Theme.getFont("large_bold")
color: pluginInfo.color color: pluginInfo.color
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
Label Label
{ {
text: model.description text: model.description
font: UM.Theme.getFont("default")
maximumLineCount: 3 maximumLineCount: 3
elide: Text.ElideRight elide: Text.ElideRight
width: parent.width width: parent.width
@ -82,6 +83,7 @@ Item
return model.author_name return model.author_name
} }
} }
font: UM.Theme.getFont("medium")
width: parent.width width: parent.width
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height) height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
@ -96,6 +98,7 @@ Item
Label Label
{ {
text: model.version text: model.version
font: UM.Theme.getFont("default")
width: parent.width width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height height: UM.Theme.getSize("toolbox_property_label").height
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")

View file

@ -223,7 +223,7 @@ Cura.MachineAction
width: parent.width width: parent.width
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: base.selectedDevice ? base.selectedDevice.name : "" text: base.selectedDevice ? base.selectedDevice.name : ""
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
elide: Text.ElideRight elide: Text.ElideRight
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View file

@ -81,7 +81,7 @@ Item
text: printer && printer.name ? printer.name : "" text: printer && printer.name ? printer.name : ""
color: "#414054" // TODO: Theme! color: "#414054" // TODO: Theme!
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("large") // 16pt, bold font: UM.Theme.getFont("large_bold") // 16pt, bold
width: parent.width width: parent.width
// FIXED-LINE-HEIGHT: // FIXED-LINE-HEIGHT:
@ -185,7 +185,7 @@ Item
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
color: "#414054" // TODO: Theme! color: "#414054" // TODO: Theme!
font: UM.Theme.getFont("large") // 16pt, bold font: UM.Theme.getFont("large_bold") // 16pt, bold
text: { text: {
if (printer && printer.state == "disabled") if (printer && printer.state == "disabled")
{ {
@ -236,7 +236,7 @@ Item
id: printerJobNameLabel id: printerJobNameLabel
color: printer.activePrintJob && printer.activePrintJob.isActive ? "#414054" : "#babac1" // TODO: Theme! color: printer.activePrintJob && printer.activePrintJob.isActive ? "#414054" : "#babac1" // TODO: Theme!
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("large") // 16pt, bold font: UM.Theme.getFont("large_bold") // 16pt, bold
text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N
width: parent.width width: parent.width

View file

@ -23,7 +23,7 @@ Item
top: parent.top top: parent.top
} }
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
font: UM.Theme.getFont("large_nonbold") font: UM.Theme.getFont("large")
text: catalog.i18nc("@label", "Queued") text: catalog.i18nc("@label", "Queued")
} }

View file

@ -90,67 +90,4 @@ Item {
source: "DiscoverUM3Action.qml"; source: "DiscoverUM3Action.qml";
} }
} }
Column {
anchors.fill: parent;
objectName: "networkPrinterConnectionInfo";
spacing: UM.Theme.getSize("default_margin").width;
visible: isUM3;
Button {
onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication();
text: catalog.i18nc("@action:button", "Request Access");
tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer");
visible: printerConnected && !printerAcceptsCommands && !authenticationRequested;
}
Row {
anchors {
left: parent.left;
right: parent.right;
}
height: childrenRect.height;
spacing: UM.Theme.getSize("default_margin").width;
visible: printerConnected;
Column {
Repeater {
model: CuraApplication.getExtrudersModel()
Label {
text: model.name;
}
}
}
Column {
Repeater {
id: nozzleColumn;
model: hotendIds
Label {
text: nozzleColumn.model[index];
}
}
}
Column {
Repeater {
id: materialColumn;
model: materialNames
Label {
text: materialColumn.model[index];
}
}
}
}
Button {
onClicked: manager.loadConfigurationFromPrinter();
text: catalog.i18nc("@action:button", "Activate Configuration");
tooltip: catalog.i18nc("@info:tooltip", "Load the configuration of the printer into Cura");
visible: false; // printerConnected && !isClusterPrinter()
}
}
} }

View file

@ -561,8 +561,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
if material_group_list is None: if material_group_list is None:
material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \ material_name = i18n_catalog.i18nc("@label:material", "Empty") if len(material_data.get("guid", "")) == 0 \
else i18n_catalog.i18nc("@label:material", "Unknown") else i18n_catalog.i18nc("@label:material", "Unknown")
return MaterialOutputModel(guid = material_data.get("guid", ""), return MaterialOutputModel(guid = material_data.get("guid", ""),
type = material_data.get("type", ""), type = material_data.get("material", ""),
color = material_data.get("color", ""), color = material_data.get("color", ""),
brand = material_data.get("brand", ""), brand = material_data.get("brand", ""),
name = material_data.get("name", material_name) name = material_data.get("name", material_name)

View file

@ -200,4 +200,3 @@ class DiscoverUM3Action(MachineAction):
# Create extra components # Create extra components
CuraApplication.getInstance().addAdditionalComponent("monitorButtons", self.__additional_components_view.findChild(QObject, "networkPrinterConnectButton")) CuraApplication.getInstance().addAdditionalComponent("monitorButtons", self.__additional_components_view.findChild(QObject, "networkPrinterConnectButton"))
CuraApplication.getInstance().addAdditionalComponent("machinesDetailPane", self.__additional_components_view.findChild(QObject, "networkPrinterConnectionInfo"))

View file

@ -2,7 +2,6 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import json import json
import os import os
import urllib.parse
from typing import Dict, TYPE_CHECKING, Set, Optional from typing import Dict, TYPE_CHECKING, Set, Optional
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
@ -10,9 +9,7 @@ from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
from UM.Application import Application from UM.Application import Application
from UM.Job import Job from UM.Job import Job
from UM.Logger import Logger from UM.Logger import Logger
from UM.MimeTypeDatabase import MimeTypeDatabase
from UM.Resources import Resources
from cura.CuraApplication import CuraApplication
# Absolute imports don't work in plugins # Absolute imports don't work in plugins
from .Models import ClusterMaterial, LocalMaterial from .Models import ClusterMaterial, LocalMaterial
@ -37,7 +34,6 @@ class SendMaterialJob(Job):
# #
# \param reply The reply from the printer, a json file. # \param reply The reply from the printer, a json file.
def _onGetRemoteMaterials(self, reply: QNetworkReply) -> None: def _onGetRemoteMaterials(self, reply: QNetworkReply) -> None:
# Got an error from the HTTP request. If we did not receive a 200 something happened. # Got an error from the HTTP request. If we did not receive a 200 something happened.
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
Logger.log("e", "Error fetching materials from printer: %s", reply.errorString()) Logger.log("e", "Error fetching materials from printer: %s", reply.errorString())
@ -52,7 +48,6 @@ class SendMaterialJob(Job):
# #
# \param remote_materials_by_guid The remote materials by GUID. # \param remote_materials_by_guid The remote materials by GUID.
def _sendMissingMaterials(self, remote_materials_by_guid: Dict[str, ClusterMaterial]) -> None: def _sendMissingMaterials(self, remote_materials_by_guid: Dict[str, ClusterMaterial]) -> None:
# Collect local materials # Collect local materials
local_materials_by_guid = self._getLocalMaterials() local_materials_by_guid = self._getLocalMaterials()
if len(local_materials_by_guid) == 0: if len(local_materials_by_guid) == 0:
@ -91,22 +86,22 @@ class SendMaterialJob(Job):
# #
# \param materials_to_send A set with id's of materials that must be sent. # \param materials_to_send A set with id's of materials that must be sent.
def _sendMaterials(self, materials_to_send: Set[str]) -> None: def _sendMaterials(self, materials_to_send: Set[str]) -> None:
file_paths = Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.MaterialInstanceContainer) container_registry = Application.getInstance().getContainerRegistry()
material_manager = Application.getInstance().getMaterialManager()
material_group_dict = material_manager.getAllMaterialGroups()
# Find all local material files and send them if needed. for root_material_id in material_group_dict:
for file_path in file_paths: if root_material_id not in materials_to_send:
try:
mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
except MimeTypeDatabase.MimeTypeNotFoundError:
continue
file_name = os.path.basename(file_path)
material_id = urllib.parse.unquote_plus(mime_type.stripExtension(file_name))
if material_id not in materials_to_send:
# If the material does not have to be sent we skip it. # If the material does not have to be sent we skip it.
continue continue
self._sendMaterialFile(file_path, file_name, material_id) file_path = container_registry.getContainerFilePathById(root_material_id)
if not file_path:
Logger.log("w", "Cannot get file path for material container [%s]", root_material_id)
continue
file_name = os.path.basename(file_path)
self._sendMaterialFile(file_path, file_name, root_material_id)
## Send a single material file to the printer. ## Send a single material file to the printer.
# #
@ -116,7 +111,6 @@ class SendMaterialJob(Job):
# \param file_name The name of the material file. # \param file_name The name of the material file.
# \param material_id The ID of the material in the file. # \param material_id The ID of the material in the file.
def _sendMaterialFile(self, file_path: str, file_name: str, material_id: str) -> None: def _sendMaterialFile(self, file_path: str, file_name: str, material_id: str) -> None:
parts = [] parts = []
# Add the material file. # Add the material file.
@ -172,17 +166,21 @@ class SendMaterialJob(Job):
# \return a dictionary of LocalMaterial objects by GUID # \return a dictionary of LocalMaterial objects by GUID
def _getLocalMaterials(self) -> Dict[str, LocalMaterial]: def _getLocalMaterials(self) -> Dict[str, LocalMaterial]:
result = {} # type: Dict[str, LocalMaterial] result = {} # type: Dict[str, LocalMaterial]
container_registry = Application.getInstance().getContainerRegistry() material_manager = Application.getInstance().getMaterialManager()
material_containers = container_registry.findContainersMetadata(type = "material")
material_group_dict = material_manager.getAllMaterialGroups()
# Find the latest version of all material containers in the registry. # Find the latest version of all material containers in the registry.
for material in material_containers: for root_material_id, material_group in material_group_dict.items():
material_metadata = material_group.root_material_node.getMetadata()
try: try:
# material version must be an int # material version must be an int
material["version"] = int(material["version"]) material_metadata["version"] = int(material_metadata["version"])
# Create a new local material # Create a new local material
local_material = LocalMaterial(**material) local_material = LocalMaterial(**material_metadata)
local_material.id = root_material_id
if local_material.GUID not in result or \ if local_material.GUID not in result or \
local_material.GUID not in result or \ local_material.GUID not in result or \
@ -190,10 +188,10 @@ class SendMaterialJob(Job):
result[local_material.GUID] = local_material result[local_material.GUID] = local_material
except KeyError: except KeyError:
Logger.logException("w", "Local material {} has missing values.".format(material["id"])) Logger.logException("w", "Local material {} has missing values.".format(material_metadata["id"]))
except ValueError: except ValueError:
Logger.logException("w", "Local material {} has invalid values.".format(material["id"])) Logger.logException("w", "Local material {} has invalid values.".format(material_metadata["id"]))
except TypeError: except TypeError:
Logger.logException("w", "Local material {} has invalid values.".format(material["id"])) Logger.logException("w", "Local material {} has invalid values.".format(material_metadata["id"]))
return result return result

View file

@ -118,6 +118,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
if key == um_network_key: if key == um_network_key:
if not self._discovered_devices[key].isConnected(): if not self._discovered_devices[key].isConnected():
Logger.log("d", "Attempting to connect with [%s]" % key) Logger.log("d", "Attempting to connect with [%s]" % key)
active_machine.setMetaDataEntry("connection_type", self._discovered_devices[key].getConnectionType().value)
self._discovered_devices[key].connect() self._discovered_devices[key].connect()
self._discovered_devices[key].connectionStateChanged.connect(self._onDeviceConnectionStateChanged) self._discovered_devices[key].connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
else: else:

View file

@ -1,26 +1,29 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import copy
import io import io
import json import json
from unittest import TestCase, mock from unittest import TestCase, mock
from unittest.mock import patch, call from unittest.mock import patch, call, MagicMock
from PyQt5.QtCore import QByteArray from PyQt5.QtCore import QByteArray
from UM.MimeTypeDatabase import MimeType
from UM.Application import Application from UM.Application import Application
from cura.Machines.MaterialGroup import MaterialGroup
from cura.Machines.MaterialNode import MaterialNode
from plugins.UM3NetworkPrinting.src.SendMaterialJob import SendMaterialJob from plugins.UM3NetworkPrinting.src.SendMaterialJob import SendMaterialJob
_FILES_MAP = {"generic_pla_white": "/materials/generic_pla_white.xml.fdm_material",
"generic_pla_black": "/materials/generic_pla_black.xml.fdm_material",
}
@patch("builtins.open", lambda _, __: io.StringIO("<xml></xml>")) @patch("builtins.open", lambda _, __: io.StringIO("<xml></xml>"))
@patch("UM.MimeTypeDatabase.MimeTypeDatabase.getMimeTypeForFile",
lambda _: MimeType(name = "application/x-ultimaker-material-profile", comment = "Ultimaker Material Profile",
suffixes = ["xml.fdm_material"]))
@patch("UM.Resources.Resources.getAllResourcesOfType", lambda _: ["/materials/generic_pla_white.xml.fdm_material"])
@patch("plugins.UM3NetworkPrinting.src.ClusterUM3OutputDevice")
@patch("PyQt5.QtNetwork.QNetworkReply")
class TestSendMaterialJob(TestCase): class TestSendMaterialJob(TestCase):
# version 1
_LOCAL_MATERIAL_WHITE = {"type": "material", "status": "unknown", "id": "generic_pla_white", _LOCAL_MATERIAL_WHITE = {"type": "material", "status": "unknown", "id": "generic_pla_white",
"base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA", "base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
"brand": "Generic", "material": "PLA", "color_name": "White", "brand": "Generic", "material": "PLA", "color_name": "White",
@ -29,6 +32,37 @@ class TestSendMaterialJob(TestCase):
"properties": {"density": "1.00", "diameter": "2.85", "weight": "750"}, "properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
"definition": "fdmprinter", "compatible": True} "definition": "fdmprinter", "compatible": True}
# version 2
_LOCAL_MATERIAL_WHITE_NEWER = {"type": "material", "status": "unknown", "id": "generic_pla_white",
"base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
"brand": "Generic", "material": "PLA", "color_name": "White",
"GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "2",
"color_code": "#ffffff",
"description": "Test PLA White", "adhesion_info": "Use glue.",
"approximate_diameter": "3",
"properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
"definition": "fdmprinter", "compatible": True}
# invalid version: "one"
_LOCAL_MATERIAL_WHITE_INVALID_VERSION = {"type": "material", "status": "unknown", "id": "generic_pla_white",
"base_file": "generic_pla_white", "setting_version": "5", "name": "White PLA",
"brand": "Generic", "material": "PLA", "color_name": "White",
"GUID": "badb0ee7-87c8-4f3f-9398-938587b67dce", "version": "one",
"color_code": "#ffffff",
"description": "Test PLA White", "adhesion_info": "Use glue.",
"approximate_diameter": "3",
"properties": {"density": "1.00", "diameter": "2.85", "weight": "750"},
"definition": "fdmprinter", "compatible": True}
_LOCAL_MATERIAL_WHITE_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
MaterialNode(_LOCAL_MATERIAL_WHITE))}
_LOCAL_MATERIAL_WHITE_NEWER_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
MaterialNode(_LOCAL_MATERIAL_WHITE_NEWER))}
_LOCAL_MATERIAL_WHITE_INVALID_VERSION_ALL_RESULT = {"generic_pla_white": MaterialGroup("generic_pla_white",
MaterialNode(_LOCAL_MATERIAL_WHITE_INVALID_VERSION))}
_LOCAL_MATERIAL_BLACK = {"type": "material", "status": "unknown", "id": "generic_pla_black", _LOCAL_MATERIAL_BLACK = {"type": "material", "status": "unknown", "id": "generic_pla_black",
"base_file": "generic_pla_black", "setting_version": "5", "name": "Yellow CPE", "base_file": "generic_pla_black", "setting_version": "5", "name": "Yellow CPE",
"brand": "Ultimaker", "material": "CPE", "color_name": "Black", "brand": "Ultimaker", "material": "CPE", "color_name": "Black",
@ -37,6 +71,9 @@ class TestSendMaterialJob(TestCase):
"properties": {"density": "1.01", "diameter": "2.85", "weight": "750"}, "properties": {"density": "1.01", "diameter": "2.85", "weight": "750"},
"definition": "fdmprinter", "compatible": True} "definition": "fdmprinter", "compatible": True}
_LOCAL_MATERIAL_BLACK_ALL_RESULT = {"generic_pla_black": MaterialGroup("generic_pla_black",
MaterialNode(_LOCAL_MATERIAL_BLACK))}
_REMOTE_MATERIAL_WHITE = { _REMOTE_MATERIAL_WHITE = {
"guid": "badb0ee7-87c8-4f3f-9398-938587b67dce", "guid": "badb0ee7-87c8-4f3f-9398-938587b67dce",
"material": "PLA", "material": "PLA",
@ -55,14 +92,17 @@ class TestSendMaterialJob(TestCase):
"density": 1.00 "density": 1.00
} }
def test_run(self, device_mock, reply_mock): def test_run(self):
device_mock = MagicMock()
job = SendMaterialJob(device_mock) job = SendMaterialJob(device_mock)
job.run() job.run()
# We expect the materials endpoint to be called when the job runs. # We expect the materials endpoint to be called when the job runs.
device_mock.get.assert_called_with("materials/", on_finished = job._onGetRemoteMaterials) device_mock.get.assert_called_with("materials/", on_finished = job._onGetRemoteMaterials)
def test__onGetRemoteMaterials_withFailedRequest(self, reply_mock, device_mock): def test__onGetRemoteMaterials_withFailedRequest(self):
reply_mock = MagicMock()
device_mock = MagicMock()
reply_mock.attribute.return_value = 404 reply_mock.attribute.return_value = 404
job = SendMaterialJob(device_mock) job = SendMaterialJob(device_mock)
job._onGetRemoteMaterials(reply_mock) job._onGetRemoteMaterials(reply_mock)
@ -70,7 +110,9 @@ class TestSendMaterialJob(TestCase):
# We expect the device not to be called for any follow up. # We expect the device not to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count) self.assertEqual(0, device_mock.createFormPart.call_count)
def test__onGetRemoteMaterials_withWrongEncoding(self, reply_mock, device_mock): def test__onGetRemoteMaterials_withWrongEncoding(self):
reply_mock = MagicMock()
device_mock = MagicMock()
reply_mock.attribute.return_value = 200 reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("cp500")) reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("cp500"))
job = SendMaterialJob(device_mock) job = SendMaterialJob(device_mock)
@ -79,7 +121,9 @@ class TestSendMaterialJob(TestCase):
# Given that the parsing fails we do no expect the device to be called for any follow up. # Given that the parsing fails we do no expect the device to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count) self.assertEqual(0, device_mock.createFormPart.call_count)
def test__onGetRemoteMaterials_withBadJsonAnswer(self, reply_mock, device_mock): def test__onGetRemoteMaterials_withBadJsonAnswer(self):
reply_mock = MagicMock()
device_mock = MagicMock()
reply_mock.attribute.return_value = 200 reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(b"Six sick hicks nick six slick bricks with picks and sticks.") reply_mock.readAll.return_value = QByteArray(b"Six sick hicks nick six slick bricks with picks and sticks.")
job = SendMaterialJob(device_mock) job = SendMaterialJob(device_mock)
@ -88,7 +132,9 @@ class TestSendMaterialJob(TestCase):
# Given that the parsing fails we do no expect the device to be called for any follow up. # Given that the parsing fails we do no expect the device to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count) self.assertEqual(0, device_mock.createFormPart.call_count)
def test__onGetRemoteMaterials_withMissingGuidInRemoteMaterial(self, reply_mock, device_mock): def test__onGetRemoteMaterials_withMissingGuidInRemoteMaterial(self):
reply_mock = MagicMock()
device_mock = MagicMock()
reply_mock.attribute.return_value = 200 reply_mock.attribute.return_value = 200
remote_material_without_guid = self._REMOTE_MATERIAL_WHITE.copy() remote_material_without_guid = self._REMOTE_MATERIAL_WHITE.copy()
del remote_material_without_guid["guid"] del remote_material_without_guid["guid"]
@ -99,18 +145,20 @@ class TestSendMaterialJob(TestCase):
# Given that parsing fails we do not expect the device to be called for any follow up. # Given that parsing fails we do not expect the device to be called for any follow up.
self.assertEqual(0, device_mock.createFormPart.call_count) self.assertEqual(0, device_mock.createFormPart.call_count)
@patch("cura.Machines.MaterialManager.MaterialManager")
@patch("cura.Settings.CuraContainerRegistry") @patch("cura.Settings.CuraContainerRegistry")
@patch("UM.Application") @patch("UM.Application")
def test__onGetRemoteMaterials_withInvalidVersionInLocalMaterial(self, application_mock, container_registry_mock, def test__onGetRemoteMaterials_withInvalidVersionInLocalMaterial(self, application_mock, container_registry_mock,
reply_mock, device_mock): material_manager_mock):
reply_mock = MagicMock()
device_mock = MagicMock()
application_mock.getContainerRegistry.return_value = container_registry_mock
application_mock.getMaterialManager.return_value = material_manager_mock
reply_mock.attribute.return_value = 200 reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii")) reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
localMaterialWhiteWithInvalidVersion = self._LOCAL_MATERIAL_WHITE.copy() material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_INVALID_VERSION_ALL_RESULT.copy()
localMaterialWhiteWithInvalidVersion["version"] = "one"
container_registry_mock.findContainersMetadata.return_value = [localMaterialWhiteWithInvalidVersion]
application_mock.getContainerRegistry.return_value = container_registry_mock
with mock.patch.object(Application, "getInstance", new = lambda: application_mock): with mock.patch.object(Application, "getInstance", new = lambda: application_mock):
job = SendMaterialJob(device_mock) job = SendMaterialJob(device_mock)
@ -118,15 +166,16 @@ class TestSendMaterialJob(TestCase):
self.assertEqual(0, device_mock.createFormPart.call_count) self.assertEqual(0, device_mock.createFormPart.call_count)
@patch("cura.Settings.CuraContainerRegistry") @patch("UM.Application.Application.getInstance")
@patch("UM.Application") def test__onGetRemoteMaterials_withNoUpdate(self, application_mock):
def test__onGetRemoteMaterials_withNoUpdate(self, application_mock, container_registry_mock, reply_mock, reply_mock = MagicMock()
device_mock): device_mock = MagicMock()
application_mock.getContainerRegistry.return_value = container_registry_mock container_registry_mock = application_mock.getContainerRegistry.return_value
material_manager_mock = application_mock.getMaterialManager.return_value
device_mock.createFormPart.return_value = "_xXx_" device_mock.createFormPart.return_value = "_xXx_"
container_registry_mock.findContainersMetadata.return_value = [self._LOCAL_MATERIAL_WHITE] material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_ALL_RESULT.copy()
reply_mock.attribute.return_value = 200 reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii")) reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
@ -138,24 +187,25 @@ class TestSendMaterialJob(TestCase):
self.assertEqual(0, device_mock.createFormPart.call_count) self.assertEqual(0, device_mock.createFormPart.call_count)
self.assertEqual(0, device_mock.postFormWithParts.call_count) self.assertEqual(0, device_mock.postFormWithParts.call_count)
@patch("cura.Settings.CuraContainerRegistry") @patch("UM.Application.Application.getInstance")
@patch("UM.Application") def test__onGetRemoteMaterials_withUpdatedMaterial(self, get_instance_mock):
def test__onGetRemoteMaterials_withUpdatedMaterial(self, application_mock, container_registry_mock, reply_mock, reply_mock = MagicMock()
device_mock): device_mock = MagicMock()
application_mock.getContainerRegistry.return_value = container_registry_mock application_mock = get_instance_mock.return_value
container_registry_mock = application_mock.getContainerRegistry.return_value
material_manager_mock = application_mock.getMaterialManager.return_value
container_registry_mock.getContainerFilePathById = lambda x: _FILES_MAP.get(x)
device_mock.createFormPart.return_value = "_xXx_" device_mock.createFormPart.return_value = "_xXx_"
localMaterialWhiteWithHigherVersion = self._LOCAL_MATERIAL_WHITE.copy() material_manager_mock.getAllMaterialGroups.return_value = self._LOCAL_MATERIAL_WHITE_NEWER_ALL_RESULT.copy()
localMaterialWhiteWithHigherVersion["version"] = "2"
container_registry_mock.findContainersMetadata.return_value = [localMaterialWhiteWithHigherVersion]
reply_mock.attribute.return_value = 200 reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii")) reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_WHITE]).encode("ascii"))
with mock.patch.object(Application, "getInstance", new = lambda: application_mock): job = SendMaterialJob(device_mock)
job = SendMaterialJob(device_mock) job._onGetRemoteMaterials(reply_mock)
job._onGetRemoteMaterials(reply_mock)
self.assertEqual(1, device_mock.createFormPart.call_count) self.assertEqual(1, device_mock.createFormPart.call_count)
self.assertEqual(1, device_mock.postFormWithParts.call_count) self.assertEqual(1, device_mock.postFormWithParts.call_count)
@ -164,16 +214,21 @@ class TestSendMaterialJob(TestCase):
call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)], call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
device_mock.method_calls) device_mock.method_calls)
@patch("cura.Settings.CuraContainerRegistry") @patch("UM.Application.Application.getInstance")
@patch("UM.Application") def test__onGetRemoteMaterials_withNewMaterial(self, application_mock):
def test__onGetRemoteMaterials_withNewMaterial(self, application_mock, container_registry_mock, reply_mock, reply_mock = MagicMock()
device_mock): device_mock = MagicMock()
application_mock.getContainerRegistry.return_value = container_registry_mock container_registry_mock = application_mock.getContainerRegistry.return_value
material_manager_mock = application_mock.getMaterialManager.return_value
container_registry_mock.getContainerFilePathById = lambda x: _FILES_MAP.get(x)
device_mock.createFormPart.return_value = "_xXx_" device_mock.createFormPart.return_value = "_xXx_"
container_registry_mock.findContainersMetadata.return_value = [self._LOCAL_MATERIAL_WHITE, all_results = self._LOCAL_MATERIAL_WHITE_ALL_RESULT.copy()
self._LOCAL_MATERIAL_BLACK] for key, value in self._LOCAL_MATERIAL_BLACK_ALL_RESULT.items():
all_results[key] = value
material_manager_mock.getAllMaterialGroups.return_value = all_results
reply_mock.attribute.return_value = 200 reply_mock.attribute.return_value = 200
reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_BLACK]).encode("ascii")) reply_mock.readAll.return_value = QByteArray(json.dumps([self._REMOTE_MATERIAL_BLACK]).encode("ascii"))

View file

@ -373,7 +373,7 @@
} }
} }
}, },
"PreviewStage": { "PreviewStage": {
"package_info": { "package_info": {
"package_id": "PreviewStage", "package_id": "PreviewStage",
"package_type": "plugin", "package_type": "plugin",
@ -1602,4 +1602,4 @@
} }
} }
} }
} }

View file

@ -44,7 +44,7 @@ Column
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
renderType: Text.NativeRendering renderType: Text.NativeRendering
text: loggedIn ? profile["username"] : catalog.i18nc("@label", "Please log in or create an account to\nenjoy all features of Ultimaker Cura.") 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") : UM.Theme.getFont("default") font: loggedIn ? UM.Theme.getFont("large_bold") : UM.Theme.getFont("default")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
} }

View file

@ -23,6 +23,7 @@ Rectangle
border.width: UM.Theme.getSize("default_lining").width border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining") border.color: UM.Theme.getColor("lining")
radius: UM.Theme.getSize("default_radius").width radius: UM.Theme.getSize("default_radius").width
z: 10
property bool outputAvailable: UM.Backend.state == UM.Backend.Done || UM.Backend.state == UM.Backend.Disabled property bool outputAvailable: UM.Backend.state == UM.Backend.Done || UM.Backend.state == UM.Backend.Disabled

View file

@ -93,7 +93,6 @@ Item
onClicked: onClicked:
{ {
UM.OutputDeviceManager.setActiveDevice(model.id) UM.OutputDeviceManager.setActiveDevice(model.id)
widget.requestWriteToDevice()
popup.close() popup.close()
} }
} }

View file

@ -40,8 +40,7 @@ Column
anchors anchors
{ {
left: parent.left left: parent.left
right: printInformationPanel.left right: parent.right
rightMargin: printInformationPanel.visible ? UM.Theme.getSize("thin_margin").width : 0
} }
Cura.IconWithText Cura.IconWithText
@ -51,7 +50,15 @@ Column
text: preSlicedData ? catalog.i18nc("@label", "No time estimation available") : PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long) text: preSlicedData ? catalog.i18nc("@label", "No time estimation available") : PrintInformation.currentPrintTime.getDisplayString(UM.DurationFormat.Long)
source: UM.Theme.getIcon("clock") source: UM.Theme.getIcon("clock")
font: UM.Theme.getFont("default_bold") font: UM.Theme.getFont("large_bold")
PrintInformationWidget
{
id: printInformationPanel
visible: !preSlicedData
anchors.left: parent.left
anchors.leftMargin: parent.contentWidth + UM.Theme.getSize("default_margin").width
}
} }
Cura.IconWithText Cura.IconWithText
@ -84,20 +91,43 @@ Column
return totalWeights + "g · " + totalLengths.toFixed(2) + "m" return totalWeights + "g · " + totalLengths.toFixed(2) + "m"
} }
source: UM.Theme.getIcon("spool") source: UM.Theme.getIcon("spool")
Item
{
id: additionalComponents
width: childrenRect.width
anchors.right: parent.right
height: parent.height
Row
{
id: additionalComponentsRow
anchors.right: parent.right
anchors.bottom: parent.bottom
spacing: UM.Theme.getSize("default_margin").width
}
}
Component.onCompleted: addAdditionalComponents("saveButton")
Connections
{
target: CuraApplication
onAdditionalComponentsChanged: addAdditionalComponents("saveButton")
}
function addAdditionalComponents (areaId)
{
if(areaId == "saveButton")
{
for (var component in CuraApplication.additionalComponents["saveButton"])
{
CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow
}
}
}
} }
} }
PrintInformationWidget
{
id: printInformationPanel
visible: !preSlicedData
anchors
{
right: parent.right
verticalCenter: timeAndCostsInformation.verticalCenter
}
}
} }
Item Item
@ -127,9 +157,6 @@ Column
onClicked: UM.Controller.setActiveStage("PreviewStage") onClicked: UM.Controller.setActiveStage("PreviewStage")
visible: UM.Controller.activeStage != null && UM.Controller.activeStage.stageId != "PreviewStage" visible: UM.Controller.activeStage != null && UM.Controller.activeStage.stageId != "PreviewStage"
shadowEnabled: true
shadowColor: UM.Theme.getColor("action_button_disabled_shadow")
} }
Cura.OutputDevicesActionButton Cura.OutputDevicesActionButton

View file

@ -44,9 +44,9 @@ Column
{ {
id: autoSlicingLabel id: autoSlicingLabel
width: parent.width width: parent.width
visible: prepareButtons.autoSlice && (widget.backendState == UM.Backend.Processing || widget.backendState == UM.Backend.NotStarted) visible: progressBar.visible
text: catalog.i18nc("@label:PrintjobStatus", "Auto slicing...") text: catalog.i18nc("@label:PrintjobStatus", "Slicing...")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
renderType: Text.NativeRendering renderType: Text.NativeRendering
@ -107,7 +107,13 @@ Column
{ {
id: sliceButton id: sliceButton
fixedWidthMode: true fixedWidthMode: true
anchors.fill: parent
height: parent.height
anchors.right: additionalComponents.left
anchors.rightMargin: additionalComponents.width != 0 ? UM.Theme.getSize("default_margin").width : 0
anchors.left: parent.left
text: catalog.i18nc("@button", "Slice") text: catalog.i18nc("@button", "Slice")
tooltip: catalog.i18nc("@label", "Start the slicing process") tooltip: catalog.i18nc("@label", "Start the slicing process")
enabled: widget.backendState != UM.Backend.Error enabled: widget.backendState != UM.Backend.Error
@ -119,12 +125,48 @@ Column
{ {
id: cancelButton id: cancelButton
fixedWidthMode: true fixedWidthMode: true
anchors.fill: parent height: parent.height
anchors.left: parent.left
anchors.right: additionalComponents.left
anchors.rightMargin: additionalComponents.width != 0 ? UM.Theme.getSize("default_margin").width : 0
text: catalog.i18nc("@button", "Cancel") text: catalog.i18nc("@button", "Cancel")
enabled: sliceButton.enabled enabled: sliceButton.enabled
visible: !sliceButton.visible visible: !sliceButton.visible
onClicked: sliceOrStopSlicing() onClicked: sliceOrStopSlicing()
} }
Item
{
id: additionalComponents
width: childrenRect.width
anchors.right: parent.right
height: parent.height
Row
{
id: additionalComponentsRow
anchors.verticalCenter: parent.verticalCenter
spacing: UM.Theme.getSize("default_margin").width
}
}
Component.onCompleted: prepareButtons.addAdditionalComponents("saveButton")
Connections
{
target: CuraApplication
onAdditionalComponentsChanged: prepareButtons.addAdditionalComponents("saveButton")
}
function addAdditionalComponents (areaId)
{
if(areaId == "saveButton")
{
for (var component in CuraApplication.additionalComponents["saveButton"])
{
CuraApplication.additionalComponents["saveButton"][component].parent = additionalComponentsRow
}
}
}
} }

View file

@ -252,7 +252,21 @@ UM.MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.rightMargin: UM.Theme.getSize("thick_margin").width anchors.rightMargin: UM.Theme.getSize("thick_margin").width
anchors.bottomMargin: UM.Theme.getSize("thick_margin").height anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
visible: CuraApplication.platformActivity
/*
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"))
} }
Loader Loader
@ -818,4 +832,21 @@ UM.MainWindow
} }
} }
} }
/**
* Function to check whether a QML object has a certain type.
* Taken from StackOverflow: https://stackoverflow.com/a/28384228 and
* adapted to our code style.
* Licensed under CC BY-SA 3.0.
* \param obj The QtObject to get the name of.
* \param class_name (str) The name of the class to check against. Has to be
* the QtObject class name, not the QML entity name.
*/
function qmlTypeOf(obj, class_name)
{
//className plus "(" is the class instance without modification.
//className plus "_QML" is the class instance with user-defined properties.
var str = obj.toString();
return str.indexOf(class_name + "(") == 0 || str.indexOf(class_name + "_QML") == 0;
}
} }

View file

@ -51,7 +51,7 @@ UM.Dialog
id: version id: version
text: catalog.i18nc("@label","version: %1").arg(UM.Application.version) text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
anchors.right : logo.right anchors.right : logo.right
anchors.top: logo.bottom anchors.top: logo.bottom

View file

@ -64,7 +64,7 @@ Item
property alias iconSize: collapseButton.height property alias iconSize: collapseButton.height
// Is the "drawer" open? // Is the "drawer" open?
readonly property alias expanded: contentContainer.visible property alias expanded: contentContainer.visible
// What should the radius of the header be. This is also influenced by the headerCornerSide // What should the radius of the header be. This is also influenced by the headerCornerSide
property alias headerRadius: background.radius property alias headerRadius: background.radius

View file

@ -25,7 +25,7 @@ Cura.RoundedRectangle
{ {
id: headerLabel id: headerLabel
text: "" text: ""
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
renderType: Text.NativeRendering renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
color: UM.Theme.getColor("small_button_text") color: UM.Theme.getColor("small_button_text")

View file

@ -48,7 +48,7 @@ Item
id: extruderNumberText id: extruderNumberText
anchors.centerIn: parent anchors.centerIn: parent
text: index + 1 text: index + 1
font: UM.Theme.getFont("very_small") font: UM.Theme.getFont("small")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
width: contentWidth width: contentWidth
height: contentHeight height: contentHeight
@ -66,7 +66,7 @@ Item
sourceSize.height: width sourceSize.height: width
source: UM.Theme.getIcon("cross1") source: UM.Theme.getIcon("cross1")
visible: !extruderEnabled visible: !extruderEnabled
color: "black" color: UM.Theme.getColor("text")
} }
} }
} }

View file

@ -97,7 +97,7 @@ Item
style: TextFieldStyle style: TextFieldStyle
{ {
textColor: UM.Theme.getColor("text_scene") textColor: UM.Theme.getColor("text_scene")
font: UM.Theme.getFont("default_bold") font: UM.Theme.getFont("default")
background: Rectangle background: Rectangle
{ {
opacity: 0 opacity: 0
@ -115,7 +115,7 @@ Item
height: UM.Theme.getSize("jobspecs_line").height height: UM.Theme.getSize("jobspecs_line").height
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
font: UM.Theme.getFont("default_bold") font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_scene") color: UM.Theme.getColor("text_scene")
text: CuraApplication.getSceneBoundingBoxString text: CuraApplication.getSceneBoundingBoxString
} }

View file

@ -83,14 +83,6 @@ Item
} }
} }
Menu
{
id: plugin_menu
title: catalog.i18nc("@title:menu menubar:toplevel", "&Marketplace")
MenuItem { action: Cura.Actions.browsePackages }
}
Menu Menu
{ {
id: preferencesMenu id: preferencesMenu

View file

@ -102,6 +102,7 @@ Item
{ {
id: label id: label
text: marketplaceButton.text text: marketplaceButton.text
font: UM.Theme.getFont("default")
color: marketplaceButton.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text") color: marketplaceButton.hovered ? UM.Theme.getColor("main_window_header_background") : UM.Theme.getColor("primary_text")
width: contentWidth width: contentWidth
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter

View file

@ -16,7 +16,7 @@ Item
{ {
id: header id: header
text: catalog.i18nc("@header", "Configurations") text: catalog.i18nc("@header", "Configurations")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("small_button_text") color: UM.Theme.getColor("small_button_text")
height: contentHeight height: contentHeight
renderType: Text.NativeRendering renderType: Text.NativeRendering

View file

@ -12,7 +12,23 @@ Button
id: configurationItem id: configurationItem
property var configuration: null property var configuration: null
hoverEnabled: true hoverEnabled: isValidMaterial
property bool isValidMaterial:
{
var extruderConfigurations = configuration.extruderConfigurations
for (var index in extruderConfigurations)
{
var name = extruderConfigurations[index].material ? extruderConfigurations[index].material.name : ""
if (name == "" || name == "Unknown")
{
return false
}
}
return true
}
background: Rectangle background: Rectangle
{ {
@ -40,17 +56,104 @@ Button
right: parent.right right: parent.right
rightMargin: UM.Theme.getSize("wide_margin").width rightMargin: UM.Theme.getSize("wide_margin").width
} }
height: childrenRect.height
spacing: UM.Theme.getSize("default_margin").width spacing: UM.Theme.getSize("default_margin").width
Repeater Repeater
{ {
id: repeater id: repeater
model: configuration.extruderConfigurations model: configuration.extruderConfigurations
delegate: PrintCoreConfiguration delegate: PrintCoreConfiguration
{ {
width: Math.round(parent.width / 2) width: Math.round(parent.width / 2)
printCoreConfiguration: modelData printCoreConfiguration: modelData
visible: configurationItem.isValidMaterial
}
}
// Unknown material
Item
{
id: unknownMaterial
height: unknownMaterialMessage.height + UM.Theme.getSize("thin_margin").width / 2
width: parent.width
anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("thin_margin").width / 2
visible: !configurationItem.isValidMaterial
UM.RecolorImage
{
id: icon
anchors.verticalCenter: unknownMaterialMessage.verticalCenter
source: UM.Theme.getIcon("warning")
color: UM.Theme.getColor("warning")
width: UM.Theme.getSize("section_icon").width
height: width
}
Label
{
id: unknownMaterialMessage
text:
{
var extruderConfigurations = configuration.extruderConfigurations
var unknownMaterials = []
for (var index in extruderConfigurations)
{
var name = extruderConfigurations[index].material ? extruderConfigurations[index].material.name : ""
if (name == "" || name == "Unknown")
{
var materialType = extruderConfigurations[index].material.type
if (extruderConfigurations[index].material.type == "")
{
materialType = "Unknown"
}
var brand = extruderConfigurations[index].material.brand
if (brand == "")
{
brand = "Unknown"
}
name = materialType + " (" + brand + ")"
unknownMaterials.push(name)
}
}
unknownMaterials = "<b>" + unknownMaterials + "</b>"
var draftResult = catalog.i18nc("@label", "This configuration is not available because %1 is not recognized. Please visit %2 to download the correct material profile.");
var result = draftResult.arg(unknownMaterials).arg("<a href=' '>" + catalog.i18nc("@label","Marketplace") + "</a> ")
return result
}
width: extruderRow.width
anchors.left: icon.right
anchors.right: unknownMaterial.right
anchors.leftMargin: UM.Theme.getSize("wide_margin").height
anchors.top: unknownMaterial.top
wrapMode: Text.WordWrap
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
linkColor: UM.Theme.getColor("text_link")
onLinkActivated:
{
Cura.Actions.browsePackages.trigger()
}
}
MouseArea
{
anchors.fill: parent
cursorShape: unknownMaterialMessage.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.NoButton
} }
} }
} }
@ -84,27 +187,15 @@ Button
rightMargin: UM.Theme.getSize("wide_margin").width rightMargin: UM.Theme.getSize("wide_margin").width
} }
height: childrenRect.height height: childrenRect.height
visible: configuration.buildplateConfiguration != "" visible: configuration.buildplateConfiguration != "" && false //Buildplate is disabled as long as we have no printers that properly support buildplate swapping (so we can't test).
UM.RecolorImage // Show the type of buildplate. The first letter is capitalized
{ Cura.IconWithText
id: buildplateIcon
anchors.left: parent.left
width: UM.Theme.getSize("main_window_header_button_icon").width
height: UM.Theme.getSize("main_window_header_button_icon").height
source: UM.Theme.getIcon("buildplate")
color: UM.Theme.getColor("text")
}
Label
{ {
id: buildplateLabel id: buildplateLabel
anchors.left: buildplateIcon.right source: UM.Theme.getIcon("buildplate")
anchors.verticalCenter: buildplateIcon.verticalCenter text: configuration.buildplateConfiguration.charAt(0).toUpperCase() + configuration.buildplateConfiguration.substr(1)
anchors.leftMargin: UM.Theme.getSize("narrow_margin").height anchors.left: parent.left
text: configuration.buildplateConfiguration
renderType: Text.NativeRendering
color: UM.Theme.getColor("text")
} }
} }
} }
@ -125,6 +216,9 @@ Button
onClicked: onClicked:
{ {
Cura.MachineManager.applyRemoteConfiguration(configuration) if(isValidMaterial)
{
Cura.MachineManager.applyRemoteConfiguration(configuration);
}
} }
} }

View file

@ -51,7 +51,7 @@ Item
anchors.left: icon.right anchors.left: icon.right
anchors.right: parent.right anchors.right: parent.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.leftMargin: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@label", "The configurations are not available because the printer is disconnected.") text: catalog.i18nc("@label", "Downloading the configurations from the remote printer")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
renderType: Text.NativeRendering renderType: Text.NativeRendering

View file

@ -86,7 +86,7 @@ Cura.ExpandablePopup
{ {
text: model.material text: model.material
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
@ -107,7 +107,7 @@ Cura.ExpandablePopup
{ {
text: catalog.i18nc("@label", "Select configuration") text: catalog.i18nc("@label", "Select configuration")
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering

View file

@ -23,7 +23,7 @@ Item
{ {
id: header id: header
text: catalog.i18nc("@header", "Custom") text: catalog.i18nc("@header", "Custom")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("small_button_text") color: UM.Theme.getColor("small_button_text")
height: contentHeight height: contentHeight
renderType: Text.NativeRendering renderType: Text.NativeRendering

View file

@ -39,7 +39,7 @@ Row
text: printCoreConfiguration.material.brand ? printCoreConfiguration.material.name : " " //Use space so that the height is still correct. text: printCoreConfiguration.material.brand ? printCoreConfiguration.material.name : " " //Use space so that the height is still correct.
renderType: Text.NativeRendering renderType: Text.NativeRendering
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
} }
Label Label

View file

@ -9,7 +9,7 @@ import Cura 1.0 as Cura
Instantiator Instantiator
{ {
model: Cura.PrintersModel {} model: Cura.GlobalStacksModel {}
MenuItem MenuItem
{ {

View file

@ -9,7 +9,7 @@ import Cura 1.0 as Cura
Instantiator Instantiator
{ {
model: Cura.PrintersModel {} model: Cura.GlobalStacksModel {}
MenuItem MenuItem
{ {
text: model.metadata["connect_group_name"] text: model.metadata["connect_group_name"]

View file

@ -168,7 +168,7 @@ Item
anchors.leftMargin: UM.Theme.getSize("thick_margin").width anchors.leftMargin: UM.Theme.getSize("thick_margin").width
color: base.statusColor color: base.statusColor
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
text: statusText text: statusText
} }
@ -179,7 +179,7 @@ Item
anchors.right: progressBar.right anchors.right: progressBar.right
color: base.statusColor color: base.statusColor
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
text: Math.round(progress) + "%" text: Math.round(progress) + "%"
visible: showProgress visible: showProgress
} }

View file

@ -70,7 +70,7 @@ UM.ManagementPage
{ {
id: machineName id: machineName
text: base.currentItem && base.currentItem.name ? base.currentItem.name : "" text: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
} }
@ -126,132 +126,15 @@ UM.ManagementPage
} }
} }
Grid
{
id: machineInfo
anchors.top: machineActions.visible ? machineActions.bottom : machineActions.anchors.top
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
anchors.right: parent.right
spacing: UM.Theme.getSize("default_margin").height
rowSpacing: UM.Theme.getSize("default_lining").height
columns: 2
visible: base.currentItem
property bool printerConnected: Cura.MachineManager.printerConnected
property var connectedPrinter: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null
property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
property var printJob: connectedPrinter != null ? connectedPrinter.activePrintJob: null
Label
{
text: catalog.i18nc("@label", "Printer type:")
visible: base.currentItem && "definition_name" in base.currentItem.metadata
}
Label
{
text: (base.currentItem && "definition_name" in base.currentItem.metadata) ? base.currentItem.metadata.definition_name : ""
}
Label
{
text: catalog.i18nc("@label", "Connection:")
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId
}
Label
{
width: (parent.width * 0.7) | 0
text: machineInfo.printerConnected ? machineInfo.connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.")
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId
wrapMode: Text.WordWrap
}
Label
{
text: catalog.i18nc("@label", "State:")
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId && machineInfo.printerAcceptsCommands
}
Label {
width: (parent.width * 0.7) | 0
text:
{
if(!machineInfo.printerConnected || !machineInfo.printerAcceptsCommands) {
return "";
}
if (machineInfo.printJob == null)
{
return catalog.i18nc("@label:MonitorStatus", "Waiting for a printjob");
}
switch(machineInfo.printJob.state)
{
case "printing":
return catalog.i18nc("@label:MonitorStatus", "Printing...");
case "paused":
return catalog.i18nc("@label:MonitorStatus", "Paused");
case "pre_print":
return catalog.i18nc("@label:MonitorStatus", "Preparing...");
case "wait_cleanup":
return catalog.i18nc("@label:MonitorStatus", "Waiting for someone to clear the build plate");
case "error":
return printerOutputDevice.errorText;
case "maintenance":
return catalog.i18nc("@label:MonitorStatus", "In maintenance. Please check the printer");
case "abort": // note sure if this jobState actually occurs in the wild
return catalog.i18nc("@label:MonitorStatus", "Aborting print...");
}
return ""
}
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId && machineInfo.printerAcceptsCommands
wrapMode: Text.WordWrap
}
}
Column {
id: additionalComponentsColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: machineInfo.visible ? machineInfo.bottom : machineInfo.anchors.top
anchors.topMargin: UM.Theme.getSize("default_margin").width
spacing: UM.Theme.getSize("default_margin").width
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId
Component.onCompleted:
{
for (var component in CuraApplication.additionalComponents["machinesDetailPane"]) {
CuraApplication.additionalComponents["machinesDetailPane"][component].parent = additionalComponentsColumn
}
}
}
Component.onCompleted: {
addAdditionalComponents("machinesDetailPane")
}
Connections {
target: CuraApplication
onAdditionalComponentsChanged: addAdditionalComponents
}
function addAdditionalComponents (areaId) {
if(areaId == "machinesDetailPane") {
for (var component in CuraApplication.additionalComponents["machinesDetailPane"]) {
CuraApplication.additionalComponents["machinesDetailPane"][component].parent = additionalComponentsColumn
}
}
}
UM.I18nCatalog { id: catalog; name: "cura"; } UM.I18nCatalog { id: catalog; name: "cura"; }
UM.ConfirmRemoveDialog UM.ConfirmRemoveDialog
{ {
id: confirmDialog; id: confirmDialog
object: base.currentItem && base.currentItem.name ? base.currentItem.name : ""; object: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
onYes: onYes:
{ {
Cura.MachineManager.removeMachine(base.currentItem.id); Cura.MachineManager.removeMachine(base.currentItem.id)
if(!base.currentItem) if(!base.currentItem)
{ {
objectList.currentIndex = activeMachineIndex() objectList.currentIndex = activeMachineIndex()

View file

@ -10,7 +10,7 @@ import QtQuick.Dialogs 1.2
import UM 1.2 as UM import UM 1.2 as UM
import Cura 1.0 as Cura import Cura 1.0 as Cura
Rectangle Item
{ {
id: brand_section id: brand_section

View file

@ -65,7 +65,7 @@ Item
Label { Label {
text: materialProperties.name text: materialProperties.name
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
} }
} }

View file

@ -10,7 +10,7 @@ import QtQuick.Dialogs 1.2
import UM 1.2 as UM import UM 1.2 as UM
import Cura 1.0 as Cura import Cura 1.0 as Cura
Rectangle Item
{ {
id: material_type_section id: material_type_section
property var materialType property var materialType

View file

@ -376,6 +376,7 @@ Item
width: true ? (parent.width * 0.4) | 0 : parent.width width: true ? (parent.width * 0.4) | 0 : parent.width
frameVisible: true frameVisible: true
clip: true
ListView ListView
{ {
@ -408,7 +409,7 @@ Item
{ {
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_lining").width anchors.leftMargin: UM.Theme.getSize("default_lining").width
text: section == "true" ? catalog.i18nc("@label", "Protected profiles") : catalog.i18nc("@label", "Custom profiles") text: section == "true" ? catalog.i18nc("@label", "Default profiles") : catalog.i18nc("@label", "Custom profiles")
font.bold: true font.bold: true
} }
} }
@ -471,7 +472,7 @@ Item
Label { Label {
text: base.currentItemName text: base.currentItemName
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
} }
} }

View file

@ -11,7 +11,6 @@ import Cura 1.0 as Cura
Item Item
{ {
id: customPrintSetup id: customPrintSetup
height: childrenRect.height + padding
property real padding: UM.Theme.getSize("default_margin").width property real padding: UM.Theme.getSize("default_margin").width
property bool multipleExtruders: extrudersModel.count > 1 property bool multipleExtruders: extrudersModel.count > 1
@ -98,15 +97,15 @@ Item
Rectangle Rectangle
{ {
height: UM.Theme.getSize("print_setup_widget").height
anchors anchors
{ {
top: tabBar.visible ? tabBar.bottom : globalProfileRow.bottom top: tabBar.visible ? tabBar.bottom : globalProfileRow.bottom
topMargin: -UM.Theme.getSize("default_lining").width
left: parent.left left: parent.left
leftMargin: parent.padding leftMargin: parent.padding
right: parent.right right: parent.right
rightMargin: parent.padding rightMargin: parent.padding
topMargin: -UM.Theme.getSize("default_lining").width bottom: parent.bottom
} }
z: tabBar.z - 1 z: tabBar.z - 1
// Don't show the border when only one extruder // Don't show the border when only one extruder

View file

@ -25,7 +25,7 @@ Item
right: globalProfileSelection.left right: globalProfileSelection.left
} }
text: catalog.i18nc("@label", "Profile") text: catalog.i18nc("@label", "Profile")
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }

View file

@ -29,4 +29,7 @@ Cura.ExpandableComponent
property var extrudersModel: CuraApplication.getExtrudersModel() property var extrudersModel: CuraApplication.getExtrudersModel()
contentItem: PrintSetupSelectorContents {} contentItem: PrintSetupSelectorContents {}
onExpandedChanged: UM.Preferences.setValue("view/settings_visible", expanded)
Component.onCompleted: expanded = UM.Preferences.getValue("view/settings_visible")
} }

View file

@ -15,7 +15,7 @@ Item
id: content id: content
width: UM.Theme.getSize("print_setup_widget").width - 2 * UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("print_setup_widget").width - 2 * UM.Theme.getSize("default_margin").width
height: childrenRect.height height: contents.height + buttonRow.height
enum Mode enum Mode
{ {
@ -71,6 +71,15 @@ Item
right: parent.right right: parent.right
top: parent.top top: parent.top
} }
height: UM.Preferences.getValue("view/settings_list_height") - UM.Theme.getSize("default_margin").height
Connections
{
target: UM.Preferences
onPreferenceChanged:
{
customPrintSetup.height = UM.Preferences.getValue("view/settings_list_height");
}
}
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom
} }
} }
@ -94,13 +103,14 @@ Item
anchors anchors
{ {
top: buttonsSeparator.bottom bottom: parent.bottom
left: parent.left left: parent.left
right: parent.right right: parent.right
} }
Cura.SecondaryButton Cura.SecondaryButton
{ {
id: recommendedButton
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.margins: parent.padding anchors.margins: parent.padding
@ -125,5 +135,58 @@ Item
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended
onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Custom onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Custom
} }
//Invisible area at the bottom with which you can resize the panel.
MouseArea
{
anchors
{
left: parent.left
right: parent.right
bottom: parent.bottom
top: recommendedButton.bottom
topMargin: UM.Theme.getSize("default_lining").height
}
cursorShape: Qt.SplitVCursor
visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom
drag
{
target: parent
axis: Drag.YAxis
}
onMouseYChanged:
{
if(drag.active)
{
// position of mouse relative to dropdown align vertical centre of mouse area to cursor
// v------------------------------v v------------v
var h = mouseY + buttonRow.y + content.y - height / 2 | 0;
if(h < 200 * screenScaleFactor) //Enforce a minimum size.
{
h = 200 * screenScaleFactor;
}
//Absolute mouse Y position in the window, to prevent it from going outside the window.
var mouse_absolute_y = mapToGlobal(mouseX, mouseY).y - UM.Preferences.getValue("general/window_top");
if(mouse_absolute_y > base.height)
{
h -= mouse_absolute_y - base.height;
}
UM.Preferences.setValue("view/settings_list_height", h);
}
}
UM.RecolorImage
{
width: parent.width * 0.05
height: parent.height * 0.3
anchors.centerIn: parent
source: UM.Theme.getIcon("grip_lines")
color: UM.Theme.getColor("lining")
}
}
} }
} }

View file

@ -29,6 +29,7 @@ RowLayout
} }
return "" return ""
} }
font: UM.Theme.getFont("medium")
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {
@ -43,6 +44,7 @@ RowLayout
{ {
source: UM.Theme.getIcon("category_infill") source: UM.Theme.getIcon("category_infill")
text: Cura.MachineManager.activeStack ? parseInt(infillDensity.properties.value) + "%" : "0%" text: Cura.MachineManager.activeStack ? parseInt(infillDensity.properties.value) + "%" : "0%"
font: UM.Theme.getFont("medium")
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {
@ -57,6 +59,7 @@ RowLayout
{ {
source: UM.Theme.getIcon("category_support") source: UM.Theme.getIcon("category_support")
text: supportEnabled.properties.value == "True" ? enabledText : disabledText text: supportEnabled.properties.value == "True" ? enabledText : disabledText
font: UM.Theme.getFont("medium")
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {
@ -71,6 +74,7 @@ RowLayout
{ {
source: UM.Theme.getIcon("category_adhesion") source: UM.Theme.getIcon("category_adhesion")
text: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" ? enabledText : disabledText text: platformAdhesionType.properties.value != "skirt" && platformAdhesionType.properties.value != "none" ? enabledText : disabledText
font: UM.Theme.getFont("medium")
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {

View file

@ -26,6 +26,7 @@ Item
anchors.left: parent.left anchors.left: parent.left
source: UM.Theme.getIcon("category_adhesion") source: UM.Theme.getIcon("category_adhesion")
text: catalog.i18nc("@label", "Adhesion") text: catalog.i18nc("@label", "Adhesion")
font: UM.Theme.getFont("medium")
width: labelColumnWidth width: labelColumnWidth
} }

View file

@ -63,6 +63,7 @@ Item
anchors.left: parent.left anchors.left: parent.left
source: UM.Theme.getIcon("category_infill") source: UM.Theme.getIcon("category_infill")
text: catalog.i18nc("@label", "Infill") + " (%)" text: catalog.i18nc("@label", "Infill") + " (%)"
font: UM.Theme.getFont("medium")
width: labelColumnWidth width: labelColumnWidth
} }
@ -140,6 +141,7 @@ Item
Label Label
{ {
text: index text: index
font: UM.Theme.getFont("default")
visible: (index % 20) == 0 // Only show steps of 20% visible: (index % 20) == 0 // Only show steps of 20%
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
y: UM.Theme.getSize("thin_margin").height y: UM.Theme.getSize("thin_margin").height

View file

@ -173,6 +173,7 @@ Item
id: qualityRowTitle id: qualityRowTitle
source: UM.Theme.getIcon("category_layer_height") source: UM.Theme.getIcon("category_layer_height")
text: catalog.i18nc("@label", "Layer Height") text: catalog.i18nc("@label", "Layer Height")
font: UM.Theme.getFont("medium")
anchors.left: parent.left anchors.left: parent.left
anchors.right: customisedSettings.left anchors.right: customisedSettings.left
} }
@ -271,6 +272,7 @@ Item
return Math.round((settingsColumnWidth / qualityModel.totalTicks) * index - (width / 2)) return Math.round((settingsColumnWidth / qualityModel.totalTicks) * index - (width / 2))
} }
} }
font: UM.Theme.getFont("default")
} }
} }
} }

View file

@ -27,6 +27,7 @@ Item
visible: enableSupportCheckBox.visible visible: enableSupportCheckBox.visible
source: UM.Theme.getIcon("category_support") source: UM.Theme.getIcon("category_support")
text: catalog.i18nc("@label", "Support") text: catalog.i18nc("@label", "Support")
font: UM.Theme.getFont("medium")
width: labelColumnWidth width: labelColumnWidth
} }

View file

@ -41,7 +41,8 @@ UM.PointingRectangle {
base.opacity = 0; base.opacity = 0;
} }
Label { Label
{
id: label; id: label;
anchors { anchors {
top: parent.top; top: parent.top;

View file

@ -80,7 +80,7 @@ Item
id: extruderCurrentTemperature id: extruderCurrentTemperature
text: Math.round(extruderModel.hotendTemperature) + "°C" text: Math.round(extruderModel.hotendTemperature) + "°C"
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
anchors.right: extruderTargetTemperature.left anchors.right: extruderTargetTemperature.left
anchors.top: parent.top anchors.top: parent.top
anchors.margins: UM.Theme.getSize("default_margin").width anchors.margins: UM.Theme.getSize("default_margin").width

View file

@ -67,7 +67,7 @@ Item
{ {
id: bedCurrentTemperature id: bedCurrentTemperature
text: printerModel != null ? printerModel.bedTemperature + "°C" : "" text: printerModel != null ? printerModel.bedTemperature + "°C" : ""
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
anchors.right: bedTargetTemperature.left anchors.right: bedTargetTemperature.left
anchors.top: parent.top anchors.top: parent.top

View file

@ -31,7 +31,7 @@ Item
Label Label
{ {
id: outputDeviceNameLabel id: outputDeviceNameLabel
font: UM.Theme.getFont("large") font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top

View file

@ -101,14 +101,16 @@ Cura.ExpandablePopup
width: scroll.width - scroll.leftPadding - scroll.rightPadding width: scroll.width - scroll.leftPadding - scroll.rightPadding
property real maximumHeight: UM.Theme.getSize("machine_selector_widget_content").height - buttonRow.height property real maximumHeight: UM.Theme.getSize("machine_selector_widget_content").height - buttonRow.height
onHeightChanged: // We use an extra property here, since we only want to to be informed about the content size changes.
onContentHeightChanged:
{ {
scroll.height = Math.min(height, maximumHeight) scroll.height = Math.min(contentHeight, maximumHeight)
popup.height = scroll.height + buttonRow.height popup.height = scroll.height + buttonRow.height
} }
Component.onCompleted: Component.onCompleted:
{ {
scroll.height = Math.min(height, maximumHeight) scroll.height = Math.min(contentHeight, maximumHeight)
popup.height = scroll.height + buttonRow.height popup.height = scroll.height + buttonRow.height
} }

View file

@ -10,15 +10,15 @@ import Cura 1.0 as Cura
ListView ListView
{ {
id: listView id: listView
height: childrenRect.height model: Cura.GlobalStacksModel {}
model: Cura.PrintersModel {}
section.property: "hasRemoteConnection" section.property: "hasRemoteConnection"
property real contentHeight: childrenRect.height
section.delegate: Label section.delegate: Label
{ {
text: section == "true" ? catalog.i18nc("@label", "Connected printers") : catalog.i18nc("@label", "Preset printers") text: section == "true" ? catalog.i18nc("@label", "Connected printers") : catalog.i18nc("@label", "Preset printers")
width: parent.width width: parent.width
height: visible ? contentHeight + 2 * UM.Theme.getSize("default_margin").height : 0 height: UM.Theme.getSize("action_button").height
leftPadding: UM.Theme.getSize("default_margin").width leftPadding: UM.Theme.getSize("default_margin").width
renderType: Text.NativeRendering renderType: Text.NativeRendering
font: UM.Theme.getFont("medium") font: UM.Theme.getFont("medium")

View file

@ -73,7 +73,7 @@ Button
text: definition.label text: definition.label
textFormat: Text.PlainText textFormat: Text.PlainText
renderType: Text.NativeRendering renderType: Text.NativeRendering
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium_bold")
color: color:
{ {
if (!base.enabled) if (!base.enabled)

View file

@ -25,7 +25,7 @@ ToolTip
text: "" text: ""
delay: 500 delay: 500
font: UM.Theme.getFont("default") font: UM.Theme.getFont("default")
// If the text is not set, just set the height to 0 to prevent it from showing // If the text is not set, just set the height to 0 to prevent it from showing
height: text != "" ? label.contentHeight + 2 * UM.Theme.getSize("thin_margin").width: 0 height: text != "" ? label.contentHeight + 2 * UM.Theme.getSize("thin_margin").width: 0

View file

@ -51,7 +51,7 @@ Cura.ExpandablePopup
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
height: parent.height height: parent.height
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text_medium") color: UM.Theme.getColor("text_medium")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@ -68,7 +68,7 @@ Cura.ExpandablePopup
} }
height: parent.height height: parent.height
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("default") font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 6">
<rect width="30" height="2" rx="1" ry="1" />
<rect width="30" height="2" rx="1" ry="1" y="4" />
</svg>

After

Width:  |  Height:  |  Size: 170 B

View file

@ -207,8 +207,8 @@ QtObject
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: control.text; text: control.text
font: Theme.getFont("button_tooltip") font: Theme.getFont("default")
color: Theme.getColor("tooltip_text") color: Theme.getColor("tooltip_text")
} }
} }
@ -256,7 +256,7 @@ QtObject
source: control.iconSource source: control.iconSource
width: Theme.getSize("button_icon").width width: Theme.getSize("button_icon").width
height: Theme.getSize("button_icon").height height: Theme.getSize("button_icon").height
color: Theme.getColor("toolbar_button_text") color: Theme.getColor("icon")
sourceSize: Theme.getSize("button_icon") sourceSize: Theme.getSize("button_icon")
} }
@ -585,6 +585,7 @@ QtObject
text: control.unit ? control.unit : "" text: control.unit ? control.unit : ""
color: Theme.getColor("setting_unit"); color: Theme.getColor("setting_unit");
font: Theme.getFont("default"); font: Theme.getFont("default");
renderType: Text.NativeRendering
} }
} }
} }

View file

@ -6,17 +6,17 @@
"fonts": { "fonts": {
"large": { "large": {
"size": 1.35, "size": 1.35,
"weight": 63, "weight": 40,
"family": "Noto Sans" "family": "Noto Sans"
}, },
"large_nonbold": { "large_bold": {
"size": 1.35, "size": 1.35,
"weight": 50, "weight": 63,
"family": "Noto Sans" "family": "Noto Sans"
}, },
"medium": { "medium": {
"size": 1.16, "size": 1.16,
"weight": 50, "weight": 40,
"family": "Noto Sans" "family": "Noto Sans"
}, },
"medium_bold": { "medium_bold": {
@ -25,29 +25,24 @@
"family": "Noto Sans" "family": "Noto Sans"
}, },
"default": { "default": {
"size": 1.0, "size": 0.95,
"weight": 50, "weight": 40,
"family": "Noto Sans" "family": "Noto Sans"
}, },
"default_bold": { "default_bold": {
"size": 1.0, "size": 0.95,
"weight": 63, "weight": 63,
"family": "Noto Sans" "family": "Noto Sans"
}, },
"default_italic": { "default_italic": {
"size": 1.0, "size": 0.95,
"weight": 50, "weight": 40,
"italic": true, "italic": true,
"family": "Noto Sans" "family": "Noto Sans"
}, },
"small": { "small": {
"size": 0.85,
"weight": 50,
"family": "Noto Sans"
},
"very_small": {
"size": 0.7, "size": 0.7,
"weight": 50, "weight": 40,
"family": "Noto Sans" "family": "Noto Sans"
} }
}, },
@ -118,7 +113,6 @@
"warning": [245, 166, 35, 255], "warning": [245, 166, 35, 255],
"disabled": [229, 229, 229, 255], "disabled": [229, 229, 229, 255],
"toolbar_button_text": [8, 7, 63, 255],
"toolbar_button_hover": [232, 242, 252, 255], "toolbar_button_hover": [232, 242, 252, 255],
"toolbar_button_active": [232, 242, 252, 255], "toolbar_button_active": [232, 242, 252, 255],
"toolbar_button_active_hover": [232, 242, 252, 255], "toolbar_button_active_hover": [232, 242, 252, 255],
@ -303,7 +297,7 @@
"printer_config_mismatch": [127, 127, 127, 255], "printer_config_mismatch": [127, 127, 127, 255],
"toolbox_header_button_text_active": [0, 0, 0, 255], "toolbox_header_button_text_active": [0, 0, 0, 255],
"toolbox_header_button_text_inactive": [128, 128, 128, 255], "toolbox_header_button_text_inactive": [0, 0, 0, 255],
"toolbox_header_button_text_hovered": [0, 0, 0, 255], "toolbox_header_button_text_hovered": [0, 0, 0, 255],
"favorites_header_bar": [245, 245, 245, 255], "favorites_header_bar": [245, 245, 245, 255],
@ -492,7 +486,7 @@
"toolbox_detail_header": [1.0, 14.0], "toolbox_detail_header": [1.0, 14.0],
"toolbox_detail_tile": [1.0, 8.0], "toolbox_detail_tile": [1.0, 8.0],
"toolbox_back_column": [6.0, 1.0], "toolbox_back_column": [6.0, 1.0],
"toolbox_back_button": [4.0, 2.0], "toolbox_back_button": [6.0, 2.0],
"toolbox_installed_tile": [1.0, 8.0], "toolbox_installed_tile": [1.0, 8.0],
"toolbox_property_label": [1.0, 2.0], "toolbox_property_label": [1.0, 2.0],
"toolbox_heading_label": [1.0, 3.8], "toolbox_heading_label": [1.0, 3.8],