From c25b10628098cdbaf4979e199d9efae9e608fe70 Mon Sep 17 00:00:00 2001
From: Alex Spataru
Date: Fri, 4 Nov 2016 09:35:13 -0600
Subject: [PATCH] Work on issue #4
---
include/QSimpleUpdater.h | 17 +++++----
src/Downloader.cpp | 5 ++-
src/Downloader.h | 2 +-
src/QSimpleUpdater.cpp | 41 +++++++++++++++-----
src/Updater.cpp | 81 ++++++++++++++++++++++++++++++----------
src/Updater.h | 14 ++++---
tutorial/src/Window.cpp | 33 ++++++++++++++--
tutorial/src/Window.h | 3 +-
tutorial/src/Window.ui | 54 ++++++++++++---------------
9 files changed, 171 insertions(+), 79 deletions(-)
diff --git a/include/QSimpleUpdater.h b/include/QSimpleUpdater.h
index eaa827e..22f7eaa 100644
--- a/include/QSimpleUpdater.h
+++ b/include/QSimpleUpdater.h
@@ -35,11 +35,11 @@
#include
#if defined (QSU_SHARED)
- #define QSU_DECL Q_DECL_EXPORT
+#define QSU_DECL Q_DECL_EXPORT
#elif defined (QSU_IMPORT)
- #define QSU_DECL Q_DECL_IMPORT
+#define QSU_DECL Q_DECL_IMPORT
#else
- #define QSU_DECL
+#define QSU_DECL
#endif
class Updater;
@@ -68,11 +68,13 @@ class QSU_DECL QSimpleUpdater : public QObject {
signals:
void checkingFinished (const QString& url);
+ void appcastDownloaded (const QString& url, const QByteArray& data);
void downloadFinished (const QString& url, const QString& filepath);
public:
static QSimpleUpdater* getInstance();
+ bool usesCustomAppcast (const QString& url) const;
bool getNotifyOnUpdate (const QString& url) const;
bool getNotifyOnFinish (const QString& url) const;
bool getUpdateAvailable (const QString& url) const;
@@ -90,12 +92,13 @@ class QSU_DECL QSimpleUpdater : public QObject {
public slots:
void checkForUpdates (const QString& url);
void setModuleName (const QString& url, const QString& name);
- void setNotifyOnUpdate (const QString& url, const bool& notify);
- void setNotifyOnFinish (const QString& url, const bool& notify);
+ void setNotifyOnUpdate (const QString& url, const bool notify);
+ void setNotifyOnFinish (const QString& url, const bool notify);
void setPlatformKey (const QString& url, const QString& platform);
void setModuleVersion (const QString& url, const QString& version);
- void setDownloaderEnabled (const QString& url, const bool& enabled);
- void setUseCustomInstallProcedures (const QString& url, const bool& custom);
+ void setDownloaderEnabled (const QString& url, const bool enabled);
+ void setUseCustomAppcast (const QString& url, const bool customAppcast);
+ void setUseCustomInstallProcedures (const QString& url, const bool custom);
protected:
~QSimpleUpdater();
diff --git a/src/Downloader.cpp b/src/Downloader.cpp
index c02db2f..e5002e2 100755
--- a/src/Downloader.cpp
+++ b/src/Downloader.cpp
@@ -201,7 +201,8 @@ void Downloader::onDownloadFinished() {
QString name = m_reply->url().toString().split ("/").last();
/* Check if we need to redirect */
- QUrl url = m_reply->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ QUrl url = m_reply->attribute (
+ QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (!url.isEmpty()) {
startDownload (url);
return;
@@ -326,6 +327,6 @@ qreal Downloader::round (const qreal& input) {
* Use the signals fired by the \c QSimpleUpdater to implement your own install
* procedures.
*/
-void Downloader::setUseCustomInstallProcedures (const bool& custom) {
+void Downloader::setUseCustomInstallProcedures (const bool custom) {
m_useCustomProcedures = custom;
}
diff --git a/src/Downloader.h b/src/Downloader.h
index eb60ad8..bb753ae 100755
--- a/src/Downloader.h
+++ b/src/Downloader.h
@@ -57,7 +57,7 @@ class Downloader : public QWidget {
public slots:
void startDownload (const QUrl& url);
- void setUseCustomInstallProcedures (const bool& custom);
+ void setUseCustomInstallProcedures (const bool custom);
private slots:
void openDownload();
diff --git a/src/QSimpleUpdater.cpp b/src/QSimpleUpdater.cpp
index a54ba91..358a239 100644
--- a/src/QSimpleUpdater.cpp
+++ b/src/QSimpleUpdater.cpp
@@ -35,6 +35,10 @@ static QList UPDATERS;
QSimpleUpdater::~QSimpleUpdater() {
URLS.clear();
+
+ foreach (Updater* updater, UPDATERS)
+ updater->deleteLater();
+
UPDATERS.clear();
}
@@ -46,6 +50,18 @@ QSimpleUpdater* QSimpleUpdater::getInstance() {
return &updater;
}
+/**
+ * Returns \c true if the \c Updater instance registered with the given \a url
+ * uses a custom appcast format and/or allows the application to read and
+ * interpret the downloaded appcast file
+ *
+ * \note If an \c Updater instance registered with the given \a url is not
+ * found, that \c Updater instance will be initialized automatically
+ */
+bool QSimpleUpdater::usesCustomAppcast (const QString& url) const {
+ return getUpdater (url)->customAppcast();
+}
+
/**
* Returns \c true if the \c Updater instance registered with the given \a url
* shall notify the user when an update is available.
@@ -115,7 +131,7 @@ bool QSimpleUpdater::usesCustomInstallProcedures (const QString& url) const {
* \note If an \c Updater instance registered with the given \a url is not
* found, that \c Updater instance will be initialized automatically
*/
-QString QSimpleUpdater::getOpenUrl (const QString &url) const {
+QString QSimpleUpdater::getOpenUrl (const QString& url) const {
return getUpdater (url)->openUrl();
}
@@ -230,7 +246,7 @@ void QSimpleUpdater::setModuleName (const QString& url, const QString& name) {
* found, that \c Updater instance will be initialized automatically
*/
void QSimpleUpdater::setNotifyOnUpdate (const QString& url,
- const bool& notify) {
+ const bool notify) {
getUpdater (url)->setNotifyOnUpdate (notify);
}
@@ -243,7 +259,7 @@ void QSimpleUpdater::setNotifyOnUpdate (const QString& url,
* found, that \c Updater instance will be initialized automatically
*/
void QSimpleUpdater::setNotifyOnFinish (const QString& url,
- const bool& notify) {
+ const bool notify) {
getUpdater (url)->setNotifyOnFinish (notify);
}
@@ -288,10 +304,15 @@ void QSimpleUpdater::setModuleVersion (const QString& url,
* found, that \c Updater instance will be initialized automatically
*/
void QSimpleUpdater::setDownloaderEnabled (const QString& url,
- const bool& enabled) {
+ const bool enabled) {
getUpdater (url)->setDownloaderEnabled (enabled);
}
+void QSimpleUpdater::setUseCustomAppcast (const QString& url,
+ const bool customAppcast) {
+ getUpdater (url)->setUseCustomAppcast (customAppcast);
+}
+
/**
* If the \a custom parameter is set to \c true, the \c Updater instance
* registered with the given \a url will not try to open the downloaded file.
@@ -304,7 +325,7 @@ void QSimpleUpdater::setDownloaderEnabled (const QString& url,
* found, that \c Updater instance will be initialized automatically
*/
void QSimpleUpdater::setUseCustomInstallProcedures (const QString& url,
- const bool& custom) {
+ const bool custom) {
getUpdater (url)->setUseCustomInstallProcedures (custom);
}
@@ -322,10 +343,12 @@ Updater* QSimpleUpdater::getUpdater (const QString& url) const {
URLS.append (url);
UPDATERS.append (updater);
- connect (updater, SIGNAL (checkingFinished (QString)),
- this, SIGNAL (checkingFinished (QString)));
- connect (updater, SIGNAL (downloadFinished (QString, QString)),
- this, SIGNAL (downloadFinished (QString, QString)));
+ connect (updater, SIGNAL (checkingFinished (QString)),
+ this, SIGNAL (checkingFinished (QString)));
+ connect (updater, SIGNAL (downloadFinished (QString, QString)),
+ this, SIGNAL (downloadFinished (QString, QString)));
+ connect (updater, SIGNAL (appcastDownloaded (QString, QByteArray)),
+ this, SIGNAL (appcastDownloaded (QString, QByteArray)));
}
return UPDATERS.at (URLS.indexOf (url));
diff --git a/src/Updater.cpp b/src/Updater.cpp
index 3a0d07b..691dce4 100644
--- a/src/Updater.cpp
+++ b/src/Updater.cpp
@@ -43,6 +43,7 @@ Updater::Updater() {
m_changelog = "";
m_downloadUrl = "";
m_latestVersion = "";
+ m_customAppcast = false;
m_notifyOnUpdate = true;
m_notifyOnFinish = false;
m_updateAvailable = false;
@@ -144,6 +145,15 @@ QString Updater::moduleVersion() const {
return m_moduleVersion;
}
+/**
+ * Returns \c true if the updater should NOT interpret the downloaded appcast.
+ * This is useful if you need to store more variables (or information) in the
+ * JSON file or use another appcast format (e.g. XML)
+ */
+bool Updater::customAppcast() const {
+ return m_customAppcast;
+}
+
/**
* Returns \c true if the updater should notify the user when an update is
* available.
@@ -218,7 +228,7 @@ void Updater::setModuleName (const QString& name) {
* If \a notify is set to \c true, then the \c Updater will notify the user
* when an update is available.
*/
-void Updater::setNotifyOnUpdate (const bool& notify) {
+void Updater::setNotifyOnUpdate (const bool notify) {
m_notifyOnUpdate = notify;
}
@@ -226,7 +236,7 @@ void Updater::setNotifyOnUpdate (const bool& notify) {
* If \a notify is set to \c true, then the \c Updater will notify the user
* when it has finished interpreting the update definitions file.
*/
-void Updater::setNotifyOnFinish (const bool& notify) {
+void Updater::setNotifyOnFinish (const bool notify) {
m_notifyOnFinish = notify;
}
@@ -244,7 +254,7 @@ void Updater::setModuleVersion (const QString& version) {
* If the \a enabled parameter is set to \c true, the \c Updater will open the
* integrated downloader if the user agrees to install the update (if any)
*/
-void Updater::setDownloaderEnabled (const bool& enabled) {
+void Updater::setDownloaderEnabled (const bool enabled) {
m_downloaderEnabled = enabled;
}
@@ -261,12 +271,22 @@ void Updater::setPlatformKey (const QString& platformKey) {
m_platform = platformKey;
}
+/**
+ * If the \a customAppcast parameter is set to \c true, then the \c Updater
+ * will not try to read the network reply from the server, instead, it will
+ * emit the \c appcastDownloaded() signal, which allows the application to
+ * read and interpret the appcast file by itself
+ */
+void Updater::setUseCustomAppcast (const bool customAppcast) {
+ m_customAppcast = customAppcast;
+}
+
/**
* If the \a custom parameter is set to \c true, the \c Updater will not try
* to open the downloaded file. Use the signals fired by the \c QSimpleUpdater
* to install the update from the downloaded file by yourself.
*/
-void Updater::setUseCustomInstallProcedures (const bool& custom) {
+void Updater::setUseCustomInstallProcedures (const bool custom) {
m_downloader->setUseCustomInstallProcedures (custom);
}
@@ -274,23 +294,44 @@ void Updater::setUseCustomInstallProcedures (const bool& custom) {
* Called when the download of the update definitions file is finished.
*/
void Updater::onReply (QNetworkReply* reply) {
- if (reply->error() == QNetworkReply::NoError) {
- QJsonDocument document = QJsonDocument::fromJson (reply->readAll());
-
- if (document.isNull())
- return;
-
- QJsonObject updates = document.object().value ("updates").toObject();
- QJsonObject platform = updates.value (platformKey()).toObject();
-
- m_openUrl = platform.value ("open-url").toString();
- m_changelog = platform.value ("changelog").toString();
- m_downloadUrl = platform.value ("download-url").toString();
- m_latestVersion = platform.value ("latest-version").toString();
-
- setUpdateAvailable (compare (latestVersion(), moduleVersion()));
+ /* Check if we need to redirect */
+ QUrl redirect = reply->attribute (
+ QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ if (!redirect.isEmpty()) {
+ setUrl (redirect.toString());
+ checkForUpdates();
+ return;
}
+ /* There was a network error */
+ if (reply->error() != QNetworkReply::NoError)
+ return;
+
+ /* The application wants to interpret the appcast by itself */
+ if (customAppcast()) {
+ emit appcastDownloaded (url(), reply->readAll());
+ return;
+ }
+
+ /* Try to create a JSON document from downloaded data */
+ QJsonDocument document = QJsonDocument::fromJson (reply->readAll());
+
+ /* JSON is invalid */
+ if (document.isNull())
+ return;
+
+ /* Get the platform information */
+ QJsonObject updates = document.object().value ("updates").toObject();
+ QJsonObject platform = updates.value (platformKey()).toObject();
+
+ /* Get update information */
+ m_openUrl = platform.value ("open-url").toString();
+ m_changelog = platform.value ("changelog").toString();
+ m_downloadUrl = platform.value ("download-url").toString();
+ m_latestVersion = platform.value ("latest-version").toString();
+
+ /* Compare latest and current version */
+ setUpdateAvailable (compare (latestVersion(), moduleVersion()));
emit checkingFinished (url());
}
@@ -298,7 +339,7 @@ void Updater::onReply (QNetworkReply* reply) {
* Prompts the user based on the value of the \a available parameter and the
* settings of this instance of the \c Updater class.
*/
-void Updater::setUpdateAvailable (const bool& available) {
+void Updater::setUpdateAvailable (const bool available) {
m_updateAvailable = available;
QMessageBox box;
diff --git a/src/Updater.h b/src/Updater.h
index 7e7d5a8..7061d09 100644
--- a/src/Updater.h
+++ b/src/Updater.h
@@ -48,6 +48,7 @@ class QSU_DECL Updater : public QObject {
signals:
void checkingFinished (const QString& url);
void downloadFinished (const QString& url, const QString& filepath);
+ void appcastDownloaded (const QString& url, const QByteArray& data);
public:
Updater();
@@ -62,6 +63,7 @@ class QSU_DECL Updater : public QObject {
QString moduleVersion() const;
QString latestVersion() const;
+ bool customAppcast() const;
bool notifyOnUpdate() const;
bool notifyOnFinish() const;
bool updateAvailable() const;
@@ -72,16 +74,17 @@ class QSU_DECL Updater : public QObject {
void checkForUpdates();
void setUrl (const QString& url);
void setModuleName (const QString& name);
- void setNotifyOnUpdate (const bool& notify);
- void setNotifyOnFinish (const bool& notify);
+ void setNotifyOnUpdate (const bool notify);
+ void setNotifyOnFinish (const bool notify);
void setModuleVersion (const QString& version);
- void setDownloaderEnabled (const bool& enabled);
+ void setDownloaderEnabled (const bool enabled);
void setPlatformKey (const QString& platformKey);
- void setUseCustomInstallProcedures (const bool& custom);
+ void setUseCustomAppcast (const bool customAppcast);
+ void setUseCustomInstallProcedures (const bool custom);
private slots:
void onReply (QNetworkReply* reply);
- void setUpdateAvailable (const bool& available);
+ void setUpdateAvailable (const bool available);
private:
bool compare (const QString& x, const QString& y);
@@ -89,6 +92,7 @@ class QSU_DECL Updater : public QObject {
private:
QString m_url;
+ bool m_customAppcast;
bool m_notifyOnUpdate;
bool m_notifyOnFinish;
bool m_updateAvailable;
diff --git a/tutorial/src/Window.cpp b/tutorial/src/Window.cpp
index 1fa35b1..250ee21 100644
--- a/tutorial/src/Window.cpp
+++ b/tutorial/src/Window.cpp
@@ -33,8 +33,10 @@ Window::Window (QWidget* parent) : QMainWindow (parent) {
m_updater = QSimpleUpdater::getInstance();
/* Check for updates when the "Check For Updates" button is clicked */
- connect (m_updater, SIGNAL (checkingFinished (QString)),
- this, SLOT (updateChangelog (QString)));
+ connect (m_updater, SIGNAL (checkingFinished (QString)),
+ this, SLOT (updateChangelog (QString)));
+ connect (m_updater, SIGNAL (appcastDownloaded (QString, QByteArray)),
+ this, SLOT (displayAppcast (QString, QByteArray)));
/* React to button clicks */
connect (m_ui->resetButton, SIGNAL (clicked()),
@@ -45,7 +47,8 @@ Window::Window (QWidget* parent) : QMainWindow (parent) {
this, SLOT (checkForUpdates()));
/* Resize the dialog to fit */
- setFixedSize (minimumSizeHint());
+ setMinimumSize (minimumSizeHint());
+ resize (minimumSizeHint());
/* Reset the UI state */
resetFields();
@@ -65,6 +68,7 @@ Window::~Window() {
void Window::resetFields() {
m_ui->installedVersion->setText ("0.1");
+ m_ui->customAppcast->setChecked (false);
m_ui->enableDownloader->setChecked (true);
m_ui->showAllNotifcations->setChecked (false);
m_ui->showUpdateNotifications->setChecked (true);
@@ -77,6 +81,7 @@ void Window::resetFields() {
void Window::checkForUpdates() {
/* Get settings from the UI */
QString version = m_ui->installedVersion->text();
+ bool customAppcast = m_ui->customAppcast->isChecked();
bool downloaderEnabled = m_ui->enableDownloader->isChecked();
bool notifyOnFinish = m_ui->showAllNotifcations->isChecked();
bool notifyOnUpdate = m_ui->showUpdateNotifications->isChecked();
@@ -85,6 +90,7 @@ void Window::checkForUpdates() {
m_updater->setModuleVersion (DEFS_URL, version);
m_updater->setNotifyOnFinish (DEFS_URL, notifyOnFinish);
m_updater->setNotifyOnUpdate (DEFS_URL, notifyOnUpdate);
+ m_updater->setUseCustomAppcast (DEFS_URL, customAppcast);
m_updater->setDownloaderEnabled (DEFS_URL, downloaderEnabled);
/* Check for updates */
@@ -95,7 +101,26 @@ void Window::checkForUpdates() {
// Window::updateChangelog
//==============================================================================
-void Window::updateChangelog (QString url) {
+void Window::updateChangelog (const QString& url) {
if (url == DEFS_URL)
m_ui->changelogText->setText (m_updater->getChangelog (url));
}
+
+
+//==============================================================================
+// Window::displayAppcast
+//==============================================================================
+
+void Window::displayAppcast (const QString& url, const QByteArray& reply) {
+ if (url == DEFS_URL) {
+ QString text = "This is the downloaded appcast: " +
+ QString::fromUtf8 (reply) +
+ "
If you need to store more information on the "
+ "appcast (or use another format), just use the "
+ "QSimpleUpdater::setCustomAppcast() function. "
+ "It allows your application to interpret the appcast "
+ "using your code and not QSU's code.
";
+
+ m_ui->changelogText->setText (text);
+ }
+}
diff --git a/tutorial/src/Window.h b/tutorial/src/Window.h
index 1d49f50..7fa75b1 100644
--- a/tutorial/src/Window.h
+++ b/tutorial/src/Window.h
@@ -28,7 +28,8 @@ class Window : public QMainWindow {
public slots:
void resetFields();
void checkForUpdates();
- void updateChangelog (QString url);
+ void updateChangelog (const QString& url);
+ void displayAppcast (const QString& url, const QByteArray& reply);
private:
Ui::Window* m_ui;
diff --git a/tutorial/src/Window.ui b/tutorial/src/Window.ui
index 109ce9f..aca6acb 100644
--- a/tutorial/src/Window.ui
+++ b/tutorial/src/Window.ui
@@ -6,8 +6,8 @@
0
0
- 496
- 487
+ 483
+ 494
@@ -82,6 +82,23 @@
Updater Options
+ -
+
+
+ Show all notifications
+
+
+
+ -
+
+
+ 0.1
+
+
+ Write a version string...
+
+
+
-
@@ -102,13 +119,6 @@
- -
-
-
- Show all notifications
-
-
-
-
@@ -116,13 +126,10 @@
- -
-
+
-
+
- 0.1
-
-
- Write a version string...
+ Do not use the QSU library to read the appcast
@@ -144,27 +151,14 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'.Lucida Grande UI'; font-size:13pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click "Check for Updates" to update this field...</p></body></html>
+</style></head><body style=" font-family:'.SF NS Text'; font-size:13pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'.Lucida Grande UI';">Click "Check for Updates" to update this field...</span></p></body></html>
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-