Warning, /frameworks/kirigami/src/controls/Page.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *  SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 import QtQuick 2.5
0008 import QtQuick.Layouts 1.2
0009 import QtQuick.Templates 2.1 as T2
0010 import QtQuick.Controls 2.1 as QQC2
0011 import org.kde.kirigami 2.10 as Kirigami
0012 import "private" as P
0013 
0014 /**
0015  * Page is a container for all the app pages: everything pushed to the
0016  * @link ApplicationWindow::pageStack pageStack @endlink should be a Page.
0017  *
0018  * For content that should be scrollable, such as QtQuick.ListView, use ScrollablePage instead.
0019  * @inherit QtQuick.Controls.Page
0020  */
0021 QQC2.Page {
0022     id: root
0023 
0024 //BEGIN properties
0025     /**
0026      * @brief If the central element of the page is a Flickable
0027      * (ListView and Gridview as well) you can set it there.
0028      *
0029      * Normally, you wouldn't need to do that, but just use the
0030      * ScrollablePage element instead.
0031      *
0032      * Use this if your flickable has some non standard properties,
0033      * such as not covering the whole Page.
0034      *
0035      * @see kirigami::ScrollablePage
0036      */
0037     property Flickable flickable
0038 
0039     /**
0040      * @brief Defines the contextual actions for the page:
0041      * an easy way to assign actions in the right sliding panel
0042      *
0043      * Example usage:
0044      * @code{.qml}
0045      * import org.kde.kirigami 2.4 as Kirigami
0046      *
0047      * Kirigami.ApplicationWindow {
0048      *  [...]
0049      *     contextDrawer: Kirigami.ContextDrawer {
0050      *         id: contextDrawer
0051      *     }
0052      *  [...]
0053      * }
0054      * @endcode
0055      *
0056      * @code{.qml}
0057      * import org.kde.kirigami 2.4 as Kirigami
0058      *
0059      * Kirigami.Page {
0060      *   [...]
0061      *     actions.contextualActions: [
0062      *         Kirigami.Action {
0063      *             icon.name: "edit"
0064      *             text: "Action text"
0065      *             onTriggered: {
0066      *                 // do stuff
0067      *             }
0068      *         },
0069      *         Kirigami.Action {
0070      *             icon.name: "edit"
0071      *             text: "Action text"
0072      *             onTriggered: {
0073      *                 // do stuff
0074      *             }
0075      *         }
0076      *     ]
0077      *   [...]
0078      * }
0079      * @endcode
0080      * @warning This will be removed in KF6.
0081      * @property list<QtQml.QtObject> contextualActions
0082      */
0083     // TODO: remove
0084     property alias contextualActions: actionsGroup.contextualActions
0085 
0086     /**
0087      * @brief An optional single action for the action button.
0088      *
0089      * Example usage:
0090      * @code{.qml}
0091      * import org.kde.kirigami 2.4 as Kirigami
0092      * Kirigami.Page {
0093      *     actions.main: Kirigami.Action {
0094      *         icon.name: "edit"
0095      *         onTriggered: {
0096      *             // do stuff
0097      *         }
0098      *     }
0099      * }
0100      * @endcode
0101      * @warning This will be removed in KF6.
0102      * @property Action mainAction
0103      */
0104     //TODO: remove
0105     property alias mainAction: actionsGroup.main
0106 
0107     /**
0108      * @brief An optional extra action at the left of the main action button.
0109      *
0110      * Example usage:
0111      * @code{.qml}
0112      * import org.kde.kirigami 2.4 as Kirigami
0113      * Kirigami.Page {
0114      *     actions.left: Kirigami.Action {
0115      *         icon.name: "edit"
0116      *         onTriggered: {
0117      *             // do stuff
0118      *         }
0119      *     }
0120      * }
0121      * @endcode
0122      * @warning This will be removed in KF6.
0123      * @property Action leftAction
0124      */
0125     // TODO: remove
0126     property alias leftAction: actionsGroup.left
0127 
0128     /**
0129      * @brief An optional extra action at the right of the main action button.
0130      *
0131      * Example usage:
0132      * @code{.qml}
0133      * import org.kde.kirigami 2.4 as Kirigami
0134      * Kirigami.Page {
0135      *     actions.right: Kirigami.Action {
0136      *         icon.name: "edit"
0137      *         onTriggered: {
0138      *             // do stuff
0139      *         }
0140      *     }
0141      * }
0142      * @endcode
0143      * @warning This will be removed in KF6.
0144      * @property Action rightAction
0145      */
0146     // TODO: remove
0147     property alias rightAction: actionsGroup.right
0148 
0149     /**
0150      * @brief This property holds the actions group.
0151      * @code
0152      * import org.kde.kirigami 2.4 as Kirigami
0153      * Kirigami.Page {
0154      *     actions {
0155      *         main: Kirigami.Action {...}
0156      *         left: Kirigami.Action {...}
0157      *         right: Kirigami.Action {...}
0158      *         contextualActions: [
0159      *             Kirigami.Action {...},
0160      *             Kirigami.Action {...}
0161      *         ]
0162      *     }
0163      * }
0164      * @endcode
0165      * @see <a href="https://develop.kde.org/hig/components/navigation/actionbutton">KDE Human Interface Guidelines on Actions</a>
0166      * @property kirigami::private::PageActionPropertyGroup actions
0167      */
0168     readonly property alias actions: actionsGroup
0169 
0170     /**
0171      * @brief This property specifies us if it is the currently active page.
0172      *
0173      * Specifies if it's the currently selected page in the window's pages
0174      * row, or if layers are used whether this is the topmost item on the
0175      * layers stack. If the page is not attached to either a column view or
0176      * a stack view, expect this to be true.
0177      *
0178      * @since org.kde.kirigami 2.1
0179      */
0180     //TODO KF6: remove this or at least all the assumptions about the internal tree structure of items
0181     readonly property bool isCurrentPage: Kirigami.ColumnView.view
0182             ? (Kirigami.ColumnView.index === Kirigami.ColumnView.view.currentIndex && Kirigami.ColumnView.view.parent.parent.currentItem === Kirigami.ColumnView.view.parent)
0183             : (parent && parent instanceof QQC2.StackView
0184                 ? parent.currentItem === root
0185                 : true)
0186 
0187     /**
0188      * An item which stays on top of every other item in the page,
0189      * if you want to make sure some elements are completely in a
0190      * layer on top of the whole content, parent items to this one.
0191      * It's a "local" version of ApplicationWindow's overlay
0192      *
0193      * @property Item overlay
0194      * @since org.kde.kirigami 2.5
0195      */
0196     readonly property alias overlay: overlayItem
0197 
0198     /**
0199      * @brief This holds the icon that represents this page.
0200      */
0201     property P.ActionIconGroup icon: P.ActionIconGroup {}
0202 
0203     /**
0204      * @brief Whether this page needs user attention.
0205      */
0206     property bool needsAttention
0207 
0208     /**
0209      * @brief Progress of a task this page is doing.
0210      *
0211      * Set to undefined to indicate that there are no ongoing tasks.
0212      *
0213      * default: ``undefined``
0214      *
0215      * @property real progress
0216      */
0217     property var progress: undefined
0218 
0219     /**
0220      * @brief The delegate which will be used to draw the page title.
0221      *
0222      * It can be customized to put any kind of Item in there.
0223      *
0224      * @since org.kde.kirigami 2.7
0225      */
0226     property Component titleDelegate: Component {
0227         id: defaultTitleDelegate
0228         P.DefaultPageTitleDelegate {
0229             text: root.title
0230         }
0231     }
0232 
0233     /**
0234      * The item used as global toolbar for the page
0235      * present only if we are in a PageRow as a page or as a layer,
0236      * and the style is either Titles or ToolBar.
0237      *
0238      * @since org.kde.kirigami 2.5
0239      */
0240     readonly property Item globalToolBarItem: globalToolBar.item
0241 
0242     /**
0243      * @brief This property holds the style for the automatically generated
0244      * toolbar of the PageRow where the Page is inserted.
0245      *
0246      * By default, the Page's globalToolBarStyle determines the style used by
0247      * the PageRow where it is inserted, updating the PageRow's globalToolBar
0248      * style. This allows for a single page to override the application toolbar
0249      * style for itself.
0250      *
0251      * It is discouraged to use this, except in very specific cases, like a
0252      * chat application that can't have controls at the bottom except for a
0253      * text field. If the Page is not in a PageRow, by default, the toolbar
0254      * will be invisible, so Page::globalToolBarStyle has to be explicitly
0255      * set to ApplicationHeaderStyle.ToolBar to be used in that case.
0256      */
0257     property int globalToolBarStyle: {
0258         if (globalToolBar.row && !globalToolBar.stack) {
0259             return globalToolBar.row.globalToolBar.actualStyle;
0260         } else if (globalToolBar.stack) {
0261             return Kirigami.Settings.isMobile ? Kirigami.ApplicationHeaderStyle.Titles : Kirigami.ApplicationHeaderStyle.ToolBar;
0262         } else {
0263             return Kirigami.ApplicationHeaderStyle.None;
0264         }
0265     }
0266 //END properties
0267 
0268 //BEGIN signals and signal handlers
0269     /**
0270      * Emitted when a visualization for the actions is about to
0271      * be shown, such as the toolbar menu or the ContextDrawer.
0272      *
0273      * @since org.kde.kirigami 2.7
0274      */
0275     signal contextualActionsAboutToShow
0276 
0277     /**
0278      * @brief Emitted when the application requests a Back action.
0279      *
0280      * For instance a global "back" shortcut or the Android
0281      * Back button has been pressed.
0282      * The page can manage the back event by itself,
0283      * and if it set event.accepted = true, it will stop the main
0284      * application to manage the back event.
0285      */
0286     signal backRequested(var event);
0287 
0288 
0289     // Look for sheets and cose them
0290     // FIXME: port Sheets to Popup?
0291     onBackRequested: event => {
0292         let item;
0293         for (const i in root.resources) {
0294             item = root.resources[i];
0295             if (item.hasOwnProperty("close") && item.hasOwnProperty("sheetOpen") && item.sheetOpen) {
0296                 item.close()
0297                 event.accepted = true;
0298                 return;
0299             }
0300         }
0301     }
0302 
0303     onHeaderChanged: {
0304         if (header) {
0305             header.anchors.top = Qt.binding(() => globalToolBar.visible ? globalToolBar.bottom : root.top);
0306         }
0307     }
0308 
0309     Component.onCompleted: {
0310         headerChanged();
0311         parentChanged(root.parent);
0312         globalToolBar.syncSource();
0313         actionButtons.pageComplete = true
0314     }
0315 
0316     onParentChanged: {
0317         if (!parent) {
0318             return;
0319         }
0320         globalToolBar.stack = null;
0321         globalToolBar.row = null;
0322 
0323         if (root.Kirigami.ColumnView.view) {
0324             globalToolBar.row = root.Kirigami.ColumnView.view.__pageRow;
0325         }
0326         if (root.T2.StackView.view) {
0327             globalToolBar.stack = root.T2.StackView.view;
0328             globalToolBar.row = root.T2.StackView.view ? root.T2.StackView.view.parent : null;
0329         }
0330         if (globalToolBar.row) {
0331             root.globalToolBarStyleChanged.connect(globalToolBar.syncSource);
0332             globalToolBar.syncSource();
0333         }
0334     }
0335 //END signals and signal handlers
0336 
0337     // NOTE: contentItem will be created if not existing (and contentChildren of Page would become its children) This with anchors enforces the geometry we want, where globalToolBar is a super-header, on top of header
0338     contentItem: Item {
0339         anchors {
0340             top: (root.header && root.header.visible)
0341                     ? root.header.bottom
0342                     : (globalToolBar.visible ? globalToolBar.bottom : parent.top)
0343             topMargin: root.topPadding + root.spacing
0344             bottom: (root.footer && root.footer.visible) ? root.footer.top : parent.bottom
0345             bottomMargin: root.bottomPadding + root.spacing
0346         }
0347     }
0348 
0349     background: Rectangle {
0350         color: Kirigami.Theme.backgroundColor
0351     }
0352 
0353     implicitHeight: ((header && header.visible) ? header.implicitHeight : 0) + ((footer && footer.visible) ? footer.implicitHeight : 0) + contentItem.implicitHeight + topPadding + bottomPadding
0354     implicitWidth: contentItem.implicitWidth + leftPadding + rightPadding
0355 
0356     // FIXME: on material the shadow would bleed over
0357     clip: root.header !== null;
0358 
0359     padding: Kirigami.Units.gridUnit
0360     bottomPadding: actionButtons.item ? actionButtons.height : verticalPadding
0361 
0362     // in data in order for them to not be considered for contentItem, contentChildren, contentData
0363     data: [
0364         P.PageActionPropertyGroup {
0365             id: actionsGroup
0366         },
0367 
0368         Item {
0369             id: overlayItem
0370             parent: root
0371             z: 9997
0372             anchors {
0373                 fill: parent
0374                 topMargin: globalToolBar.height
0375             }
0376         },
0377         // global top toolbar if we are in a PageRow (in the row or as a layer)
0378         Loader {
0379             id: globalToolBar
0380             z: 9999
0381             height: item ? item.implicitHeight : 0
0382             anchors {
0383                 left:  parent.left
0384                 right: parent.right
0385                 top: parent.top
0386             }
0387             property Kirigami.PageRow row
0388             property T2.StackView stack
0389 
0390             // don't load async so that on slower devices we don't have the page content height changing while loading in
0391             // otherwise, it looks unpolished and jumpy
0392             asynchronous: false
0393 
0394             visible: active
0395             active: (root.titleDelegate !== defaultTitleDelegate || root.globalToolBarStyle === Kirigami.ApplicationHeaderStyle.ToolBar || root.globalToolBarStyle === Kirigami.ApplicationHeaderStyle.Titles)
0396             onActiveChanged: {
0397                 if (active) {
0398                     syncSource();
0399                 }
0400             }
0401 
0402             function syncSource() {
0403                 if (root.globalToolBarStyle !== Kirigami.ApplicationHeaderStyle.ToolBar &&
0404                     root.globalToolBarStyle !== Kirigami.ApplicationHeaderStyle.Titles &&
0405                     root.titleDelegate !== defaultTitleDelegate) {
0406                     sourceComponent = root.titleDelegate;
0407                 } else if (active) {
0408                     const url = root.globalToolBarStyle === Kirigami.ApplicationHeaderStyle.ToolBar
0409                         ? "private/globaltoolbar/ToolBarPageHeader.qml"
0410                         : "private/globaltoolbar/TitlesPageHeader.qml";
0411                     // TODO: find container reliably, remove assumption
0412                     setSource(Qt.resolvedUrl(url), {
0413                         pageRow: Qt.binding(() => row),
0414                         page: root,
0415                         current: Qt.binding(() => {
0416                             if (!row && !stack) {
0417                                 return true;
0418                             } else if (stack) {
0419                                 return stack;
0420                             } else {
0421                                 return row.currentIndex === root.Kirigami.ColumnView.level;
0422                             }
0423                         }),
0424                     });
0425                 }
0426             }
0427         },
0428         // bottom action buttons
0429         Loader {
0430             id: actionButtons
0431             z: 9999
0432             parent: root
0433             anchors {
0434                 left: parent.left
0435                 right: parent.right
0436                 bottom: parent.bottom
0437             }
0438             // if the page doesn't inherit, assume it has custom colors we want to use them here too
0439             Kirigami.Theme.inherit: !root.Kirigami.Theme.inherit
0440             Kirigami.Theme.colorSet: Kirigami.Theme.Button
0441 
0442             // It should be T2.Page, Qt 5.7 doesn't like it
0443             property Item page: root
0444             height: item ? item.implicitHeight : 0
0445 
0446             asynchronous: true
0447 
0448             property bool pageComplete: false
0449 
0450             active: {
0451                 // Important! Do not do anything until the page has been
0452                 // completed, so we are sure what the globalToolBarStyle is,
0453                 // otherwise we risk creating the content and then discarding it.
0454                 if (!pageComplete) {
0455                     return false;
0456                 }
0457 
0458                 if ((globalToolBar.row && globalToolBar.row.globalToolBar.actualStyle === Kirigami.ApplicationHeaderStyle.ToolBar)
0459                     || root.globalToolBarStyle === Kirigami.ApplicationHeaderStyle.ToolBar
0460                     || root.globalToolBarStyle === Kirigami.ApplicationHeaderStyle.None) {
0461                     return false;
0462                 }
0463 
0464                 if (!root.actions.main && !root.actions.left && !root.actions.right && root.actions.contextualActions.length === 0) {
0465                     return false;
0466                 }
0467 
0468                 // Legacy
0469                 if (typeof applicationWindow === "undefined") {
0470                     return true;
0471                 }
0472 
0473                 if (applicationWindow().header && applicationWindow().header.toString().indexOf("ToolBarApplicationHeader") !== -1) {
0474                     return false;
0475                 }
0476 
0477                 if (applicationWindow().footer && applicationWindow().footer.toString().indexOf("ToolBarApplicationHeader") !== -1) {
0478                     return false;
0479                 }
0480 
0481                 return true;
0482             }
0483 
0484             source: Qt.resolvedUrl("./private/ActionButton.qml")
0485         }
0486     ]
0487 
0488     Layout.fillWidth: true
0489 }