File indexing completed on 2024-04-28 05:46:37

0001 /***************************************************************************
0002  *   Copyright (C) 2015 Lukáš Tinkl <lukas@kde.org>                        *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; see the file COPYING. If not, write to       *
0016  *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,  *
0017  *   Boston, MA 02110-1301, USA.                                           *
0018  ***************************************************************************/
0019 
0020 
0021 #ifndef PLASMA_PK_UPDATES_H
0022 #define PLASMA_PK_UPDATES_H
0023 
0024 #include <QObject>
0025 #include <QPointer>
0026 #include <QLoggingCategory>
0027 
0028 #include <PackageKit/Daemon>
0029 #include <PackageKit/Transaction>
0030 
0031 class QTimer;
0032 class KNotification;
0033 
0034 Q_DECLARE_LOGGING_CATEGORY(PLASMA_PK_UPDATES)
0035 
0036 /**
0037  * @brief The PkUpdates class
0038  *
0039  * Backend class to check for available PackageKit system updates.
0040  * Use checkUpdates() to perform the check, retrieve them with packages()
0041  */
0042 class PkUpdates : public QObject
0043 {
0044     Q_OBJECT
0045     Q_PROPERTY(int count READ count NOTIFY updatesChanged)
0046     Q_PROPERTY(int importantCount READ importantCount NOTIFY updatesChanged)
0047     Q_PROPERTY(int securityCount READ securityCount NOTIFY updatesChanged)
0048     Q_PROPERTY(bool isSystemUpToDate READ isSystemUpToDate NOTIFY updatesChanged)
0049     Q_PROPERTY(QString iconName READ iconName NOTIFY updatesChanged)
0050     Q_PROPERTY(QString message READ message NOTIFY messageChanged)
0051     Q_PROPERTY(int percentage READ percentage NOTIFY percentageChanged)
0052     Q_PROPERTY(QString timestamp READ timestamp NOTIFY updatesChanged)
0053     Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY statusMessageChanged)
0054     Q_PROPERTY(QVariantMap packages READ packages NOTIFY updatesChanged)
0055     Q_PROPERTY(bool isActive READ isActive NOTIFY isActiveChanged)
0056     Q_PROPERTY(bool isNetworkOnline READ isNetworkOnline NOTIFY networkStateChanged)
0057     Q_PROPERTY(bool isNetworkMobile READ isNetworkMobile NOTIFY networkStateChanged)
0058     Q_PROPERTY(bool isOnBattery READ isOnBattery NOTIFY isOnBatteryChanged)
0059     Q_PROPERTY(bool lastCheckSuccessful READ lastCheckSuccessful NOTIFY lastCheckSuccessfulChanged)
0060 
0061 public:
0062     enum Activity {Idle, CheckingUpdates, GettingUpdates, InstallingUpdates};
0063     Q_ENUM(Activity)
0064 
0065     explicit PkUpdates(QObject *parent = nullptr);
0066     ~PkUpdates();
0067 
0068     /**
0069      * @return the total number of updates, including important and/or security ones
0070      */
0071     int count() const;
0072 
0073     /**
0074      * @return the number of important updates, included in total count()
0075      */
0076     int importantCount() const;
0077 
0078     /**
0079      * @return the number of security updates, included in total count()
0080      */
0081     int securityCount() const;
0082 
0083     /**
0084      * @return whether the system is up to date (count() == 0)
0085      */
0086     bool isSystemUpToDate() const;
0087 
0088     /**
0089      * @return the system update status icon name
0090      */
0091     QString iconName() const;
0092 
0093     /**
0094      * @return the overall status with number of available updates
0095      */
0096     QString message() const;
0097 
0098     /**
0099      * @return the progress percentage (0..100), 101 as a special value indicating indeterminate value
0100      */
0101     int percentage() const;
0102 
0103     /**
0104      * @return time stamp of the last update check
0105      */
0106     QString timestamp() const;
0107 
0108     /**
0109      * @return status messsage conveying the action being currently performed
0110      */
0111     QString statusMessage() const;
0112 
0113     /**
0114      * @return whether we're currently checking for updates or not
0115      */
0116     bool isActive() const;
0117 
0118     /**
0119      * @return the packages to update (key=packageId, value=description)
0120      */
0121     QVariantMap packages() const;
0122 
0123     /**
0124      * @return whether the network is online
0125      */
0126     bool isNetworkOnline() const;
0127 
0128     /**
0129      * @return whether we are on a mobile network connection (assumes isNetworkOnline())
0130      */
0131     bool isNetworkMobile() const;
0132 
0133     /**
0134      * @return whether we are running on battery
0135      */
0136     bool isOnBattery() const;
0137 
0138         /**
0139      * @return whether the last check for updates succeeded
0140      */
0141     bool lastCheckSuccessful() const;
0142 
0143 signals:
0144     /**
0145      * Emitted when the number uf updates has changed
0146      */
0147     void updatesChanged();
0148 
0149     /**
0150      * Emitted when the updates check is finished (with success or error)
0151      */
0152     void done();
0153 
0154     /**
0155      * Emitted after updates were installed successfully
0156      */
0157     void updatesInstalled();
0158 
0159     /**
0160      * Emitted with update details
0161      * @see getUpdateDetails()
0162      */
0163     void updateDetail(const QString &packageID, const QString &updateText, const QStringList &urls);
0164 
0165     /**
0166      * Emitted when an EULA agreement prevents the transaction from running
0167      * @param eulaId the EULA identifier
0168      * @param packageID ID of the package for which an EULA is required
0169      * @param vendorName the vendor name
0170      * @param licenseAgreement the EULA text
0171      *
0172      * @see eulaAgreementResult()
0173      */
0174     void eulaRequired(const QString &eulaID, const QString &packageID, const QString &vendor, const QString &licenseAgreement);
0175 
0176     // private ;)
0177     void statusMessageChanged();
0178     void isActiveChanged();
0179     void percentageChanged();
0180     void networkStateChanged();
0181     void isOnBatteryChanged();
0182     void lastCheckSuccessfulChanged();
0183     void messageChanged();
0184 
0185 public slots:
0186     /**
0187       * Perform a cache update, possibly resulting in an update check. Signal updatesChanged() gets emitted
0188       * as a result. Consult the count() property whether there are new updates available.
0189       *
0190       * @param manual whether this check was triggered via explicit user interaction
0191       */
0192     Q_INVOKABLE void checkUpdates(bool manual = false);
0193 
0194     /**
0195       * Launch the update process
0196       *
0197       * @param packageIds list of package IDs to update
0198       */
0199     Q_INVOKABLE void installUpdates(const QStringList & packageIds, bool simulate = true, bool untrusted = false);
0200 
0201     /**
0202       * @return the timestamp (in milliseconds) of the last cache check, -1 if never
0203       */
0204     Q_INVOKABLE qint64 lastRefreshTimestamp() const;
0205 
0206     /**
0207       * @return the package name extracted from its ID
0208       */
0209     Q_INVOKABLE static QString packageName(const QString & pkgId);
0210 
0211     /**
0212       * @return the package version extracted from its ID
0213       */
0214     Q_INVOKABLE static QString packageVersion(const QString & pkgId);
0215 
0216     /**
0217      * Request details about the details
0218      * @param pkgIds Package IDs
0219      *
0220      * Emits updateDetail()
0221      */
0222     Q_INVOKABLE void getUpdateDetails(const QString & pkgID);
0223 
0224     Q_INVOKABLE void doDelayedCheckUpdates();
0225 
0226     /**
0227      * If agreed to eulaID, starts an EULA acceptance transaction and continues.
0228      */
0229     Q_INVOKABLE void eulaAgreementResult(const QString &eulaID, bool agreed);
0230 
0231 private slots:
0232     void getUpdates();
0233     void onChanged();
0234     void onUpdatesChanged();
0235     void onStatusChanged();
0236     void onPackage(PackageKit::Transaction::Info info, const QString &packageID, const QString &summary);
0237     void onPackageUpdating(PackageKit::Transaction::Info info, const QString &packageID, const QString &summary);
0238     void onFinished(PackageKit::Transaction::Exit status, uint runtime);
0239     void onErrorCode(PackageKit::Transaction::Error error, const QString &details);
0240     void onRefreshErrorCode(PackageKit::Transaction::Error error, const QString &details);
0241     void onRequireRestart(PackageKit::Transaction::Restart type, const QString &packageID);
0242     void onUpdateDetail(const QString &packageID, const QStringList &updates, const QStringList &obsoletes, const QStringList &vendorUrls,
0243                         const QStringList &bugzillaUrls, const QStringList &cveUrls, PackageKit::Transaction::Restart restart,
0244                         const QString &updateText, const QString &changelog, PackageKit::Transaction::UpdateState state,
0245                         const QDateTime &issued, const QDateTime &updated);
0246     void onRepoSignatureRequired(const QString & packageID, const QString & repoName, const QString & keyUrl, const QString & keyUserid,
0247                                  const QString & keyId, const QString & keyFingerprint, const QString & keyTimestamp, PackageKit::Transaction::SigType type);
0248     void onEulaRequired(const QString &eulaID, const QString &packageID, const QString &vendor, const QString &licenseAgreement);
0249 
0250 private:
0251     struct EulaData {
0252         QString packageID;
0253         QString vendor;
0254         QString licenseAgreement;
0255     };
0256 
0257     void setStatusMessage(const QString &message);
0258     void setActivity(Activity act);
0259     void setPercentage(int value);
0260     void showError(PackageKit::Transaction::Error error, const QString &details);
0261     void promptNextEulaAgreement();
0262     void showRestartNotification();
0263     QPointer<PackageKit::Transaction> m_updatesTrans;
0264     QPointer<PackageKit::Transaction> m_cacheTrans;
0265     QPointer<PackageKit::Transaction> m_installTrans;
0266     QPointer<PackageKit::Transaction> m_detailTrans;
0267     QPointer<PackageKit::Transaction> m_eulaTrans;
0268     QStringList m_packages;
0269     QPointer<KNotification> m_lastNotification;
0270     int m_lastUpdateCount = 0;
0271     QVariantMap m_updateList;
0272     QStringList m_importantList;
0273     QStringList m_securityList;
0274     QString m_statusMessage;
0275     int m_percentage = 0;
0276     Activity m_activity = Idle;
0277     enum {
0278         NoCheckDone,
0279         CheckFailed,
0280         CheckSucceeded
0281     } m_lastCheckState = NoCheckDone;
0282     bool m_checkUpdatesWhenNetworkOnline = false;
0283     bool m_isOnBattery;
0284     // If the current check was triggered manually
0285     bool m_isManualCheck;
0286     // If a transaction failed because of required EULAs,
0287     // this contains a map of their IDs to their data
0288     QMap<QString, EulaData> m_requiredEulas;
0289     PackageKit::Transaction::Restart m_restartType = PackageKit::Transaction::RestartNone;
0290     QString m_restartPackageID;
0291 };
0292 
0293 #endif // PLASMA_PK_UPDATES_H