/*SPDX-FileCopyrightText: 2020 Mikel Johnson <mikel5764@gmail.com>SPDX-FileCopyrightText: 2021 Kai Uwe Broulik <kde@broulik.de>SPDX-License-Identifier: GPL-2.0-or-later*/pragma ComponentBehavior: Boundimport QtQuickimport QtQuick.Layoutsimport org.kde.plasma.private.kicker as Kickerimport org.kde.plasma.extras as PlasmaExtrasimport org.kde.plasma.components as PC3import org.kde.plasma.core as PlasmaCoreimport org.kde.kirigami as Kirigamiimport org.kde.kitemmodels as KItemModelsimport org.kde.plasma.plasmoidRowLayout {id: rootrequired property real maximumWidth// When all actions are configured as primary, none of them should be// hidden into the overflow menu as long as the available space allows// it.readonly property var __layout: {const allActionsArePrimary = Plasmoid.configuration.primaryActions === 3;const actionButtonsImplicitWidth = buttonsRepeaterRow.implicitWidth;let configuredImplicitWidth_IconOnly = actionButtonsImplicitWidth;let configuredImplicitWidth_TextBesideIcon = actionButtonsImplicitWidth;if (!allActionsArePrimary) {configuredImplicitWidth_IconOnly += overflowMenuButtonIconOnly.implicitWidth + spacing;configuredImplicitWidth_TextBesideIcon += overflowMenuButtonTextBesideIcon.implicitWidth + spacing;}const collapseActionButtons = configuredImplicitWidth_IconOnly > maximumWidth;const collapseOverflowMenuButton = !collapseActionButtons && configuredImplicitWidth_TextBesideIcon > maximumWidth;// Can't rely on the transient Item::visible propertyconst overflowMenuButtonIsVisible = collapseActionButtons || !allActionsArePrimary;return {allActionsArePrimary,collapseActionButtons,collapseOverflowMenuButton,overflowMenuButtonIsVisible,};}spacing: kickoff.backgroundMetrics.spacingKicker.SystemModel {id: systemModelfavoritesModel: kickoff.rootModel.systemFavoritesModel}component FilteredModel : KItemModels.KSortFilterProxyModel {sourceModel: systemModelfunction systemFavoritesContainsRow(sourceRow, sourceParent) {const FavoriteIdRole = sourceModel.KItemModels.KRoleNames.role("favoriteId");const favoriteId = sourceModel.data(sourceModel.index(sourceRow, 0, sourceParent), FavoriteIdRole);return String(Plasmoid.configuration.systemFavorites).includes(favoriteId);}function trigger(index) {const sourceIndex = mapToSource(this.index(index, 0));systemModel.trigger(sourceIndex.row, "", null);}Component.onCompleted: {Plasmoid.configuration.valueChanged.connect((key, value) => {if (key === "systemFavorites") {invalidateFilter();}});}}FilteredModel {id: filteredButtonsModelfilterRowCallback: (sourceRow, sourceParent) =>systemFavoritesContainsRow(sourceRow, sourceParent)}FilteredModel {id: filteredMenuItemsModelfilterRowCallback: root.__layout.collapseActionButtons? null /*i.e. keep all rows*/: (sourceRow, sourceParent) => !systemFavoritesContainsRow(sourceRow, sourceParent)}Item {Layout.fillWidth: !Plasmoid.configuration.showActionButtonCaptions && root.__layout.allActionsArePrimary}RowLayout {id: buttonsRepeaterRow// HACK Can't use `visible` property, as the layout needs to be// visible to be able to update its implicit size, which in turn is// be used to set collapseActionButtons.enabled: !root.__layout.collapseActionButtonsopacity: !root.__layout.collapseActionButtons ? 1 : 0spacing: parent.spacingRepeater {id: buttonRepeatermodel: filteredButtonsModeldelegate: PC3.ToolButton {required property int indexrequired property var modeltext: model.displayicon.name: model.decorationonClicked: {filteredButtonsModel.trigger(index);if (kickoff.hideOnWindowDeactivate) {kickoff.expanded = false;}}display: Plasmoid.configuration.showActionButtonCaptions ? PC3.AbstractButton.TextBesideIcon : PC3.AbstractButton.IconOnly;Layout.rightMargin: model.favoriteId === "switch-user" && root.__layout.allActionsArePrimary ? Kirigami.Units.gridUnit : undefinedPC3.ToolTip.text: textPC3.ToolTip.delay: Kirigami.Units.toolTipDelayPC3.ToolTip.visible: display === PC3.AbstractButton.IconOnly && hoveredKeys.onTabPressed: event => {if (index === buttonRepeater.count - 1 && !root.__layout.overflowMenuButtonIsVisible) {kickoff.firstHeaderItem.forceActiveFocus(Qt.TabFocusReason)} else {event.accepted = false}}Keys.onLeftPressed: event => {if (Application.layoutDirection === Qt.LeftToRight) {nextItemInFocusChain(false).forceActiveFocus(Qt.BacktabFocusReason)} else if (index < buttonRepeater.count - 1 || root.__layout.overflowMenuButtonIsVisible) {nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason)}}Keys.onRightPressed: event => {if (Application.layoutDirection === Qt.RightToLeft) {nextItemInFocusChain(false).forceActiveFocus(Qt.BacktabFocusReason)} else if (index < buttonRepeater.count - 1 || root.__layout.overflowMenuButtonIsVisible) {nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason)}}Keys.onEnterPressed: clicked()Keys.onReturnPressed: clicked()}}}Item {Layout.fillWidth: !Plasmoid.configuration.showActionButtonCaptions || !root.__layout.allActionsArePrimary}// Just like Kirigami.ActionToolBar, it takes two actual instances of a// button with different display modes to calculate the layout properly// without binding loops.component OverflowMenuButton : PC3.ToolButton {Accessible.role: Accessible.ButtonMenuicon.width: Kirigami.Units.iconSizes.smallMediumicon.height: Kirigami.Units.iconSizes.smallMediumicon.name: ["system-log-out", "system-shutdown", "view-more-symbolic", "view-more-symbolic"][Plasmoid.configuration.primaryActions]text: [i18nc("@title:menu menubutton","Session"), i18nc("@title:menu menubutton", "Power"), i18nc("@title:menu menubutton", "More"), i18nc("@title:menu menubutton", "Session and Power")][Plasmoid.configuration.primaryActions]// Make it look pressed while the menu is opendown: contextMenu.status === PlasmaExtras.Menu.Open || pressedKeys.onTabPressed: event => {kickoff.firstHeaderItem.forceActiveFocus(Qt.TabFocusReason);}Keys.onLeftPressed: event => {if (!mirrored) {nextItemInFocusChain(false).forceActiveFocus(Qt.BacktabFocusReason)}}Keys.onRightPressed: event => {if (mirrored) {nextItemInFocusChain(false).forceActiveFocus(Qt.BacktabFocusReason)}}onPressed: {contextMenu.visualParent = this;contextMenu.openRelative();}}OverflowMenuButton {id: overflowMenuButtonTextBesideIcondisplay: PC3.AbstractButton.TextBesideIconvisible: root.__layout.overflowMenuButtonIsVisible && !root.__layout.collapseOverflowMenuButton}OverflowMenuButton {id: overflowMenuButtonIconOnlydisplay: PC3.AbstractButton.IconOnlyvisible: root.__layout.overflowMenuButtonIsVisible && root.__layout.collapseOverflowMenuButtonPC3.ToolTip.text: textPC3.ToolTip.visible: hovered || activeFocusPC3.ToolTip.delay: Kirigami.Units.toolTipDelay}Instantiator {model: filteredMenuItemsModeldelegate: PlasmaExtras.MenuItem {required property int indexrequired property var modeltext: model.displayicon: model.decorationonClicked: {filteredMenuItemsModel.trigger(index)if (kickoff.hideOnWindowDeactivate) {kickoff.expanded = false;}}}onObjectAdded: (index, object) => contextMenu.addMenuItem(object)onObjectRemoved: (index, object) => contextMenu.removeMenuItem(object)}PlasmaExtras.Menu {id: contextMenuplacement: {switch (Plasmoid.location) {case PlasmaCore.Types.LeftEdge:case PlasmaCore.Types.RightEdge:case PlasmaCore.Types.TopEdge:return PlasmaExtras.Menu.BottomPosedRightAlignedPopup;case PlasmaCore.Types.BottomEdge:default:return PlasmaExtras.Menu.TopPosedRightAlignedPopup;}}}}