diff --git a/kirigami.qrc b/kirigami.qrc
--- a/kirigami.qrc
+++ b/kirigami.qrc
@@ -18,6 +18,8 @@
src/controls/InlineMessage.qml
src/controls/ToolBarApplicationHeader.qml
src/controls/private/PrivateActionToolButton.qml
+ src/controls/private/GlobalDrawerActionItem.qml
+ src/controls/private/ContextDrawerActionItem.qml
src/controls/private/RefreshableScrollView.qml
src/controls/private/SwipeItemEventFilter.qml
src/controls/private/PageActionPropertyGroup.qml
diff --git a/kirigami.qrc.in b/kirigami.qrc.in
--- a/kirigami.qrc.in
+++ b/kirigami.qrc.in
@@ -18,6 +18,8 @@
@kirigami_QML_DIR@/src/controls/InlineMessage.qml
@kirigami_QML_DIR@/src/controls/ToolBarApplicationHeader.qml
@kirigami_QML_DIR@/src/controls/private/PrivateActionToolButton.qml
+ @kirigami_QML_DIR@/src/controls/private/GlobalDrawerActionItem.qml
+ @kirigami_QML_DIR@/src/controls/private/ContextDrawerActionItem.qml
@kirigami_QML_DIR@/src/controls/private/RefreshableScrollView.qml
@kirigami_QML_DIR@/src/controls/private/SwipeItemEventFilter.qml
@kirigami_QML_DIR@/src/controls/private/PageActionPropertyGroup.qml
diff --git a/src/controls/Action.qml b/src/controls/Action.qml
--- a/src/controls/Action.qml
+++ b/src/controls/Action.qml
@@ -147,8 +147,22 @@
*/
property bool separator: false
+ /**
+ * expandible: bool
+ * When true, actions in globalDrawers and contextDrawers will become titles displaying te child actions as sub items
+ * @since 2.6
+ */
+ property bool expandible: false
+
+ property QtObject parent
+
default property alias children: root.__children
property list __children
+ onChildrenChanged: {
+ for (var i in children) {
+ children[i].parent = root
+ }
+ }
property Shortcut __shortcut: Shortcut {
property bool checked: false
id: shortcutItem
diff --git a/src/controls/BasicListItem.qml b/src/controls/BasicListItem.qml
--- a/src/controls/BasicListItem.qml
+++ b/src/controls/BasicListItem.qml
@@ -84,16 +84,18 @@
Layout.minimumHeight: size
Layout.maximumHeight: size
Layout.minimumWidth: size
- selected: layout.indicateActiveFocus && (listItem.highlighted || listItem.checked || listItem.pressed)
+ selected: layout.indicateActiveFocus && (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents))
color: listItem.icon && listItem.icon.color && listItem.icon.color.a > 0 ? listItem.icon.color : (selected ? Theme.highlightedTextColor : Theme.textColor)
+ opacity: 1
}
QQC2.Label {
id: labelItem
text: listItem.text
Layout.fillWidth: true
- color: layout.indicateActiveFocus && (listItem.highlighted || listItem.checked || listItem.pressed) ? listItem.activeTextColor : listItem.textColor
+ color: layout.indicateActiveFocus && (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents)) ? listItem.activeTextColor : listItem.textColor
elide: Text.ElideRight
font: listItem.font
+ opacity: 1
}
}
}
diff --git a/src/controls/ContextDrawer.qml b/src/controls/ContextDrawer.qml
--- a/src/controls/ContextDrawer.qml
+++ b/src/controls/ContextDrawer.qml
@@ -21,6 +21,7 @@
import QtQuick.Layouts 1.2
import org.kde.kirigami 2.4
+import "private"
import "templates/private"
/**
@@ -133,39 +134,17 @@
text: root.title
}
}
- delegate: BasicListItem {
- id: listItem
-
- readonly property bool isSeparator: modelData.hasOwnProperty("separator") && modelData.separator
-
- checked: modelData.checked
- icon: modelData.icon
- supportsMouseEvents: true
- separatorVisible: false
- reserveSpaceForIcon: !isSeparator
- reserveSpaceForLabel: !isSeparator
-
- label: model ? (model.tooltip ? model.tooltip : model.text) : (modelData.tooltip ? modelData.tooltip : modelData.text)
- enabled: !isSeparator && (model ? model.enabled : modelData.enabled)
- visible: model ? model.visible : modelData.visible
- opacity: enabled ? 1.0 : 0.6
-
- Separator {
- id: separatorAction
-
- visible: listItem.isSeparator
- Layout.fillWidth: true
+ delegate: Column {
+ width: parent.width
+ ContextDrawerActionItem {
+ width: parent.width
}
-
- onClicked: {
- root.drawerOpen = false;
- if (modelData && modelData.trigger !== undefined) {
- modelData.trigger();
- // assume the model is a list of QAction or Action
- } else if (menu.model.length > index) {
- menu.model[index].trigger();
- } else {
- console.warning("Don't know how to trigger the action")
+ Repeater {
+ model: modelData.hasOwnProperty("expandible") && modelData.expandible ? modelData.children : null
+ delegate: ContextDrawerActionItem {
+ width: parent.width
+ leftPadding: Units.largeSpacing * 2
+ opacity: !root.collapsed
}
}
}
diff --git a/src/controls/GlobalDrawer.qml b/src/controls/GlobalDrawer.qml
--- a/src/controls/GlobalDrawer.qml
+++ b/src/controls/GlobalDrawer.qml
@@ -127,7 +127,6 @@
*/
property list actions
-
/**
* content: list- default property
* Any random Item can be instantiated inside the drawer and
@@ -242,6 +241,7 @@
id: mainFlickable
contentWidth: width
contentHeight: mainColumn.Layout.minimumHeight
+
ColumnLayout {
id: mainColumn
width: mainFlickable.width
@@ -455,122 +455,20 @@
Repeater {
id: actionsRepeater
- model: actions
- delegate:
- BasicListItem {
- id: listItem
- supportsMouseEvents: true
- readonly property bool wideMode: width > height * 2
- readonly property bool isSeparator: modelData.hasOwnProperty("separator") && modelData.separator
- reserveSpaceForIcon: !isSeparator
- reserveSpaceForLabel: !isSeparator
- checked: modelData.checked || (actionsMenu && actionsMenu.visible)
+ model: root.actions
+ delegate: Column {
width: parent.width
-
- icon: modelData.iconName
-
- label: width > height * 2 ? MnemonicData.richTextLabel : ""
-
- MnemonicData.enabled: listItem.enabled && listItem.visible
- MnemonicData.controlType: MnemonicData.MenuItem
- MnemonicData.label: modelData.text
- property ActionsMenu actionsMenu: ActionsMenu {
- x: Qt.application.layoutDirection == Qt.RightToLeft ? -width : listItem.width
- actions: modelData.children
- submenuComponent: Component {
- ActionsMenu {}
- }
- onVisibleChanged: {
- if (visible) {
- stackView.openSubMenu = listItem.actionsMenu;
- } else if (stackView.openSubMenu == listItem.actionsMenu) {
- stackView.openSubMenu = null;
- }
- }
- }
-
- separatorVisible: false
- //TODO: animate the hide by collapse
- visible: (model ? model.visible || model.visible===undefined : modelData.visible) && opacity > 0
- opacity: (!root.collapsed || icon.length > 0)
- Behavior on opacity {
- OpacityAnimator {
- duration: Units.longDuration/2
- easing.type: Easing.InOutQuad
- }
- }
- enabled: !isSeparator && ( (model && model.enabled !== undefined) ? model.enabled : modelData.enabled)
- opacity: enabled ? 1.0 : 0.3
-
- Separator {
- id: separatorAction
-
- visible: listItem.isSeparator
- Layout.fillWidth: true
- }
-
- Icon {
- Shortcut {
- sequence: listItem.MnemonicData.sequence
- onActivated: listItem.clicked()
- }
- isMask: true
- Layout.alignment: Qt.AlignVCenter
- Layout.rightMargin: !Settings.isMobile && mainFlickable.contentHeight > mainFlickable.height ? Units.gridUnit : 0
- Layout.leftMargin: !root.collapsed ? 0 : parent.width - listItem.width
- Layout.preferredHeight: !root.collapsed ? Units.iconSizes.smallMedium : Units.iconSizes.small/2
- selected: listItem.checked || listItem.pressed
- Layout.preferredWidth: Layout.preferredHeight
- source: (LayoutMirroring.enabled ? "go-next-symbolic-rtl" : "go-next-symbolic")
- visible: !listItem.isSeparator && modelData.children!==undefined && modelData.children.length > 0
- }
- data: [
- QQC2.ToolTip {
- visible: !listItem.isSeparator && (modelData.tooltip.length || root.collapsed) && (!actionsMenu || !actionsMenu.visible) && listItem.hovered && text.length > 0
- text: modelData.tooltip.length ? modelData.tooltip : modelData.text
- delay: 1000
- timeout: 5000
- y: listItem.height/2 - height/2
- x: Qt.application.layoutDirection == Qt.RightToLeft ? -width : listItem.width
- }
- ]
-
- onHoveredChanged: {
- if (!hovered) {
- return;
- }
- if (stackView.openSubMenu) {
- stackView.openSubMenu.visible = false;
-
- if (!listItem.actionsMenu.hasOwnProperty("count") || listItem.actionsMenu.count>0) {
- if (listItem.actionsMenu.hasOwnProperty("popup")) {
- listItem.actionsMenu.popup(listItem, listItem.width, 0)
- } else {
- listItem.actionsMenu.visible = true;
- }
- }
- }
+ GlobalDrawerActionItem {
+ id: drawerItem
+ width: parent.width
}
- onClicked: {
- modelData.trigger();
- if (modelData.children!==undefined && modelData.children.length > 0) {
- if (root.collapsed) {
- //fallbacks needed for Qt 5.9
- if ((!listItem.actionsMenu.hasOwnProperty("count") || listItem.actionsMenu.count>0) && !listItem.actionsMenu.visible) {
- stackView.openSubMenu = listItem.actionsMenu;
- if (listItem.actionsMenu.hasOwnProperty("popup")) {
- listItem.actionsMenu.popup(listItem, listItem.width, 0)
- } else {
- listItem.actionsMenu.visible = true;
- }
- }
- } else {
- stackView.push(menuComponent, {model: modelData.children, level: level + 1, current: modelData });
- }
- } else if (root.resetMenuOnTriggered) {
- root.resetMenu();
+ Repeater {
+ model: drawerItem.visible && modelData.hasOwnProperty("expandible") && modelData.expandible ? modelData.children : null
+ delegate: GlobalDrawerActionItem {
+ width: parent.width
+ leftPadding: Units.largeSpacing * 2
+ opacity: !root.collapsed
}
- checked = Qt.binding(function() { return modelData.checked || (actionsMenu && actionsMenu.visible) });
}
}
}
diff --git a/src/controls/private/ContextDrawerActionItem.qml b/src/controls/private/ContextDrawerActionItem.qml
new file mode 100644
--- /dev/null
+++ b/src/controls/private/ContextDrawerActionItem.qml
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019 Marco Martin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0 as QQC2
+import QtQuick.Layouts 1.2
+import org.kde.kirigami 2.5
+
+BasicListItem {
+ id: listItem
+
+ readonly property bool isSeparator: modelData.hasOwnProperty("separator") && modelData.separator
+
+ readonly property bool isExpandible: modelData && modelData.hasOwnProperty("expandible") && modelData.expandible
+
+ checked: modelData.checked
+ icon: modelData.icon
+ separatorVisible: false
+ reserveSpaceForIcon: !isSeparator
+ reserveSpaceForLabel: !isSeparator
+
+ label: model ? (model.tooltip ? model.tooltip : model.text) : (modelData.tooltip ? modelData.tooltip : modelData.text)
+ hoverEnabled: (!isExpandible || root.collapsed) && !Settings.tabletMode
+ sectionDelegate: isExpandible
+ font.pointSize: isExpandible ? Theme.defaultFont.pointSize * 1.30 : Theme.defaultFont.pointSize
+
+ enabled: !isExpandible && !isSeparator && (model ? model.enabled : modelData.enabled)
+ visible: model ? model.visible : modelData.visible
+ opacity: enabled || isExpandible ? 1.0 : 0.6
+
+ Separator {
+ id: separatorAction
+
+ visible: listItem.isSeparator
+ Layout.fillWidth: true
+
+ ActionsMenu {
+ id: actionsMenu
+ y: Settings.isMobile ? -height : listItem.height
+ z: 9999
+ actions: modelData.children
+ submenuComponent: Component {
+ ActionsMenu {}
+ }
+ }
+ }
+
+ Icon {
+ isMask: true
+ Layout.alignment: Qt.AlignVCenter
+ Layout.rightMargin: !Settings.isMobile && mainFlickable.contentHeight > mainFlickable.height ? Units.gridUnit : 0
+ Layout.preferredHeight: Units.iconSizes.small/2
+ selected: listItem.checked || listItem.pressed
+ Layout.preferredWidth: Layout.preferredHeight
+ source: "go-up-symbolic"
+ visible: !isExpandible && !listItem.isSeparator && modelData.children!== undefined && modelData.children.length > 0
+ }
+
+ onPressed: {
+ if (modelData.children.length > 0) {
+ actionsMenu.open();
+ }
+ }
+ onClicked: {
+ if (modelData.children.length == 0) {
+ root.drawerOpen = false;
+ }
+
+ if (modelData && modelData.trigger !== undefined) {
+ modelData.trigger();
+ // assume the model is a list of QAction or Action
+ } else if (menu.model.length > index) {
+ menu.model[index].trigger();
+ } else {
+ console.warning("Don't know how to trigger the action")
+ }
+ }
+}
diff --git a/src/controls/private/GlobalDrawerActionItem.qml b/src/controls/private/GlobalDrawerActionItem.qml
new file mode 100644
--- /dev/null
+++ b/src/controls/private/GlobalDrawerActionItem.qml
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2015 Marco Martin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0 as QQC2
+import QtQuick.Layouts 1.2
+import org.kde.kirigami 2.5
+
+BasicListItem {
+ id: listItem
+ supportsMouseEvents: (!isExpandible || root.collapsed)
+ readonly property bool wideMode: width > height * 2
+ readonly property bool isSeparator: modelData.hasOwnProperty("separator") && modelData.separator
+
+ readonly property bool isExpandible: modelData && modelData.hasOwnProperty("expandible") && modelData.expandible
+
+ reserveSpaceForIcon: !isSeparator
+ reserveSpaceForLabel: !isSeparator
+ checked: modelData.checked || (actionsMenu && actionsMenu.visible)
+ width: parent.width
+
+ icon: modelData.iconName
+
+ label: width > height * 2 ? MnemonicData.richTextLabel : ""
+
+ MnemonicData.enabled: listItem.enabled && listItem.visible
+ MnemonicData.controlType: MnemonicData.MenuItem
+ MnemonicData.label: modelData.text
+ property ActionsMenu actionsMenu: ActionsMenu {
+ x: Qt.application.layoutDirection == Qt.RightToLeft ? -width : listItem.width
+ actions: modelData.children
+ submenuComponent: Component {
+ ActionsMenu {}
+ }
+ onVisibleChanged: {
+ if (visible) {
+ stackView.openSubMenu = listItem.actionsMenu;
+ } else if (stackView.openSubMenu == listItem.actionsMenu) {
+ stackView.openSubMenu = null;
+ }
+ }
+ }
+
+ separatorVisible: false
+ //TODO: animate the hide by collapse
+ visible: (model ? model.visible || model.visible===undefined : modelData.visible) && opacity > 0
+ opacity: !root.collapsed || icon.length > 0
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: Units.longDuration/2
+ easing.type: Easing.InOutQuad
+ }
+ }
+ enabled: !isSeparator && ( (model && model.enabled != undefined) ? model.enabled : modelData.enabled)
+
+ hoverEnabled: (!isExpandible || root.collapsed) && !Settings.tabletMode
+ sectionDelegate: isExpandible
+ font.pointSize: isExpandible ? Theme.defaultFont.pointSize * 1.30 : Theme.defaultFont.pointSize
+
+
+ Separator {
+ id: separatorAction
+
+ visible: listItem.isSeparator
+ Layout.fillWidth: true
+ }
+
+ Icon {
+ Shortcut {
+ sequence: listItem.MnemonicData.sequence
+ onActivated: listItem.clicked()
+ }
+ isMask: true
+ Layout.alignment: Qt.AlignVCenter
+ Layout.rightMargin: !Settings.isMobile && mainFlickable.contentHeight > mainFlickable.height ? Units.gridUnit : 0
+ Layout.leftMargin: !root.collapsed ? 0 : parent.width - listItem.width
+ Layout.preferredHeight: !root.collapsed ? Units.iconSizes.smallMedium : Units.iconSizes.small/2
+ selected: listItem.checked || listItem.pressed
+ Layout.preferredWidth: Layout.preferredHeight
+ source: (LayoutMirroring.enabled ? "go-next-symbolic-rtl" : "go-next-symbolic")
+ visible: (!isExpandible || root.collapsed) && !listItem.isSeparator && modelData.children!==undefined && modelData.children.length > 0
+ }
+ data: [
+ QQC2.ToolTip {
+ visible: !listItem.isSeparator && (modelData.tooltip.length || root.collapsed) && (!actionsMenu || !actionsMenu.visible) && listItem.hovered && text.length > 0
+ text: modelData.tooltip.length ? modelData.tooltip : modelData.text
+ delay: 1000
+ timeout: 5000
+ y: listItem.height/2 - height/2
+ x: Qt.application.layoutDirection == Qt.RightToLeft ? -width : listItem.width
+ }
+ ]
+
+ onHoveredChanged: {
+ if (!hovered) {
+ return;
+ }
+ if (stackView.openSubMenu) {
+ stackView.openSubMenu.visible = false;
+
+ if (!listItem.actionsMenu.hasOwnProperty("count") || listItem.actionsMenu.count>0) {
+ if (listItem.actionsMenu.hasOwnProperty("popup")) {
+ listItem.actionsMenu.popup(listItem, listItem.width, 0)
+ } else {
+ listItem.actionsMenu.visible = true;
+ }
+ }
+ }
+ }
+ onClicked: {
+ if (!supportsMouseEvents) {
+ return;
+ }
+ modelData.trigger();
+ if (modelData.children!==undefined && modelData.children.length > 0) {
+ if (root.collapsed) {
+ //fallbacks needed for Qt 5.9
+ if ((!listItem.actionsMenu.hasOwnProperty("count") || listItem.actionsMenu.count>0) && !listItem.actionsMenu.visible) {
+ stackView.openSubMenu = listItem.actionsMenu;
+ if (listItem.actionsMenu.hasOwnProperty("popup")) {
+ listItem.actionsMenu.popup(listItem, listItem.width, 0)
+ } else {
+ listItem.actionsMenu.visible = true;
+ }
+ }
+ } else {
+ stackView.push(menuComponent, {model: modelData.children, level: level + 1, current: modelData });
+ }
+ } else if (root.resetMenuOnTriggered) {
+ root.resetMenu();
+ }
+ checked = Qt.binding(function() { return modelData.checked || (actionsMenu && actionsMenu.visible) });
+ }
+}
diff --git a/src/controls/templates/OverlayDrawer.qml b/src/controls/templates/OverlayDrawer.qml
--- a/src/controls/templates/OverlayDrawer.qml
+++ b/src/controls/templates/OverlayDrawer.qml
@@ -351,14 +351,20 @@
//BEGIN signal handlers
onCollapsedChanged: {
+ if (Settings.isMobile) {
+ collapsed = false;
+ }
if (!__internal.completed) {
return;
}
if ((!collapsible || modal) && collapsed) {
collapsed = true;
}
}
onCollapsibleChanged: {
+ if (Settings.isMobile) {
+ collapsible = false;
+ }
if (!__internal.completed) {
return;
}