From d88c4955ebae9ca5c3fbd69c755e7ab8b189c25a Mon Sep 17 00:00:00 2001 From: Alex Spataru Date: Thu, 6 Nov 2014 18:59:09 -0600 Subject: [PATCH] Implemented a "download and install" dialog --- Example/example.cpp | 4 + QSimpleUpdater/qsimpleupdater.pri | 12 +- QSimpleUpdater/res/internet_icon.png | Bin 0 -> 8817 bytes QSimpleUpdater/res/res.qrc | 5 + .../src/dialogs/download_dialog.cpp | 188 ++++++++++++++++++ QSimpleUpdater/src/dialogs/download_dialog.h | 44 ++++ QSimpleUpdater/src/dialogs/download_dialog.ui | 144 ++++++++++++++ QSimpleUpdater/src/qsimpleupdater.cpp | 137 ++++++------- QSimpleUpdater/src/qsimpleupdater.h | 23 ++- 9 files changed, 475 insertions(+), 82 deletions(-) create mode 100644 QSimpleUpdater/res/internet_icon.png create mode 100644 QSimpleUpdater/res/res.qrc create mode 100644 QSimpleUpdater/src/dialogs/download_dialog.cpp create mode 100644 QSimpleUpdater/src/dialogs/download_dialog.h create mode 100644 QSimpleUpdater/src/dialogs/download_dialog.ui diff --git a/Example/example.cpp b/Example/example.cpp index f7a51e6..1619cb9 100644 --- a/Example/example.cpp +++ b/Example/example.cpp @@ -63,6 +63,9 @@ void Example::checkForUpdates() { updater->setReferenceUrl("https://raw.githubusercontent.com/alex-97/" "QSimpleUpdater/Files-for-example-project/current_version.txt"); + // Tell the updater where to download the update, its recommended to use direct links + updater->setDownloadUrl("https://github.com/alex-97/QSimpleUpdater/archive/master.zip"); + // Finally, check for updates... updater->checkForUpdates(); } @@ -81,6 +84,7 @@ void Example::onCheckingFinished() { QMessageBox::information(this, tr("Update available"), tr("There's a newer version available! The latest version is ") + updater->latestVersion()); + updater->downloadLatestVersion(); } // The installed version is equal or greater to the "official" latest version, diff --git a/QSimpleUpdater/qsimpleupdater.pri b/QSimpleUpdater/qsimpleupdater.pri index 2d8a49d..17c59b1 100755 --- a/QSimpleUpdater/qsimpleupdater.pri +++ b/QSimpleUpdater/qsimpleupdater.pri @@ -8,8 +8,10 @@ QT += network -HEADERS += $$PWD/src/qsimpleupdater.h -SOURCES += $$PWD/src/qsimpleupdater.cpp +HEADERS += $$PWD/src/qsimpleupdater.h \ + $$PWD/src/dialogs/download_dialog.h +SOURCES += $$PWD/src/qsimpleupdater.cpp \ + $$PWD/src/dialogs/download_dialog.cpp OTHER_FILES += $$PWD/src/QSimpleUpdater INCLUDEPATH += $$PWD/src @@ -22,3 +24,9 @@ win32* { CONFIG += openssl-linked LIBS += -L$$PWD/dependencies/win32/ -llibeay32 } + +RESOURCES += \ + $$PWD/res/res.qrc + +FORMS += \ + $$PWD/src/dialogs/download_dialog.ui diff --git a/QSimpleUpdater/res/internet_icon.png b/QSimpleUpdater/res/internet_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8fd54fbc77bf0a49d23abb5ff1ba360121a76643 GIT binary patch literal 8817 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 literal 0 HcmV?d00001 diff --git a/QSimpleUpdater/res/res.qrc b/QSimpleUpdater/res/res.qrc new file mode 100644 index 0000000..aebed36 --- /dev/null +++ b/QSimpleUpdater/res/res.qrc @@ -0,0 +1,5 @@ + + + internet_icon.png + + diff --git a/QSimpleUpdater/src/dialogs/download_dialog.cpp b/QSimpleUpdater/src/dialogs/download_dialog.cpp new file mode 100644 index 0000000..3eed979 --- /dev/null +++ b/QSimpleUpdater/src/dialogs/download_dialog.cpp @@ -0,0 +1,188 @@ +// +// This file is part of QSimpleUpdater +// +// Copyright (c) 2014 Alex Spataru +// +// Please check the license.txt file for more information. +// + +#include "download_dialog.h" +#include "ui_download_dialog.h" + +DownloadDialog::DownloadDialog(QWidget *parent) : + QWidget(parent), + ui(new Ui::DownloadDialog) +{ + // Setup the UI + ui->setupUi(this); + ui->installButton->setEnabled(false); + + // Connect SIGNALS/SLOTS + connect(ui->installButton, SIGNAL(clicked()), this, SLOT(openDownload())); + connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(cancelDownload())); + + // Initialize the network access manager + m_manager = new QNetworkAccessManager(this); + + // Avoid SSL issues + connect(m_manager, SIGNAL(sslErrors(QNetworkReply*,QList)), + this, SLOT(ignoreSslErrors(QNetworkReply*,QList))); +} + +DownloadDialog::~DownloadDialog() +{ + delete ui; +} + +void DownloadDialog::beginDownload(const QUrl &url) +{ + // Reset the UI + ui->progressBar->setValue(0); + ui->installButton->setEnabled(false); + ui->downloadLabel->setText(tr("Downloading update...")); + + // Begin the download + m_reply = m_manager->get(QNetworkRequest(url)); + + // Update the progress bar value automatically + connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(updateProgress(qint64,qint64))); + + // Write the file to the hard disk once the download is finished + connect(m_reply, SIGNAL(finished()), this, SLOT(downloadFinished())); + + // Show the dialog + showNormal(); +} + +void DownloadDialog::openDownload() +{ + if (!m_path.isEmpty()) { + QString url = m_path; + + // Build a correct URL to open local files + if (url.startsWith("/")) + url = "file://" + url; + else + url = "file:///" + url; + + // Let the system open the downloaded file + QDesktopServices::openUrl(url); + } + + else { + qWarning() << "QSimpleUpdater: cannot open downloaded file!"; + } +} + +void DownloadDialog::cancelDownload() +{ + // Cancel download + m_reply->abort(); + + // Close the dialog + close(); +} + +void DownloadDialog::downloadFinished() +{ + // Setup the UI + ui->installButton->setEnabled(true); + + // Write the file + QByteArray data = m_reply->readAll(); + + if (!data.isEmpty()) { + // Create a QFile with the name of the downloaded file + QStringList list = m_reply->url().toString().split("/"); + QFile file(QDir::tempPath() + "/" + list.at(list.count() - 1)); + + // Write download data to the opened file + if (file.open(QIODevice::WriteOnly)) { + file.write(data); + m_path = file.fileName(); + } + + // Show a warning if we cannot open the file for writting + else { + qWarning() << "QSimpleUpdater: cannot write downloaded data!"; + } + + // Close the file + file.close(); + } + + else { + qWarning() << "QSimpleUpdater: invalid download data!"; + } +} + +void DownloadDialog::updateProgress(qint64 received, qint64 total) +{ + // We know the size of the download, so we can calculate the progress.... + if (total > 0) { + ui->progressBar->setMinimum(0); + ui->progressBar->setMaximum(100); + + // Calculate and show download progress + int _progress = (int) ((received * 100) / total); + ui->progressBar->setValue(_progress); + ui->downloadLabel->setText(tr("Downloading update (%1%)...").arg(_progress)); + + // Get size information + QString _total_string; + QString _received_string; + + float _total = total; + float _received = received; + + // Calculate the lenght unit for + // the total size of the download + if (_total < 1024) { + _total_string = tr("%1 bytes").arg(_total); + } else if (_total < 1024 * 1024) { + _total = roundNumber(_total / 1024); + _total_string = tr("%1 KB").arg(_total); + } else { + _total = roundNumber(_total / (1024 * 1024)); + _total_string = tr("%1 MB").arg(_total); + } + + // Calculate the lenght unit for + // the received data of the download + if (_received < 1024) { + _received_string = tr("%1 bytes").arg(_received); + } else if (received < 1024 * 1024) { + _received = roundNumber(_received / 1024); + _received_string = tr("%1 KB").arg(_received); + } else { + _received = roundNumber(_received / (1024 * 1024)); + _received_string = tr("%1 MB").arg(_received); + } + + // Update the progress label + ui->progressLabel->setText(_received_string + " " + tr("of") + " " + _total_string); + } + + // We do not know the size of the download, so we improvise... + else { + + // Enable a marquee animation + ui->progressBar->setValue(-1); + ui->progressBar->setMinimum(0); + ui->progressBar->setMaximum(0); + + ui->downloadLabel->setText(tr("Downloading update...")); + } +} + +void DownloadDialog::ignoreSslErrors (QNetworkReply *reply, const QList &error) +{ + reply->ignoreSslErrors (error); +} + +float DownloadDialog::roundNumber(const float &input) +{ + // Round the input number to two decimal places + return roundf(input * 100) / 100; +} diff --git a/QSimpleUpdater/src/dialogs/download_dialog.h b/QSimpleUpdater/src/dialogs/download_dialog.h new file mode 100644 index 0000000..d3815ac --- /dev/null +++ b/QSimpleUpdater/src/dialogs/download_dialog.h @@ -0,0 +1,44 @@ +#ifndef DOWNLOAD_DIALOG_H +#define DOWNLOAD_DIALOG_H + +#include +#include +#include +#include +#include + +#include + +namespace Ui { +class DownloadDialog; +} + +class DownloadDialog : public QWidget +{ + Q_OBJECT + +public: + explicit DownloadDialog(QWidget *parent = 0); + ~DownloadDialog(); + + void beginDownload(const QUrl &url); + +private slots: + void openDownload(); + void cancelDownload(); + void downloadFinished(); + void updateProgress(qint64 received, qint64 total); + void ignoreSslErrors(QNetworkReply *reply, const QList &error); + +private: + Ui::DownloadDialog *ui; + + QString m_path; + + QNetworkReply *m_reply; + QNetworkAccessManager *m_manager; + + float roundNumber(const float &input); +}; + +#endif diff --git a/QSimpleUpdater/src/dialogs/download_dialog.ui b/QSimpleUpdater/src/dialogs/download_dialog.ui new file mode 100644 index 0000000..eab0c2d --- /dev/null +++ b/QSimpleUpdater/src/dialogs/download_dialog.ui @@ -0,0 +1,144 @@ + + + DownloadDialog + + + + 0 + 0 + 385 + 168 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Updater + + + + 0 + + + 12 + + + 0 + + + 0 + + + 0 + + + + + + + + :/icons/internet_icon.png + + + Qt::AlignCenter + + + + + + + + + + + + + + 75 + true + + + + Downloading update... + + + + + + + 0 + + + false + + + + + + + 0 kb / 0 kb + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + Install + + + + + + + + + + + + + + + + diff --git a/QSimpleUpdater/src/qsimpleupdater.cpp b/QSimpleUpdater/src/qsimpleupdater.cpp index 0fbf471..3503b1e 100755 --- a/QSimpleUpdater/src/qsimpleupdater.cpp +++ b/QSimpleUpdater/src/qsimpleupdater.cpp @@ -8,25 +8,23 @@ #include "qsimpleupdater.h" -QSimpleUpdater::QSimpleUpdater(QObject *parent) : QObject(parent) +QSimpleUpdater::QSimpleUpdater(QObject *parent) + : QObject(parent) + , m_changelog_downloaded(false) + , m_version_check_finished(false) + , m_new_version_available(false) { - m_new_version_available = false; + m_downloadDialog = new DownloadDialog(); } -QString QSimpleUpdater::changeLog() { - // Return the contents of the downloaded changelog - if (!m_changelog.isEmpty()) { - return m_changelog; - } - - // If the changelog is empty, we issue a warning message in - // the console and return an empty string - else { +// Return the contents of the downloaded changelog +QString QSimpleUpdater::changeLog() const { + if (m_changelog.isEmpty()) { qWarning() << "QSimpleUpdater: change log is empty," << "did you call setChangelogUrl() and checkForUpdates()?"; - return NULL; } + return m_changelog; } void QSimpleUpdater::checkForUpdates() { @@ -56,38 +54,7 @@ void QSimpleUpdater::checkForUpdates() { } } -QString QSimpleUpdater::latestVersion() { - // Return the application version referenced by the string - // that we downloaded - if (!m_latest_version.isEmpty()) { - return m_latest_version; - } - - // Issue a warning message in the case that the downloaded - // application version string is empty - else { - qWarning() << "QSimpleUpdater: latest version is empty," - << "did you call checkForUpdates() and setReferenceUrl()?"; - return NULL; - } -} - -QString QSimpleUpdater::installedVersion() { - // Return the string issued by the user in the setApplicationVersion() function - if (!m_installed_version.isEmpty()) { - return m_installed_version; - } - - // Issue a warning message in the case that the installed application - // version is empty - else { - qWarning() << "QSimpleUpdater: installed version is empty," - << "did you call setApplicationVersion()?"; - return NULL; - } -} - -void QSimpleUpdater::downloadLatestVersion() { +void QSimpleUpdater::openDownloadLink() { // Open the download URL in a web browser if (!m_download_url.isEmpty()) { QDesktopServices::openUrl(m_download_url); @@ -100,59 +67,87 @@ void QSimpleUpdater::downloadLatestVersion() { } } -bool QSimpleUpdater::newerVersionAvailable() { +// Return the application version referenced by the string +// that we downloaded +QString QSimpleUpdater::latestVersion() const { + if (m_latest_version.isEmpty()) { + qWarning() << "QSimpleUpdater: latest version is empty," + << "did you call checkForUpdates() and setReferenceUrl()?"; + } + return m_latest_version; +} + +// Return the string issued by the user in the setApplicationVersion() function +QString QSimpleUpdater::installedVersion() const { + if (m_installed_version.isEmpty()) { + qWarning() << "QSimpleUpdater: installed version is empty," + << "did you call setApplicationVersion()?"; + } + + return m_installed_version; +} + +void QSimpleUpdater::downloadLatestVersion() { + // Show the download dialog + if (!m_download_url.isEmpty()) { + m_downloadDialog->beginDownload(m_download_url); + } + + // The m_download_url is empty, so we issue another warning message + else { + qWarning() << "QSimpleUpdater: cannot download latest version," + << "did you call setDownloadUrl() and checkForUpdates()?"; + } +} + +bool QSimpleUpdater::newerVersionAvailable() const { return m_new_version_available; } -void QSimpleUpdater::setDownloadUrl(const QString url) { - // Change the download URL if the issued URL is valid +// Change the download URL if the issued URL is valid +void QSimpleUpdater::setDownloadUrl(const QString &url) { + Q_ASSERT(!url.isEmpty()); + if (!url.isEmpty()) { m_download_url.setUrl(url); - } - - // The issued URL is ilegal, so we warn the user - else { + } else { qWarning() << "QSimpleUpdater: input URL cannot be empty!"; } } -void QSimpleUpdater::setReferenceUrl(const QString url) { - // Change the reference URL if the issued URL is valid +// Change the reference URL if the issued URL is valid +void QSimpleUpdater::setReferenceUrl(const QString &url) { + Q_ASSERT(!url.isEmpty()); + if (!url.isEmpty()) { m_reference_url.setUrl(url); - } - - // The issued URL is ilegal, so we warn the user - else { + } else { qWarning() << "QSimpleUpdater: input URL cannot be empty!"; } } -void QSimpleUpdater::setChangelogUrl(const QString url) { - // Change the changelog URL if the issued URL is valid +// Change the changelog URL if the issued URL is valid +void QSimpleUpdater::setChangelogUrl(const QString &url) { + Q_ASSERT(!url.isEmpty()); + if (!url.isEmpty()) { m_changelog_url.setUrl(url); - } - - // The issued URL is ilegal, so we warn the user - else { + } else { qWarning() << "QSimpleUpdater: input URL cannot be empty!"; } } -void QSimpleUpdater::setApplicationVersion(const QString version) { - // Change the installed application version if the issued string is valid +// Change the installed application version if the issued string is valid +void QSimpleUpdater::setApplicationVersion(const QString &version) { + Q_ASSERT(!version.isEmpty()); + if (!version.isEmpty()) { m_installed_version = version; - } - - // The application version cannot be empty, so we warn the user - else { + } else { qWarning() << "QSimpleUpdater: input string cannot be empty!"; } } - void QSimpleUpdater::checkDownloadedVersion(QNetworkReply *reply) { bool _new_update = false; @@ -261,6 +256,6 @@ void QSimpleUpdater::processDownloadedChangelog(QNetworkReply *reply) { emit checkingFinished(); } -void QSimpleUpdater::ignoreSslErrors (QNetworkReply *reply, QList error) { +void QSimpleUpdater::ignoreSslErrors (QNetworkReply *reply, const QList &error) { reply->ignoreSslErrors (error); } diff --git a/QSimpleUpdater/src/qsimpleupdater.h b/QSimpleUpdater/src/qsimpleupdater.h index ededa7e..edb115a 100755 --- a/QSimpleUpdater/src/qsimpleupdater.h +++ b/QSimpleUpdater/src/qsimpleupdater.h @@ -13,29 +13,32 @@ #include #include +#include "dialogs/download_dialog.h" + class QSimpleUpdater : public QObject { Q_OBJECT public: QSimpleUpdater(QObject *parent = 0); - QString changeLog(); + QString changeLog() const; void checkForUpdates(); - QString latestVersion(); - QString installedVersion(); + void openDownloadLink(); + QString latestVersion() const; + QString installedVersion() const; void downloadLatestVersion(); - bool newerVersionAvailable(); + bool newerVersionAvailable() const; public slots: - void setDownloadUrl(const QString url); - void setReferenceUrl(const QString url); - void setChangelogUrl(const QString url); - void setApplicationVersion(const QString version); + void setDownloadUrl(const QString &url); + void setReferenceUrl(const QString &url); + void setChangelogUrl(const QString &url); + void setApplicationVersion(const QString &version); private slots: void checkDownloadedVersion(QNetworkReply *reply); void processDownloadedChangelog(QNetworkReply *reply); - void ignoreSslErrors(QNetworkReply *reply, QList error); + void ignoreSslErrors(QNetworkReply *reply, const QList &error); signals: void checkingFinished(); @@ -55,6 +58,8 @@ private: bool m_version_check_finished; bool m_new_version_available; + + DownloadDialog *m_downloadDialog; }; #endif