diff --git a/kirigami.qrc b/kirigami.qrc index 3177f75d..b6111df5 100644 --- a/kirigami.qrc +++ b/kirigami.qrc @@ -1,90 +1,91 @@ src/controls/AbstractApplicationWindow.qml src/controls/ContextDrawer.qml src/controls/Action.qml src/controls/Page.qml src/controls/PageRow.qml src/controls/AbstractListItem.qml src/controls/Theme.qml src/controls/AbstractCard.qml src/controls/templates/AbstractCard.qml src/controls/Card.qml src/controls/CardsLayout.qml src/controls/CardsListView.qml src/controls/CardsGridView.qml src/controls/ActionToolBar.qml src/controls/templates/InlineMessage.qml src/controls/InlineMessage.qml src/controls/ToolBarApplicationHeader.qml src/controls/ActionTextField.qml src/controls/SearchField.qml src/controls/PasswordField.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 src/controls/private/ActionIconGroup.qml src/controls/private/CornerShadow.qml src/controls/private/ActionButton.qml src/controls/private/DefaultListItemBackground.qml 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 src/controls/private/PrivateActionToolButton.qml src/controls/private/globaltoolbar/TitlesPageHeader.qml src/controls/private/globaltoolbar/ToolBarPageHeader.qml src/controls/private/globaltoolbar/BreadcrumbControl.qml src/controls/private/globaltoolbar/TabBarControl.qml src/controls/private/ActionsMenu.qml src/controls/private/ActionMenuItem.qml src/controls/Separator.qml src/controls/OverlayDrawer.qml src/controls/OverlaySheet.qml src/controls/GlobalDrawer.qml src/controls/templates/AbstractListItem.qml src/controls/templates/private/MenuIcon.qml src/controls/templates/private/GenericDrawerIcon.qml src/controls/templates/private/PassiveNotification.qml src/controls/templates/private/ContextIcon.qml src/controls/templates/private/ScrollView.qml src/controls/templates/private/BackButton.qml src/controls/templates/private/IconPropertiesGroup.qml src/controls/templates/private/ForwardButton.qml src/controls/templates/OverlayDrawer.qml src/controls/templates/OverlaySheet.qml src/controls/templates/SwipeListItem.qml src/controls/templates/ApplicationHeader.qml src/controls/templates/AbstractApplicationHeader.qml src/controls/Units.qml src/controls/SwipeListItem.qml src/controls/ApplicationWindow.qml src/controls/AbstractApplicationItem.qml src/controls/ApplicationItem.qml src/controls/ApplicationHeader.qml src/controls/Heading.qml src/controls/ScrollablePage.qml src/controls/AboutPage.qml src/controls/UrlButton.qml src/controls/LinkButton.qml src/controls/Label.qml src/controls/BasicListItem.qml src/controls/AbstractApplicationHeader.qml src/controls/FormLayout.qml src/controls/ListItemDragHandle.qml src/styles/Material/AbstractListItem.qml src/styles/Material/Theme.qml src/styles/Material/SwipeListItem.qml src/styles/Material/Label.qml src/styles/org.kde.desktop/AbstractListItem.qml src/styles/org.kde.desktop/Theme.qml src/styles/org.kde.desktop/Units.qml src/styles/org.kde.desktop/SwipeListItem.qml src/styles/org.kde.desktop/ApplicationWindow.qml src/styles/org.kde.desktop/AbstractApplicationHeader.qml diff --git a/kirigami.qrc.in b/kirigami.qrc.in index 65daaadd..c347c295 100644 --- a/kirigami.qrc.in +++ b/kirigami.qrc.in @@ -1,92 +1,93 @@ @kirigami_QML_DIR@/src/controls/AbstractApplicationWindow.qml @kirigami_QML_DIR@/src/controls/ContextDrawer.qml @kirigami_QML_DIR@/src/controls/Action.qml @kirigami_QML_DIR@/src/controls/Page.qml @kirigami_QML_DIR@/src/controls/PageRow.qml @kirigami_QML_DIR@/src/controls/AbstractListItem.qml @kirigami_QML_DIR@/src/controls/Theme.qml @kirigami_QML_DIR@/src/controls/AbstractCard.qml @kirigami_QML_DIR@/src/controls/templates/AbstractCard.qml @kirigami_QML_DIR@/src/controls/Card.qml @kirigami_QML_DIR@/src/controls/CardsLayout.qml @kirigami_QML_DIR@/src/controls/CardsListView.qml @kirigami_QML_DIR@/src/controls/CardsGridView.qml @kirigami_QML_DIR@/src/controls/ActionToolBar.qml @kirigami_QML_DIR@/src/controls/templates/InlineMessage.qml @kirigami_QML_DIR@/src/controls/InlineMessage.qml @kirigami_QML_DIR@/src/controls/ToolBarApplicationHeader.qml @kirigami_QML_DIR@/src/controls/ActionTextField.qml @kirigami_QML_DIR@/src/controls/SearchField.qml @kirigami_QML_DIR@/src/controls/PasswordField.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 @kirigami_QML_DIR@/src/controls/private/ActionIconGroup.qml @kirigami_QML_DIR@/src/controls/private/CornerShadow.qml @kirigami_QML_DIR@/src/controls/private/ActionButton.qml @kirigami_QML_DIR@/src/controls/private/DefaultListItemBackground.qml @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 @kirigami_QML_DIR@/src/controls/private/globaltoolbar/PageRowGlobalToolBarUI.qml @kirigami_QML_DIR@/src/controls/private/PrivateActionToolButton.qml @kirigami_QML_DIR@/src/controls/private/globaltoolbar/TabBarControl.qml @kirigami_QML_DIR@/src/controls/private/globaltoolbar/TitlesPageHeader.qml @kirigami_QML_DIR@/src/controls/private/globaltoolbar/ToolBarPageHeader.qml @kirigami_QML_DIR@/src/controls/private/ActionsMenu.qml @kirigami_QML_DIR@/src/controls/private/ActionMenuItem.qml @kirigami_QML_DIR@/src/controls/Separator.qml @kirigami_QML_DIR@/src/controls/OverlayDrawer.qml @kirigami_QML_DIR@/src/controls/OverlaySheet.qml @kirigami_QML_DIR@/src/controls/GlobalDrawer.qml @kirigami_QML_DIR@/src/controls/templates/AbstractListItem.qml @kirigami_QML_DIR@/src/controls/templates/private/MenuIcon.qml @kirigami_QML_DIR@/src/controls/templates/private/GenericDrawerIcon.qml @kirigami_QML_DIR@/src/controls/templates/private/PassiveNotification.qml @kirigami_QML_DIR@/src/controls/templates/private/ContextIcon.qml @kirigami_QML_DIR@/src/controls/templates/private/ScrollView.qml @kirigami_QML_DIR@/src/controls/templates/private/BackButton.qml @kirigami_QML_DIR@/src/controls/templates/private/IconPropertiesGroup.qml @kirigami_QML_DIR@/src/controls/templates/private/ForwardButton.qml @kirigami_QML_DIR@/src/controls/templates/OverlayDrawer.qml @kirigami_QML_DIR@/src/controls/templates/OverlaySheet.qml @kirigami_QML_DIR@/src/controls/templates/SwipeListItem.qml @kirigami_QML_DIR@/src/controls/templates/ApplicationHeader.qml @kirigami_QML_DIR@/src/controls/templates/AbstractApplicationHeader.qml @kirigami_QML_DIR@/src/controls/Units.qml @kirigami_QML_DIR@/src/controls/SwipeListItem.qml @kirigami_QML_DIR@/src/controls/ApplicationWindow.qml @kirigami_QML_DIR@/src/controls/AbstractApplicationItem.qml @kirigami_QML_DIR@/src/controls/ApplicationItem.qml @kirigami_QML_DIR@/src/controls/ApplicationHeader.qml @kirigami_QML_DIR@/src/controls/Heading.qml @kirigami_QML_DIR@/src/controls/ScrollablePage.qml @kirigami_QML_DIR@/src/controls/AboutPage.qml @kirigami_QML_DIR@/src/controls/UrlButton.qml @kirigami_QML_DIR@/src/controls/LinkButton.qml @kirigami_QML_DIR@/src/controls/Label.qml @kirigami_QML_DIR@/src/controls/BasicListItem.qml @kirigami_QML_DIR@/src/controls/ListSectionHeader.qml @kirigami_QML_DIR@/src/controls/AbstractApplicationHeader.qml @kirigami_QML_DIR@/src/controls/FormLayout.qml @kirigami_QML_DIR@/src/controls/ListItemDragHandle.qml @kirigami_QML_DIR@/src/styles/Material/AbstractListItem.qml @kirigami_QML_DIR@/src/styles/Material/Theme.qml @kirigami_QML_DIR@/src/styles/Material/SwipeListItem.qml @kirigami_QML_DIR@/src/styles/Material/Label.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/AbstractListItem.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/Theme.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/Units.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/SwipeListItem.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/ApplicationWindow.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/AbstractApplicationHeader.qml diff --git a/src/controls/ActionToolBar.qml b/src/controls/ActionToolBar.qml index 07a4407f..572312de 100644 --- a/src/controls/ActionToolBar.qml +++ b/src/controls/ActionToolBar.qml @@ -1,203 +1,160 @@ /* * Copyright 2018 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.7 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.4 as Controls import org.kde.kirigami 2.5 as Kirigami import "private" /** * This is a simple toolbar built out of a list of actions * each action is represented by a ToolButton, those that won't fit * the size will go in a menu under a button with the overflow ... icon * * @inherits Item * @since 2.5 */ Item { id: root /** * actions: list * if the card should provide clickable actions, put them in this property, * they will be put in the footer as a list of ToolButtons plus an optional * overflow menu, when not all of them will fit in the available Card width. */ property list actions /** * actions: hiddenActions * This list of actions is for those you always want in the menu, even if there * is enough space. * @since 2.6 */ property list hiddenActions /** * flat: bool * Wether we want our buttons to have a flat appearance. Default: true */ property bool flat: true /** * display: enum * This controls the label position regarding the icon, is the same value to control individual Button components, * permitted values are: * * Button.IconOnly * * Button.TextOnly * * Button.TextBesideIcon * * Button.TextUnderIcon */ property int display: Controls.Button.TextBesideIcon property int alignment: Qt.AlignLeft /** * position enum * This property holds the position of the toolbar. * if this ActionToolBar is the contentItem of a QQC2 Toolbar, the position is binded to the ToolBar's position * * permitted values are: * *ToolBar.Header: The toolbar is at the top, as a window or page header. * *ToolBar.Footer: The toolbar is at the bottom, as a window or page footer. */ property int position: parent && parent.hasOwnProperty("position") ? parent.position : Controls.ToolBar.Header implicitHeight: actionsLayout.implicitHeight implicitWidth: actionsLayout.implicitWidth Layout.minimumWidth: moreButton.visible ? moreButton.implicitWidth : 0 RowLayout { id: actionsLayout anchors.fill: parent spacing: 0 Item { Layout.fillWidth: root.alignment == Qt.AlignRight || root.alignment == Qt.AlignHCenter || root.alignment == Qt.AlignCenter; Layout.fillHeight: true } Repeater { - model: placeholderLayout.visibleActions + model: root.actions 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 + 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 } } Item { 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 || 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 index 00000000..0924eb61 --- /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) + } + } + } +}