diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 2f845c710f..1155c67423 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -523,6 +523,7 @@ class CuraApplication(QtApplication): preferences.addPreference("cura/choice_on_profile_override", "always_ask") preferences.addPreference("cura/choice_on_open_project", "always_ask") preferences.addPreference("cura/use_multi_build_plate", False) + preferences.addPreference("cura/show_list_of_objects", False) preferences.addPreference("view/settings_list_height", 400) preferences.addPreference("view/settings_visible", False) preferences.addPreference("view/settings_xpos", 0) @@ -929,7 +930,7 @@ class CuraApplication(QtApplication): def getObjectsModel(self, *args): if self._object_manager is None: - self._object_manager = ObjectsModel.createObjectsModel() + self._object_manager = ObjectsModel(self) return self._object_manager @pyqtSlot(result = QObject) @@ -1039,7 +1040,7 @@ class CuraApplication(QtApplication): qmlRegisterType(NetworkMJPGImage, "Cura", 1, 0, "NetworkMJPGImage") - qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel) + qmlRegisterType(ObjectsModel, "Cura", 1, 0, "ObjectsModel") qmlRegisterType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel") qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel") qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") diff --git a/cura/UI/ObjectsModel.py b/cura/UI/ObjectsModel.py index 36d590a668..d1ca3353f5 100644 --- a/cura/UI/ObjectsModel.py +++ b/cura/UI/ObjectsModel.py @@ -4,7 +4,7 @@ from collections import defaultdict from typing import Dict -from PyQt5.QtCore import QTimer +from PyQt5.QtCore import QTimer, Qt from UM.Application import Application from UM.Qt.ListModel import ListModel @@ -19,8 +19,20 @@ catalog = i18nCatalog("cura") ## Keep track of all objects in the project class ObjectsModel(ListModel): - def __init__(self) -> None: - super().__init__() + NameRole = Qt.UserRole + 1 + SelectedRole = Qt.UserRole + 2 + OutsideAreaRole = Qt.UserRole + 3 + BuilplateNumberRole = Qt.UserRole + 4 + NodeRole = Qt.UserRole + 5 + + def __init__(self, parent = None) -> None: + super().__init__(parent) + + self.addRoleName(self.NameRole, "name") + self.addRoleName(self.SelectedRole, "selected") + self.addRoleName(self.OutsideAreaRole, "outside_build_area") + self.addRoleName(self.BuilplateNumberRole, "buildplate_number") + self.addRoleName(self.NodeRole, "node") Application.getInstance().getController().getScene().sceneChanged.connect(self._updateSceneDelayed) Application.getInstance().getPreferences().preferenceChanged.connect(self._updateDelayed) @@ -78,7 +90,7 @@ class ObjectsModel(ListModel): else: is_outside_build_area = False - #check if we already have an instance of the object based on name + # Check if we already have an instance of the object based on name name_count_dict[name] += 1 name_count = name_count_dict[name] @@ -88,9 +100,9 @@ class ObjectsModel(ListModel): nodes.append({ "name": name, - "isSelected": Selection.isSelected(node), - "isOutsideBuildArea": is_outside_build_area, - "buildPlateNumber": node_build_plate_number, + "selected": Selection.isSelected(node), + "outside_build_area": is_outside_build_area, + "buildplate_number": node_build_plate_number, "node": node }) @@ -98,7 +110,3 @@ class ObjectsModel(ListModel): self.setItems(nodes) self.itemsChanged.emit() - - @staticmethod - def createObjectsModel(): - return ObjectsModel() diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index ab02887774..ef2b19003c 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -260,15 +260,17 @@ UM.MainWindow visible: CuraApplication.platformActivity && !PrintInformation.preSliced } - ObjectsList + ObjectSelector { - id: objectsList - visible: UM.Preferences.getValue("cura/use_multi_build_plate") + id: objectSelector + visible: CuraApplication.platformActivity anchors { - bottom: viewOrientationControls.top + bottom: jobSpecs.top left: toolbar.right - margins: UM.Theme.getSize("default_margin").width + leftMargin: UM.Theme.getSize("default_margin").width + rightMargin: UM.Theme.getSize("default_margin").width + bottomMargin: UM.Theme.getSize("narrow_margin").height } } @@ -278,10 +280,12 @@ UM.MainWindow visible: CuraApplication.platformActivity anchors { - left: parent.left + left: toolbar.right bottom: viewOrientationControls.top - margins: UM.Theme.getSize("default_margin").width + leftMargin: UM.Theme.getSize("default_margin").width + rightMargin: UM.Theme.getSize("default_margin").width bottomMargin: UM.Theme.getSize("thin_margin").width + topMargin: UM.Theme.getSize("thin_margin").width } } @@ -291,7 +295,7 @@ UM.MainWindow anchors { - left: parent.left + left: toolbar.right bottom: parent.bottom margins: UM.Theme.getSize("default_margin").width } diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 144616c22d..63ccbc336a 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -65,7 +65,7 @@ Item height: UM.Theme.getSize("save_button_specs_icons").height sourceSize.width: width sourceSize.height: width - color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene") + color: control.hovered ? UM.Theme.getColor("small_button_text_hover") : UM.Theme.getColor("small_button_text") source: UM.Theme.getIcon("pencil") } } diff --git a/resources/qml/ObjectItemButton.qml b/resources/qml/ObjectItemButton.qml new file mode 100644 index 0000000000..683d0ed52b --- /dev/null +++ b/resources/qml/ObjectItemButton.qml @@ -0,0 +1,55 @@ +// Copyright (c) 2018 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.1 as UM +import Cura 1.0 as Cura + +Button +{ + id: objectItemButton + + width: parent.width + height: UM.Theme.getSize("action_button").height + leftPadding: UM.Theme.getSize("thin_margin").width + rightPadding: UM.Theme.getSize("thin_margin").width + checkable: true + hoverEnabled: true + + contentItem: Item + { + width: objectItemButton.width - objectItemButton.leftPadding + height: UM.Theme.getSize("action_button").height + + Label + { + id: buttonText + anchors + { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + text: objectItemButton.text + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text_scene") + visible: text != "" + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + } + + background: Rectangle + { + id: backgroundRect + color: objectItemButton.hovered ? UM.Theme.getColor("action_button_hovered") : "transparent" + radius: UM.Theme.getSize("action_button_radius").width + border.width: UM.Theme.getSize("default_lining").width + border.color: objectItemButton.checked ? UM.Theme.getColor("primary") : "transparent" + } + + onClicked: Cura.SceneController.changeSelection(index) +} diff --git a/resources/qml/ObjectSelector.qml b/resources/qml/ObjectSelector.qml new file mode 100644 index 0000000000..3b7f3455b3 --- /dev/null +++ b/resources/qml/ObjectSelector.qml @@ -0,0 +1,120 @@ +// Copyright (c) 2019 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.10 +import QtQuick.Controls 2.3 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Item +{ + id: objectSelector + width: UM.Theme.getSize("objects_menu_size").width + property bool opened: UM.Preferences.getValue("cura/show_list_of_objects") + + Button + { + id: openCloseButton + width: parent.width + height: contentItem.height + bottomPadding + hoverEnabled: true + padding: 0 + bottomPadding: UM.Theme.getSize("narrow_margin").height / 2 | 0 + + anchors + { + bottom: contents.top + horizontalCenter: parent.horizontalCenter + } + + contentItem: Item + { + width: parent.width + height: label.height + + UM.RecolorImage + { + id: openCloseIcon + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + anchors.left: parent.left + color: openCloseButton.hovered ? UM.Theme.getColor("small_button_text_hover") : UM.Theme.getColor("small_button_text") + source: objectSelector.opened ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_top") + } + + Label + { + id: label + anchors.left: openCloseIcon.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + text: catalog.i18nc("@label", "Object list") + font: UM.Theme.getFont("default") + color: openCloseButton.hovered ? UM.Theme.getColor("small_button_text_hover") : UM.Theme.getColor("small_button_text") + renderType: Text.NativeRendering + elide: Text.ElideRight + } + } + + background: Item {} + + onClicked: + { + UM.Preferences.setValue("cura/show_list_of_objects", !objectSelector.opened) + objectSelector.opened = UM.Preferences.getValue("cura/show_list_of_objects") + } + } + + Rectangle + { + id: contents + width: parent.width + visible: objectSelector.opened + height: visible ? scroll.height : 0 + color: UM.Theme.getColor("main_background") + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + + Behavior on height { NumberAnimation { duration: 100 } } + + anchors.bottom: parent.bottom + + ScrollView + { + id: scroll + width: parent.width + clip: true + padding: UM.Theme.getSize("default_lining").width + + contentItem: ListView + { + id: listView + + // Can't use parent.width since the parent is the flickable component and not the ScrollView + width: scroll.width - scroll.leftPadding - scroll.rightPadding + property real maximumHeight: UM.Theme.getSize("objects_menu_size").height + + // We use an extra property here, since we only want to to be informed about the content size changes. + onContentHeightChanged: + { + scroll.height = Math.min(contentHeight, maximumHeight) + scroll.topPadding + scroll.bottomPadding + } + + Component.onCompleted: + { + scroll.height = Math.min(contentHeight, maximumHeight) + scroll.topPadding + scroll.bottomPadding + } + model: Cura.ObjectsModel {} + + delegate: ObjectItemButton + { + text: model.name + width: listView.width + + checked: model.selected + } + } + } + } +} diff --git a/resources/qml/ObjectsList.qml b/resources/qml/ObjectsList.qml deleted file mode 100644 index fd5175fce2..0000000000 --- a/resources/qml/ObjectsList.qml +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Controls.Styles 1.1 -import QtQuick.Layouts 1.1 -import QtQuick.Dialogs 1.1 - -import UM 1.3 as UM -import Cura 1.0 as Cura - -import "Menus" - -Rectangle -{ - id: base; - - color: UM.Theme.getColor("tool_panel_background") - - width: UM.Theme.getSize("objects_menu_size").width - height: { - if (collapsed) { - return UM.Theme.getSize("objects_menu_size_collapsed").height; - } else { - return UM.Theme.getSize("objects_menu_size").height; - } - } - Behavior on height { NumberAnimation { duration: 100 } } - - border.width: UM.Theme.getSize("default_lining").width - border.color: UM.Theme.getColor("lining") - - property bool collapsed: true - - property var multiBuildPlateModel: CuraApplication.getMultiBuildPlateModel() - - SystemPalette { id: palette } - - Button { - id: collapseButton - anchors.top: parent.top - anchors.topMargin: Math.round(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2) - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - - onClicked: collapsed = !collapsed - - style: ButtonStyle - { - background: UM.RecolorImage - { - width: control.width - height: control.height - sourceSize.height: width - color: UM.Theme.getColor("setting_control_text") - source: collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom") - } - label: Label{ } - } - } - - Component { - id: buildPlateDelegate - Rectangle - { - height: childrenRect.height - color: multiBuildPlateModel.getItem(index).buildPlateNumber == multiBuildPlateModel.activeBuildPlate ? palette.highlight : index % 2 ? palette.base : palette.alternateBase - width: parent.width - Label - { - id: buildPlateNameLabel - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - width: parent.width - 2 * UM.Theme.getSize("default_margin").width - 30 - text: multiBuildPlateModel.getItem(index) ? multiBuildPlateModel.getItem(index).name : ""; - color: multiBuildPlateModel.activeBuildPlate == index ? palette.highlightedText : palette.text - elide: Text.ElideRight - } - - MouseArea - { - anchors.fill: parent; - onClicked: - { - Cura.SceneController.setActiveBuildPlate(index); - } - } - } - } - - ScrollView - { - id: buildPlateSelection - frameVisible: true - height: UM.Theme.getSize("build_plate_selection_size").height - width: parent.width - 2 * UM.Theme.getSize("default_margin").height - style: UM.Theme.styles.scrollview - - anchors - { - top: collapseButton.bottom; - topMargin: UM.Theme.getSize("default_margin").height; - left: parent.left; - leftMargin: UM.Theme.getSize("default_margin").height; - bottomMargin: UM.Theme.getSize("default_margin").height; - } - - Rectangle - { - parent: viewport - anchors.fill: parent - color: palette.light - } - - ListView - { - id: buildPlateListView - model: multiBuildPlateModel - width: parent.width - delegate: buildPlateDelegate - } - } - - Component { - id: objectDelegate - Rectangle - { - height: childrenRect.height - color: Cura.ObjectsModel.getItem(index).isSelected ? palette.highlight : index % 2 ? palette.base : palette.alternateBase - width: parent.width - Label - { - id: nodeNameLabel - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - width: parent.width - 2 * UM.Theme.getSize("default_margin").width - 30 - text: (index >= 0) && Cura.ObjectsModel.getItem(index) ? Cura.ObjectsModel.getItem(index).name : ""; - color: Cura.ObjectsModel.getItem(index).isSelected ? palette.highlightedText : (Cura.ObjectsModel.getItem(index).isOutsideBuildArea ? palette.mid : palette.text) - elide: Text.ElideRight - } - - Label - { - id: buildPlateNumberLabel - width: 20 - anchors.left: nodeNameLabel.right - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - text: Cura.ObjectsModel.getItem(index).buildPlateNumber != -1 ? Cura.ObjectsModel.getItem(index).buildPlateNumber + 1 : ""; - color: Cura.ObjectsModel.getItem(index).isSelected ? palette.highlightedText : palette.text - elide: Text.ElideRight - } - - MouseArea - { - anchors.fill: parent; - onClicked: - { - Cura.SceneController.changeSelection(index); - } - } - } - } - - // list all the scene nodes - ScrollView - { - id: objectsList - frameVisible: true - visible: !collapsed - width: parent.width - 2 * UM.Theme.getSize("default_margin").height - - anchors - { - top: buildPlateSelection.bottom; - topMargin: UM.Theme.getSize("default_margin").height; - left: parent.left; - leftMargin: UM.Theme.getSize("default_margin").height; - bottom: filterBuildPlateCheckbox.top; - bottomMargin: UM.Theme.getSize("default_margin").height; - } - - Rectangle - { - parent: viewport - anchors.fill: parent - color: palette.light - } - - ListView - { - id: listview - model: Cura.ObjectsModel - width: parent.width - delegate: objectDelegate - } - } - - CheckBox - { - id: filterBuildPlateCheckbox - visible: !collapsed - checked: UM.Preferences.getValue("view/filter_current_build_plate") - onClicked: UM.Preferences.setValue("view/filter_current_build_plate", checked) - - text: catalog.i18nc("@option:check","See only current build plate"); - style: UM.Theme.styles.checkbox; - - anchors - { - left: parent.left; - topMargin: UM.Theme.getSize("default_margin").height; - bottomMargin: UM.Theme.getSize("default_margin").height; - leftMargin: UM.Theme.getSize("default_margin").height; - bottom: arrangeAllBuildPlatesButton.top; - } - } - - Button - { - id: arrangeAllBuildPlatesButton; - text: catalog.i18nc("@action:button","Arrange to all build plates"); - style: UM.Theme.styles.print_setup_action_button - height: UM.Theme.getSize("objects_menu_button").height; - tooltip: ''; - anchors - { - topMargin: UM.Theme.getSize("default_margin").height; - left: parent.left; - leftMargin: UM.Theme.getSize("default_margin").height; - right: parent.right; - rightMargin: UM.Theme.getSize("default_margin").height; - bottom: arrangeBuildPlateButton.top; - bottomMargin: UM.Theme.getSize("default_margin").height; - } - action: Cura.Actions.arrangeAllBuildPlates; - } - - Button - { - id: arrangeBuildPlateButton; - text: catalog.i18nc("@action:button","Arrange current build plate"); - style: UM.Theme.styles.print_setup_action_button - height: UM.Theme.getSize("objects_menu_button").height; - tooltip: ''; - anchors - { - topMargin: UM.Theme.getSize("default_margin").height; - left: parent.left; - leftMargin: UM.Theme.getSize("default_margin").height; - right: parent.right; - rightMargin: UM.Theme.getSize("default_margin").height; - bottom: parent.bottom; - bottomMargin: UM.Theme.getSize("default_margin").height; - } - action: Cura.Actions.arrangeAll; - } -} diff --git a/resources/qml/PrinterSelector/MachineSelector.qml b/resources/qml/PrinterSelector/MachineSelector.qml index c5ed9f56dc..2a101e4ae3 100644 --- a/resources/qml/PrinterSelector/MachineSelector.qml +++ b/resources/qml/PrinterSelector/MachineSelector.qml @@ -135,7 +135,6 @@ Cura.ExpandablePopup scroll.height = Math.min(contentHeight, maximumHeight) popup.height = scroll.height + buttonRow.height } - } } diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index d1c4600f27..218055ba6e 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -581,7 +581,7 @@ "jobspecs_line": [2.0, 2.0], - "objects_menu_size": [20, 40], + "objects_menu_size": [15, 15], "objects_menu_size_collapsed": [20, 17], "build_plate_selection_size": [15, 5], "objects_menu_button": [0.3, 2.7],