1 | /* |
2 | SPDX-FileCopyrightText: 2007 Josef Spillner <spillner@kde.org> |
3 | SPDX-FileCopyrightText: 2007-2010 Frederik Gladhorn <gladhorn@kde.org> |
4 | SPDX-FileCopyrightText: 2009 Jeremy Whiting <jpwhiting@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.1-or-later |
7 | */ |
8 | |
9 | #ifndef KNEWSTUFF3_ENGINEBASE_H |
10 | #define KNEWSTUFF3_ENGINEBASE_H |
11 | |
12 | #include <QHash> |
13 | #include <QMetaEnum> |
14 | #include <QObject> |
15 | #include <QSharedPointer> |
16 | #include <QString> |
17 | |
18 | #include "entry.h" |
19 | #include "errorcode.h" |
20 | #include "provider.h" |
21 | |
22 | #include "knewstuffcore_export.h" |
23 | |
24 | #include <memory> |
25 | |
26 | class KJob; |
27 | class EnginePrivate; |
28 | class QDomDocument; |
29 | |
30 | namespace Attica |
31 | { |
32 | class Provider; |
33 | } |
34 | |
35 | namespace KNSCore |
36 | { |
37 | class Cache; |
38 | class ; |
39 | class ResultsStream; |
40 | class EngineBasePrivate; |
41 | class Installation; |
42 | |
43 | /** |
44 | * KNewStuff engine. |
45 | * An engine keeps track of data which is available locally and remote |
46 | * and offers high-level synchronization calls as well as upload and download |
47 | * primitives using an underlying GHNS protocol. |
48 | * |
49 | * This is a base class for different engine implementations |
50 | */ |
51 | class KNEWSTUFFCORE_EXPORT EngineBase : public QObject |
52 | { |
53 | Q_OBJECT |
54 | |
55 | /** |
56 | * Text that should be displayed for the adoption button, this defaults to "Use" |
57 | * @since 5.77 |
58 | */ |
59 | Q_PROPERTY(QString useLabel READ useLabel NOTIFY useLabelChanged) |
60 | |
61 | /** |
62 | * Whether or not the configuration says that the providers are expected to support uploading. |
63 | * As it stands, this is used to determine whether or not to show the Upload... action where |
64 | * that is displayed (primarily NewStuff.Page). |
65 | * @since 5.85 |
66 | */ |
67 | Q_PROPERTY(bool uploadEnabled READ uploadEnabled NOTIFY uploadEnabledChanged) |
68 | |
69 | /** |
70 | * @since 5.85 |
71 | */ |
72 | Q_PROPERTY(QStringList providerIDs READ providerIDs NOTIFY providersChanged) |
73 | |
74 | /** |
75 | * @copydoc contentWarningType |
76 | */ |
77 | Q_PROPERTY(ContentWarningType contentWarningType READ contentWarningType NOTIFY contentWarningTypeChanged) |
78 | |
79 | public: |
80 | EngineBase(QObject *parent = nullptr); |
81 | ~EngineBase(); |
82 | |
83 | /** |
84 | * List of all available config files. This list will contain no duplicated filenames. |
85 | * The returned file paths are absolute. |
86 | * @since 5.83 |
87 | */ |
88 | static QStringList availableConfigFiles(); |
89 | |
90 | /** |
91 | * Initializes the engine. This step is application-specific and relies |
92 | * on an external configuration file, which determines all the details |
93 | * about the initialization. |
94 | * |
95 | * @param configfile KNewStuff2 configuration file (*.knsrc) |
96 | * @return \b true if any valid configuration was found, \b false otherwise |
97 | * @see KNS3::DownloadDialog |
98 | */ |
99 | virtual bool init(const QString &configfile); |
100 | |
101 | /** |
102 | * The name as defined by the knsrc file |
103 | * @return The name associated with the engine's configuration file |
104 | * @since 5.63 |
105 | */ |
106 | QString name() const; |
107 | |
108 | /** |
109 | * Text that should be displayed for the adoption button, this defaults to i18n("Use") |
110 | * @since 5.77 |
111 | */ |
112 | QString useLabel() const; |
113 | |
114 | /** |
115 | * Signal gets emitted when the useLabel property changes |
116 | * @since 5.77 |
117 | */ |
118 | Q_SIGNAL void useLabelChanged(); |
119 | |
120 | /** |
121 | * Whether or not the configuration says that the providers are expected to support uploading. |
122 | * @return True if the providers are expected to support uploading |
123 | * @since 5.85 |
124 | */ |
125 | bool uploadEnabled() const; |
126 | |
127 | /** |
128 | * Fired when the uploadEnabled property changes |
129 | * @since 5.85 |
130 | */ |
131 | Q_SIGNAL void uploadEnabledChanged(); |
132 | |
133 | /** |
134 | * The list of the server-side names of the categories handled by this |
135 | * engine instance. This corresponds directly to the list of categories |
136 | * in your knsrc file. This is not supposed to be used as user-facing |
137 | * strings - @see categoriesMetadata() for that. |
138 | * |
139 | * @return The categories which this instance of Engine handles |
140 | */ |
141 | QStringList categories() const; |
142 | |
143 | /** |
144 | * Get the entries cache for this engine (note that it may be null if the engine is |
145 | * not yet initialized). |
146 | * @return The cache for this engine (or null if the engine is not initialized) |
147 | * @since 5.74 |
148 | */ |
149 | QSharedPointer<Cache> cache() const; |
150 | |
151 | /** |
152 | * The list of metadata for the categories handled by this engine instance. |
153 | * If you wish to show the categories to the user, this is the data to use. |
154 | * The category name is the string used to set categories for the filter, |
155 | * and also what is returned by both categories() and categoriesFilter(). |
156 | * The human-readable name is displayName, and the only thing which should |
157 | * be shown to the user. |
158 | * |
159 | * @return The metadata for all categories handled by this engine |
160 | */ |
161 | QList<Provider::CategoryMetadata> categoriesMetadata(); |
162 | |
163 | QList<Provider::SearchPreset> searchPresets(); |
164 | |
165 | /** |
166 | * @returns the list of attica (OCS) providers this engine is connected to |
167 | * @since 5.92 |
168 | */ |
169 | QList<Attica::Provider *> atticaProviders() const; |
170 | |
171 | /** |
172 | * Set a filter for results, which filters out all entries which do not match |
173 | * the filter, as applied to the tags for the entry. This filters only on the |
174 | * tags specified for the entry itself. To filter the downloadlinks, use |
175 | * setDownloadTagFilter(QStringList). |
176 | * |
177 | * @note The default filter if one is not set from your knsrc file will filter |
178 | * out entries marked as ghns_excluded=1. To retain this when setting a custom |
179 | * filter, add "ghns_excluded!=1" as one of the filters. |
180 | * |
181 | * @note Some tags provided by OCS do not supply a value (and are simply passed |
182 | * as a key). These will be interpreted as having the value 1 for filtering |
183 | * purposes. An example of this might be ghns_excluded, which in reality will |
184 | * generally be passed through ocs as "ghns_excluded" rather than "ghns_excluded=1" |
185 | * |
186 | * @note As tags are metadata, they are provided in the form of adjectives. They |
187 | * are never supplied as action verbs or instructions (as an example, a good tag |
188 | * to suggest that for example a wallpaper is painted would be "painted" as opposed |
189 | * to "paint", and another example might be that an item should be "excluded" as |
190 | * opposed to "exclude"). |
191 | * |
192 | * == Examples of use == |
193 | * Value for tag "tagname" must be exactly "tagdata": |
194 | * tagname==tagdata |
195 | * |
196 | * Value for tag "tagname" must be different from "tagdata": |
197 | * tagname!=tagdata |
198 | * |
199 | * == KNSRC entry == |
200 | * A tag filter line in a .knsrc file, which is a comma separated list of |
201 | * tag/value pairs, might look like: |
202 | * |
203 | * TagFilter=ghns_excluded!=1,data##mimetype==application/cbr+zip,data##mimetype==application/cbr+rar |
204 | * which would honour the exclusion and filter out anything that does not |
205 | * include a comic book archive in either zip or rar format in one or more |
206 | * of the download items. |
207 | * Notice in particular that there are two data##mimetype entries. Use this |
208 | * for when a tag may have multiple values. |
209 | * |
210 | * TagFilter=application##architecture==x86_64 |
211 | * which would not honour the exclusion, and would filter out all entries |
212 | * which do not mark themselves as having a 64bit application binary in at |
213 | * least one download item. |
214 | * |
215 | * The value does not current support wildcards. The list should be considered |
216 | * a binary AND operation (that is, all filter entries must match for the data |
217 | * entry to be included in the return data) |
218 | * |
219 | * @param filter The filter in the form of a list of strings |
220 | * @see setDownloadTagFilter(QStringList) |
221 | * @since 5.51 |
222 | */ |
223 | void setTagFilter(const QStringList &filter); |
224 | /** |
225 | * Gets the current tag filter list |
226 | * @see setTagFilter(QStringList) |
227 | * @since 5.51 |
228 | */ |
229 | QStringList tagFilter() const; |
230 | /** |
231 | * Add a single filter entry to the entry tag filter. The filter should be in |
232 | * the same form as the filter lines in the list used by setTagFilter(QStringList) |
233 | * @param filter The filter in the form of a string |
234 | * @see setTagFilter(QStringList) |
235 | * @since 5.51 |
236 | */ |
237 | void addTagFilter(const QString &filter); |
238 | /** |
239 | * Sets a filter to be applied to the downloads for an entry. The logic is the |
240 | * same as used in setTagFilter(QStringList), but vitally, only one downloadlink |
241 | * is required to match the filter for the list to be valid. If you do not wish |
242 | * to show the others in your client, you must hide them yourself. |
243 | * |
244 | * For an entry to be accepted when a download tag filter is set, it must also |
245 | * be accepted by the entry filter (so, for example, while a list of downloads |
246 | * might be accepted, if the entry has ghns_excluded set, and the default entry |
247 | * filter is set, the entry will still be filtered out). |
248 | * |
249 | * In your knsrc file, set DownloadTagFilter to the filter you wish to apply, |
250 | * using the same logic as described for the entry tagfilter. |
251 | * |
252 | * @param filter The filter in the form of a list of strings |
253 | * @see setTagFilter(QStringList) |
254 | * @since 5.51 |
255 | */ |
256 | void setDownloadTagFilter(const QStringList &filter); |
257 | /** |
258 | * Gets the current downloadlink tag filter list |
259 | * @see setDownloadTagFilter(QStringList) |
260 | * @since 5.51 |
261 | */ |
262 | QStringList downloadTagFilter() const; |
263 | /** |
264 | * Add a single filter entry to the download tag filter. The filter should be in |
265 | * the same form as the filter lines in the list used by setDownloadsTagFilter(QStringList) |
266 | * @param filter The filter in the form of a string |
267 | * @see setTagFilter(QStringList) |
268 | * @see setDownloadTagFilter(QStringList) |
269 | * @since 5.51 |
270 | */ |
271 | void addDownloadTagFilter(const QString &filter); |
272 | |
273 | /** |
274 | * Whether or not a user is able to vote on the passed entry. |
275 | * |
276 | * @param entry The entry to check votability on |
277 | * @return True if the user is able to vote on the entry |
278 | */ |
279 | bool userCanVote(const Entry &entry); |
280 | /** |
281 | * Cast a vote on the passed entry. |
282 | * |
283 | * @param entry The entry to vote on |
284 | * @param rating A number from 0 to 100, 50 being neutral, 0 being most negative and 100 being most positive. |
285 | */ |
286 | void vote(const Entry &entry, uint rating); |
287 | |
288 | /** |
289 | * Whether or not the user is allowed to become a fan of |
290 | * a particular entry. |
291 | * Not all providers (and consequently entries) support the fan functionality |
292 | * and you can use this function to determine this ability. |
293 | * @param entry The entry the user might wish to be a fan of |
294 | * @return Whether or not it is possible for the user to become a fan of that entry |
295 | */ |
296 | bool userCanBecomeFan(const Entry &entry); |
297 | /** |
298 | * This will mark the user who is currently authenticated as a fan |
299 | * of the entry passed to the function. |
300 | * @param entry The entry the user wants to be a fan of |
301 | */ |
302 | void becomeFan(const Entry &entry); |
303 | // FIXME There is currently no exposed API to remove the fan status |
304 | |
305 | /** |
306 | * The Provider instance with the passed ID |
307 | * |
308 | * @param providerId The ID of the Provider to fetch |
309 | * @return The Provider with the passed ID, or null if non such Provider exists |
310 | * @since 5.63 |
311 | */ |
312 | QSharedPointer<Provider> provider(const QString &providerId) const; |
313 | |
314 | /** |
315 | * Return the first provider in the providers list (usually the default provider) |
316 | * @return The first Provider (or null if the engine is not initialized) |
317 | * @since 5.63 |
318 | */ |
319 | QSharedPointer<Provider> defaultProvider() const; |
320 | |
321 | /** |
322 | * The IDs of all providers known by this engine. Use this in combination with |
323 | * provider(const QString&) to iterate over all providers. |
324 | * @return The string IDs of all known providers |
325 | * @since 5.85 |
326 | */ |
327 | QStringList providerIDs() const; |
328 | |
329 | /** |
330 | * Whether or not an adoption command exists for this engine |
331 | * |
332 | * @see adoptionCommand(KNSCore::Entry) |
333 | * @return True if an adoption command exists |
334 | */ |
335 | bool hasAdoptionCommand() const; |
336 | |
337 | /** |
338 | * Returns a stream object that will fulfill the @p request. |
339 | * |
340 | * @since 6.0 |
341 | */ |
342 | ResultsStream *search(const KNSCore::Provider::SearchRequest &request); |
343 | |
344 | /** |
345 | * @brief The ContentWarningType enum |
346 | * @since 6.1 |
347 | */ |
348 | enum class ContentWarningType { |
349 | /** |
350 | * Content consists of static assets only |
351 | * Installation should not pose a security risk |
352 | */ |
353 | Static, |
354 | /** |
355 | * Content may contain scripts or other executable code |
356 | * Users should be warned to treat it like any other program |
357 | */ |
358 | Executables |
359 | }; |
360 | Q_ENUM(ContentWarningType) |
361 | |
362 | /** |
363 | * @brief The level of warning that should be presented to the user |
364 | * @since 6.1 |
365 | * @see ContentWarningType |
366 | */ |
367 | ContentWarningType contentWarningType() const; |
368 | |
369 | /** |
370 | * Emitted after the initial config load |
371 | * @since 6.1 |
372 | */ |
373 | Q_SIGNAL void contentWarningTypeChanged(); |
374 | |
375 | Q_SIGNALS: |
376 | /** |
377 | * Indicates a message to be added to the ui's log, or sent to a messagebox |
378 | */ |
379 | void signalMessage(const QString &message); |
380 | |
381 | void signalProvidersLoaded(); |
382 | |
383 | /** |
384 | * Fires in the case of any critical or serious errors, such as network or API problems. |
385 | * @param errorCode Represents the specific type of error which has occurred |
386 | * @param message A human-readable message which can be shown to the end user |
387 | * @param metadata Any additional data which might be hepful to further work out the details of the error (see KNSCore::Entry::ErrorCode for the |
388 | * metadata details) |
389 | * @see KNSCore::Entry::ErrorCode |
390 | * @since 5.53 |
391 | */ |
392 | void signalErrorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata); |
393 | |
394 | void signalCategoriesMetadataLoded(const QList<Provider::CategoryMetadata> &categories); |
395 | |
396 | /** |
397 | * Fires when the engine has loaded search presets. These represent interesting |
398 | * searches for the user, such as recommendations. |
399 | * @since 5.83 |
400 | */ |
401 | void signalSearchPresetsLoaded(const QList<Provider::SearchPreset> &presets); |
402 | |
403 | /** |
404 | * Fired whenever the list of providers changes |
405 | * @since 5.85 |
406 | */ |
407 | void providersChanged(); |
408 | |
409 | void loadingProvider(); |
410 | |
411 | private: |
412 | // the .knsrc file was loaded |
413 | void slotProviderFileLoaded(const QDomDocument &doc); |
414 | // instead of getting providers from knsrc, use what was configured in ocs systemsettings |
415 | void atticaProviderLoaded(const Attica::Provider &provider); |
416 | // called when a provider is ready to work |
417 | void providerInitialized(KNSCore::Provider *); |
418 | |
419 | // loading the .knsrc file failed |
420 | void slotProvidersFailed(); |
421 | |
422 | /** |
423 | * load providers from the providersurl in the knsrc file |
424 | * creates providers based on their type and adds them to the list of providers |
425 | */ |
426 | void loadProviders(); |
427 | |
428 | protected: |
429 | /** |
430 | Add a provider and connect it to the right slots |
431 | */ |
432 | virtual void addProvider(QSharedPointer<KNSCore::Provider> provider); |
433 | virtual void updateStatus(); |
434 | |
435 | friend class ResultsStream; |
436 | friend class Transaction; |
437 | Installation *installation() const; // Needed for quick engine |
438 | QList<QSharedPointer<Provider>> providers() const; |
439 | std::unique_ptr<EngineBasePrivate> d; |
440 | }; |
441 | |
442 | } |
443 | |
444 | #endif |
445 | |