diff --git a/src/controls/Action.qml b/src/controls/Action.qml --- a/src/controls/Action.qml +++ b/src/controls/Action.qml @@ -146,6 +146,14 @@ return (displayHint & hint) } + /** + * A Component that should be preferred when displaying this Action. + * + * @since 5.65 + * @since 2.12 + */ + property Component displayComponent: null + default property alias children: root.__children property list __children diff --git a/src/controls/ActionToolBar.qml b/src/controls/ActionToolBar.qml --- a/src/controls/ActionToolBar.qml +++ b/src/controls/ActionToolBar.qml @@ -106,22 +106,36 @@ Repeater { model: root.actions - delegate: PrivateActionToolButton { - id: actionDelegate + delegate: Loader { + id: delegate Layout.alignment: Qt.AlignVCenter - Layout.minimumWidth: implicitWidth // Use leftMargin instead of spacing on the layout to prevent spacer items // from creating useless spacing, only for items that are actually next to // other items. Layout.leftMargin: index > 0 ? Kirigami.Units.smallSpacing : 0 + Layout.fillWidth: item ? item.Layout.fillWidth : false + Layout.minimumWidth: item ? item.Layout.minimumWidth : implicitWidth + Layout.preferredWidth: item ? item.Layout.preferredWidth : implicitWidth + Layout.maximumWidth: item ? item.Layout.maximumWidth : -1 + + property var kirigamiAction: modelData + + sourceComponent: { + if (modelData.displayComponent && !modelData.displayHintSet(Action.DisplayHint.IconOnly)) { + return modelData.displayComponent + } + return toolButtonDelegate + } visible: details.visibleActions.indexOf(modelData) != -1 && (modelData.visible === undefined || modelData.visible) - flat: root.flat && !modelData.icon.color.a - display: details.iconOnlyActions.indexOf(modelData) != -1 ? Controls.Button.IconOnly : root.display - kirigamiAction: modelData + onLoaded: { + if (sourceComponent == toolButtonDelegate) { + item.kirigamiAction = modelData + } + } } } @@ -155,6 +169,13 @@ visible: details.visibleActions.indexOf(action) == -1 && (action.visible === undefined || action.visible) } + + menu.loaderDelegate: Loader { + property var kirigamiAction + height: visible ? implicitHeight : 0 + visible: details.visibleActions.indexOf(kirigamiAction) == -1 && + (kirigamiAction.visible === undefined || kirigamiAction.visible) + } } } @@ -166,4 +187,27 @@ flat: root.flat display: root.display } + + Component { + id: toolButtonDelegate + + PrivateActionToolButton { + id: button + flat: root.flat && !kirigamiAction.icon.color.a + display: details.iconOnlyActions.indexOf(kirigamiAction) != -1 ? Controls.Button.IconOnly : root.display + + menu.actions: { + if (kirigamiAction.displayComponent && kirigamiAction.displayHintSet(Kirigami.Action.DisplayHint.IconOnly)) { + kirigamiAction.displayHint |= Kirigami.Action.DisplayHint.HideChildIndicator + return [kirigamiAction] + } + + if (kirigamiAction.children) { + return kirigamiAction.children + } + + return [] + } + } + } } diff --git a/src/controls/private/ActionToolBarLayoutDetails.qml b/src/controls/private/ActionToolBarLayoutDetails.qml --- a/src/controls/private/ActionToolBarLayoutDetails.qml +++ b/src/controls/private/ActionToolBarLayoutDetails.qml @@ -72,14 +72,6 @@ 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) @@ -116,13 +108,45 @@ model: details.actions - PrivateActionToolButton { - flat: details.flat && !modelData.icon.color.a - display: details.display + Loader { + property var kirigamiAction: modelData + + sourceComponent: { + if (modelData.displayComponent && !modelData.displayHintSet(Kirigami.Action.DisplayHint.IconOnly)) { + return modelData.displayComponent + } + return toolButtonDelegate + } + visible: (modelData.visible === undefined || modelData.visible) - && (modelData.displayHint !== undefined && !modelData.displayHintSet(Kirigami.Action.DisplayHint.AlwaysHide)) - kirigamiAction: modelData + && (modelData.displayHint !== undefined && !modelData.displayHintSet(Kirigami.Action.DisplayHint.AlwaysHide)) + property bool actionVisible: visible && (x + width < details.fullLayoutWidth) + + onLoaded: { + if (sourceComponent == toolButtonDelegate) { + item.kirigamiAction = modelData + } + } + } + } + } + + Component { + id: toolButtonDelegate + PrivateActionToolButton { + flat: details.flat && !kirigamiAction.icon.color.a + display: details.display + menu.actions: { + if (kirigamiAction.displayComponent && kirigamiAction.displayHintSet(Kirigami.Action.DisplayHint.IconOnly)) { + return [kirigamiAction] + } + + if (kirigamiAction.children) { + return kirigamiAction.children + } + + return [] } } } diff --git a/src/controls/private/ActionsMenu.qml b/src/controls/private/ActionsMenu.qml --- a/src/controls/private/ActionsMenu.qml +++ b/src/controls/private/ActionsMenu.qml @@ -30,6 +30,7 @@ //renamed to work on both Qt 5.9 and 5.10 property Component itemDelegate: ActionMenuItem {} property Component separatorDelegate: Controls.MenuSeparator { } + property Component loaderDelegate: Loader { property var kirigamiAction } property Controls.Action parentAction property Controls.MenuItem parentItem @@ -50,6 +51,10 @@ if (action.hasOwnProperty("separator") && action.separator) { item = theMenu.separatorDelegate.createObject(null, {}); } + else if (action.displayComponent) { + item = theMenu.loaderDelegate.createObject(null, + { kirigamiAction: action, sourceComponent: action.displayComponent }); + } else { item = theMenu.itemDelegate.createObject(null, { action: action }); }