1/*
2 SPDX-FileCopyrightText: 2016 Dan Leinir Turthra Jensen <admin@leinir.dk>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#ifndef ENGINE_H
8#define ENGINE_H
9
10#include <QObject>
11#include <QQmlListProperty>
12
13#include "categoriesmodel.h"
14#include "enginebase.h"
15#include "entry.h"
16#include "errorcode.h"
17#include "provider.h"
18#include "searchpresetmodel.h"
19#include "transaction.h"
20
21class EnginePrivate;
22
23/**
24 * KNSCore::EngineBase for interfacing with QML
25 *
26 * @see ItemsModel
27 */
28class Engine : public KNSCore::EngineBase
29{
30 Q_OBJECT
31 Q_PROPERTY(QString configFile READ configFile WRITE setConfigFile NOTIFY configFileChanged)
32 Q_PROPERTY(bool isLoading READ isLoading NOTIFY busyStateChanged)
33 Q_PROPERTY(bool needsLazyLoadSpinner READ needsLazyLoadSpinner NOTIFY busyStateChanged)
34 Q_PROPERTY(bool hasAdoptionCommand READ hasAdoptionCommand NOTIFY configFileChanged)
35 Q_PROPERTY(QString name READ name NOTIFY configFileChanged)
36 Q_PROPERTY(bool isValid READ isValid NOTIFY configFileChanged)
37
38 Q_PROPERTY(CategoriesModel *categories READ categories NOTIFY categoriesChanged)
39 Q_PROPERTY(QStringList categoriesFilter READ categoriesFilter WRITE setCategoriesFilter RESET resetCategoriesFilter NOTIFY categoriesFilterChanged)
40 Q_PROPERTY(KNSCore::Provider::Filter filter READ filter WRITE setFilter NOTIFY filterChanged)
41 Q_PROPERTY(KNSCore::Filter filter2 READ filter2 WRITE setFilter2 NOTIFY filterChanged)
42 Q_PROPERTY(KNSCore::Provider::SortMode sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
43 Q_PROPERTY(KNSCore::SortMode sortOrder2 READ sortOrder2 WRITE setSortOrder2 NOTIFY sortOrderChanged)
44 Q_PROPERTY(QString searchTerm READ searchTerm WRITE setSearchTerm RESET resetSearchTerm NOTIFY searchTermChanged)
45 Q_PROPERTY(SearchPresetModel *searchPresetModel READ searchPresetModel NOTIFY searchPresetModelChanged)
46
47 /**
48 * Current state of the engine, the state con contain multiple operations
49 * an empty BusyState represents the idle status
50 * @since 5.74
51 */
52 Q_PROPERTY(BusyState busyState READ busyState WRITE setBusyState NOTIFY busyStateChanged)
53 Q_PROPERTY(QString busyMessage READ busyMessage NOTIFY busyStateChanged)
54public:
55 explicit Engine(QObject *parent = nullptr);
56 ~Engine() override;
57 Q_DISABLE_COPY_MOVE(Engine)
58
59 enum class BusyOperation {
60 Initializing = 1,
61 LoadingData,
62 LoadingPreview,
63 InstallingEntry,
64 };
65 Q_DECLARE_FLAGS(BusyState, BusyOperation)
66 Q_ENUM(BusyOperation)
67
68 enum EntryEvent { // TODO KF6 remove in favor of using NewStuff.Entry values
69 UnknownEvent = KNSCore::Entry::UnknownEvent,
70 StatusChangedEvent = KNSCore::Entry::StatusChangedEvent,
71 AdoptedEvent = KNSCore::Entry::AdoptedEvent,
72 DetailsLoadedEvent = KNSCore::Entry::DetailsLoadedEvent,
73 };
74 Q_ENUM(EntryEvent)
75
76 QString configFile() const;
77 void setConfigFile(const QString &newFile);
78 Q_SIGNAL void configFileChanged();
79
80 Engine::BusyState busyState() const;
81 QString busyMessage() const;
82 void setBusyState(Engine::BusyState state);
83
84 /**
85 * Signal gets emitted when the busy state changes
86 * @since 5.74
87 */
88 Q_SIGNAL void busyStateChanged();
89
90 /**
91 * Whether or not the engine is performing its initial loading operations
92 * @since 5.65
93 */
94 bool isLoading() const
95 {
96 // When installing entries, we don't want to block the UI
97 return busyState().toInt() != 0 && ((busyState() & BusyOperation::InstallingEntry) != BusyOperation::InstallingEntry);
98 }
99
100 CategoriesModel *categories() const;
101 Q_SIGNAL void categoriesChanged();
102
103 QStringList categoriesFilter() const;
104 void setCategoriesFilter(const QStringList &newCategoriesFilter);
105 Q_INVOKABLE void resetCategoriesFilter()
106 {
107 setCategoriesFilter(categoriesFilter());
108 }
109 Q_SIGNAL void categoriesFilterChanged();
110
111#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
112 /// @deprecated since 6.9 Use filter2
113 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use filter2")
114 KNSCore::Provider::Filter filter() const;
115#endif
116#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
117 /// @deprecated since 6.9 Use setFilter2
118 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use setFilter2")
119 void setFilter(KNSCore::Provider::Filter filter);
120#endif
121 [[nodiscard]] KNSCore::Filter filter2() const;
122 void setFilter2(KNSCore::Filter filter);
123 Q_SIGNAL void filterChanged();
124
125#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
126 /// @deprecated since 6.9 Use sortOrder2
127 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use sortOrder2")
128 KNSCore::Provider::SortMode sortOrder() const;
129#endif
130#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
131 /// @deprecated since 6.9 Use setSortOrder2
132 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use setSortOrder2")
133 void setSortOrder(KNSCore::Provider::SortMode newSortOrder);
134#endif
135 [[nodiscard]] KNSCore::SortMode sortOrder2() const;
136 void setSortOrder2(KNSCore::SortMode newSortOrder);
137 Q_SIGNAL void sortOrderChanged();
138
139 QString searchTerm() const;
140 void setSearchTerm(const QString &newSearchTerm);
141 Q_INVOKABLE void resetSearchTerm()
142 {
143 setSearchTerm(QString());
144 }
145 Q_SIGNAL void searchTermChanged();
146
147 SearchPresetModel *searchPresetModel() const;
148 Q_SIGNAL void searchPresetModelChanged();
149
150 Q_INVOKABLE void updateEntryContents(const KNSCore::Entry &entry);
151 Q_INVOKABLE KNSCore::Entry __createEntry(const QString &providerId, const QString &entryId)
152 {
153 KNSCore::Entry e;
154 e.setProviderId(providerId);
155 e.setUniqueId(entryId);
156 return e;
157 }
158
159 bool isValid();
160 void reloadEntries();
161
162 void loadPreview(const KNSCore::Entry &entry, KNSCore::Entry::PreviewType type);
163
164 /**
165 * Adopt an entry using the adoption command. This will also take care of displaying error messages
166 * @param entry Entry that should be adopted
167 * @see signalErrorCode
168 * @see signalEntryEvent
169 * @since 5.77
170 */
171 Q_INVOKABLE void adoptEntry(const KNSCore::Entry &entry);
172
173#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
174 /**
175 * Installs an entry's payload file. This includes verification, if
176 * necessary, as well as decompression and other steps according to the
177 * application's *.knsrc file.
178 *
179 * @param entry Entry to be installed
180 *
181 * @see signalInstallationFinished
182 * @see signalInstallationFailed
183 * @deprecated since 6.9, use installLatest or installLinkId instead
184 */
185 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "use installLatest or installLinkId instead")
186 Q_INVOKABLE void install(const KNSCore::Entry &entry, int linkId = 1);
187#endif
188
189 /**
190 * Performs an install on the given @p entry
191 *
192 * @param linkId specifies which of the assets we want to see installed.
193 * @since 6.9
194 */
195 Q_INVOKABLE void installLinkId(const KNSCore::Entry &entry, quint8 linkId);
196
197 /**
198 * Performs an install of the latest version on the given @p entry
199 *
200 * The latest version is determined using heuristics. If you want tight control over which offering gets installed
201 * you need to use installLinkId and manually figure out the id.
202 *
203 * @since 6.9
204 */
205 Q_INVOKABLE void installLatest(const KNSCore::Entry &entry);
206
207 /**
208 * Uninstalls an entry. It reverses the steps which were performed
209 * during the installation.
210 *
211 * @param entry The entry to uninstall
212 */
213 Q_INVOKABLE void uninstall(const KNSCore::Entry &entry);
214
215 void requestMoreData();
216
217 Q_INVOKABLE void revalidateCacheEntries();
218 Q_INVOKABLE void restoreSearch();
219 Q_INVOKABLE void storeSearch();
220Q_SIGNALS:
221 void signalResetView();
222
223 /**
224 * This is fired for events related directly to a single Entry instance
225 * The intermediate states Updating and Installing are not forwarded. In case you
226 * need those you have to listen to the signals of the KNSCore::Engine instance of the engine property.
227 *
228 * As an example, if you need to know when the status of an entry changes, you might write:
229 \code
230 function onEntryEvent(entry, event) {
231 if (event == NewStuff.Engine.StatusChangedEvent) {
232 myModel.ghnsEntryChanged(entry);
233 }
234 }
235 \endcode
236 *
237 * nb: The above example is also how one would port a handler for the old changedEntries signal
238 *
239 * @see Entry::EntryEvent for details on which specific event is being notified
240 */
241 void entryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event);
242
243 /**
244 * Fires in the case of any critical or serious errors, such as network or API problems.
245 * This forwards the signal from KNSCore::Engine::signalErrorCode, but with QML friendly
246 * enumerations.
247 * @param errorCode Represents the specific type of error which has occurred
248 * @param message A human-readable message which can be shown to the end user
249 * @param metadata Any additional data which might be helpful to further work out the details of the error (see KNSCore::Entry::ErrorCode for the
250 * metadata details)
251 * @see KNSCore::Engine::signalErrorCode
252 * @since 5.84
253 */
254 void errorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata);
255
256 void entryPreviewLoaded(const KNSCore::Entry &, KNSCore::Entry::PreviewType);
257
258 void signalEntriesLoaded(const KNSCore::Entry::List &entries); ///@internal
259 void signalEntryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event); ///@internal
260
261private:
262 bool init(const QString &configfile) override;
263 void updateStatus() override;
264 bool needsLazyLoadSpinner();
265 Q_SIGNAL void signalEntryPreviewLoaded(const KNSCore::Entry &, KNSCore::Entry::PreviewType);
266 void registerTransaction(KNSCore::Transaction *transactions);
267 void doRequest();
268 const std::unique_ptr<EnginePrivate> d;
269 KNSCore::EngineBasePrivate *dd;
270};
271
272#endif // ENGINE_H
273

source code of knewstuff/src/qtquick/quickengine.h