File indexing completed on 2024-04-21 03:56:26

0001 /*
0002     SPDX-FileCopyrightText: 2016 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 #ifndef ENGINE_H
0008 #define ENGINE_H
0009 
0010 #include <QObject>
0011 #include <QQmlListProperty>
0012 
0013 #include "enginebase.h"
0014 #include "entry.h"
0015 #include "errorcode.h"
0016 #include "provider.h"
0017 #include "transaction.h"
0018 
0019 class EnginePrivate;
0020 
0021 /**
0022  * KNSCore::EngineBase for interfacing with QML
0023  *
0024  * @see ItemsModel
0025  */
0026 class Engine : public KNSCore::EngineBase
0027 {
0028     Q_OBJECT
0029     Q_PROPERTY(QString configFile READ configFile WRITE setConfigFile NOTIFY configFileChanged)
0030     Q_PROPERTY(bool isLoading READ isLoading NOTIFY busyStateChanged)
0031     Q_PROPERTY(bool needsLazyLoadSpinner READ needsLazyLoadSpinner NOTIFY busyStateChanged)
0032     Q_PROPERTY(bool hasAdoptionCommand READ hasAdoptionCommand NOTIFY configFileChanged)
0033     Q_PROPERTY(QString name READ name NOTIFY configFileChanged)
0034     Q_PROPERTY(bool isValid READ isValid NOTIFY configFileChanged)
0035 
0036     Q_PROPERTY(QObject *categories READ categories NOTIFY categoriesChanged)
0037     Q_PROPERTY(QStringList categoriesFilter READ categoriesFilter WRITE setCategoriesFilter RESET resetCategoriesFilter NOTIFY categoriesFilterChanged)
0038     Q_PROPERTY(KNSCore::Provider::Filter filter READ filter WRITE setFilter NOTIFY filterChanged)
0039     Q_PROPERTY(KNSCore::Provider::SortMode sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
0040     Q_PROPERTY(QString searchTerm READ searchTerm WRITE setSearchTerm RESET resetSearchTerm NOTIFY searchTermChanged)
0041     Q_PROPERTY(QObject *searchPresetModel READ searchPresetModel NOTIFY searchPresetModelChanged)
0042 
0043     /**
0044      * Current state of the engine, the state con contain multiple operations
0045      * an empty BusyState represents the idle status
0046      * @since 5.74
0047      */
0048     Q_PROPERTY(BusyState busyState READ busyState WRITE setBusyState NOTIFY busyStateChanged)
0049     Q_PROPERTY(QString busyMessage READ busyMessage NOTIFY busyStateChanged)
0050 public:
0051     explicit Engine(QObject *parent = nullptr);
0052     ~Engine() override;
0053 
0054     enum class BusyOperation {
0055         Initializing = 1,
0056         LoadingData,
0057         LoadingPreview,
0058         InstallingEntry,
0059     };
0060     Q_DECLARE_FLAGS(BusyState, BusyOperation)
0061     Q_ENUM(BusyOperation)
0062 
0063     enum EntryEvent { // TODO KF6 remove in favor of using NewStuff.Entry values
0064         UnknownEvent = KNSCore::Entry::UnknownEvent,
0065         StatusChangedEvent = KNSCore::Entry::StatusChangedEvent,
0066         AdoptedEvent = KNSCore::Entry::AdoptedEvent,
0067         DetailsLoadedEvent = KNSCore::Entry::DetailsLoadedEvent,
0068     };
0069     Q_ENUM(EntryEvent)
0070 
0071     QString configFile() const;
0072     void setConfigFile(const QString &newFile);
0073     Q_SIGNAL void configFileChanged();
0074 
0075     Engine::BusyState busyState() const;
0076     QString busyMessage() const;
0077     void setBusyState(Engine::BusyState state);
0078 
0079     /**
0080      * Signal gets emitted when the busy state changes
0081      * @since 5.74
0082      */
0083     Q_SIGNAL void busyStateChanged();
0084 
0085     /**
0086      * Whether or not the engine is performing its initial loading operations
0087      * @since 5.65
0088      */
0089     bool isLoading() const
0090     {
0091         // When installing entries, we don't want to block the UI
0092         return busyState().toInt() != 0 && ((busyState() & BusyOperation::InstallingEntry) != BusyOperation::InstallingEntry);
0093     }
0094 
0095     QObject *categories() const;
0096     Q_SIGNAL void categoriesChanged();
0097 
0098     QStringList categoriesFilter() const;
0099     void setCategoriesFilter(const QStringList &newCategoriesFilter);
0100     Q_INVOKABLE void resetCategoriesFilter()
0101     {
0102         setCategoriesFilter(categoriesFilter());
0103     }
0104     Q_SIGNAL void categoriesFilterChanged();
0105 
0106     KNSCore::Provider::Filter filter() const;
0107     void setFilter(KNSCore::Provider::Filter filter);
0108     Q_SIGNAL void filterChanged();
0109 
0110     KNSCore::Provider::SortMode sortOrder() const;
0111     void setSortOrder(KNSCore::Provider::SortMode newSortOrder);
0112     Q_SIGNAL void sortOrderChanged();
0113 
0114     QString searchTerm() const;
0115     void setSearchTerm(const QString &newSearchTerm);
0116     Q_INVOKABLE void resetSearchTerm()
0117     {
0118         setSearchTerm(QString());
0119     }
0120     Q_SIGNAL void searchTermChanged();
0121 
0122     QObject *searchPresetModel() const;
0123     Q_SIGNAL void searchPresetModelChanged();
0124 
0125     Q_INVOKABLE void updateEntryContents(const KNSCore::Entry &entry);
0126     Q_INVOKABLE KNSCore::Entry __createEntry(const QString &providerId, const QString &entryId)
0127     {
0128         KNSCore::Entry e;
0129         e.setProviderId(providerId);
0130         e.setUniqueId(entryId);
0131         return e;
0132     }
0133 
0134     bool isValid();
0135     void reloadEntries();
0136 
0137     void loadPreview(const KNSCore::Entry &entry, KNSCore::Entry::PreviewType type);
0138 
0139     void addProvider(QSharedPointer<KNSCore::Provider> provider) override;
0140 
0141     /**
0142      * Adopt an entry using the adoption command. This will also take care of displaying error messages
0143      * @param entry Entry that should be adopted
0144      * @see signalErrorCode
0145      * @see signalEntryEvent
0146      * @since 5.77
0147      */
0148     Q_INVOKABLE void adoptEntry(const KNSCore::Entry &entry);
0149 
0150     /**
0151      * Installs an entry's payload file. This includes verification, if
0152      * necessary, as well as decompression and other steps according to the
0153      * application's *.knsrc file.
0154      *
0155      * @param entry Entry to be installed
0156      *
0157      * @see signalInstallationFinished
0158      * @see signalInstallationFailed
0159      */
0160     Q_INVOKABLE void install(const KNSCore::Entry &entry, int linkId = 1);
0161 
0162     /**
0163      * Uninstalls an entry. It reverses the steps which were performed
0164      * during the installation.
0165      *
0166      * @param entry The entry to deinstall
0167      */
0168     Q_INVOKABLE void uninstall(const KNSCore::Entry &entry);
0169 
0170     void requestMoreData();
0171 
0172     Q_INVOKABLE void revalidateCacheEntries();
0173     Q_INVOKABLE void restoreSearch();
0174     Q_INVOKABLE void storeSearch();
0175 Q_SIGNALS:
0176     void signalResetView();
0177 
0178     /**
0179      * This is fired for events related directly to a single Entry instance
0180      * The intermediate states Updating and Installing are not forwarded. In case you
0181      * need those you have to listen to the signals of the KNSCore::Engine instance of the engine property.
0182      *
0183      * As an example, if you need to know when the status of an entry changes, you might write:
0184      \code
0185         function onEntryEvent(entry, event) {
0186             if (event == NewStuff.Engine.StatusChangedEvent) {
0187                 myModel.ghnsEntryChanged(entry);
0188             }
0189         }
0190      \endcode
0191      *
0192      * nb: The above example is also how one would port a handler for the old changedEntries signal
0193      *
0194      * @see Entry::EntryEvent for details on which specific event is being notified
0195      */
0196     void entryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event);
0197 
0198     /**
0199      * Fires in the case of any critical or serious errors, such as network or API problems.
0200      * This forwards the signal from KNSCore::Engine::signalErrorCode, but with QML friendly
0201      * enumerations.
0202      * @param errorCode Represents the specific type of error which has occurred
0203      * @param message A human-readable message which can be shown to the end user
0204      * @param metadata Any additional data which might be hepful to further work out the details of the error (see KNSCore::Entry::ErrorCode for the
0205      * metadata details)
0206      * @see KNSCore::Engine::signalErrorCode
0207      * @since 5.84
0208      */
0209     void errorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata);
0210 
0211     void entryPreviewLoaded(const KNSCore::Entry &, KNSCore::Entry::PreviewType);
0212 
0213     void signalEntriesLoaded(const KNSCore::Entry::List &entries); ///@internal
0214     void signalEntryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event); ///@internal
0215 
0216 private:
0217     bool init(const QString &configfile) override;
0218     void updateStatus() override;
0219     bool needsLazyLoadSpinner();
0220     Q_SIGNAL void signalEntryPreviewLoaded(const KNSCore::Entry &, KNSCore::Entry::PreviewType);
0221     void registerTransaction(KNSCore::Transaction *transactions);
0222     void doRequest();
0223     const std::unique_ptr<EnginePrivate> d;
0224 };
0225 
0226 #endif // ENGINE_H