From 11b557b3d97f5f797e607ac8c583bd8b8499063e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 8 Apr 2022 11:57:03 +0200 Subject: [PATCH] Replace material sub-menus with custom Popup The sub-menus were giving segfaults for some reason. We couldn't figure out how to circumvent that. So now we're at a last resort: Implement the whole thing ourselves, but with Popup instead of Menu. Contributes to issue CURA-8640. --- resources/qml/Menus/MaterialBrandMenu.qml | 101 ++++++++++++++++++++++ resources/qml/Menus/MaterialMenu.qml | 41 +-------- resources/qml/Widgets/MenuItem.qml | 4 +- 3 files changed, 108 insertions(+), 38 deletions(-) create mode 100644 resources/qml/Menus/MaterialBrandMenu.qml diff --git a/resources/qml/Menus/MaterialBrandMenu.qml b/resources/qml/Menus/MaterialBrandMenu.qml new file mode 100644 index 0000000000..f6fcbe3039 --- /dev/null +++ b/resources/qml/Menus/MaterialBrandMenu.qml @@ -0,0 +1,101 @@ +// Copyright (c) 2022 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.4 +import QtQuick.Layouts 2.7 + +import UM 1.5 as UM +import Cura 1.7 as Cura + +/* This element is a workaround for MacOS, where it can crash in Qt6 when nested menus are closed. +Instead we'll use a pop-up which doesn't seem to have that problem. */ + +Cura.MenuItem +{ + id: materialBrandMenu + overrideShowArrow: true + + contentItem: MouseArea + { + hoverEnabled: true + + RowLayout + { + spacing: 0 + opacity: materialBrandMenu.enabled ? 1 : 0.5 + + Item + { + // Spacer + width: UM.Theme.getSize("default_margin").width + } + + UM.Label + { + text: replaceText(materialBrandMenu.text) + Layout.fillWidth: true + Layout.fillHeight:true + elide: Label.ElideRight + wrapMode: Text.NoWrap + } + + Item + { + Layout.fillWidth: true + } + + Item + { + // Right side margin + width: UM.Theme.getSize("default_margin").width + } + } + + onEntered: showTimer.restartTimer() + onExited: hideTimer.restartTimer() + } + + Timer + { + id: showTimer + interval: 100 + function restartTimer() + { + restart(); + running = materialBrandMenu.enabled && materialBrandMenu.contentItem.containsMouse; + hideTimer.running = false; + } + onTriggered: menuPopup.open() + } + Timer + { + id: hideTimer + interval: 250 + function restartTimer() //Restart but re-evaluate the running property then. + { + restart(); + running = materialBrandMenu.enabled && !materialBrandMenu.contentItem.containsMouse && !submenuArea.containsMouse; + showTimer.running = false; + } + onTriggered: menuPopup.close() + } + + Popup + { + id: menuPopup + x: parent.width + y: 0 + width: 100 + height: 100 + + MouseArea + { + id: submenuArea + anchors.fill: parent + + hoverEnabled: true + onEntered: hideTimer.restartTimer() + } + } +} diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 5ffe4efbb6..fd1236feb7 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -98,45 +98,12 @@ Cura.Menu Instantiator { model: brandModel - Cura.Menu + delegate: Cura.MaterialBrandMenu { - id: brandMenu - title: brandName - property string brandName: model.name - property var brandMaterials: model.material_types - - Instantiator - { - model: brandMaterials - delegate: Cura.Menu - { - id: brandMaterialsMenu - title: materialName - property string materialName: model.name - property var brandMaterialColors: model.colors - - Instantiator - { - model: brandMaterialColors - delegate: Cura.MenuItem - { - text: model.name - checkable: true - enabled: isActiveExtruderEnabled - checked: model.id === materialMenu.activeMaterialId - - onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) - } - onObjectAdded: function(index, object) { brandMaterialsMenu.insertItem(index, object)} - onObjectRemoved: function(object) {brandMaterialsMenu.removeItem(object)} - } - } - onObjectAdded: function(index, object) { brandMenu.insertMenu(index, object)} - onObjectRemoved: function(object) {brandMenu.removeMenu(object)} - } + text: model.name } - onObjectAdded: function(index, object) {materialMenu.insertMenu(index + 4, object)} - onObjectRemoved: function(object) { materialMenu.removeMenu(object)} + onObjectAdded: function(index, object) { materialMenu.insertItem(index + 4, object)} + onObjectRemoved: function(object) { materialMenu.removeItem(index) } } Cura.MenuSeparator {} diff --git a/resources/qml/Widgets/MenuItem.qml b/resources/qml/Widgets/MenuItem.qml index 0b01f95217..30df317d82 100644 --- a/resources/qml/Widgets/MenuItem.qml +++ b/resources/qml/Widgets/MenuItem.qml @@ -16,9 +16,11 @@ UM.MenuItem implicitHeight: UM.Theme.getSize("menu").height + UM.Theme.getSize("narrow_margin").height implicitWidth: UM.Theme.getSize("menu").width + property bool overrideShowArrow: false + arrow: UM.RecolorImage { - visible: menuItem.subMenu + visible: menuItem.subMenu || overrideShowArrow height: UM.Theme.getSize("default_arrow").height width: height anchors.verticalCenter: parent.verticalCenter