Merge pull request #13774 from Ultimaker/CURA-9424_update_loading_projects_design

Cura 9424 update loading projects design
This commit is contained in:
Casper Lamboo 2022-11-15 15:38:15 +01:00 committed by GitHub
commit 63b27d3ca8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 572 additions and 485 deletions

View file

@ -5,7 +5,7 @@
# online cloud connected printers are represented within this ListModel. Additional information such as the number of
# connected printers for each printer type is gathered.
from typing import Optional
from typing import Optional, List, cast
from PyQt6.QtCore import Qt, QTimer, QObject, pyqtSlot, pyqtProperty, pyqtSignal
@ -14,7 +14,6 @@ from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.Interfaces import ContainerInterface
from UM.i18n import i18nCatalog
from UM.Util import parseBool
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.GlobalStack import GlobalStack
@ -29,11 +28,13 @@ class MachineListModel(ListModel):
MachineCountRole = Qt.ItemDataRole.UserRole + 6
IsAbstractMachineRole = Qt.ItemDataRole.UserRole + 7
ComponentTypeRole = Qt.ItemDataRole.UserRole + 8
IsNetworkedMachineRole = Qt.ItemDataRole.UserRole + 9
def __init__(self, parent: Optional[QObject] = None) -> None:
def __init__(self, parent: Optional[QObject] = None, machines_filter: List[GlobalStack] = None, listenToChanges: bool = True) -> None:
super().__init__(parent)
self._show_cloud_printers = False
self._machines_filter = machines_filter
self._catalog = i18nCatalog("cura")
@ -45,17 +46,18 @@ class MachineListModel(ListModel):
self.addRoleName(self.MachineCountRole, "machineCount")
self.addRoleName(self.IsAbstractMachineRole, "isAbstractMachine")
self.addRoleName(self.ComponentTypeRole, "componentType")
self.addRoleName(self.IsNetworkedMachineRole, "isNetworked")
self._change_timer = QTimer()
self._change_timer.setInterval(200)
self._change_timer.setSingleShot(True)
self._change_timer.timeout.connect(self._update)
# Listen to changes
CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
self._updateDelayed()
if listenToChanges:
CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
self._updateDelayed()
showCloudPrintersChanged = pyqtSignal(bool)
@ -79,17 +81,33 @@ class MachineListModel(ListModel):
def _updateDelayed(self) -> None:
self._change_timer.start()
def _getMachineStacks(self) -> List[ContainerStack]:
return CuraContainerRegistry.getInstance().findContainerStacks(type = "machine")
def _getAbstractMachineStacks(self) -> List[ContainerStack]:
return CuraContainerRegistry.getInstance().findContainerStacks(is_abstract_machine = "True")
def set_machines_filter(self, machines_filter: Optional[List[GlobalStack]]) -> None:
self._machines_filter = machines_filter
self._update()
def _update(self) -> None:
self.clear()
from cura.CuraApplication import CuraApplication
machines_manager = CuraApplication.getInstance().getMachineManager()
other_machine_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type="machine")
other_machine_stacks = self._getMachineStacks()
other_machine_stacks.sort(key = lambda machine: machine.getName().upper())
abstract_machine_stacks = CuraContainerRegistry.getInstance().findContainerStacks(is_abstract_machine = "True")
abstract_machine_stacks = self._getAbstractMachineStacks()
abstract_machine_stacks.sort(key = lambda machine: machine.getName().upper(), reverse = True)
if self._machines_filter is not None:
filter_ids = [machine_filter.id for machine_filter in self._machines_filter]
other_machine_stacks = [machine for machine in other_machine_stacks if machine.id in filter_ids]
abstract_machine_stacks = [machine for machine in abstract_machine_stacks if machine.id in filter_ids]
for abstract_machine in abstract_machine_stacks:
definition_id = abstract_machine.definition.getId()
online_machine_stacks = machines_manager.getMachinesWithDefinition(definition_id, online_only = True)
@ -113,18 +131,13 @@ class MachineListModel(ListModel):
other_machine_stacks.remove(stack)
if len(abstract_machine_stacks) > 0:
if self._show_cloud_printers:
self.appendItem({"componentType": "HIDE_BUTTON",
"isOnline": True,
"isAbstractMachine": False,
"machineCount": 0
})
else:
self.appendItem({"componentType": "SHOW_BUTTON",
"isOnline": True,
"isAbstractMachine": False,
"machineCount": 0
})
self.appendItem({
"componentType": "HIDE_BUTTON" if self._show_cloud_printers else "SHOW_BUTTON",
"isOnline": True,
"isAbstractMachine": False,
"machineCount": 0,
"catergory": "connected",
})
for stack in other_machine_stacks:
self.addItem(stack, False)
@ -134,11 +147,13 @@ class MachineListModel(ListModel):
return
self.appendItem({
"componentType": "MACHINE",
"name": container_stack.getName(),
"id": container_stack.getId(),
"metadata": container_stack.getMetaData().copy(),
"isOnline": is_online,
"isAbstractMachine": parseBool(container_stack.getMetaDataEntry("is_abstract_machine", False)),
"machineCount": machine_count,
})
"componentType": "MACHINE",
"name": container_stack.getName(),
"id": container_stack.getId(),
"metadata": container_stack.getMetaData().copy(),
"isOnline": is_online,
"isAbstractMachine": parseBool(container_stack.getMetaDataEntry("is_abstract_machine", False)),
"isNetworked": cast(GlobalStack, container_stack).hasNetworkedConnection() if isinstance(container_stack, GlobalStack) else False,
"machineCount": machine_count,
"catergory": "connected" if is_online else "other",
})

View file

@ -9,6 +9,7 @@ from typing import cast, Dict, List, Optional, Tuple, Any, Set
import xml.etree.ElementTree as ET
from UM.Util import parseBool
from UM.Workspace.WorkspaceReader import WorkspaceReader
from UM.Application import Application
@ -600,6 +601,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._dialog.setActiveMode(active_mode)
self._dialog.setUpdatableMachines(updatable_machines)
self._dialog.setMachineName(machine_name)
self._dialog.setIsNetworkedMachine(existing_global_stack.hasNetworkedConnection())
self._dialog.setIsAbstractMachine(parseBool(existing_global_stack.getMetaDataEntry("is_abstract_machine", False)))
self._dialog.setMachineToOverride(global_stack_id)
self._dialog.setMaterialLabels(material_labels)
self._dialog.setMachineType(machine_type)
self._dialog.setExtruders(extruders)

View file

@ -1,43 +0,0 @@
# Copyright (c) 2020 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Dict, List
from PyQt6.QtCore import Qt
from UM.Qt.ListModel import ListModel
from cura.Settings.GlobalStack import GlobalStack
create_new_list_item = {
"id": "new",
"name": "Create new",
"displayName": "Create new",
"type": "default_option" # to make sure we are not mixing the "Create new" option with a printer with id "new"
} # type: Dict[str, str]
class UpdatableMachinesModel(ListModel):
"""Model that holds cura packages.
By setting the filter property the instances held by this model can be changed.
"""
def __init__(self, parent = None) -> None:
super().__init__(parent)
self.addRoleName(Qt.ItemDataRole.UserRole + 1, "id")
self.addRoleName(Qt.ItemDataRole.UserRole + 2, "name")
self.addRoleName(Qt.ItemDataRole.UserRole + 3, "displayName")
self.addRoleName(Qt.ItemDataRole.UserRole + 4, "type") # Either "default_option" or "machine"
def update(self, machines: List[GlobalStack]) -> None:
items = [create_new_list_item] # type: List[Dict[str, str]]
for machine in sorted(machines, key = lambda printer: printer.name):
items.append({
"id": machine.id,
"name": machine.name,
"displayName": "Update " + machine.name,
"type": "machine"
})
self.setItems(items)

View file

@ -5,6 +5,7 @@ from PyQt6.QtCore import pyqtSignal, QObject, pyqtProperty, QCoreApplication, QU
from PyQt6.QtGui import QDesktopServices
from typing import List, Optional, Dict, cast
from cura.Machines.Models.MachineListModel import MachineListModel
from cura.Settings.GlobalStack import GlobalStack
from UM.Application import Application
from UM.FlameProfiler import pyqtSlot
@ -14,8 +15,6 @@ from UM.Message import Message
from UM.PluginRegistry import PluginRegistry
from UM.Settings.ContainerRegistry import ContainerRegistry
from .UpdatableMachinesModel import UpdatableMachinesModel
import os
import threading
import time
@ -63,10 +62,12 @@ class WorkspaceDialog(QObject):
self._extruders = []
self._objects_on_plate = False
self._is_printer_group = False
self._updatable_machines_model = UpdatableMachinesModel(self)
self._updatable_machines_model = MachineListModel(self, listenToChanges=False)
self._missing_package_metadata: List[Dict[str, str]] = []
self._plugin_registry: PluginRegistry = CuraApplication.getInstance().getPluginRegistry()
self._install_missing_package_dialog: Optional[QObject] = None
self._is_abstract_machine = False
self._is_networked_machine = False
machineConflictChanged = pyqtSignal()
qualityChangesConflictChanged = pyqtSignal()
@ -80,6 +81,8 @@ class WorkspaceDialog(QObject):
intentNameChanged = pyqtSignal()
machineNameChanged = pyqtSignal()
updatableMachinesChanged = pyqtSignal()
isAbstractMachineChanged = pyqtSignal()
isNetworkedChanged = pyqtSignal()
materialLabelsChanged = pyqtSignal()
objectsOnPlateChanged = pyqtSignal()
numUserSettingsChanged = pyqtSignal()
@ -161,13 +164,31 @@ class WorkspaceDialog(QObject):
self.machineNameChanged.emit()
@pyqtProperty(QObject, notify = updatableMachinesChanged)
def updatableMachinesModel(self) -> UpdatableMachinesModel:
return cast(UpdatableMachinesModel, self._updatable_machines_model)
def updatableMachinesModel(self) -> MachineListModel:
return cast(MachineListModel, self._updatable_machines_model)
def setUpdatableMachines(self, updatable_machines: List[GlobalStack]) -> None:
self._updatable_machines_model.update(updatable_machines)
self._updatable_machines_model.set_machines_filter(updatable_machines)
self.updatableMachinesChanged.emit()
@pyqtProperty(bool, notify = isAbstractMachineChanged)
def isAbstractMachine(self) -> bool:
return self._is_abstract_machine
@pyqtSlot(bool)
def setIsAbstractMachine(self, is_abstract_machine: bool) -> None:
self._is_abstract_machine = is_abstract_machine
self.isAbstractMachineChanged.emit()
@pyqtProperty(bool, notify = isNetworkedChanged)
def isNetworked(self) -> bool:
return self._is_networked_machine
@pyqtSlot(bool)
def setIsNetworkedMachine(self, is_networked_machine: bool) -> None:
self._is_networked_machine = is_networked_machine
self.isNetworkedChanged.emit()
@pyqtProperty(str, notify=qualityTypeChanged)
def qualityType(self) -> str:
return self._quality_type

View file

@ -1,4 +1,4 @@
// Copyright (c) 2020 Ultimaker B.V.
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
@ -11,47 +11,48 @@ import Cura 1.1 as Cura
UM.Dialog
{
id: base
id: workspaceDialog
title: catalog.i18nc("@title:window", "Open Project")
minimumWidth: UM.Theme.getSize("popup_dialog").width
minimumHeight: UM.Theme.getSize("popup_dialog").height
width: minimumWidth
backgroundColor: UM.Theme.getColor("main_background")
margin: UM.Theme.getSize("default_margin").width
property int comboboxHeight: UM.Theme.getSize("default_margin").height
minimumWidth: UM.Theme.getSize("modal_window_minimum").width
minimumHeight: UM.Theme.getSize("modal_window_minimum").height
onClosing: manager.notifyClosed()
onVisibleChanged:
backgroundColor: UM.Theme.getColor("detail_background")
headerComponent: Rectangle
{
if (visible)
height: childrenRect.height + 2 * UM.Theme.getSize("default_margin").height
color: UM.Theme.getColor("main_background")
UM.Label
{
machineResolveComboBox.currentIndex = 0
qualityChangesResolveComboBox.currentIndex = 0
materialResolveComboBox.currentIndex = 0
id: titleLabel
text: catalog.i18nc("@action:title", "Summary - Cura Project")
font: UM.Theme.getFont("large")
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.leftMargin: UM.Theme.getSize("default_margin").height
}
}
Flickable
Rectangle
{
clip: true
width: parent.width
height: parent.height
contentHeight: dialogSummaryItem.height
ScrollBar.vertical: UM.ScrollBar { id: verticalScrollBar }
anchors.fill: parent
UM.I18nCatalog { id: catalog; name: "cura" }
color: UM.Theme.getColor("main_background")
Item
Flickable
{
id: dialogSummaryItem
width: verticalScrollBar.visible ? parent.width - verticalScrollBar.width - UM.Theme.getSize("default_margin").width : parent.width
height: childrenRect.height
anchors.margins: 10 * screenScaleFactor
width: parent.width
height: parent.height
UM.I18nCatalog
{
id: catalog
name: "cura"
}
clip: true
contentHeight: contentColumn.height
ScrollBar.vertical: UM.ScrollBar { id: scrollbar }
ListModel
{
@ -68,373 +69,224 @@ UM.Dialog
Column
{
width: parent.width
id: contentColumn
width: parent.width - scrollbar.width - UM.Theme.getSize("default_margin").width
height: childrenRect.height
spacing: UM.Theme.getSize("default_margin").height
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
Column
WorkspaceSection
{
width: parent.width
height: childrenRect.height
UM.Label
id: printerSection
title: catalog.i18nc("@action:label", "Printer settings")
iconSource: UM.Theme.getIcon("Printer")
content: Column
{
id: titleLabel
text: catalog.i18nc("@action:title", "Summary - Cura Project")
font: UM.Theme.getFont("large")
}
spacing: UM.Theme.getSize("default_margin").height
leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
Rectangle
{
id: separator
color: UM.Theme.getColor("text")
width: parent.width
height: UM.Theme.getSize("default_lining").height
}
}
Item
{
width: parent.width
height: childrenRect.height
UM.TooltipArea
{
id: machineResolveStrategyTooltip
anchors.top: parent.top
anchors.right: parent.right
width: (parent.width / 3) | 0
height: visible ? comboboxHeight : 0
visible: base.visible && machineResolveComboBox.model.count > 1
text: catalog.i18nc("@info:tooltip", "How should the conflict in the machine be resolved?")
Cura.ComboBox
WorkspaceRow
{
id: machineResolveComboBox
model: manager.updatableMachinesModel
visible: machineResolveStrategyTooltip.visible
textRole: "displayName"
width: parent.width
height: UM.Theme.getSize("button").height
onCurrentIndexChanged:
leftLabelText: catalog.i18nc("@action:label", "Type")
rightLabelText: manager.machineType
}
WorkspaceRow
{
leftLabelText: catalog.i18nc("@action:label", manager.isPrinterGroup ? "Printer Group" : "Printer Name")
rightLabelText: manager.machineName
}
}
comboboxTitle: catalog.i18nc("@action:label", "Open With")
comboboxTooltipText: catalog.i18nc("@info:tooltip", "Printer settings will be updated to match the settings saved with the project.")
comboboxVisible: workspaceDialog.visible && manager.updatableMachinesModel.count > 1
combobox: Cura.MachineSelector
{
id: machineSelector
headerCornerSide: Cura.RoundedRectangle.Direction.All
width: parent.width
height: parent.height
machineListModel: manager.updatableMachinesModel
machineName: manager.machineName
isConnectedCloudPrinter: false
isCloudRegistered: false
isNetworkPrinter: manager.isNetworked
isGroup: manager.isAbstractMachine
connectionStatus: ""
minDropDownWidth: machineSelector.width
buttons: [
Cura.SecondaryButton
{
if (model.getItem(currentIndex).id == "new"
&& model.getItem(currentIndex).type == "default_option")
id: createNewPrinter
text: catalog.i18nc("@button", "Create new")
fixedWidthMode: true
width: parent.width - leftPadding * 1.5
onClicked:
{
machineSelector.machineName = catalog.i18nc("@button", "Create new")
manager.setIsAbstractMachine(false)
manager.setIsNetworkedMachine(false)
toggleContent()
manager.setResolveStrategy("machine", "new")
}
else
{
manager.setResolveStrategy("machine", "override")
manager.setMachineToOverride(model.getItem(currentIndex).id)
}
}
]
onVisibleChanged:
{
if (!visible) {return}
currentIndex = 0
// If the project printer exists in Cura, set it as the default dropdown menu option.
// No need to check object 0, which is the "Create new" option
for (var i = 1; i < model.count; i++)
{
if (model.getItem(i).name == manager.machineName)
{
currentIndex = i
break
}
}
// The project printer does not exist in Cura. If there is at least one printer of the same
// type, select the first one, else set the index to "Create new"
if (currentIndex == 0 && model.count > 1)
{
currentIndex = 1
}
}
}
}
Column
{
width: parent.width
height: childrenRect.height
UM.Label
onSelectPrinter: function(machine)
{
id: printer_settings_label
text: catalog.i18nc("@action:label", "Printer settings")
font: UM.Theme.getFont("default_bold")
}
Row
{
width: parent.width
height: childrenRect.height
UM.Label
{
text: catalog.i18nc("@action:label", "Type")
width: (parent.width / 3) | 0
}
UM.Label
{
text: manager.machineType
width: (parent.width / 3) | 0
}
}
Row
{
width: parent.width
height: childrenRect.height
UM.Label
{
text: catalog.i18nc("@action:label", manager.isPrinterGroup ? "Printer Group" : "Printer Name")
width: (parent.width / 3) | 0
}
UM.Label
{
text: manager.machineName
width: (parent.width / 3) | 0
wrapMode: Text.WordWrap
}
toggleContent();
manager.setResolveStrategy("machine", "override")
manager.setMachineToOverride(machine.id)
manager.setIsAbstractMachine(machine.isAbstractMachine)
manager.setIsNetworkedMachine(machine.isNetworked)
machineSelector.machineName = machine.name
}
}
}
Item
WorkspaceSection
{
width: parent.width
height: childrenRect.height
UM.TooltipArea
id: profileSection
title: catalog.i18nc("@action:label", "Profile settings")
iconSource: UM.Theme.getIcon("Sliders")
content: Column
{
anchors.right: parent.right
anchors.top: parent.top
width: (parent.width / 3) | 0
height: visible ? comboboxHeight : 0
id: profileSettingsValuesTable
spacing: UM.Theme.getSize("default_margin").height
leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
WorkspaceRow
{
leftLabelText: catalog.i18nc("@action:label", "Name")
rightLabelText: manager.qualityName
}
WorkspaceRow
{
leftLabelText: catalog.i18nc("@action:label", "Intent")
rightLabelText: manager.intentName
}
WorkspaceRow
{
leftLabelText: catalog.i18nc("@action:label", "Not in profile")
rightLabelText: catalog.i18ncp("@action:label", "%1 override", "%1 overrides", manager.numUserSettings).arg(manager.numUserSettings)
visible: manager.numUserSettings != 0
}
WorkspaceRow
{
leftLabelText: catalog.i18nc("@action:label", "Derivative from")
rightLabelText: catalog.i18ncp("@action:label", "%1, %2 override", "%1, %2 overrides", manager.numSettingsOverridenByQualityChanges).arg(manager.qualityType).arg(manager.numSettingsOverridenByQualityChanges)
visible: manager.numSettingsOverridenByQualityChanges != 0
}
}
comboboxVisible: manager.qualityChangesConflict
combobox: Cura.ComboBox
{
id: qualityChangesResolveComboBox
model: resolveStrategiesModel
textRole: "label"
visible: manager.qualityChangesConflict
text: catalog.i18nc("@info:tooltip", "How should the conflict in the profile be resolved?")
Cura.ComboBox
{
model: resolveStrategiesModel
textRole: "label"
id: qualityChangesResolveComboBox
width: parent.width
height: UM.Theme.getSize("button").height
onActivated:
{
manager.setResolveStrategy("quality_changes", resolveStrategiesModel.get(index).key)
}
}
}
Column
{
width: parent.width
height: childrenRect.height
UM.Label
// This is a hack. This will trigger onCurrentIndexChanged and set the index when this component in loaded
currentIndex:
{
text: catalog.i18nc("@action:label", "Profile settings")
font: UM.Theme.getFont("default_bold")
currentIndex = 0
}
Row
onCurrentIndexChanged:
{
width: parent.width
height: childrenRect.height
UM.Label
{
text: catalog.i18nc("@action:label", "Name")
width: (parent.width / 3) | 0
}
UM.Label
{
text: manager.qualityName
width: (parent.width / 3) | 0
wrapMode: Text.WordWrap
}
}
Row
{
width: parent.width
height: childrenRect.height
UM.Label
{
text: catalog.i18nc("@action:label", "Intent")
width: (parent.width / 3) | 0
}
UM.Label
{
text: manager.intentName
width: (parent.width / 3) | 0
wrapMode: Text.WordWrap
}
}
Row
{
width: parent.width
height: childrenRect.height
UM.Label
{
text: catalog.i18nc("@action:label", "Not in profile")
visible: manager.numUserSettings != 0
width: (parent.width / 3) | 0
}
UM.Label
{
text: catalog.i18ncp("@action:label", "%1 override", "%1 overrides", manager.numUserSettings).arg(manager.numUserSettings)
visible: manager.numUserSettings != 0
width: (parent.width / 3) | 0
}
}
Row
{
width: parent.width
height: childrenRect.height
UM.Label
{
text: catalog.i18nc("@action:label", "Derivative from")
visible: manager.numSettingsOverridenByQualityChanges != 0
width: (parent.width / 3) | 0
}
UM.Label
{
text: catalog.i18ncp("@action:label", "%1, %2 override", "%1, %2 overrides", manager.numSettingsOverridenByQualityChanges).arg(manager.qualityType).arg(manager.numSettingsOverridenByQualityChanges)
width: (parent.width / 3) | 0
visible: manager.numSettingsOverridenByQualityChanges != 0
wrapMode: Text.WordWrap
}
manager.setResolveStrategy("quality_changes", resolveStrategiesModel.get(currentIndex).key)
}
}
}
Item
WorkspaceSection
{
width: parent.width
height: childrenRect.height
UM.TooltipArea
id: materialSection
title: catalog.i18nc("@action:label", "Material settings")
iconSource: UM.Theme.getIcon("Spool")
content: Column
{
id: materialResolveTooltip
anchors.right: parent.right
anchors.top: parent.top
width: (parent.width / 3) | 0
height: visible ? comboboxHeight : 0
visible: manager.materialConflict
text: catalog.i18nc("@info:tooltip", "How should the conflict in the material be resolved?")
Cura.ComboBox
{
model: resolveStrategiesModel
textRole: "label"
id: materialResolveComboBox
width: parent.width
height: UM.Theme.getSize("button").height
onActivated:
{
manager.setResolveStrategy("material", resolveStrategiesModel.get(index).key)
}
}
}
Column
{
width: parent.width
height: childrenRect.height
Row
{
height: childrenRect.height
width: parent.width
spacing: UM.Theme.getSize("narrow_margin").width
UM.Label
{
text: catalog.i18nc("@action:label", "Material settings")
font: UM.Theme.getFont("default_bold")
width: (parent.width / 3) | 0
}
}
spacing: UM.Theme.getSize("default_margin").height
leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
Repeater
{
model: manager.materialLabels
delegate: Row
delegate: WorkspaceRow
{
width: parent.width
height: childrenRect.height
UM.Label
{
text: catalog.i18nc("@action:label", "Name")
width: (parent.width / 3) | 0
}
UM.Label
{
text: modelData
width: (parent.width / 3) | 0
wrapMode: Text.WordWrap
}
leftLabelText: catalog.i18nc("@action:label", "Name")
rightLabelText: modelData
}
}
}
comboboxVisible: manager.materialConflict
combobox: Cura.ComboBox
{
id: materialResolveComboBox
model: resolveStrategiesModel
textRole: "label"
visible: manager.materialConflict
// This is a hack. This will trigger onCurrentIndexChanged and set the index when this component in loaded
currentIndex:
{
currentIndex = 0
}
onCurrentIndexChanged:
{
manager.setResolveStrategy("material", resolveStrategiesModel.get(currentIndex).key)
}
}
}
Column
WorkspaceSection
{
width: parent.width
height: childrenRect.height
id: visibilitySection
title: catalog.i18nc("@action:label", "Setting visibility")
iconSource: UM.Theme.getIcon("Eye")
content: Column
{
spacing: UM.Theme.getSize("default_margin").height
leftPadding: UM.Theme.getSize("medium_button_icon").width + UM.Theme.getSize("default_margin").width
bottomPadding: UM.Theme.getSize("narrow_margin").height
UM.Label
{
text: catalog.i18nc("@action:label", "Setting visibility")
font: UM.Theme.getFont("default_bold")
}
Row
{
width: parent.width
height: childrenRect.height
UM.Label
WorkspaceRow
{
text: catalog.i18nc("@action:label", "Mode")
width: (parent.width / 3) | 0
leftLabelText: catalog.i18nc("@action:label", "Mode")
rightLabelText: manager.activeMode
}
UM.Label
WorkspaceRow
{
text: manager.activeMode
width: (parent.width / 3) | 0
}
}
Row
{
width: parent.width
height: childrenRect.height
visible: manager.hasVisibleSettingsField
UM.Label
{
text: catalog.i18nc("@action:label", "Visible settings:")
width: (parent.width / 3) | 0
}
UM.Label
{
text: catalog.i18nc("@action:label", "%1 out of %2" ).arg(manager.numVisibleSettings).arg(manager.totalNumberOfSettings)
width: (parent.width / 3) | 0
leftLabelText: catalog.i18nc("@action:label", "%1 out of %2" ).arg(manager.numVisibleSettings).arg(manager.totalNumberOfSettings)
rightLabelText: manager.activeMode
visible: manager.hasVisibleSettingsField
}
}
}
Row
{
id: clearBuildPlateWarning
width: parent.width
height: childrenRect.height
spacing: UM.Theme.getSize("default_margin").width
visible: manager.hasObjectsOnPlate
UM.ColorImage
{
width: warningLabel.height
@ -459,14 +311,18 @@ UM.Dialog
color: warning ? UM.Theme.getColor("warning") : "transparent"
anchors.bottom: parent.bottom
width: parent.width
height: childrenRect.height + 2 * base.margin
height: childrenRect.height + (warning ? 2 * workspaceDialog.margin : workspaceDialog.margin)
Column
{
height: childrenRect.height
spacing: base.margin
spacing: workspaceDialog.margin
anchors.leftMargin: workspaceDialog.margin
anchors.rightMargin: workspaceDialog.margin
anchors.bottomMargin: workspaceDialog.margin
anchors.topMargin: warning ? workspaceDialog.margin : 0
anchors.margins: base.margin
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
@ -476,7 +332,7 @@ UM.Dialog
id: warningRow
height: childrenRect.height
visible: warning
spacing: base.margin
spacing: workspaceDialog.margin
UM.ColorImage
{
width: UM.Theme.getSize("extruder_icon").width
@ -500,7 +356,7 @@ UM.Dialog
}
}
buttonSpacing: UM.Theme.getSize("default_margin").width
buttonSpacing: UM.Theme.getSize("wide_margin").width
rightButtons: [
Cura.TertiaryButton
@ -532,6 +388,19 @@ UM.Dialog
}
]
onClosing: manager.notifyClosed()
onRejected: manager.onCancelButtonClicked()
onAccepted: manager.onOkButtonClicked()
onVisibleChanged:
{
if (visible)
{
// Force relead the comboboxes
// Since this dialog is only created once the first time you open it, these comboxes need to be reloaded
// each time it is shown after the first time so that the indexes will update correctly.
materialSection.reloadValues()
profileSection.reloadValues()
printerSection.reloadValues()
}
}
}

View file

@ -0,0 +1,34 @@
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Window 2.2
import UM 1.5 as UM
import Cura 1.1 as Cura
Row
{
property alias leftLabelText: leftLabel.text
property alias rightLabelText: rightLabel.text
width: parent.width
height: visible ? childrenRect.height : 0
UM.Label
{
id: leftLabel
text: catalog.i18nc("@action:label", "Type")
width: Math.round(parent.width / 4)
wrapMode: Text.WordWrap
}
UM.Label
{
id: rightLabel
text: manager.machineType
width: Math.round(parent.width / 3)
wrapMode: Text.WordWrap
}
}

View file

@ -0,0 +1,126 @@
// Copyright (c) 2022 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.5 as UM
Item
{
property alias title: sectionTitle.text
property alias iconSource: sectionTitleIcon.source
property Component content: Item { visible: false }
property alias comboboxTitle: comboboxLabel.text
property Component combobox: Item { visible: false }
property string comboboxTooltipText: ""
property bool comboboxVisible: false
width: parent.width
height: childrenRect.height
anchors.leftMargin: UM.Theme.getSize("default_margin").width
Row
{
id: sectionTitleRow
anchors.top: parent.top
bottomPadding: UM.Theme.getSize("default_margin").height
spacing: UM.Theme.getSize("default_margin").width
UM.ColorImage
{
id: sectionTitleIcon
anchors.verticalCenter: parent.verticalCenter
source: ""
height: UM.Theme.getSize("medium_button_icon").height
width: height
}
UM.Label
{
id: sectionTitle
text: ""
anchors.verticalCenter: parent.verticalCenter
font: UM.Theme.getFont("default_bold")
}
}
Item
{
id: comboboxTooltip
width: Math.round(parent.width / 2.5)
height: visible ? UM.Theme.getSize("default_margin").height : 0
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width
visible: comboboxVisible
UM.Label
{
id: comboboxLabel
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: UM.Theme.getSize("default_margin").height
visible: comboboxVisible && text != ""
text: ""
font: UM.Theme.getFont("default_bold")
}
Loader
{
id: comboboxLoader
width: parent.width
height: UM.Theme.getSize("button").height
anchors.top: comboboxLabel.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
sourceComponent: combobox
}
MouseArea
{
id: helpIconMouseArea
anchors.right: parent.right
anchors.verticalCenter: comboboxLabel.verticalCenter
width: childrenRect.width
height: childrenRect.height
hoverEnabled: true
UM.ColorImage
{
width: UM.Theme.getSize("section_icon").width
height: width
visible: comboboxTooltipText != ""
source: UM.Theme.getIcon("Help")
UM.ToolTip
{
text: comboboxTooltipText
visible: helpIconMouseArea.containsMouse
targetPoint: Qt.point(parent.x + Math.round(parent.width / 2), parent.y)
x: 0
y: parent.y + parent.height + UM.Theme.getSize("default_margin").height
width: UM.Theme.getSize("tooltip").width
}
}
}
}
Loader
{
width: parent.width
height: content.height
anchors.top: sectionTitleRow.bottom
sourceComponent: content
}
function reloadValues()
{
comboboxLoader.sourceComponent = null
comboboxLoader.sourceComponent = combobox
}
}

View file

@ -19,5 +19,7 @@ Item
width: UM.Theme.getSize("machine_selector_widget").width
height: parent.height
anchors.centerIn: parent
machineListModel: Cura.MachineListModel {}
}
}

View file

@ -150,6 +150,7 @@ Item
width: parent.width / 2 - UM.Theme.getSize("default_margin").width
height: UM.Theme.getSize("setting_control").height
textRole: "text"
forceHighlight: base.hovered
model: ListModel
{

View file

@ -55,6 +55,50 @@ Item
Layout.preferredWidth: parent.machineSelectorWidth
Layout.fillWidth: true
Layout.fillHeight: true
machineManager: Cura.MachineManager
onSelectPrinter: function(machine)
{
toggleContent();
Cura.MachineManager.setActiveMachine(machine.id);
}
machineListModel: Cura.MachineListModel {}
buttons: [
Cura.SecondaryButton
{
id: addPrinterButton
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@button", "Add printer")
// The maximum width of the button is half of the total space, minus the padding of the parent, the left
// padding of the component and half the spacing because of the space between buttons.
fixedWidthMode: true
width: Math.round(parent.width / 2 - leftPadding * 1.5)
onClicked:
{
machineSelection.toggleContent()
Cura.Actions.addMachine.trigger()
}
},
Cura.SecondaryButton
{
id: managePrinterButton
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@button", "Manage printers")
fixedWidthMode: true
// The maximum width of the button is half of the total space, minus the padding of the parent, the right
// padding of the component and half the spacing because of the space between buttons.
width: Math.round(parent.width / 2 - rightPadding * 1.5)
onClicked:
{
machineSelection.toggleContent()
Cura.Actions.configureMachines.trigger()
}
}
]
}
Cura.ConfigurationMenu

View file

@ -11,12 +11,29 @@ Cura.ExpandablePopup
{
id: machineSelector
property bool isNetworkPrinter: Cura.MachineManager.activeMachineHasNetworkConnection
property bool isConnectedCloudPrinter: Cura.MachineManager.activeMachineHasCloudConnection
property bool isCloudRegistered: Cura.MachineManager.activeMachineHasCloudRegistration
property bool isGroup: Cura.MachineManager.activeMachineIsGroup
property Cura.MachineManager machineManager
property bool isNetworkPrinter: machineManager.activeMachineHasNetworkConnection
property bool isConnectedCloudPrinter: machineManager.activeMachineHasCloudConnection
property bool isCloudRegistered: machineManager.activeMachineHasCloudRegistration
property bool isGroup: machineManager.activeMachineIsGroup
property string machineName: {
if (isNetworkPrinter && machineManager.activeMachineNetworkGroupName != "")
{
return machineManager.activeMachineNetworkGroupName
}
if (machineManager.activeMachine != null)
{
return machineManager.activeMachine.name
}
return ""
}
readonly property string connectionStatus: {
property alias machineListModel: machineSelectorList.model
property alias onSelectPrinter: machineSelectorList.onSelectPrinter
property list<Item> buttons
property string connectionStatus: {
if (isNetworkPrinter)
{
return "printer_connected"
@ -42,7 +59,7 @@ Cura.ExpandablePopup
{
if (Cura.API.account.isLoggedIn)
{
if (Cura.MachineManager.activeMachineIsLinkedToCurrentAccount)
if (machineManager.activeMachineIsLinkedToCurrentAccount)
{
return catalog.i18nc("@status", "The cloud printer is offline. Please check if the printer is turned on and connected to the internet.")
}
@ -55,7 +72,8 @@ Cura.ExpandablePopup
{
return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please sign in to connect to the cloud printer.")
}
} else
}
else
{
return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please check your internet connection.")
}
@ -77,18 +95,8 @@ Cura.ExpandablePopup
headerItem: Cura.IconWithText
{
text:
{
if (isNetworkPrinter && Cura.MachineManager.activeMachineNetworkGroupName != "")
{
return Cura.MachineManager.activeMachineNetworkGroupName
}
if(Cura.MachineManager.activeMachine != null)
{
return Cura.MachineManager.activeMachine.name
}
return ""
}
text: machineName
source:
{
if (isGroup)
@ -140,7 +148,7 @@ Cura.ExpandablePopup
color: connectionStatus == "printer_cloud_not_available" ? UM.Theme.getColor("cloud_unavailable") : UM.Theme.getColor("primary")
visible: isNetworkPrinter || isCloudRegistered
visible: (isNetworkPrinter || isCloudRegistered) && source != ""
// Make a themable circle in the background so we can change it in other themes
Rectangle
@ -156,7 +164,8 @@ Cura.ExpandablePopup
}
MouseArea // Connection status tooltip hover area
// Connection status tooltip hover area
MouseArea
{
id: connectionStatusTooltipHoverArea
anchors.fill: parent
@ -189,11 +198,14 @@ Cura.ExpandablePopup
}
}
property int minDropDownWidth: UM.Theme.getSize("machine_selector_widget_content").width
property int maxDropDownHeight: UM.Theme.getSize("machine_selector_widget_content").height
contentItem: Item
{
id: popup
implicitWidth: Math.max(machineSelector.width, UM.Theme.getSize("machine_selector_widget_content").width)
implicitHeight: Math.min(machineSelectorList.contentHeight + separator.height + buttonRow.height, UM.Theme.getSize("machine_selector_widget_content").height) //Maximum height is the theme entry.
implicitWidth: Math.max(machineSelector.width, minDropDownWidth)
implicitHeight: Math.min(machineSelectorList.contentHeight + separator.height + buttonRow.height, maxDropDownHeight) //Maximum height is the theme entry.
MachineSelectorList
{
id: machineSelectorList
@ -229,39 +241,25 @@ Cura.ExpandablePopup
padding: UM.Theme.getSize("default_margin").width
spacing: UM.Theme.getSize("default_margin").width
Cura.SecondaryButton
{
id: addPrinterButton
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@button", "Add printer")
// The maximum width of the button is half of the total space, minus the padding of the parent, the left
// padding of the component and half the spacing because of the space between buttons.
fixedWidthMode: true
width: buttonRow.width / 2 - leftPadding * 1.5
onClicked:
{
toggleContent()
Cura.Actions.addMachine.trigger()
}
}
Cura.SecondaryButton
{
id: managePrinterButton
leftPadding: UM.Theme.getSize("default_margin").width
rightPadding: UM.Theme.getSize("default_margin").width
text: catalog.i18nc("@button", "Manage printers")
fixedWidthMode: true
// The maximum width of the button is half of the total space, minus the padding of the parent, the right
// padding of the component and half the spacing because of the space between buttons.
width: buttonRow.width / 2 - rightPadding * 1.5
onClicked:
{
toggleContent()
Cura.Actions.configureMachines.trigger()
}
}
children: buttons
}
states: [
State {
name: "noButtons"
when: !buttons || buttons.length == 0
PropertyChanges
{
target: buttonRow
height: 0
padding: 0
}
PropertyChanges
{
target: separator
height: 0
}
}
]
}
}

View file

@ -10,9 +10,9 @@ import Cura 1.0 as Cura
ListView
{
id: listView
model: Cura.MachineListModel {}
section.property: "isOnline"
section.property: "category"
property real contentHeight: childrenRect.height
property var onSelectPrinter
ScrollBar.vertical: UM.ScrollBar
{
@ -21,7 +21,17 @@ ListView
section.delegate: UM.Label
{
text: section == "true" ? catalog.i18nc("@label", "Connected printers") : catalog.i18nc("@label", "Other printers")
text: {
switch (section)
{
case "connected":
return catalog.i18nc("@label", "Connected printers");
case "other":
return catalog.i18nc("@label", "Other printers");
default:
return catalog.i18nc("@label", "Other printers");
}
}
height: UM.Theme.getSize("action_button").height
width: parent.width - scrollBar.width
leftPadding: UM.Theme.getSize("default_margin").width
@ -43,8 +53,7 @@ ListView
listView.model.setShowCloudPrinters(true);
break;
case "MACHINE":
toggleContent()
Cura.MachineManager.setActiveMachine(model.id)
if (typeof onSelectPrinter === "function") onSelectPrinter(model);
break;
default:
}

View file

@ -18,6 +18,7 @@ SettingItem
model: definition.options
textRole: "value"
forceHighlight: base.hovered
anchors.fill: parent

View file

@ -17,6 +17,8 @@ SettingItem
id: control
anchors.fill: parent
forceHighlight: base.hovered
property var extrudersModel: CuraApplication.getExtrudersModel()
model: extrudersModel

View file

@ -23,6 +23,7 @@ SettingItem
{
id: control
anchors.fill: parent
forceHighlight: base.hovered
model: base.extrudersWithOptionalModel

View file

@ -18,6 +18,8 @@ ComboBox
property var defaultTextOnEmptyModel: catalog.i18nc("@label", "No items to select from") // Text displayed in the combobox when the model is empty
property var defaultTextOnEmptyIndex: "" // Text displayed in the combobox when the model has items but no item is selected
property alias textFormat: contentLabel.textFormat
property alias backgroundColor: background.color
property bool forceHighlight: false
enabled: delegateModel.count > 0
@ -45,7 +47,7 @@ ComboBox
State
{
name: "highlighted"
when: (base.hovered || control.hovered) && !control.activeFocus
when: (control.hovered && !control.activeFocus) || forceHighlight
PropertyChanges
{
target: background
@ -56,6 +58,7 @@ ComboBox
background: UM.UnderlineBackground
{
id: background
// Rectangle for highlighting when this combobox needs to pulse.
Rectangle
{