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 };