File indexing completed on 2024-04-28 03:56:25

0001 /*
0002     SPDX-FileCopyrightText: 2007 Josef Spillner <spillner@kde.org>
0003     SPDX-FileCopyrightText: 2007-2010 Frederik Gladhorn <gladhorn@kde.org>
0004     SPDX-FileCopyrightText: 2009 Jeremy Whiting <jpwhiting@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-or-later
0007 */
0008 
0009 #ifndef KNEWSTUFF3_ENGINEBASE_H
0010 #define KNEWSTUFF3_ENGINEBASE_H
0011 
0012 #include <QHash>
0013 #include <QObject>
0014 #include <QSharedPointer>
0015 #include <QString>
0016 
0017 #include "entry.h"
0018 #include "errorcode.h"
0019 #include "provider.h"
0020 
0021 #include "knewstuffcore_export.h"
0022 
0023 #include <memory>
0024 
0025 class KJob;
0026 class EnginePrivate;
0027 class QDomDocument;
0028 
0029 namespace Attica
0030 {
0031 class Provider;
0032 }
0033 
0034 namespace KNSCore
0035 {
0036 class Cache;
0037 class CommentsModel;
0038 class ResultsStream;
0039 class EngineBasePrivate;
0040 class Installation;
0041 
0042 /**
0043  * KNewStuff engine.
0044  * An engine keeps track of data which is available locally and remote
0045  * and offers high-level synchronization calls as well as upload and download
0046  * primitives using an underlying GHNS protocol.
0047  *
0048  * This is a base class for different engine implementations
0049  */
0050 class KNEWSTUFFCORE_EXPORT EngineBase : public QObject
0051 {
0052     Q_OBJECT
0053 
0054     /**
0055      * Text that should be displayed for the adoption button, this defaults to "Use"
0056      * @since 5.77
0057      */
0058     Q_PROPERTY(QString useLabel READ useLabel NOTIFY useLabelChanged)
0059 
0060     /**
0061      * Whether or not the configuration says that the providers are expected to support uploading.
0062      * As it stands, this is used to determine whether or not to show the Upload... action where
0063      * that is displayed (primarily NewStuff.Page).
0064      * @since 5.85
0065      */
0066     Q_PROPERTY(bool uploadEnabled READ uploadEnabled NOTIFY uploadEnabledChanged)
0067 
0068     /**
0069      * @since 5.85
0070      */
0071     Q_PROPERTY(QStringList providerIDs READ providerIDs NOTIFY providersChanged)
0072 
0073 public:
0074     EngineBase(QObject *parent = nullptr);
0075     ~EngineBase();
0076 
0077     /**
0078      * List of all available config files. This list will contain no duplicated filenames.
0079      * The returned file paths are absolute.
0080      * @since 5.83
0081      */
0082     static QStringList availableConfigFiles();
0083 
0084     /**
0085      * Initializes the engine. This step is application-specific and relies
0086      * on an external configuration file, which determines all the details
0087      * about the initialization.
0088      *
0089      * @param configfile KNewStuff2 configuration file (*.knsrc)
0090      * @return \b true if any valid configuration was found, \b false otherwise
0091      * @see KNS3::DownloadDialog
0092      */
0093     virtual bool init(const QString &configfile);
0094 
0095     /**
0096      * The name as defined by the knsrc file
0097      * @return The name associated with the engine's configuration file
0098      * @since 5.63
0099      */
0100     QString name() const;
0101 
0102     /**
0103      * Text that should be displayed for the adoption button, this defaults to i18n("Use")
0104      * @since 5.77
0105      */
0106     QString useLabel() const;
0107 
0108     /**
0109      * Signal gets emitted when the useLabel property changes
0110      * @since 5.77
0111      */
0112     Q_SIGNAL void useLabelChanged();
0113 
0114     /**
0115      * Whether or not the configuration says that the providers are expected to support uploading.
0116      * @return True if the providers are expected to support uploading
0117      * @since 5.85
0118      */
0119     bool uploadEnabled() const;
0120 
0121     /**
0122      * Fired when the uploadEnabled property changes
0123      * @since 5.85
0124      */
0125     Q_SIGNAL void uploadEnabledChanged();
0126 
0127     /**
0128      * The list of the server-side names of the categories handled by this
0129      * engine instance. This corresponds directly to the list of categories
0130      * in your knsrc file. This is not supposed to be used as user-facing
0131      * strings - @see categoriesMetadata() for that.
0132      *
0133      * @return The categories which this instance of Engine handles
0134      */
0135     QStringList categories() const;
0136 
0137     /**
0138      * Get the entries cache for this engine (note that it may be null if the engine is
0139      * not yet initialized).
0140      * @return The cache for this engine (or null if the engine is not initialized)
0141      * @since 5.74
0142      */
0143     QSharedPointer<Cache> cache() const;
0144 
0145     /**
0146      * The list of metadata for the categories handled by this engine instance.
0147      * If you wish to show the categories to the user, this is the data to use.
0148      * The category name is the string used to set categories for the filter,
0149      * and also what is returned by both categories() and categoriesFilter().
0150      * The human-readable name is displayName, and the only thing which should
0151      * be shown to the user.
0152      *
0153      * @return The metadata for all categories handled by this engine
0154      */
0155     QList<Provider::CategoryMetadata> categoriesMetadata();
0156 
0157     QList<Provider::SearchPreset> searchPresets();
0158 
0159     /**
0160      * @returns the list of attica (OCS) providers this engine is connected to
0161      * @since 5.92
0162      */
0163     QList<Attica::Provider *> atticaProviders() const;
0164 
0165     /**
0166      * Set a filter for results, which filters out all entries which do not match
0167      * the filter, as applied to the tags for the entry. This filters only on the
0168      * tags specified for the entry itself. To filter the downloadlinks, use
0169      * setDownloadTagFilter(QStringList).
0170      *
0171      * @note The default filter if one is not set from your knsrc file will filter
0172      * out entries marked as ghns_excluded=1. To retain this when setting a custom
0173      * filter, add "ghns_excluded!=1" as one of the filters.
0174      *
0175      * @note Some tags provided by OCS do not supply a value (and are simply passed
0176      * as a key). These will be interpreted as having the value 1 for filtering
0177      * purposes. An example of this might be ghns_excluded, which in reality will
0178      * generally be passed through ocs as "ghns_excluded" rather than "ghns_excluded=1"
0179      *
0180      * @note As tags are metadata, they are provided in the form of adjectives. They
0181      * are never supplied as action verbs or instructions (as an example, a good tag
0182      * to suggest that for example a wallpaper is painted would be "painted" as opposed
0183      * to "paint", and another example might be that an item should be "excluded" as
0184      * opposed to "exclude").
0185      *
0186      * == Examples of use ==
0187      * Value for tag "tagname" must be exactly "tagdata":
0188      * tagname==tagdata
0189      *
0190      * Value for tag "tagname" must be different from "tagdata":
0191      * tagname!=tagdata
0192      *
0193      * == KNSRC entry ==
0194      * A tag filter line in a .knsrc file, which is a comma separated list of
0195      * tag/value pairs, might look like:
0196      *
0197      * TagFilter=ghns_excluded!=1,data##mimetype==application/cbr+zip,data##mimetype==application/cbr+rar
0198      * which would honour the exclusion and filter out anything that does not
0199      * include a comic book archive in either zip or rar format in one or more
0200      * of the download items.
0201      * Notice in particular that there are two data##mimetype entries. Use this
0202      * for when a tag may have multiple values.
0203      *
0204      * TagFilter=application##architecture==x86_64
0205      * which would not honour the exclusion, and would filter out all entries
0206      * which do not mark themselves as having a 64bit application binary in at
0207      * least one download item.
0208      *
0209      * The value does not current support wildcards. The list should be considered
0210      * a binary AND operation (that is, all filter entries must match for the data
0211      * entry to be included in the return data)
0212      *
0213      * @param filter The filter in the form of a list of strings
0214      * @see setDownloadTagFilter(QStringList)
0215      * @since 5.51
0216      */
0217     void setTagFilter(const QStringList &filter);
0218     /**
0219      * Gets the current tag filter list
0220      * @see setTagFilter(QStringList)
0221      * @since 5.51
0222      */
0223     QStringList tagFilter() const;
0224     /**
0225      * Add a single filter entry to the entry tag filter. The filter should be in
0226      * the same form as the filter lines in the list used by setTagFilter(QStringList)
0227      * @param filter The filter in the form of a string
0228      * @see setTagFilter(QStringList)
0229      * @since 5.51
0230      */
0231     void addTagFilter(const QString &filter);
0232     /**
0233      * Sets a filter to be applied to the downloads for an entry. The logic is the
0234      * same as used in setTagFilter(QStringList), but vitally, only one downloadlink
0235      * is required to match the filter for the list to be valid. If you do not wish
0236      * to show the others in your client, you must hide them yourself.
0237      *
0238      * For an entry to be accepted when a download tag filter is set, it must also
0239      * be accepted by the entry filter (so, for example, while a list of downloads
0240      * might be accepted, if the entry has ghns_excluded set, and the default entry
0241      * filter is set, the entry will still be filtered out).
0242      *
0243      * In your knsrc file, set DownloadTagFilter to the filter you wish to apply,
0244      * using the same logic as described for the entry tagfilter.
0245      *
0246      * @param filter The filter in the form of a list of strings
0247      * @see setTagFilter(QStringList)
0248      * @since 5.51
0249      */
0250     void setDownloadTagFilter(const QStringList &filter);
0251     /**
0252      * Gets the current downloadlink tag filter list
0253      * @see setDownloadTagFilter(QStringList)
0254      * @since 5.51
0255      */
0256     QStringList downloadTagFilter() const;
0257     /**
0258      * Add a single filter entry to the download tag filter. The filter should be in
0259      * the same form as the filter lines in the list used by setDownloadsTagFilter(QStringList)
0260      * @param filter The filter in the form of a string
0261      * @see setTagFilter(QStringList)
0262      * @see setDownloadTagFilter(QStringList)
0263      * @since 5.51
0264      */
0265     void addDownloadTagFilter(const QString &filter);
0266 
0267     /**
0268      * Whether or not a user is able to vote on the passed entry.
0269      *
0270      * @param entry The entry to check votability on
0271      * @return True if the user is able to vote on the entry
0272      */
0273     bool userCanVote(const Entry &entry);
0274     /**
0275      * Cast a vote on the passed entry.
0276      *
0277      * @param entry The entry to vote on
0278      * @param rating A number from 0 to 100, 50 being neutral, 0 being most negative and 100 being most positive.
0279      */
0280     void vote(const Entry &entry, uint rating);
0281 
0282     /**
0283      * Whether or not the user is allowed to become a fan of
0284      * a particular entry.
0285      * Not all providers (and consequently entries) support the fan functionality
0286      * and you can use this function to determine this ability.
0287      * @param entry The entry the user might wish to be a fan of
0288      * @return Whether or not it is possible for the user to become a fan of that entry
0289      */
0290     bool userCanBecomeFan(const Entry &entry);
0291     /**
0292      * This will mark the user who is currently authenticated as a fan
0293      * of the entry passed to the function.
0294      * @param entry The entry the user wants to be a fan of
0295      */
0296     void becomeFan(const Entry &entry);
0297     // FIXME There is currently no exposed API to remove the fan status
0298 
0299     /**
0300      * The Provider instance with the passed ID
0301      *
0302      * @param providerId The ID of the Provider to fetch
0303      * @return The Provider with the passed ID, or null if non such Provider exists
0304      * @since 5.63
0305      */
0306     QSharedPointer<Provider> provider(const QString &providerId) const;
0307 
0308     /**
0309      * Return the first provider in the providers list (usually the default provider)
0310      * @return The first Provider (or null if the engine is not initialized)
0311      * @since 5.63
0312      */
0313     QSharedPointer<Provider> defaultProvider() const;
0314 
0315     /**
0316      * The IDs of all providers known by this engine. Use this in combination with
0317      * provider(const QString&) to iterate over all providers.
0318      * @return The string IDs of all known providers
0319      * @since 5.85
0320      */
0321     QStringList providerIDs() const;
0322 
0323     /**
0324      * Whether or not an adoption command exists for this engine
0325      *
0326      * @see adoptionCommand(KNSCore::Entry)
0327      * @return True if an adoption command exists
0328      */
0329     bool hasAdoptionCommand() const;
0330 
0331     /**
0332      * Returns a stream object that will fulfill the @p request.
0333      *
0334      * @since 6.0
0335      */
0336     ResultsStream *search(const KNSCore::Provider::SearchRequest &request);
0337 
0338 Q_SIGNALS:
0339     /**
0340      * Indicates a message to be added to the ui's log, or sent to a messagebox
0341      */
0342     void signalMessage(const QString &message);
0343 
0344     void signalProvidersLoaded();
0345 
0346     /**
0347      * Fires in the case of any critical or serious errors, such as network or API problems.
0348      * @param errorCode Represents the specific type of error which has occurred
0349      * @param message A human-readable message which can be shown to the end user
0350      * @param metadata Any additional data which might be hepful to further work out the details of the error (see KNSCore::Entry::ErrorCode for the
0351      * metadata details)
0352      * @see KNSCore::Entry::ErrorCode
0353      * @since 5.53
0354      */
0355     void signalErrorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata);
0356 
0357     void signalCategoriesMetadataLoded(const QList<Provider::CategoryMetadata> &categories);
0358 
0359     /**
0360      * Fires when the engine has loaded search presets. These represent interesting
0361      * searches for the user, such as recommendations.
0362      * @since 5.83
0363      */
0364     void signalSearchPresetsLoaded(const QList<Provider::SearchPreset> &presets);
0365 
0366     /**
0367      * Fired whenever the list of providers changes
0368      * @since 5.85
0369      */
0370     void providersChanged();
0371 
0372     void loadingProvider();
0373 
0374 private:
0375     // the .knsrc file was loaded
0376     void slotProviderFileLoaded(const QDomDocument &doc);
0377     // instead of getting providers from knsrc, use what was configured in ocs systemsettings
0378     void atticaProviderLoaded(const Attica::Provider &provider);
0379     // called when a provider is ready to work
0380     void providerInitialized(KNSCore::Provider *);
0381 
0382     // loading the .knsrc file failed
0383     void slotProvidersFailed();
0384 
0385     /**
0386      * load providers from the providersurl in the knsrc file
0387      * creates providers based on their type and adds them to the list of providers
0388      */
0389     void loadProviders();
0390 
0391 protected:
0392     /**
0393       Add a provider and connect it to the right slots
0394      */
0395     virtual void addProvider(QSharedPointer<KNSCore::Provider> provider);
0396     virtual void updateStatus();
0397 
0398     friend class ResultsStream;
0399     friend class Transaction;
0400     Installation *installation() const; // Needed for quick engine
0401     QList<QSharedPointer<Provider>> providers() const;
0402     std::unique_ptr<EngineBasePrivate> d;
0403 };
0404 
0405 }
0406 
0407 #endif