File indexing completed on 2024-05-05 17:33:21

0001 /*
0002  *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #pragma once
0008 
0009 #include <QSet>
0010 #include <QTimer>
0011 #include <QVector>
0012 
0013 #include "AbstractResourcesBackend.h"
0014 #include "discovercommon_export.h"
0015 
0016 class DiscoverAction;
0017 
0018 class DISCOVERCOMMON_EXPORT AggregatedResultsStream : public ResultsStream
0019 {
0020     Q_OBJECT
0021 public:
0022     AggregatedResultsStream(const QSet<ResultsStream *> &streams);
0023     ~AggregatedResultsStream();
0024 
0025     QSet<QObject *> streams() const
0026     {
0027         return m_streams;
0028     }
0029 
0030 Q_SIGNALS:
0031     void finished();
0032 
0033 private:
0034     void addResults(const QVector<AbstractResource *> &res);
0035     void emitResults();
0036     void streamDestruction(QObject *obj);
0037     void resourceDestruction(QObject *obj);
0038     void clear();
0039 
0040     QSet<QObject *> m_streams;
0041     QVector<AbstractResource *> m_results;
0042     QTimer m_delayedEmission;
0043 };
0044 
0045 template<typename T>
0046 class EmitWhenChanged
0047 {
0048 public:
0049     EmitWhenChanged(T initial, const std::function<T()> &get, const std::function<void(T)> &emitChanged)
0050         : m_get(get)
0051         , m_emitChanged(emitChanged)
0052         , m_value(initial)
0053     {
0054     }
0055 
0056     void reevaluate()
0057     {
0058         auto newValue = m_get();
0059         if (newValue != m_value) {
0060             m_value = newValue;
0061             m_emitChanged(m_value);
0062         }
0063     }
0064 
0065     std::function<T()> const m_get;
0066     std::function<void(T)> const m_emitChanged;
0067     T m_value;
0068 };
0069 
0070 class DISCOVERCOMMON_EXPORT ResourcesModel : public QObject
0071 {
0072     Q_OBJECT
0073     Q_PROPERTY(int updatesCount READ updatesCount NOTIFY updatesCountChanged)
0074     Q_PROPERTY(bool hasSecurityUpdates READ hasSecurityUpdates NOTIFY updatesCountChanged)
0075     Q_PROPERTY(bool isFetching READ isFetching NOTIFY fetchingChanged)
0076     Q_PROPERTY(bool isInitializing READ isInitializing NOTIFY allInitialized)
0077     Q_PROPERTY(AbstractResourcesBackend *currentApplicationBackend READ currentApplicationBackend WRITE setCurrentApplicationBackend NOTIFY
0078                    currentApplicationBackendChanged)
0079     Q_PROPERTY(DiscoverAction *updateAction READ updateAction CONSTANT)
0080     Q_PROPERTY(int fetchingUpdatesProgress READ fetchingUpdatesProgress NOTIFY fetchingUpdatesProgressChanged)
0081     Q_PROPERTY(QString applicationSourceName READ applicationSourceName NOTIFY currentApplicationBackendChanged)
0082     Q_PROPERTY(InlineMessage *inlineMessage READ inlineMessage NOTIFY inlineMessageChanged)
0083 public:
0084     /** This constructor should be only used by unit tests.
0085      *  @p backendName defines what backend will be loaded when the backend is constructed.
0086      */
0087     explicit ResourcesModel(const QString &backendName, QObject *parent = nullptr);
0088     static ResourcesModel *global();
0089     ~ResourcesModel() override;
0090 
0091     QVector<AbstractResourcesBackend *> backends() const;
0092     int updatesCount() const
0093     {
0094         return m_updatesCount.m_value;
0095     }
0096     bool hasSecurityUpdates() const;
0097 
0098     bool isBusy() const;
0099     bool isFetching() const;
0100     bool isInitializing() const;
0101 
0102     Q_SCRIPTABLE bool isExtended(const QString &id);
0103 
0104     AggregatedResultsStream *search(const AbstractResourcesBackend::Filters &search);
0105     void checkForUpdates();
0106 
0107     QString applicationSourceName() const;
0108 
0109     void setCurrentApplicationBackend(AbstractResourcesBackend *backend, bool writeConfig = true);
0110     AbstractResourcesBackend *currentApplicationBackend() const;
0111 
0112     DiscoverAction *updateAction() const
0113     {
0114         return m_updateAction;
0115     }
0116     int fetchingUpdatesProgress() const
0117     {
0118         return m_fetchingUpdatesProgress.m_value;
0119     }
0120 
0121     Q_INVOKABLE QUrl distroBugReportUrl();
0122 
0123     void setInlineMessage(const QSharedPointer<InlineMessage> &inlineMessage);
0124     InlineMessage *inlineMessage() const
0125     {
0126         return m_inlineMessage.data();
0127     }
0128 
0129 public Q_SLOTS:
0130     void installApplication(AbstractResource *app, const AddonList &addons);
0131     void installApplication(AbstractResource *app);
0132     void removeApplication(AbstractResource *app);
0133 
0134 Q_SIGNALS:
0135     void fetchingChanged(bool isFetching);
0136     void allInitialized();
0137     void backendsChanged();
0138     void updatesCountChanged(int updatesCount);
0139     void backendDataChanged(AbstractResourcesBackend *backend, const QVector<QByteArray> &properties);
0140     void resourceDataChanged(AbstractResource *resource, const QVector<QByteArray> &properties);
0141     void resourceRemoved(AbstractResource *resource);
0142     void passiveMessage(const QString &message);
0143     void currentApplicationBackendChanged(AbstractResourcesBackend *currentApplicationBackend);
0144     void fetchingUpdatesProgressChanged(int fetchingUpdatesProgress);
0145     void inlineMessageChanged(const QSharedPointer<InlineMessage> &inlineMessage);
0146 
0147 private Q_SLOTS:
0148     void callerFetchingChanged();
0149     void updateCaller(const QVector<QByteArray> &properties);
0150     void registerAllBackends();
0151 
0152 private:
0153     ///@p initialize tells if all backends load will be triggered on construction
0154     explicit ResourcesModel(QObject *parent = nullptr);
0155     void init(bool load);
0156     void addResourcesBackend(AbstractResourcesBackend *backend);
0157     void registerBackendByName(const QString &name);
0158     void initApplicationsBackend();
0159     void slotFetching();
0160 
0161     bool m_isFetching;
0162     bool m_isInitializing = true;
0163     QVector<AbstractResourcesBackend *> m_backends;
0164     int m_initializingBackendsCount;
0165     DiscoverAction *m_updateAction = nullptr;
0166     AbstractResourcesBackend *m_currentApplicationBackend;
0167     QTimer *m_allInitializedEmitter;
0168 
0169     EmitWhenChanged<int> m_updatesCount;
0170     EmitWhenChanged<int> m_fetchingUpdatesProgress;
0171     QSharedPointer<InlineMessage> m_inlineMessage;
0172 
0173     static ResourcesModel *s_self;
0174 };