/* * SPDX-FileCopyrightText: 2016 Marco Martin * * SPDX-License-Identifier: LGPL-2.0-or-later */ import QtQuick import QtQml import QtQuick.Templates as T import org.kde.kirigami as Kirigami /** * An action used to load Pages coming from a common PagePool * in a PageRow or QtQuickControls2 StackView. * * @see PagePool */ Kirigami.Action { id: root //BEGIN properties /** * @brief This property holds the url or filename of the page that this action will load. */ property string page /** * @brief This property holds the PagePool object used by this PagePoolAction. * * PagePool will make sure only one instance of the page identified by the page url will be created and reused. * PagePool's lastLoaderUrl property will be used to control the mutual exclusivity of the checked * state of the PagePoolAction instances sharing the same PagePool. */ property Kirigami.PagePool pagePool /** * The pageStack property accepts either a Kirigami.PageRow or a QtQuickControls2 StackView. * The component that will instantiate the pages, which has to work with a stack logic. * Kirigami.PageRow is recommended, but will work with QtQuicControls2 StackView as well. * * default: `bound to ApplicationWindow's global pageStack, which is a PageRow by default` */ property Item pageStack: typeof applicationWindow !== 'undefined' ? applicationWindow().pageStack : null /** * @brief This property sets the page in the pageStack after which * new pages will be pushed. * * All pages present after the given basePage will be removed from the pageStack */ property T.Page basePage /** * This property holds a function that generate the property values for the created page * when it is pushed onto the Kirigami.PagePool. * * Example usage: * @code{.qml} * Kirigami.PagePoolAction { * text: i18n("Security") * icon.name: "security-low" * page: Qt.resolvedUrl("Security.qml") * initialProperties: { * return { * room: root.room * } * } * } * @endcode * @property QVariantMap initialProperties */ property var initialProperties /** * @brief This property sets whether PagePoolAction will use the layers property * implemented by the pageStack. * * This is intended for use with PageRow layers to allow PagePoolActions to * push context-specific pages onto the layers stack. * * default: ``false`` * * @since 5.70 * @since org.kde.kirigami 2.12 */ property bool useLayers: false //END properties /** * @returns the page item held in the PagePool or null if it has not been loaded yet. */ function pageItem(): Item { return pagePool.pageForUrl(page) } /** * @returns true if the page has been loaded and placed on pageStack.layers * and useLayers is true, otherwise returns null. */ function layerContainsPage(): bool { if (!useLayers || !pageStack.hasOwnProperty("layers")) { return false; } const pageItem = this.pageItem(); const item = pageStack.layers.find(item => item === pageItem); return item !== null; } /** * @returns true if the page has been loaded and placed on the pageStack, * otherwise returns null. */ function stackContainsPage(): bool { if (useLayers) { return false; } return pageStack.columnView.containsItem(pagePool.pageForUrl(page)); } checkable: true onTriggered: { if (page.length === 0 || !pagePool || !pageStack) { return; } // User intends to "go back" to this layer. const pageItem = this.pageItem(); if (layerContainsPage() && pageItem !== pageStack.layers.currentItem) { pageStack.layers.replace(pageItem, pageItem); // force pop above return; } // User intends to "go back" to this page. if (stackContainsPage()) { if (pageStack.hasOwnProperty("layers")) { pageStack.layers.clear(); } } const stack = useLayers ? pageStack.layers : pageStack if (pageItem != null && stack.currentItem == pageItem) { return; } if (initialProperties && typeof(initialProperties) !== "object") { console.warn("initialProperties must be of type object"); return; } if (!stack.hasOwnProperty("pop") || typeof stack.pop !== "function" || !stack.hasOwnProperty("push") || typeof stack.push !== "function") { return; } if (pagePool.isLocalUrl(page)) { if (basePage) { stack.pop(basePage); } else if (!useLayers) { stack.clear(); } stack.push(initialProperties ? pagePool.loadPageWithProperties(page, initialProperties) : pagePool.loadPage(page)); } else { const callback = item => { if (basePage) { stack.pop(basePage); } else if (!useLayers) { stack.clear(); } stack.push(item); }; if (initialProperties) { pagePool.loadPage(page, initialProperties, callback); } else { pagePool.loadPage(page, callback); } } } // Exposing this as a property is required as Action does not have a default property property QtObject _private: QtObject { id: _private function setChecked(checked) { root.checked = checked; } function clearLayers() { root.pageStack.layers.clear(); } property list connections: [ Connections { target: root.pageStack function onCurrentItemChanged() { if (root.useLayers) { if (root.layerContainsPage()) { _private.clearLayers(); } if (root.checkable) { _private.setChecked(false); } } else { if (root.checkable) { _private.setChecked(root.stackContainsPage()); } } } }, Connections { enabled: root.pageStack.hasOwnProperty("layers") target: root.pageStack.layers function onCurrentItemChanged() { if (root.useLayers && root.checkable) { _private.setChecked(root.layerContainsPage()); } else { if (root.pageStack.layers.depth === 1 && root.stackContainsPage()) { _private.setChecked(true); } } } } ] } }