diff --git a/kirigami.qrc b/kirigami.qrc
--- a/kirigami.qrc
+++ b/kirigami.qrc
@@ -32,6 +32,7 @@
src/controls/private/DefaultCardBackground.qml
src/controls/private/BannerImage.qml
src/controls/private/EdgeShadow.qml
+ src/controls/private/ActionToolBarLayoutDetails.qml
src/controls/private/globaltoolbar/AbstractPageHeader.qml
src/controls/private/globaltoolbar/PageRowGlobalToolBarStyleGroup.qml
src/controls/private/globaltoolbar/PageRowGlobalToolBarUI.qml
diff --git a/kirigami.qrc.in b/kirigami.qrc.in
--- a/kirigami.qrc.in
+++ b/kirigami.qrc.in
@@ -33,6 +33,7 @@
@kirigami_QML_DIR@/src/controls/private/DefaultCardBackground.qml
@kirigami_QML_DIR@/src/controls/private/BannerImage.qml
@kirigami_QML_DIR@/src/controls/private/EdgeShadow.qml
+ @kirigami_QML_DIR@/src/controls/private/ActionToolBarLayoutDetails.qml
@kirigami_QML_DIR@/src/controls/private/globaltoolbar/AbstractPageHeader.qml
@kirigami_QML_DIR@/src/controls/private/globaltoolbar/BreadcrumbControl.qml
@kirigami_QML_DIR@/src/controls/private/globaltoolbar/PageRowGlobalToolBarStyleGroup.qml
diff --git a/src/controls/ActionToolBar.qml b/src/controls/ActionToolBar.qml
--- a/src/controls/ActionToolBar.qml
+++ b/src/controls/ActionToolBar.qml
@@ -96,7 +96,7 @@
}
Repeater {
- model: placeholderLayout.visibleActions
+ model: root.actions
delegate: PrivateActionToolButton {
id: actionDelegate
@@ -107,8 +107,11 @@
// from creating useless spacing
Layout.rightMargin: Kirigami.Units.smallSpacing
+ visible: details.visibleActions.indexOf(modelData) != -1
+ && (modelData.visible === undefined || modelData.visible)
+
flat: root.flat && !modelData.icon.color.a
- display: root.display
+ display: details.iconOnlyActions.indexOf(modelData) != -1 ? Controls.Button.IconOnly : root.display
kirigamiAction: modelData
}
}
@@ -122,82 +125,36 @@
id: moreButton
Layout.alignment: Qt.AlignRight
-
- visible: hiddenActions.length > 0 || placeholderLayout.hiddenActions.length > 0
- showMenuArrow: false
+ visible: root.hiddenActions.length > 0 || details.hiddenActions.length > 0
kirigamiAction: Kirigami.Action {
icon.name: "overflow-menu"
+ displayHint: Kirigami.Action.DisplayHint.IconOnly | Kirigami.Action.DisplayHint.HideChildIndicator
children: Array.prototype.map.call(root.actions, function (i) { return i }).concat(Array.prototype.map.call(hiddenActions, function (i) { return i }))
}
menu.submenuComponent: ActionsMenu {
Binding {
target: parentItem
property: "visible"
- value: placeholderLayout.visibleActions.indexOf(parentAction) == -1 &&
+ value: details.visibleActions.indexOf(parentAction) == -1 &&
(parentAction.visible === undefined || parentAction.visible)
}
}
menu.itemDelegate: ActionMenuItem {
- visible: placeholderLayout.visibleActions.indexOf(action) == -1 &&
+ visible: details.visibleActions.indexOf(action) == -1 &&
(action.visible === undefined || action.visible)
}
}
}
- RowLayout {
- id: placeholderLayout
- enabled: false
- opacity: 0 // Cannot use visible: false because then relayout doesn't happen correctly
- spacing: Kirigami.Units.smallSpacing
-
- property var visibleActions: []
- property var hiddenActions: []
- property real layoutWidth: root.width - moreButton.width - Kirigami.Units.smallSpacing
-
- Repeater {
- id: placeholderRepeater
- model: root.actions
-
- PrivateActionToolButton {
- flat: root.flat && !modelData.icon.color.a
- display: root.display
- visible: modelData.visible === undefined || modelData.visible
- kirigamiAction: modelData
-
- property bool actionVisible: x + width < placeholderLayout.layoutWidth
- }
- }
-
- Component.onCompleted: Qt.callLater(updateVisibleActions)
- onWidthChanged: Qt.callLater(updateVisibleActions)
-
- function updateVisibleActions() {
- var visible = []
- var hidden = []
-
- if (root.width >= placeholderLayout.width + moreButton.width + Kirigami.Units.smallSpacing) {
- visibleActions = Array.prototype.map.call(root.actions, function(item) { return item })
- hiddenActions = []
- return
- }
-
- for (var i = 0; i < root.actions.length; ++i) {
- var item = placeholderRepeater.itemAt(i)
- if (item.actionVisible) {
- visible.push(item.kirigamiAction)
- } else {
- hidden.push(item.kirigamiAction)
-
- }
- }
-
- visibleActions = visible
- hiddenActions = hidden
- }
+ ActionToolBarLayoutDetails {
+ id: details
+ anchors.fill: parent
+ actions: root.actions
+ rightPadding: moreButton.width + Kirigami.Units.smallSpacing
+ flat: root.flat
+ display: root.display
}
-
- onWidthChanged: Qt.callLater(placeholderLayout.updateVisibleActions)
}
diff --git a/src/controls/private/ActionToolBarLayoutDetails.qml b/src/controls/private/ActionToolBarLayoutDetails.qml
new file mode 100644
--- /dev/null
+++ b/src/controls/private/ActionToolBarLayoutDetails.qml
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2018 Marco Martin
+ * Copyright 2019 Arjen Hiemstra
+ *
+ * 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.7
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.4 as Controls
+import org.kde.kirigami 2.5 as Kirigami
+
+/**
+ * This fairly complex thing determines the layout of ActionToolBar, that is,
+ * which actions should be displayed in full width toolbutton form, which should
+ * be displayed in an icon-only reduced size and which should be placed in the
+ * overflow menu.
+ *
+ * It makes use of two fairly static layouts, one contains all actions in expanded
+ * full-size form, the other in reduced icon-only form. The items in these layouts
+ * determine if they should be visible based on their relative position and size
+ * and some properties of the action. The update function then goes through these
+ * items, adding the actions to the relevant lists, so they can be used by the
+ * ActionToolBar to determine which action should be visible in what state.
+ *
+ * The reason for using two separate layouts from ActionToolBar's main layout is
+ * so that we can use the actual geometry of the buttons to calculate the
+ * visibility, completely disregarding any other layouting quirks. We can then
+ * use that information so only the relevant things in the ActionToolBar are
+ * visible. This allows the main ActionToolBar to use normal layout features for
+ * things like the positioning of the visible actions.
+ */
+Item {
+ id: details
+
+ property var actions
+
+ property var visibleActions: []
+ property var hiddenActions: []
+ property var iconOnlyActions: []
+
+ property bool flat: false
+ property int display: Controls.Button.TextBesideIcon
+ property real spacing: Kirigami.Units.smallSpacing
+ property real leftPadding: 0
+ property real rightPadding: 0
+
+ property real iconOnlyWidth: 0
+ readonly property real iconLayoutWidth: width - rightPadding
+ readonly property real fullLayoutWidth: iconLayoutWidth - iconOnlyWidth
+
+ enabled: false
+ opacity: 0 // Cannot use visible: false because then relayout doesn't happen correctly
+
+ function update() {
+ var visible = []
+ var hidden = []
+ var iconOnly = []
+ var iconsWidth = 0
+
+ if (details.width >= fullSizePlaceholderLayout.width + details.rightPadding) {
+ visibleActions = Array.prototype.map.call(details.actions, function(i) { return i })
+ hiddenActions = []
+ iconOnlyActions = []
+ iconOnlyWidth = 0
+ return
+ }
+
+ for (var i = 0; i < root.actions.length; ++i) {
+ var item = fullSizePlaceholderRepeater.itemAt(i)
+ var iconOnlyItem = iconOnlyPlaceholderRepeater.itemAt(i)
+
+ if (item.actionVisible) {
+ visible.push(item.kirigamiAction)
+ } else if (iconOnlyItem.actionVisible) {
+ visible.push(item.kirigamiAction)
+ iconOnly.push(item.kirigamiAction)
+ iconsWidth += iconOnlyItem.width + details.spacing
+ } else {
+ hidden.push(item.kirigamiAction)
+ }
+ }
+
+ visibleActions = visible
+ hiddenActions = hidden
+ iconOnlyActions = iconOnly
+ iconOnlyWidth = iconsWidth
+ }
+
+ onWidthChanged: Qt.callLater(update)
+ Component.onCompleted: Qt.callLater(update)
+
+ RowLayout {
+ id: fullSizePlaceholderLayout
+ spacing: details.spacing
+
+ // This binding is here to take care of things like visibility changes
+ onWidthChanged: Qt.callLater(details.update)
+
+ Repeater {
+ id: fullSizePlaceholderRepeater
+
+ model: details.actions
+
+ PrivateActionToolButton {
+ flat: details.flat && !modelData.icon.color.a
+ display: details.display
+ visible: (modelData.visible === undefined || modelData.visible)
+ && (modelData.displayHint !== undefined && !modelData.displayHintSet(Kirigami.Action.DisplayHint.AlwaysHide))
+ kirigamiAction: modelData
+ property bool actionVisible: visible && (x + width < details.fullLayoutWidth)
+ }
+ }
+ }
+
+ RowLayout {
+ id: iconOnlyPlaceholderLayout
+ spacing: details.spacing
+
+ Repeater {
+ id: iconOnlyPlaceholderRepeater
+
+ model: details.actions
+
+ PrivateActionToolButton {
+ flat: details.flat && !modelData.icon.color.a
+ display: Controls.Button.IconOnly
+ visible: (modelData.visible === undefined || modelData.visible)
+ && (modelData.displayHint !== undefined && modelData.displayHintSet(Kirigami.Action.DisplayHint.KeepVisible))
+ kirigamiAction: modelData
+ property bool actionVisible: visible && (x + width < details.iconLayoutWidth)
+ }
+ }
+ }
+}