Warning, /frameworks/knewstuff/src/qtquick/qml/Action.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2021 Dan Leinir Turthra Jensen <admin@leinir.dk>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 /**
0008  * @brief An action which when triggered will open a NewStuff.Dialog or a NewStuff.Page, depending on settings
0009  *
0010  * This component is equivalent to the old Button component, but functions in more modern applications
0011  *
0012  * The following is a simple example of how to use this Action to show wallpapers from the KDE Store, on a
0013  * system where Plasma has been installed (and consequently the wallpaper knsrc file is available). This also
0014  * shows how to make the action push a page to a pageStack rather than opening a dialog:
0015  *
0016 \code{.qml}
0017 import org.kde.newstuff 1.91 as NewStuff
0018 
0019 NewStuff.Action {
0020     configFile: "wallpaper.knsrc"
0021     text: i18n("&Get New Wallpapers...")
0022     pageStack: applicationWindow().pageStack
0023     onEntryEvent: function(entry, event) {
0024         if (event === NewStuff.Entry.StatusChangedEvent) {
0025             // A entry was installed, updated or removed
0026         } else if (event === NewStuff.Entry.AdoptedEvent) {
0027             // The "AdoptionCommand" from the knsrc file was run for the given entry.
0028             // This should not require refreshing the data for the model
0029         }
0030     }
0031 }
0032 \endcode
0033  *
0034  * @see NewStuff.Button
0035  * @since 5.81
0036  */
0037 
0038 import QtQuick 2.11
0039 import QtQuick.Controls 2.11 as QtControls
0040 import org.kde.kirigami 2.5 as Kirigami
0041 
0042 import org.kde.newstuff 1.81 as NewStuff
0043 
0044 Kirigami.Action {
0045     id: component
0046 
0047     /*
0048      * The configuration file is not aliased, because then we end up initialising the
0049      * KNSCore::Engine immediately the Action is instantiated, which we want to avoid (as that
0050      * is effectively a phone-home scenario, and causes internet traffic in situations
0051      * where it would not seem likely that there should be any).
0052      * If we want, in the future, to add some status display to the Action (such as "there
0053      * are updates to be had" or somesuch, then we can do this, but until that choice is
0054      * made, let's not)
0055      */
0056     /**
0057      * The configuration file to use for the Page created by this action
0058      */
0059     property string configFile
0060 
0061     /**
0062      * The default view mode of the page spawned by this action. This should be
0063      * set using the NewStuff.Page.ViewMode enum
0064      * @see NewStuff.Page.ViewMode
0065      */
0066     property int viewMode: NewStuff.Page.ViewMode.Preview
0067 
0068     /**
0069      * If this is set, the action will push a NewStuff.Page onto this page stack
0070      * (and request it is made visible if triggered again). If you do not set this
0071      * property, the action will spawn a NewStuff.Dialog instead.
0072      * @note If you are building a KCM, set this to your ```kcm``` object.
0073      */
0074     property QtObject pageStack: null
0075 
0076     /**
0077      * The engine which handles the content in this Action
0078      * This will be null until the action has been triggered the first time
0079      */
0080     readonly property QtObject engine: component._private.engine
0081 
0082     /**
0083      * Contains the entries which have been changed.
0084      * @note This is cleared when the page is shown, so the changed entries are those
0085      * changed since the page was opened most recently (rather than the lifetime
0086      * of the instance of the Action component)
0087      * @deprecated Since 5.82, use entryEvent instead
0088      */
0089     property var changedEntries
0090 
0091     /**
0092      * This forwards the entry changed event from the QtQuick engine
0093      * @see Engine::entryEvent
0094      */
0095     signal entryEvent(QtObject entry, int event);
0096 
0097     /**
0098      * Show the details page for a specific entry.
0099      * If you call this function before the engine initialisation has been completed,
0100      * the action itself will be postponed until that has happened.
0101      * @param providerId The provider ID for the entry you wish to show details for
0102      * @param entryId The unique ID for the entry you wish to show details for
0103      * @since 5.79
0104      */
0105     function showEntryDetails(providerId, entryId) {
0106         component._private.providerId = providerId;
0107         component._private.entryId = entryId;
0108         component._private.showHotNewStuff();
0109     }
0110 
0111     /**
0112      * If this is true (default is false), the action will be shown when the Kiosk settings are such
0113      * that Get Hot New Stuff is disallowed (and any other time enabled is set to false).
0114      * Usually you would want to leave this alone, but occasionally you may have a reason to
0115      * leave a action in place that the user is unable to enable.
0116      */
0117     property bool visibleWhenDisabled: false
0118 
0119     /**
0120     * Show the page/dialog (same as activating the action), if allowed by the Kiosk settings
0121     */
0122     function showHotNewStuff() {
0123         component._private.showHotNewStuff();
0124     }
0125 
0126     onTriggered: { component._private.showHotNewStuff(); }
0127 
0128     icon.name: "get-hot-new-stuff"
0129     visible: enabled || visibleWhenDisabled
0130     enabled: NewStuff.Settings.allowedByKiosk
0131     onEnabledChanged: {
0132         // If the user resets this when kiosk has disallowed ghns, force enabled back to false
0133         if (enabled === true && NewStuff.Settings.allowedByKiosk === false) {
0134             enabled = false;
0135         }
0136     }
0137 
0138     readonly property QtObject _private: QtObject {
0139         property QtObject engine: pageItem ? pageItem.engine : null
0140         // Probably wants to be deleted and cleared if the "mode" changes at runtime...
0141         property QtObject pageItem;
0142 
0143         property string providerId;
0144         property string entryId;
0145         property Connections showSpecificEntryConnection: Connections {
0146             target: component.engine
0147             function onInitialized() {
0148                 pageItem.showEntryDetails(providerId, component._private.entryId);
0149             }
0150         }
0151 
0152         property Connections engineConnections: Connections {
0153             target: component.engine
0154             function onEntryEvent(entry, event) {
0155                 component.entryEvent(entry, event);
0156             }
0157         }
0158         property Binding changedEntriesBinding: Binding {
0159             target: component
0160             property: "changedEntries"
0161             value: component.engine ? component.engine.changedEntries : []
0162         }
0163         function showHotNewStuff() {
0164             if (NewStuff.Settings.allowedByKiosk) {
0165                 if (component.pageStack !== null) {
0166                     if (component._private.pageItem // If we already have a page created...
0167                         && (component.pageStack.columnView !== undefined // first make sure that this pagestack is a Kirigami-style one (otherwise just assume we're ok)
0168                             && component.pageStack.columnView.contains(component._private.pageItem))) // and then check if the page is still in the stack before attempting to...
0169                     {
0170                         // ...set the already existing page as the current page
0171                         component.pageStack.currentItem = component._private.pageItem;
0172                     } else {
0173                         component._private.pageItem = newStuffPage.createObject(component);
0174                         component.pageStack.push(component._private.pageItem);
0175                     }
0176                 } else {
0177                     newStuffDialog.open();
0178                 }
0179             } else {
0180                 // make some noise, because silently doing nothing is a bit annoying
0181             }
0182         }
0183         property Component newStuffPage: Component {
0184             NewStuff.Page {
0185                 configFile: component.configFile
0186                 viewMode: component.viewMode
0187             }
0188         }
0189         property Item newStuffDialog: Loader {
0190             // Use this function to open the dialog. It seems roundabout, but this ensures
0191             // that the dialog is not constructed until we want it to be shown the first time,
0192             // since it will initialise itself on the first load (which causes it to phone
0193             // home) and we don't want that until the user explicitly asks for it.
0194             function open() {
0195                 if (item) {
0196                     item.open();
0197                 } else {
0198                     active = true;
0199                 }
0200             }
0201             onLoaded: {
0202                 component._private.pageItem = item;
0203                 item.open();
0204             }
0205 
0206             active: false
0207             asynchronous: true
0208 
0209             sourceComponent: NewStuff.Dialog {
0210                 configFile: component.configFile
0211                 viewMode: component.viewMode
0212             }
0213         }
0214     }
0215 }