Non-modal Drawer blocks shortcuts
-
Hello everyone,
I am in Qt 5.15.1, I stumbled on an issue while using the Drawer item. I followed the example "Qt Quick Controls - Side Panel" . The idea is to create a non-modal drawer usable as a fixed side dock when the the width of the window is sufficient.
Yet, I found out by trials and errors that Shortcut items, "shortcut" properties in Action andr more worrisome (for me) the "Alt+...." shortcuts in the ApplicationWindow.menuBar are unusable. If these are created as children of Drawer, no problem. If the drawer is not "visible", all shortcuts are working. The moment the non-modal drawer is "visible", the parent/ancestors' shortcuts are lost.
I found a little workaround in adding context: Qt.ApplicationShortcut to Shortcut and coupling each Action with a Shortcut to use this property. Yet, the menuBar is still out of reach of shortcuts.
I find strange that a non-modal Drawer blocks all its ancestors shortcuts. I know it's inheriting Popup behavior, but it makes using the Side Panel idea difficult.
Any thought ? Any idea for a workaround ? Do I need to couple all shortcuts from Action or menus with the snippet below :
Shortcut { sequence: KeySequence.Save context: Qt.ApplicationShortcut onActivated: saveAction.trigger() }
Here is a working example, switch the visible property of the drawer to see the difference. Type Ctrl+A, Ctrl+B and Alt+F and read the result.
import QtQuick.Window 2.15 import QtQuick 2.15 import QtQml 2.15 import QtQuick.Controls 2.15 ApplicationWindow { id: base width: 640 height: 480 visible: true title: qsTr("Hello World") Drawer { id: leftDrawer parent: base visible: true // switch it to false width: 200 height: base.height modal: false interactive: false edge: Qt.LeftEdge Rectangle{ color: "red" } Action { shortcut: "Ctrl+B" onTriggered: { console.log("Ctrl+B") } } } Action { shortcut: "Ctrl+A" onTriggered: { console.log("Ctrl+A") } } menuBar: MenuBar{ Menu { id: fileMenu title: qsTr("&File") MenuItem{ text: "Save" } } } }
Thank you for your interest !
-
To avoid using Drawer, I created my own. I hope this will help someone !
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQml 2.15 Item { id: root default property alias contents : container.data property bool interactive : false property double position : 1.0 property int edge : 0 property bool isVisible: false z:1 height: parent.height width: parent.width y: 0 onIsVisibleChanged: { isVisible ? position = 1.0 : position = 0 } Component.onCompleted: { container.children[0].anchors.fill = container if(state === "right_edge"){ root.x = (root.parent.width - root.width) + (root.width * (1 - position)) } } Behavior on position { NumberAnimation{ easing.type: Easing.InQuad duration: 200 } } function open(){ position = 1.0 } Item{ id: leftFeelingZone anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: parent.left width: 10 visible: edge === Qt.RightEdge && interactive TapHandler{ id: leftTapHandler enabled: interactive && root.position === 0 onTapped: { root.position = 1.0 } // grab: dragThreshold: 0 margin: 5 onGrabChanged: { root.position = 1.0 } } } FocusScope { id: dockBase anchors.fill: parent Rectangle { id: backgroundRectangle color: "white" anchors.fill: parent Item { id: container anchors.fill: parent } } onActiveFocusChanged: { if(!activeFocus && root.interactive && root.position === 1.0 ){ console.log("!activeFocus") root.position = 1.0 } } } Item{ id: rightFeelingZone anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.right width: 10 visible: edge === Qt.LeftEdge && interactive TapHandler{ id: rightTapHandler enabled: interactive && root.position === 0 onTapped: { console.log("rightTapHandler") root.position = 1.0 } // grab: dragThreshold: 0 margin: 5 onGrabChanged: { root.position = 1.0 } } } Connections { enabled: state === "right_edge" target: root.parent function onWidthChanged(){ root.x = (root.parent.width - root.width) + (root.width * (1 - position)) } } onWidthChanged: { if(state === "right_edge"){ root.x = (root.parent.width - root.width) + (root.width * (1 - position)) } } onPositionChanged: { if(state === "left_edge"){ root.x = 0 - (root.width * (1 - position)) } if(state === "right_edge"){ root.x = (root.parent.width - root.width) + (root.width * (1 - position)) } if(position === 0.0){ isVisible = false } else if(position === 1.0){ isVisible = true } dockBase.visible = position > 0.0 } states: [ State{ name: "left_edge" when: root.edge === Qt.LeftEdge }, State{ name: "right_edge" when: root.edge === Qt.RightEdge } ] Item{ id: overlayLayer parent: Overlay.overlay visible: root.interactive && root.position === 1.0 height: root.height y: Overlay.overlay.mapToItem(root.parent, root.x, root.y).y TapHandler { id: overlayTapHandler enabled: root.interactive && root.position === 1.0 onTapped: { console.log('overlay pressed') root.position = 0.0 eventPoint.accepted = false } } states: [ State{ name: "left_edge" when: root.edge === Qt.LeftEdge PropertyChanges { target: overlayLayer x: Overlay.overlay.mapToItem(root.parent, root.width, root.y).x width: Overlay.overlay.width - root.width } }, State{ name: "right_edge" when: root.edge === Qt.RightEdge PropertyChanges { target: overlayLayer x: Overlay.overlay.mapToItem(root.parent, 0, 0).x width: Overlay.overlay.width - root.width } } ] } }
-
I reported the bug to Qt : https://bugreports.qt.io/browse/QTBUG-86801