446 lines
14 KiB
QML
446 lines
14 KiB
QML
// Copyright (C) 2024 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
|
|
|
import QtCore
|
|
import QtQuick
|
|
import QtQuick.Layouts
|
|
import QtQuick.Controls
|
|
import QtQuick.Dialogs
|
|
|
|
ApplicationWindow {
|
|
id: window
|
|
width: 800
|
|
height: 600
|
|
visible: true
|
|
title: qsTr("Menus - style: %1").arg(currentStyle)
|
|
|
|
required property string currentStyle
|
|
|
|
Shortcut {
|
|
sequence: "Ctrl+Q"
|
|
onActivated: Qt.quit()
|
|
}
|
|
|
|
Settings {
|
|
id: settings
|
|
|
|
property alias windowX: window.x
|
|
property alias windowY: window.y
|
|
}
|
|
|
|
menuBar: MenuBar {
|
|
visible: menuBarVisibleSwitch.checked
|
|
|
|
Menu {
|
|
id: fileMenu
|
|
objectName: "file"
|
|
title: qsTr("&File")
|
|
popupType: popupTypeCombo.popupType()
|
|
ContextAction { text: qsTr("&New...") }
|
|
ContextMenuItem { text: "menuItem" }
|
|
ContextAction { text: qsTr("&Open...") }
|
|
ContextAction { text: qsTr("&Save") }
|
|
ContextAction { text: qsTr("Save &As...") }
|
|
Menu {
|
|
title: qsTr("Sub...")
|
|
ContextAction { text: qsTr("Sub action 1") }
|
|
ContextAction { text: qsTr("Sub action 2") }
|
|
Menu {
|
|
title: qsTr("SubSub...")
|
|
ContextAction { text: qsTr("SubSub action 1") }
|
|
ContextAction { text: qsTr("SubSub action 2") }
|
|
}
|
|
}
|
|
MenuSeparator { }
|
|
ContextAction {
|
|
text: qsTr("&Quit")
|
|
// This is needed for macOS since it takes priority over the Shortcut.
|
|
onTriggered: Qt.quit()
|
|
}
|
|
Action {
|
|
text: qsTr("Remove menu")
|
|
onTriggered: menuBar.removeMenu(fileMenu)
|
|
}
|
|
}
|
|
Menu {
|
|
id: editMenu
|
|
objectName: "edit"
|
|
title: qsTr("&Edit")
|
|
popupType: popupTypeCombo.popupType()
|
|
ContextAction {
|
|
id: cutAction
|
|
text: qsTr("Cut")
|
|
enabled: textArea.selectedText.length > 0
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Copy")
|
|
enabled: textArea.selectedText.length > 0
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Paste")
|
|
enabled: textArea.activeFocus
|
|
}
|
|
|
|
MenuSeparator {}
|
|
|
|
Action {
|
|
text: qsTr("Checkable menu")
|
|
checkable: true
|
|
checked: true
|
|
}
|
|
Action {
|
|
text: qsTr("Remove menu")
|
|
onTriggered: menuBar.removeMenu(editMenu)
|
|
}
|
|
Menu {
|
|
id: editSubMenu
|
|
title: qsTr("Find / Replace")
|
|
Action { text: qsTr("&Find") }
|
|
}
|
|
|
|
MenuSeparator {}
|
|
|
|
ContextAction {
|
|
text: qsTr("Dummy Action")
|
|
shortcut: "Ctrl+I"
|
|
}
|
|
}
|
|
MenuBarItem {
|
|
id: explicitMenuBarItem
|
|
menu: Menu {
|
|
id: menuBarItemMenu
|
|
objectName: "MenuBarItem"
|
|
title: "MenuBarItem"
|
|
popupType: popupTypeCombo.popupType()
|
|
ContextAction { text: qsTr("Action") }
|
|
Action {
|
|
text: qsTr("Remove menu")
|
|
onTriggered: menuBar.removeMenu(menuBarItemMenu)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: extraMenuComp
|
|
Menu {
|
|
id: extraMenu
|
|
objectName: "Extra"
|
|
title: qsTr("&Extra")
|
|
ContextAction { text: qsTr("&Trigger") }
|
|
Action {
|
|
text: qsTr("Remove Extra menu")
|
|
onTriggered: menuBar.removeMenu(extraMenu)
|
|
}
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
|
|
Label {
|
|
text: qsTr("Right click on the window background to open a context menu. "
|
|
+ "Right click on the TextArea to access its edit context menu.\n\n"
|
|
+ "Things to check:\n\n"
|
|
+ "- Do the menu items trigger their actions (check console for output)?\n"
|
|
+ "- Do checkable menu items work?\n"
|
|
+ "- Do the Edit menu items (in the MenuBar menu and edit context menu)"
|
|
+ " work as expected with the TextArea?\n"
|
|
+ " - Are they enabled/disabled as expected?\n"
|
|
+ " - Does the TextArea keep focus after interacting with the Edit menu items?\n"
|
|
+ "- Does adding and removing menu items work?\n"
|
|
+ "- Do the menus in the MenuBar work?\n"
|
|
+ "- Can you add and remove menus from the MenuBar?\n"
|
|
+ "- Do shortcuts work?")
|
|
verticalAlignment: Text.AlignVCenter
|
|
wrapMode: Text.Wrap
|
|
|
|
Layout.alignment: Qt.AlignHCenter
|
|
Layout.preferredWidth: window.width * 0.5
|
|
Layout.fillHeight: true
|
|
}
|
|
|
|
GroupBox {
|
|
title: qsTr("Context menu")
|
|
|
|
Layout.fillWidth: true
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
|
|
RowLayout {
|
|
Label {
|
|
text: qsTr("Popup type")
|
|
}
|
|
|
|
ComboBox {
|
|
id: popupTypeCombo
|
|
model: ["Item", "Window", "Native"]
|
|
onCurrentIndexChanged: CppSettings.popupType = currentIndex
|
|
currentIndex: CppSettings.popupType
|
|
|
|
function popupType() {
|
|
if (currentText === "Window")
|
|
return Popup.Window
|
|
else if (currentText === "Native")
|
|
return Popup.Native
|
|
else
|
|
return Popup.Item
|
|
}
|
|
}
|
|
}
|
|
|
|
Row {
|
|
Button {
|
|
text: qsTr("Add action")
|
|
onClicked: backgroundContextMenu.appendAction()
|
|
}
|
|
Button {
|
|
text: qsTr("Remove action")
|
|
onClicked: backgroundContextMenu.removeLastAction()
|
|
}
|
|
|
|
Button {
|
|
text: qsTr("Add sub-menu action")
|
|
onClicked: subMenu.appendAction()
|
|
}
|
|
Button {
|
|
text: qsTr("Remove sub-menu action")
|
|
onClicked: subMenu.removeLastAction()
|
|
}
|
|
}
|
|
Row {
|
|
Switch {
|
|
text: qsTr("Don't use native menu windows")
|
|
checked: CppSettings.dontUseNativeMenuWindows
|
|
onClicked: CppSettings.dontUseNativeMenuWindows = checked
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TextArea {
|
|
id: textArea
|
|
text: qsTr("Dummy TextArea to test disabled menu items")
|
|
|
|
Layout.fillWidth: true
|
|
Layout.minimumHeight: 100
|
|
}
|
|
|
|
Component {
|
|
id: menuBarItemComp
|
|
MenuBarItem {
|
|
}
|
|
}
|
|
|
|
MessageDialog {
|
|
id: restartNeededDialog
|
|
buttons: MessageDialog.Ok
|
|
text: "Your current changes requires a restart to take effect!"
|
|
}
|
|
|
|
GroupBox {
|
|
title: qsTr("MenuBar")
|
|
|
|
Layout.fillWidth: true
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
|
|
Row {
|
|
Switch {
|
|
text: qsTr("Don't use native menu bar")
|
|
checked: CppSettings.dontUseNativeMenuBar
|
|
|
|
onClicked: {
|
|
CppSettings.dontUseNativeMenuBar = checked
|
|
restartNeededDialog.open()
|
|
}
|
|
}
|
|
Switch {
|
|
id: menuBarVisibleSwitch
|
|
text: qsTr("MenuBar visible")
|
|
checked: true
|
|
}
|
|
}
|
|
Row {
|
|
Button {
|
|
text: "Append menu"
|
|
onClicked: {
|
|
let menu = extraMenuComp.createObject(menuBar, { title: "Extra " + menuBar.count })
|
|
menuBar.addMenu(menu)
|
|
}
|
|
}
|
|
Button {
|
|
text: "Prepend menu"
|
|
onClicked: {
|
|
let menu = extraMenuComp.createObject(menuBar, { title: "Extra " + menuBar.count })
|
|
menuBar.insertMenu(0, menu)
|
|
}
|
|
}
|
|
Button {
|
|
text: qsTr("Add file menu")
|
|
onClicked: menuBar.addMenu(fileMenu)
|
|
}
|
|
Button {
|
|
text: "Change labels"
|
|
onClicked: {
|
|
fileMenu.title = "File changed"
|
|
cutAction.text = "Cut changed"
|
|
}
|
|
}
|
|
Button {
|
|
text: "toggle delegate"
|
|
onClicked: menuBar.delegate = menuBar.delegate ? null : menuBarItemComp
|
|
}
|
|
Switch {
|
|
text: "MenuBarItem visible"
|
|
checked: true
|
|
onCheckedChanged: explicitMenuBarItem.visible = checked
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TapHandler {
|
|
objectName: "backgroundTouchTapHandler"
|
|
acceptedDevices: PointerDevice.TouchScreen
|
|
onLongPressed: backgroundContextMenu.popup()
|
|
}
|
|
|
|
Component {
|
|
id: actionComponent
|
|
|
|
Action {}
|
|
}
|
|
|
|
component ContextAction: Action {
|
|
onCheckedChanged: (checked) => print("checked of \"" + text + "\" changed to " + checked)
|
|
onTriggered: print("triggered \"" + text + "\"")
|
|
}
|
|
|
|
component ContextMenuItem: MenuItem {
|
|
onCheckedChanged: print("checked of \"" + text + "\" changed to " + checked)
|
|
onTriggered: print("triggered \"" + text + "\"")
|
|
}
|
|
|
|
contentItem.ContextMenu.menu: Menu {
|
|
id: backgroundContextMenu
|
|
objectName: "backgroundContextMenu"
|
|
popupType: popupTypeCombo.popupType()
|
|
|
|
function appendAction() {
|
|
let action = actionComponent.createObject(null, { text: qsTr("Extra context menu item") })
|
|
backgroundContextMenu.addAction(action)
|
|
}
|
|
|
|
function removeLastAction() {
|
|
// TODO: Can't use count here because it's 0: it uses contentModel->count(), but native menu items
|
|
// are not Qt Quick items, so we either need to document that you should use contentData.count
|
|
// or add an "actions" property. The problem with contentData is that it could contain
|
|
// non-Action objects. Another potential issue is that "It is not re-ordered when items are inserted or moved",
|
|
// making it unreliable as a general purpose container of actions if users add or remove them dynamically.
|
|
backgroundContextMenu.removeAction(backgroundContextMenu.actionAt(backgroundContextMenu.contentData.length - 1))
|
|
}
|
|
|
|
ContextAction {
|
|
text: qsTr("Context menu item")
|
|
shortcut: "A"
|
|
}
|
|
ContextMenuItem {
|
|
text: qsTr("Checkable context menu item")
|
|
checkable: true
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Checked context menu item")
|
|
checkable: true
|
|
checked: true
|
|
shortcut: "C"
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Disabled context menu item")
|
|
enabled: false
|
|
shortcut: "D"
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Checked and disabled context menu item")
|
|
checkable: true
|
|
checked: true
|
|
enabled: false
|
|
shortcut: "E"
|
|
}
|
|
|
|
MenuSeparator {}
|
|
|
|
ContextAction {
|
|
text: qsTr("Context menu item with icon (name)")
|
|
icon.name: "mail-send"
|
|
}
|
|
|
|
ContextAction {
|
|
text: qsTr("Context menu item with icon (source)")
|
|
icon.source: "qrc:/qt/qml/Menus/icons/warning.png"
|
|
}
|
|
|
|
ContextAction {
|
|
text: qsTr("Context menu item with disabled icon (source)")
|
|
icon.source: "qrc:/qt/qml/Menus/icons/warning.png"
|
|
enabled: false
|
|
}
|
|
|
|
MenuSeparator {}
|
|
|
|
Menu {
|
|
id: subMenu
|
|
title: qsTr("Sub-menu")
|
|
objectName: title
|
|
popupType: popupTypeCombo.popupType()
|
|
|
|
function appendAction() {
|
|
let action = actionComponent.createObject(null, { text: qsTr("Extra sub-menu item") })
|
|
subMenu.addAction(action)
|
|
}
|
|
|
|
function removeLastAction() {
|
|
subMenu.removeAction(subMenu.actionAt(subMenu.contentData.length - 1))
|
|
}
|
|
|
|
ContextAction {
|
|
text: qsTr("Sub-menu item")
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Checkable sub-menu item")
|
|
checkable: true
|
|
shortcut: "G"
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Checked sub-menu item")
|
|
checkable: true
|
|
checked: true
|
|
}
|
|
|
|
MenuSeparator {}
|
|
|
|
ContextAction {
|
|
text: qsTr("Disabled sub-menu item")
|
|
enabled: false
|
|
shortcut: "I"
|
|
}
|
|
ContextAction {
|
|
text: qsTr("Checked and disabled sub-menu item")
|
|
checkable: true
|
|
checked: true
|
|
enabled: false
|
|
shortcut: "J"
|
|
}
|
|
Menu {
|
|
title: qsTr("SubSub...")
|
|
ContextAction { text: qsTr("SubSub action 1") }
|
|
ContextAction { text: qsTr("SubSub action 2") }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|