File indexing completed on 2024-11-17 04:55:42

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 "PackageKitResource.h"
0010 #include <AppStreamQt/pool.h>
0011 #include <PackageKit/Transaction>
0012 #include <QFile>
0013 #include <QPointer>
0014 #include <QSet>
0015 #include <QSharedPointer>
0016 #include <QStringList>
0017 #include <QThreadPool>
0018 #include <QTimer>
0019 #include <QVariantList>
0020 #include <resources/AbstractResourcesBackend.h>
0021 
0022 class AppPackageKitResource;
0023 class PackageKitUpdater;
0024 class OdrsReviewsBackend;
0025 class PKResultsStream;
0026 class PKResolveTransaction;
0027 
0028 /** This is either a package name or an appstream id */
0029 struct PackageOrAppId {
0030     QString id;
0031     bool isPackageName;
0032 };
0033 PackageOrAppId makePackageId(const QString &id);
0034 PackageOrAppId makeAppId(const QString &id);
0035 
0036 class Delay : public QObject
0037 {
0038     Q_OBJECT
0039 public:
0040     Delay();
0041     void add(const QString &pkgid)
0042     {
0043         if (!m_delay.isActive()) {
0044             m_delay.start();
0045         }
0046 
0047         m_pkgids << pkgid;
0048     }
0049     void add(const QSet<QString> &pkgids)
0050     {
0051         if (!m_delay.isActive()) {
0052             m_delay.start();
0053         }
0054 
0055         m_pkgids += pkgids;
0056     }
0057 
0058 Q_SIGNALS:
0059     void perform(const QSet<QString> &pkgids);
0060 
0061 private:
0062     QTimer m_delay;
0063     QSet<QString> m_pkgids;
0064 };
0065 
0066 class DISCOVERCOMMON_EXPORT PackageKitBackend : public AbstractResourcesBackend
0067 {
0068     Q_OBJECT
0069 public:
0070     explicit PackageKitBackend(QObject *parent = nullptr);
0071     ~PackageKitBackend() override;
0072 
0073     AbstractBackendUpdater *backendUpdater() const override;
0074     AbstractReviewsBackend *reviewsBackend() const override;
0075     QSet<AbstractResource *> resourcesByPackageName(const QString &name) const;
0076 
0077     ResultsStream *search(const AbstractResourcesBackend::Filters &search) override;
0078     PKResultsStream *findResourceByPackageName(const QUrl &search);
0079     int updatesCount() const override;
0080     bool hasSecurityUpdates() const override;
0081 
0082     Transaction *installApplication(AbstractResource *app) override;
0083     Transaction *installApplication(AbstractResource *app, const AddonList &addons) override;
0084     Transaction *removeApplication(AbstractResource *app) override;
0085     bool isValid() const override
0086     {
0087         return !QFile::exists(QStringLiteral("/run/ostree-booted"));
0088     }
0089     QSet<AbstractResource *> upgradeablePackages() const;
0090     bool isFetching() const override;
0091 
0092     bool isPackageNameUpgradeable(const PackageKitResource *res) const;
0093     QSet<QString> upgradeablePackageId(const PackageKitResource *res) const;
0094     QVector<AbstractResource *> extendedBy(const QString &id) const;
0095 
0096     PKResolveTransaction *resolvePackages(const QStringList &packageNames);
0097     void fetchDetails(const QString &pkgid)
0098     {
0099         m_details.add(pkgid);
0100     }
0101     void fetchDetails(const QSet<QString> &pkgid);
0102 
0103     void checkForUpdates() override;
0104     QString displayName() const override;
0105 
0106     bool hasApplications() const override
0107     {
0108         return true;
0109     }
0110     static QString locateService(const QString &filename);
0111 
0112     AppStream::ComponentBox componentsById(const QString &id) const;
0113     void fetchUpdates();
0114     int fetchingUpdatesProgress() const override;
0115     uint fetchingUpdatesProgressWeight() const override;
0116 
0117     InlineMessage *explainDysfunction() const override;
0118 
0119     void addPackageArch(PackageKit::Transaction::Info info, const QString &packageId, const QString &summary);
0120     void addPackageNotArch(PackageKit::Transaction::Info info, const QString &packageId, const QString &summary);
0121     void clear()
0122     {
0123         m_updatesPackageId.clear();
0124     }
0125     Delay &updateDetails()
0126     {
0127         return m_updateDetails;
0128     }
0129     template<typename T, typename W>
0130     T resourcesByPackageNames(const W &names) const;
0131 
0132     QStringList globalHints()
0133     {
0134         return m_globalHints;
0135     }
0136 
0137 public Q_SLOTS:
0138     void reloadPackageList();
0139     void transactionError(PackageKit::Transaction::Error, const QString &message);
0140 
0141 private Q_SLOTS:
0142     void getPackagesFinished();
0143     void addPackage(PackageKit::Transaction::Info info, const QString &packageId, const QString &summary, bool arch);
0144     void packageDetails(const PackageKit::Details &details);
0145     void addPackageToUpdate(PackageKit::Transaction::Info, const QString &pkgid, const QString &summary);
0146     void getUpdatesFinished(PackageKit::Transaction::Exit, uint);
0147 
0148 Q_SIGNALS:
0149     void loadedAppStream();
0150     void available();
0151 
0152 private:
0153     friend class PackageKitResource;
0154 
0155     template<typename T, typename W>
0156     T resourcesByAppNames(const W &names) const;
0157 
0158     template<typename T>
0159     T resourcesByComponents(const AppStream::ComponentBox &names) const;
0160 
0161     QVector<StreamResult> resultsByComponents(const AppStream::ComponentBox &names) const;
0162 
0163     void runWhenInitialized(const std::function<void()> &f, QObject *stream);
0164 
0165     void checkDaemonRunning();
0166     void acquireFetching(bool f);
0167     void includePackagesToAdd();
0168     void performDetailsFetch(const QSet<QString> &pkgids);
0169     AppPackageKitResource *addComponent(const AppStream::Component &component) const;
0170     void updateProxy();
0171     void foundNewMajorVersion(const AppStream::Release &release);
0172 
0173     QScopedPointer<AppStream::Pool> m_appdata;
0174     PackageKitUpdater *m_updater;
0175     QPointer<PackageKit::Transaction> m_refresher;
0176     int m_isFetching;
0177     QSet<QString> m_updatesPackageId;
0178     bool m_hasSecurityUpdates = false;
0179     mutable QHash<PackageOrAppId, PackageKitResource *> m_packagesToAdd;
0180     QSet<PackageKitResource *> m_packagesToDelete;
0181     bool m_appstreamInitialized = false;
0182 
0183     mutable struct {
0184         QHash<PackageOrAppId, AbstractResource *> packages;
0185         QHash<QString, QStringList> packageToApp;
0186     } m_packages;
0187 
0188     Delay m_details;
0189     Delay m_updateDetails;
0190     QSharedPointer<OdrsReviewsBackend> m_reviews;
0191     QThreadPool m_threadPool;
0192     QPointer<PKResolveTransaction> m_resolveTransaction;
0193     QStringList m_globalHints;
0194 };