1 /* 2 Drawpile - a collaborative drawing program. 3 4 Copyright (C) 2019 Calle Laakkonen 5 6 Drawpile is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 Drawpile is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with Drawpile. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef DP_CLIENT_NEWVERSION_CHECK_H 21 #define DP_CLIENT_NEWVERSION_CHECK_H 22 23 #include <QObject> 24 #include <QUrl> 25 #include <QVector> 26 27 class QXmlStreamReader; 28 29 /** 30 * A tool for checking if a new version of the software is available. 31 * 32 * This class fetches and parses an AppStream appdata file and returns a 33 * list of versions newer than the current one. 34 * 35 */ 36 class NewVersionCheck : public QObject { 37 Q_OBJECT 38 public: 39 //! Discovered version 40 struct Version { 41 //! Version string 42 QString version; 43 44 //! URL of the release announcement page 45 QString announcementUrl; 46 47 //! What's new in this version (in a simple HTML subset format) 48 QString description; 49 50 //! Direct download link 51 QString downloadUrl; 52 53 //! Hash of the download 54 QString downloadChecksum; 55 56 //! Type of the checksum (e.g. sha256) 57 QString downloadChecksumType; 58 59 //! Size of the download in bytes 60 int downloadSize = 0; 61 }; 62 63 //! Construct a version checker with the current version info 64 explicit NewVersionCheck(QObject *parent=nullptr); 65 66 //! Construct a version checker with the given version 67 NewVersionCheck(int server, int major, int minor, QObject *parent=nullptr); 68 69 /** 70 * Is a new version check needed? 71 * 72 * A version check should be performed if: 73 * 74 * - the user hasn't opted out (QSettings: versioncheck/enabled, default=true) 75 * - it has been at least one day since the previous check 76 * - if the last version checked failed, it has been at least one week 77 */ 78 static bool needCheck(); 79 80 /** 81 * @brief Is a new series (e.g. 2.0 --> 2.1) out? (cached) 82 * 83 * Check the cached latest release if a newer incompatible version 84 * is out. 85 */ 86 static bool isThereANewSeries(); 87 88 /** 89 * Show beta releases? 90 * 91 * By default, only stable releases are shown. 92 * This must be called before queryVersion or parseAppDataFile. 93 */ setShowBetas(bool show)94 void setShowBetas(bool show) { m_showBetas = show; } 95 96 /** 97 * Explicitly set this system's platform 98 * 99 * This is used to select which artifact to include in the Version structure. 100 * If not set explicitly, the platform is selected by the build type: 101 * 102 * - win64 if built for 64 bit windows 103 * - win32 if built for 32 bit windows 104 * - macos if built of macOS 105 * - blank for everything else 106 * 107 * If a blank platform is set, the download fields will not be populated. 108 */ setPlatform(const QString & platform)109 void setPlatform(const QString &platform) { m_platform = platform; } 110 111 /** 112 * Make a HTTP request and check the version file 113 * 114 * Emits versionChecked when done. 115 * The "newVersionAvailable" parameter will be true if a new version has 116 * been released since the last time queryVersions was called. 117 * 118 * @param url the URL to query (if null, the default built-in URL is used) 119 */ 120 void queryVersions(QUrl url=QUrl()); 121 122 /** 123 * Parse an AppData file and get the list of releases. 124 * 125 * Typically, you should not need to call this directly. Call 126 * queryVersions() instead to fetch and parse the version list. 127 * 128 * @return true if the file was parsed successfully 129 */ 130 bool parseAppDataFile(QXmlStreamReader &reader); 131 132 /** 133 * Get all available versions newer than this one. 134 * 135 * The list of new versions is populated by parseAppDataFile, 136 * which (or queryVersions, rather) should be called before this. 137 * The list is returned in the order it appears in the appdata file. 138 * 139 * If nothing newer is available, an empty vector is returned. 140 */ getNewer()141 QVector<Version> getNewer() const { return m_newer; } 142 143 signals: 144 /** 145 * @brief Version check complete 146 * 147 * The errorMessage parameter will be non-empty if an error occurred. 148 */ 149 void versionChecked(bool isNewVersionAvailable, const QString &errorMessage); 150 151 private: 152 bool parseDesktopElement(QXmlStreamReader &reader); 153 bool parseReleasesElement(QXmlStreamReader &reader); 154 155 void queryFail(const QString &errorMessage); 156 void querySuccess(); 157 158 int m_server, m_major, m_minor; 159 QVector<Version> m_newer; 160 bool m_showBetas; 161 QString m_platform; 162 }; 163 164 #endif 165 166