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 "categorymetadata.h"
19#include "entry.h"
20#include "errorcode.h"
21#include "knewstuffcore_export.h"
22#include "provider.h"
23#include "searchpreset.h"
24
25#include <memory>
26
27class KJob;
28class EnginePrivate;
29class QDomDocument;
30class SearchPresetModel;
31
32namespace Attica
33{
34class Provider;
35}
36
37/*!
38 * \namespace KNSCore
39 * \inmodule KNewStuffCore
40 *
41 * \brief The KNewStuff core.
42 */
43namespace KNSCore
44{
45class Cache;
46class CommentsModel;
47class ResultsStream;
48class EngineBasePrivate;
49class Installation;
50class SearchRequest;
51class ProviderCore;
52
53/*!
54 * \class KNSCore::EngineBase
55 * \inmodule KNewStuffCore
56 *
57 * \brief KNewStuff engine.
58 *
59 * An engine keeps track of data which is available locally and remote
60 * and offers high-level synchronization calls as well as upload and download
61 * primitives using an underlying GHNS protocol.
62 *
63 * This is a base class for different engine implementations
64 */
65class KNEWSTUFFCORE_EXPORT EngineBase : public QObject
66{
67 Q_OBJECT
68
69 /*!
70 * \qmlproperty string EngineBase::useLabel
71 * Text that should be displayed for the adoption button, this defaults to "Use"
72 * \since 5.77
73 */
74 /*!
75 * \property KNSCore::EngineBase::useLabel
76 * Text that should be displayed for the adoption button, this defaults to "Use"
77 * \since 5.77
78 */
79 Q_PROPERTY(QString useLabel READ useLabel NOTIFY useLabelChanged)
80
81 /*!
82 * \qmlproperty bool EngineBase::uploadEnabled
83 * Whether or not the configuration says that the providers are expected to support uploading.
84 * As it stands, this is used to determine whether or not to show the Upload... action where
85 * that is displayed (primarily NewStuff.Page).
86 * \since 5.85
87 */
88 /*!
89 * \property KNSCore::EngineBase::uploadEnabled
90 * Whether or not the configuration says that the providers are expected to support uploading.
91 * As it stands, this is used to determine whether or not to show the Upload... action where
92 * that is displayed (primarily NewStuff.Page).
93 * \since 5.85
94 */
95 Q_PROPERTY(bool uploadEnabled READ uploadEnabled NOTIFY uploadEnabledChanged)
96
97 /*!
98 * \qmlproperty list<string> EngineBase::providerIDs
99 * \since 5.85
100 */
101 /*!
102 * \property KNSCore::EngineBase::providerIDs
103 * \since 5.85
104 */
105 Q_PROPERTY(QStringList providerIDs READ providerIDs NOTIFY providersChanged)
106
107 /*!
108 * \qmlproperty ContentWarningType EngineBase::contentWarningType
109 */
110 /*!
111 * \property KNSCore::EngineBase::contentWarningType
112 */
113 Q_PROPERTY(ContentWarningType contentWarningType READ contentWarningType NOTIFY contentWarningTypeChanged)
114
115public:
116 /*!
117 *
118 */
119 EngineBase(QObject *parent = nullptr);
120 ~EngineBase() override;
121 Q_DISABLE_COPY_MOVE(EngineBase)
122
123 /*!
124 * List of all available config files. This list will contain no duplicated filenames.
125 * The returned file paths are absolute.
126 * \since 5.83
127 */
128 static QStringList availableConfigFiles();
129
130 /*!
131 * Initializes the engine. This step is application-specific and relies
132 * on an external configuration file, which determines all the details
133 * about the initialization.
134 *
135 * \a configfile KNewStuff2 configuration file (*.knsrc)
136 *
137 * Returns \b true if any valid configuration was found, \b false otherwise
138 */
139 virtual bool init(const QString &configfile);
140
141 /*!
142 * The name as defined by the knsrc file
143 * Returns The name associated with the engine's configuration file
144 * \since 5.63
145 */
146 QString name() const;
147
148 /*!
149 * Text that should be displayed for the adoption button, this defaults to i18n("Use")
150 * \since 5.77
151 */
152 QString useLabel() const;
153
154 /*!
155 * Signal gets emitted when the useLabel property changes
156 * \since 5.77
157 */
158 Q_SIGNAL void useLabelChanged();
159
160 /*!
161 * Whether or not the configuration says that the providers are expected to support uploading.
162 * Returns True if the providers are expected to support uploading
163 * \since 5.85
164 */
165 bool uploadEnabled() const;
166
167 /*!
168 * Fired when the uploadEnabled property changes
169 * \since 5.85
170 */
171 Q_SIGNAL void uploadEnabledChanged();
172
173 /*!
174 * The list of the server-side names of the categories handled by this
175 * engine instance. This corresponds directly to the list of categories
176 * in your knsrc file. This is not supposed to be used as user-facing
177 * strings - see categoriesMetadata() for that.
178 *
179 * Returns The categories which this instance of Engine handles
180 */
181 QStringList categories() const;
182
183#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
184 /*!
185 * Get the entries cache for this engine (note that it may be null if the engine is
186 * not yet initialized).
187 *
188 * Returns the cache for this engine (or null if the engine is not initialized)
189 * \since 5.74
190 * \deprecated[6.9]
191 *
192 * Do not use the cache directly
193 */
194 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Do not use the cache directly")
195 QSharedPointer<Cache> cache() const;
196#endif
197
198#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
199 /*!
200 * \deprecated[6.9]
201 * Use categoriesMetadata2
202 */
203 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use categoriesMetadata2")
204 QList<Provider::CategoryMetadata> categoriesMetadata();
205#endif
206 /*!
207 * The list of metadata for the categories handled by this engine instance.
208 * If you wish to show the categories to the user, this is the data to use.
209 * The category name is the string used to set categories for the filter,
210 * and also what is returned by both categories() and categoriesFilter().
211 * The human-readable name is displayName, and the only thing which should
212 * be shown to the user.
213 *
214 * Returns The metadata for all categories handled by this engine
215 */
216 QList<CategoryMetadata> categoriesMetadata2();
217
218#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
219 /*!
220 * \deprecated[6.9]
221 * Use searchPresets2
222 */
223 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use searchPresets2")
224 QList<Provider::SearchPreset> searchPresets();
225#endif
226 /*!
227 * \since 6.9
228 */
229 QList<SearchPreset> searchPresets2();
230
231 /*!
232 * Returns the list of attica (OCS) providers this engine is connected to
233 * \since 5.92
234 */
235 QList<Attica::Provider *> atticaProviders() const;
236
237 /*!
238 * Set a filter for results, which filters out all entries which do not match
239 * the filter, as applied to the tags for the entry. This filters only on the
240 * tags specified for the entry itself. To filter the downloadlinks, use
241 * setDownloadTagFilter(QStringList).
242 *
243 * \note The default filter if one is not set from your knsrc file will filter
244 * out entries marked as ghns_excluded=1. To retain this when setting a custom
245 * filter, add "ghns_excluded!=1" as one of the filters.
246 *
247 * \note Some tags provided by OCS do not supply a value (and are simply passed
248 * as a key). These will be interpreted as having the value 1 for filtering
249 * purposes. An example of this might be ghns_excluded, which in reality will
250 * generally be passed through ocs as "ghns_excluded" rather than "ghns_excluded=1"
251 *
252 * \note As tags are metadata, they are provided in the form of adjectives. They
253 * are never supplied as action verbs or instructions (as an example, a good tag
254 * to suggest that for example a wallpaper is painted would be "painted" as opposed
255 * to "paint", and another example might be that an item should be "excluded" as
256 * opposed to "exclude").
257 *
258 * == Examples of use ==
259 * Value for tag "tagname" must be exactly "tagdata":
260 * tagname==tagdata
261 *
262 * Value for tag "tagname" must be different from "tagdata":
263 * tagname!=tagdata
264 *
265 * == KNSRC entry ==
266 * A tag filter line in a .knsrc file, which is a comma separated list of
267 * tag/value pairs, might look like:
268 *
269 * TagFilter=ghns_excluded!=1,data##mimetype==application/cbr+zip,data##mimetype==application/cbr+rar
270 * which would honour the exclusion and filter out anything that does not
271 * include a comic book archive in either zip or rar format in one or more
272 * of the download items.
273 * Notice in particular that there are two data##mimetype entries. Use this
274 * for when a tag may have multiple values.
275 *
276 * TagFilter=application##architecture==x86_64
277 * which would not honour the exclusion, and would filter out all entries
278 * which do not mark themselves as having a 64bit application binary in at
279 * least one download item.
280 *
281 * The value does not current support wildcards. The list should be considered
282 * a binary AND operation (that is, all filter entries must match for the data
283 * entry to be included in the return data)
284 *
285 * \a filter The filter in the form of a list of strings
286 *
287 * \sa setDownloadTagFilter
288 * \since 5.51
289 */
290 void setTagFilter(const QStringList &filter);
291
292 /*!
293 * Returns the current tag filter list
294 * \sa setTagFilter
295 * \since 5.51
296 */
297 QStringList tagFilter() const;
298
299 /*!
300 * Adds a single filter entry to the entry tag filter. The filter should be in
301 * the same form as the filter lines in the list used by setTagFilter(QStringList)
302 *
303 * \a filter The filter in the form of a string
304 *
305 * \sa setTagFilter
306 * \since 5.51
307 */
308 void addTagFilter(const QString &filter);
309
310 /*!
311 * Sets a filter to be applied to the downloads for an entry. The logic is the
312 * same as used in setTagFilter(QStringList), but vitally, only one downloadlink
313 * is required to match the filter for the list to be valid. If you do not wish
314 * to show the others in your client, you must hide them yourself.
315 *
316 * For an entry to be accepted when a download tag filter is set, it must also
317 * be accepted by the entry filter (so, for example, while a list of downloads
318 * might be accepted, if the entry has ghns_excluded set, and the default entry
319 * filter is set, the entry will still be filtered out).
320 *
321 * In your knsrc file, set DownloadTagFilter to the filter you wish to apply,
322 * using the same logic as described for the entry tagfilter.
323 *
324 * \a filter The filter in the form of a list of strings
325 *
326 * \sa setTagFilter
327 * \since 5.51
328 */
329 void setDownloadTagFilter(const QStringList &filter);
330
331 /*!
332 * Returns the current downloadlink tag filter list
333 * \sa setDownloadTagFilter
334 * \since 5.51
335 */
336 QStringList downloadTagFilter() const;
337
338 /*!
339 * Add a single filter entry to the download tag filter. The filter should be in
340 * the same form as the filter lines in the list used by setDownloadsTagFilter(QStringList)
341 *
342 * \a filter The filter in the form of a string
343 *
344 * \sa setTagFilter
345 * \sa setDownloadTagFilter
346 * \since 5.51
347 */
348 void addDownloadTagFilter(const QString &filter);
349
350 /*!
351 * Whether or not a user is able to vote on the passed entry.
352 *
353 * \a entry The entry to check votability on
354 *
355 * Returns True if the user is able to vote on the entry
356 */
357 bool userCanVote(const Entry &entry);
358
359 /*!
360 * Cast a vote on the passed entry.
361 *
362 * \a entry The entry to vote on
363 *
364 * \a rating A number from 0 to 100, 50 being neutral, 0 being most negative and 100 being most positive.
365 *
366 */
367 void vote(const Entry &entry, uint rating);
368
369 /*!
370 * Whether or not the user is allowed to become a fan of
371 * a particular entry.
372 * Not all providers (and consequently entries) support the fan functionality
373 * and you can use this function to determine this ability.
374 *
375 * \a entry The entry the user might wish to be a fan of
376 *
377 * Returns Whether or not it is possible for the user to become a fan of that entry
378 */
379 bool userCanBecomeFan(const Entry &entry);
380
381 /*!
382 * This will mark the user who is currently authenticated as a fan
383 * of the entry passed to the function.
384 *
385 * \a entry The entry the user wants to be a fan of
386 */
387 void becomeFan(const Entry &entry);
388 // FIXME There is currently no exposed API to remove the fan status
389
390#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
391 /*!
392 * The Provider instance with the passed ID
393 *
394 * \a providerId The ID of the Provider to fetch
395 *
396 * Returns the Provider with the passed ID, or null if non such Provider exists
397 * \since 5.63
398 * \deprecated[6.9]
399 * Do not write provider-specific code
400 */
401 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Do not write provider-specific code")
402 QSharedPointer<Provider> provider(const QString &providerId) const;
403#endif
404
405#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
406 /*!
407 * Return the first provider in the providers list (usually the default provider)
408 * \since 5.63
409 * \deprecated[6.9]
410 * Do not write provider-specific code
411 */
412 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Do not write provider-specific code")
413 QSharedPointer<Provider> defaultProvider() const;
414#endif
415
416 /*!
417 * The IDs of all providers known by this engine. Use this in combination with
418 * provider(const QString&) to iterate over all providers.
419 * Returns The string IDs of all known providers
420 * \since 5.85
421 */
422 QStringList providerIDs() const;
423
424 /*!
425 * Whether or not an adoption command exists for this engine
426 *
427 * Returns True if an adoption command exists
428 */
429 bool hasAdoptionCommand() const;
430
431#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
432 /**
433 * Returns a stream object that will fulfill the @p request.
434 *
435 * @since 6.0
436 * @deprecated since 6.9 Use the new search function
437 */
438 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use the new search function")
439 ResultsStream *search(const KNSCore::Provider::SearchRequest &request);
440#endif
441
442 /**
443 * Returns a stream object that will fulfill the @p request.
444 *
445 * @since 6.9
446 */
447 ResultsStream *search(const KNSCore::SearchRequest &request);
448
449 /*!
450 * \enum KNSCore::EngineBase::ContentWarningType
451 *
452 * \brief The ContentWarningType enum
453 *
454 * \value Static
455 * Content consists of static assets only.
456 * Installation should not pose a security risk.
457 *
458 * \value Executables
459 * Content may contain scripts or other executable code.
460 * Users should be warned to treat it like any other program.
461 *
462 * \since 6.1
463 */
464 enum class ContentWarningType {
465 Static,
466 Executables
467 };
468 Q_ENUM(ContentWarningType)
469
470 /*!
471 * \brief The level of warning that should be presented to the user
472 * \since 6.1
473 * \sa ContentWarningType
474 */
475 ContentWarningType contentWarningType() const;
476
477 /*!
478 * Emitted after the initial config load
479 * \since 6.1
480 */
481 Q_SIGNAL void contentWarningTypeChanged();
482
483Q_SIGNALS:
484 /*!
485 * Indicates a \a message to be added to the ui's log, or sent to a messagebox
486 */
487 void signalMessage(const QString &message);
488
489 void signalProvidersLoaded();
490
491 /*!
492 * Fires in the case of any critical or serious errors, such as network or API problems.
493 *
494 * \a errorCode Represents the specific type of error which has occurred
495 *
496 * \a message A human-readable message which can be shown to the end user
497 *
498 * \a metadata Any additional data which might be helpful to further work out the details of the error (see KNSCore::Entry::ErrorCode for the
499 * metadata details)
500 *
501 * \sa KNSCore::ErrorCode
502 * \since 5.53
503 */
504 void signalErrorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata);
505
506#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
507 /*!
508 * \deprecated[6.9]
509 * Use variant with new argument type
510 */
511 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use variant with new argument type")
512 void signalCategoriesMetadataLoded(const QList<Provider::CategoryMetadata> &categories);
513#endif
514 /*!
515 *
516 */
517 void signalCategoriesMetadataLoaded(const QList<KNSCore::CategoryMetadata> &categories);
518
519#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
520 /*!
521 * Fires when the engine has loaded search presets. These represent interesting
522 * searches for the user, such as recommendations.
523 * \since 5.83
524 * \deprecated[6.9]
525 * Use variant with new argument type
526 */
527 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use variant with new argument type")
528 void signalSearchPresetsLoaded(const QList<Provider::SearchPreset> &presets);
529#endif
530
531 /*!
532 * Fires when the engine has loaded search presets. These represent interesting
533 * searches for the user, such as recommendations.
534 * \since 6.9
535 */
536 void signalSearchPresetsLoaded(const QList<KNSCore::SearchPreset> &presets);
537
538#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
539 /*!
540 * Fired whenever the list of providers changes
541 * \since 5.85
542 * \deprecated[6.9]
543 * Use providerAdded signal
544 */
545 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use providerAdded signal")
546 void providersChanged();
547#endif
548
549 /*!
550 *
551 */
552 void loadingProvider();
553
554 /*!
555 *
556 */
557 void providerAdded(KNSCore::ProviderCore *provider);
558
559private:
560 // the .knsrc file was loaded
561 void slotProviderFileLoaded(const QDomDocument &doc);
562 // instead of getting providers from knsrc, use what was configured in ocs systemsettings
563 void atticaProviderLoaded(const Attica::Provider &provider);
564 // called when a provider is ready to work
565 void providerInitialized(KNSCore::Provider *);
566
567 // loading the .knsrc file failed
568 void slotProvidersFailed();
569
570 /*
571 * load providers from the providersurl in the knsrc file
572 * creates providers based on their type and adds them to the list of providers
573 */
574 void loadProviders();
575
576protected:
577#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
578 /*!
579 * Add a provider and connect it to the right slots
580 * \deprecated[6.9]
581 * Use providerAdded signal
582 */
583 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Use providerAdded signal")
584 virtual void addProvider(QSharedPointer<KNSCore::Provider> provider);
585#endif
586 virtual void updateStatus();
587
588 friend class ResultsStream;
589 friend class Transaction;
590 friend class TransactionPrivate;
591 friend class EngineBasePrivate;
592 friend class ::SearchPresetModel;
593 Installation *installation() const; // Needed for quick engine
594#if KNEWSTUFFCORE_ENABLE_DEPRECATED_SINCE(6, 9)
595 /*!
596 * \deprecated[6.9]
597 * Do not write provider-specific code
598 */
599 KNEWSTUFFCORE_DEPRECATED_VERSION(6, 9, "Do not write provider-specific code")
600 QList<QSharedPointer<Provider>> providers() const;
601#endif
602 // FIXME KF7: make this private and declare QuickEngine a friend. this cannot be used from the outside!
603 std::unique_ptr<EngineBasePrivate> d;
604};
605
606}
607
608#endif
609

source code of knewstuff/src/core/enginebase.h