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 0000000..8fd54fb
Binary files /dev/null and b/QSimpleUpdater/res/internet_icon.png differ
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