diff --git a/src/controls/ActionToolBar.qml b/src/controls/ActionToolBar.qml --- a/src/controls/ActionToolBar.qml +++ b/src/controls/ActionToolBar.qml @@ -66,6 +66,8 @@ */ property int display: Controls.Button.TextBesideIcon + property int alignment: Qt.AlignLeft + /** * position enum * This property holds the position of the toolbar. @@ -84,88 +86,47 @@ implicitWidth: actionsLayout.implicitWidth Layout.minimumWidth: moreButton.implicitWidth + Layout.maximumWidth: placeholderLayout.implicitWidth + moreButton.width RowLayout { id: actionsLayout anchors.fill: parent - //anchors.rightMargin: moreButton.width - - spacing: Kirigami.Units.smallSpacing - property var overflowSet: [] + spacing: 0 - // TODO use Array.findIndex once we depend on Qt 5.9 - function findIndex(array, cb) { - for (var i = 0, length = array.length; i < length; ++i) { - if (cb(array[i])) { - return i; - } - } - return -1; + Item { + Layout.fillWidth: root.alignment == Qt.AlignRight || root.alignment == Qt.AlignHCenter || root.alignment == Qt.AlignCenter; + Layout.fillHeight: true } - function isActionVisible(action) { - var index = actionsLayout.findIndex(actionsLayout.overflowSet, function(act){return act === action}); - if (index === -1) { - index = actionsLayout.findIndex(root.hiddenActions, function(act){return act === action}); - if (index === -1) { - return true - } - } - return false - } + Repeater { + model: placeholderLayout.visibleActions - RowLayout { - Layout.minimumWidth: 0 - Layout.fillHeight: true - Repeater { - model: root.actions - delegate: PrivateActionToolButton { - id: actionDelegate - flat: root.flat - opacity: x + width <= parent.width - enabled: opacity > 0 && modelData.enabled - - display: root.display - visible: !modelData.hasOwnProperty("visible") || modelData.visible - Layout.fillWidth: false - Layout.alignment: Qt.AlignVCenter - Layout.minimumWidth: implicitWidth - kirigamiAction: modelData - onOpacityChanged: updateOverflowSet() - function updateOverflowSet() { - var index = actionsLayout.findIndex(actionsLayout.overflowSet, function(act) { - return act === modelData}); - - if ((opacity > 0 || (modelData.hasOwnProperty("visible") || !modelData.visible)) && index > -1) { - actionsLayout.overflowSet.splice(index, 1); - } else if (opacity === 0 && (!modelData.hasOwnProperty("visible") || modelData.visible) && index === -1) { - actionsLayout.overflowSet.push(modelData); - } - actionsLayout.overflowSetChanged(); - } - Connections { - target: modelData - ignoreUnknownSignals: !modelData.hasOwnProperty("visible") - onVisibleChanged: actionDelegate.updateOverflowSet(); - } - Component.onCompleted: { - actionDelegate.updateOverflowSet(); - } - } + delegate: PrivateActionToolButton { + id: actionDelegate + + Layout.alignment: Qt.AlignVCenter + Layout.minimumWidth: implicitWidth + // Use rightMargin instead of spacing on the layout to prevent spacer items + // from creating useless spacing + Layout.rightMargin: Kirigami.Units.smallSpacing + + flat: root.flat && !modelData.icon.color.a + display: root.display + kirigamiAction: modelData } } Item { - Layout.fillWidth: true - visible: root.Layout.fillWidth + Layout.fillWidth: root.alignment == Qt.AlignLeft || root.alignment == Qt.AlignHCenter || root.alignment == Qt.AlignCenter; + Layout.fillHeight: true } PrivateActionToolButton { id: moreButton Layout.alignment: Qt.AlignRight - visible: hiddenActions.length > 0 || actionsLayout.overflowSet.length > 0 + visible: hiddenActions.length > 0 || placeholderLayout.hiddenActions.length > 0 showMenuArrow: false kirigamiAction: Kirigami.Action { @@ -177,13 +138,69 @@ Binding { target: parentItem property: "visible" - value: !actionsLayout.isActionVisible(parentAction) && (parentAction.visible === undefined || parentAction.visible) + value: placeholderLayout.visibleActions.indexOf(parentAction) == -1 && + (parentAction.visible === undefined || parentAction.visible) } } menu.itemDelegate: ActionMenuItem { - visible: !actionsLayout.isActionVisible(action) && (action.visible === undefined || action.visible) + visible: placeholderLayout.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 } } + + onWidthChanged: Qt.callLater(placeholderLayout.updateVisibleActions) } diff --git a/src/controls/private/globaltoolbar/ToolBarPageHeader.qml b/src/controls/private/globaltoolbar/ToolBarPageHeader.qml --- a/src/controls/private/globaltoolbar/ToolBarPageHeader.qml +++ b/src/controls/private/globaltoolbar/ToolBarPageHeader.qml @@ -20,17 +20,16 @@ import QtQuick 2.5 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 -import org.kde.kirigami 2.4 +import org.kde.kirigami 2.5 import "../" as Private AbstractPageHeader { id: root - implicitWidth: titleLoader.implicitWidth.width/2 + buttonTextMetrics.collapsedButtonsWidth - Layout.minimumWidth: ctxActionsButton.width*4 + implicitWidth: titleLoader.implcitWidth + toolBar.implicitWidth + Units.smallSpacing * 3 - Layout.preferredHeight: Math.max(titleLoader.implicitHeight, actionsLayout.implicitHeight) + Units.smallSpacing * 2 + Layout.preferredHeight: Math.max(titleLoader.implicitHeight, toolBar.implicitHeight) + Units.smallSpacing * 2 MouseArea { anchors.fill: parent @@ -43,82 +42,60 @@ anchors { verticalCenter: parent.verticalCenter left: parent.left - right: parent.right - leftMargin: Units.largeSpacing + leftMargin: Units.smallSpacing rightMargin: Units.smallSpacing } visible: pageRow.globalToolBar.toolbarActionAlignment == Qt.AlignRight && width > item.Layout.minimumWidth sourceComponent: page ? page.titleDelegate : null - - Layout.preferredWidth: item - ? (item.Layout.preferredWidth > 0 ? item.Layout.preferredWidth : item.implicitWidth) - : 0 } + ActionToolBar { + id: toolBar - TextMetrics { - id: buttonTextMetrics - text: (page.actions.left ? page.actions.left.text : "") + (page.actions.main ? page.actions.main.text : "") + (page.actions.right ? page.actions.right.text : "") - readonly property int collapsedButtonsWidth: ctxActionsButton.width + (page.actions.left ? ctxActionsButton.width + Units.gridUnit : 0) + (page.actions.main ? ctxActionsButton.width + Units.gridUnit : 0) + (page.actions.right ? ctxActionsButton.width + Units.gridUnit : 0) - readonly property int requiredWidth: width + collapsedButtonsWidth - } - - RowLayout { - id: actionsLayout anchors { + left: titleLoader.right + leftMargin: Units.smallSpacing + right: parent.right + rightMargin: Units.smallSpacing verticalCenter: parent.verticalCenter - left: parent.left - right: ctxActionsButton.visible ? ctxActionsButton.left : parent.right } - readonly property bool toobig: root.width - root.leftPadding - root.rightPadding - titleLoader.implicitWidth - Units.gridUnit < buttonTextMetrics.requiredWidth - - Item { - Layout.fillWidth: true - visible: pageRow.globalToolBar.toolbarActionAlignment != Qt.AlignLeft - } - Private.PrivateActionToolButton { - Layout.alignment: Qt.AlignVCenter - kirigamiAction: page && page.actions ? page.actions.left : null - showText: !parent.toobig - } - Private.PrivateActionToolButton { - Layout.alignment: Qt.AlignVCenter - Layout.rightMargin: Units.smallSpacing - kirigamiAction: page && page.actions ? page.actions.main : null - showText: !parent.toobig - } - Private.PrivateActionToolButton { - Layout.alignment: Qt.AlignVCenter - kirigamiAction: page && page.actions ? page.actions.right : null - showText: !parent.toobig - } - Item { - Layout.fillWidth: true - visible: pageRow.globalToolBar.toolbarActionAlignment != Qt.AlignRight + alignment: pageRow.globalToolBar.toolbarActionAlignment + display: buttonTextMetrics.toobig ? Controls.Button.IconOnly : Controls.Button.TextBesideIcon + + actions: { + var result = [] + + if (page) { + if (page.actions.main) { + result.push(page.actions.main) + } + if (page.actions.left) { + result.push(page.actions.left) + } + if (page.actions.right) { + result.push(page.actions.right) + } + if (page.actions.contextualActions.length > 0 && !buttonTextMetrics.toobig) { + result = result.concat(Array.prototype.map.call(page.actions.contextualActions, function(item) { return item })) + } + } + + return result } + + hiddenActions: page && buttonTextMetrics.toobig ? page.actions.contextualActions : [] } - Private.PrivateActionToolButton { - id: ctxActionsButton - showMenuArrow: page.actions.contextualActions.length == 1 - onMenuAboutToShow: page.contextualActionsAboutToShow(); - anchors { - right: parent.right - verticalCenter: parent.verticalCenter - rightMargin: Units.smallSpacing - } - Action { - id: overflowAction - icon.name: "overflow-menu" - tooltip: qsTr("More Actions") - visible: visibleChildren.length > 0 - children: page && page.actions.contextualActions ? page.actions.contextualActions : null - } - kirigamiAction: page && page.actions.contextualActions.length === 1 ? page.actions.contextualActions[0] : overflowAction + TextMetrics { + id: buttonTextMetrics + text: (page.actions.left ? page.actions.left.text : "") + (page.actions.main ? page.actions.main.text : "") + (page.actions.right ? page.actions.right.text : "") + readonly property int collapsedButtonsWidth: toolBar.Layout.minimumWidth + (page.actions.left ? toolBar.Layout.minimumWidth + Units.gridUnit : 0) + (page.actions.main ? toolBar.Layout.minimumWidth + Units.gridUnit : 0) + (page.actions.right ? toolBar.Layout.minimumWidth + Units.gridUnit : 0) + readonly property int requiredWidth: width + collapsedButtonsWidth + readonly property bool toobig: root.width - root.leftPadding - root.rightPadding - titleLoader.implicitWidth - Units.gridUnit < buttonTextMetrics.requiredWidth } }