Rework the open project dialog to contain only 1 dropdown

With the caveat that the qtQuickControls had to be updated to 2.3, due to a qt bug in 1.x that did
not update the dropdown popup list according to the ListModel.
This leads to a different look in the dropdowns and in the buttons of the open project dialog,
compaired to the rest of the application.

CURA-7609
This commit is contained in:
Kostas Karmas 2020-08-04 16:33:11 +02:00
parent e5d3271698
commit 4e20c7dddc
4 changed files with 98 additions and 67 deletions

View file

@ -227,7 +227,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# Read definition containers # Read definition containers
# #
machine_definition_id = None machine_definition_id = None
updatable_machine_names = [] updatable_machines = []
machine_definition_container_count = 0 machine_definition_container_count = 0
extruder_definition_container_count = 0 extruder_definition_container_count = 0
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)] definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
@ -246,7 +246,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
machine_definition_id = container_id machine_definition_id = container_id
machine_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id) machine_definition_containers = self._container_registry.findDefinitionContainers(id = machine_definition_id)
if machine_definition_containers: if machine_definition_containers:
updatable_machine_names = [machine.name for machine in self._container_registry.findContainerStacks(type = "machine") if machine.definition == machine_definition_containers[0]] updatable_machines = [machine for machine in self._container_registry.findContainerStacks(type = "machine") if machine.definition == machine_definition_containers[0]]
machine_type = definition_container["name"] machine_type = definition_container["name"]
variant_type_name = definition_container.get("variants_name", variant_type_name) variant_type_name = definition_container.get("variants_name", variant_type_name)
@ -403,7 +403,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
machine_conflict = True machine_conflict = True
break break
if updatable_machine_names and not containers_found_dict["machine"]: if updatable_machines and not containers_found_dict["machine"]:
containers_found_dict["machine"] = True containers_found_dict["machine"] = True
# Get quality type # Get quality type
@ -572,7 +572,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes) self._dialog.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes)
self._dialog.setNumUserSettings(num_user_settings) self._dialog.setNumUserSettings(num_user_settings)
self._dialog.setActiveMode(active_mode) self._dialog.setActiveMode(active_mode)
self._dialog.setUpdatableMachineNames(updatable_machine_names) self._dialog.setUpdatableMachinesModel(updatable_machines)
self._dialog.setMachineName(machine_name) self._dialog.setMachineName(machine_name)
self._dialog.setMaterialLabels(material_labels) self._dialog.setMaterialLabels(material_labels)
self._dialog.setMachineType(machine_type) self._dialog.setMachineType(machine_type)
@ -654,7 +654,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
application.expandedCategoriesChanged.emit() # Notify the GUI of the change application.expandedCategoriesChanged.emit() # Notify the GUI of the change
# If there are no machines of the same type, create a new machine. # If there are no machines of the same type, create a new machine.
if self._resolve_strategies["machine"] != "override" or not self._dialog.updatableMachineNames: if self._resolve_strategies["machine"] != "override" or self._dialog.updatableMachinesModel.count <= 1:
# We need to create a new machine # We need to create a new machine
machine_name = self._container_registry.uniqueName(self._machine_info.name) machine_name = self._container_registry.uniqueName(self._machine_info.name)

View file

@ -0,0 +1,43 @@
# Copyright (c) 2020 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Dict, List
from PyQt5.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.UserRole + 1, "id")
self.addRoleName(Qt.UserRole + 2, "name")
self.addRoleName(Qt.UserRole + 3, "displayName")
self.addRoleName(Qt.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

@ -1,6 +1,6 @@
# Copyright (c) 2016 Ultimaker B.V. # Copyright (c) 2020 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 typing import List, Optional, Dict from typing import List, Optional, Dict, cast
from PyQt5.QtCore import pyqtSignal, QObject, pyqtProperty, QCoreApplication from PyQt5.QtCore import pyqtSignal, QObject, pyqtProperty, QCoreApplication
from UM.FlameProfiler import pyqtSlot from UM.FlameProfiler import pyqtSlot
@ -8,6 +8,8 @@ from UM.PluginRegistry import PluginRegistry
from UM.Application import Application from UM.Application import Application
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from cura.Settings.GlobalStack import GlobalStack
from .UpdatableMachinesModel import UpdatableMachinesModel
import os import os
import threading import threading
@ -50,13 +52,13 @@ class WorkspaceDialog(QObject):
self._quality_type = "" self._quality_type = ""
self._intent_name = "" self._intent_name = ""
self._machine_name = "" self._machine_name = ""
self._updatable_machines = []
self._machine_type = "" self._machine_type = ""
self._variant_type = "" self._variant_type = ""
self._material_labels = [] self._material_labels = []
self._extruders = [] self._extruders = []
self._objects_on_plate = False self._objects_on_plate = False
self._is_printer_group = False self._is_printer_group = False
self._updatable_machines_model = UpdatableMachinesModel(self)
machineConflictChanged = pyqtSignal() machineConflictChanged = pyqtSignal()
qualityChangesConflictChanged = pyqtSignal() qualityChangesConflictChanged = pyqtSignal()
@ -69,7 +71,7 @@ class WorkspaceDialog(QObject):
qualityTypeChanged = pyqtSignal() qualityTypeChanged = pyqtSignal()
intentNameChanged = pyqtSignal() intentNameChanged = pyqtSignal()
machineNameChanged = pyqtSignal() machineNameChanged = pyqtSignal()
updatableMachineNamesChanged = pyqtSignal() updatableMachinesChanged = pyqtSignal()
materialLabelsChanged = pyqtSignal() materialLabelsChanged = pyqtSignal()
objectsOnPlateChanged = pyqtSignal() objectsOnPlateChanged = pyqtSignal()
numUserSettingsChanged = pyqtSignal() numUserSettingsChanged = pyqtSignal()
@ -149,18 +151,13 @@ class WorkspaceDialog(QObject):
self._machine_name = machine_name self._machine_name = machine_name
self.machineNameChanged.emit() self.machineNameChanged.emit()
@pyqtProperty("QVariantList", notify = updatableMachineNamesChanged) @pyqtProperty(QObject, notify = updatableMachinesChanged)
def updatableMachineNames(self) -> List[str]: def updatableMachinesModel(self) -> UpdatableMachinesModel:
return self._updatable_machines return cast(UpdatableMachinesModel, self._updatable_machines_model)
def setUpdatableMachineNames(self, updatable_machines: List[str]) -> None: def setUpdatableMachinesModel(self, updatable_machines: List[GlobalStack]) -> None:
if self._updatable_machines != updatable_machines: self._updatable_machines_model.update(updatable_machines)
self._updatable_machines = sorted(updatable_machines) self.updatableMachinesChanged.emit()
self.updatableMachineNamesChanged.emit()
@pyqtProperty(int, notify = updatableMachineNamesChanged)
def updatableMachineNamesCount(self) -> int:
return len(self._updatable_machines)
@pyqtProperty(str, notify=qualityTypeChanged) @pyqtProperty(str, notify=qualityTypeChanged)
def qualityType(self) -> str: def qualityType(self) -> str:
@ -245,7 +242,7 @@ class WorkspaceDialog(QObject):
return self._has_material_conflict return self._has_material_conflict
@pyqtSlot(str, str) @pyqtSlot(str, str)
def setResolveStrategy(self, key: str, strategy: str) -> None: def setResolveStrategy(self, key: str, strategy: Optional[str]) -> None:
if key in self._result: if key in self._result:
self._result[key] = strategy self._result[key] = strategy
@ -278,7 +275,7 @@ class WorkspaceDialog(QObject):
self.qualityChangesConflictChanged.emit() self.qualityChangesConflictChanged.emit()
def getResult(self) -> Dict[str, Optional[str]]: def getResult(self) -> Dict[str, Optional[str]]:
if "machine" in self._result and not self._updatable_machines: if "machine" in self._result and self.updatableMachinesModel.count <= 1:
self._result["machine"] = None self._result["machine"] = None
if "quality_changes" in self._result and not self._has_quality_changes_conflict: if "quality_changes" in self._result and not self._has_quality_changes_conflict:
self._result["quality_changes"] = None self._result["quality_changes"] = None

View file

@ -2,7 +2,7 @@
// Cura is released under the terms of the LGPLv3 or higher. // 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 2.3
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtQuick.Window 2.2 import QtQuick.Window 2.2
@ -21,7 +21,6 @@ UM.Dialog
property int comboboxHeight: 15 * screenScaleFactor property int comboboxHeight: 15 * screenScaleFactor
property int spacerHeight: 10 * screenScaleFactor property int spacerHeight: 10 * screenScaleFactor
property int doubleSpacerHeight: 20 * screenScaleFactor property int doubleSpacerHeight: 20 * screenScaleFactor
property string machineResolveStrategyCurrentKey: "override"
onClosing: manager.notifyClosed() onClosing: manager.notifyClosed()
onVisibleChanged: onVisibleChanged:
@ -106,25 +105,50 @@ UM.Dialog
id: machineResolveStrategyTooltip id: machineResolveStrategyTooltip
width: (parent.width / 3) | 0 width: (parent.width / 3) | 0
height: visible ? comboboxHeight : 0 height: visible ? comboboxHeight : 0
visible: manager.updatableMachineNamesCount != 0 visible: base.visible && machineResolveComboBox.model.count > 1
text: catalog.i18nc("@info:tooltip", "How should the conflict in the machine be resolved?") text: catalog.i18nc("@info:tooltip", "How should the conflict in the machine be resolved?")
ComboBox ComboBox
{ {
id: machineResolveComboBox id: machineResolveComboBox
model: ListModel model: manager.updatableMachinesModel
{ visible: machineResolveStrategyTooltip.visible
Component.onCompleted: textRole: "displayName"
{
append({"key": "override", "label": catalog.i18nc("@action:ComboBox option", "Update existing...")});
append({"key": "new", "label": catalog.i18nc("@action:ComboBox option", "Create new printer")});
}
}
textRole: "label"
width: parent.width width: parent.width
onActivated: onCurrentIndexChanged:
{ {
machineResolveStrategyCurrentKey = resolveStrategiesModel.get(index).key if (model.getItem(currentIndex).id == "new"
manager.setResolveStrategy("machine", resolveStrategiesModel.get(index).key) && model.getItem(currentIndex).type == "default_option")
{
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
}
} }
} }
} }
@ -159,39 +183,6 @@ UM.Dialog
text: manager.machineName text: manager.machineName
width: (parent.width / 3) | 0 width: (parent.width / 3) | 0
} }
UM.TooltipArea
{
id: machineResolveTooltip
width: (parent.width / 3) | 0
height: visible ? comboboxHeight : 0
visible: base.visible && manager.updatableMachineNamesCount != 0 && machineResolveStrategyCurrentKey == "override"
text: catalog.i18nc("@info:tooltip", "Which machine of the same type should be overriden?")
ComboBox
{
id: selectMachineComboBox
model: manager.updatableMachineNames
width: parent.width
onCurrentIndexChanged:
{
manager.setMachineToOverride(model[currentIndex])
}
onVisibleChanged:
{
if (!visible) {return}
currentIndex = 0
for (var i = 0; i < count; i++)
{
if (model[i] == manager.machineName)
{
currentIndex = i
break
}
}
}
}
}
} }
Item // Spacer Item // Spacer