Rewrite library to allow multiple updaters & JSON appcasts
- The update definitions are now stored in the JSON format - The QSimpleUpdater now allows updating separate “modules” of the application, this can be useful if you are using a large application with several updatable plugins - You can now implement your own procedures to install the downloaded updates
This commit is contained in:
parent
365bb632ea
commit
47c6909259
27
COPYING.md
Normal file
27
COPYING.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# DON'T BE A DICK PUBLIC LICENSE
|
||||||
|
|
||||||
|
> Version 1, December 2009
|
||||||
|
|
||||||
|
> Copyright (C) 2009 Philip Sturgeon <me@philsturgeon.uk>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
> DON'T BE A DICK PUBLIC LICENSE
|
||||||
|
> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
1. Do whatever you like with the original work, just don't be a dick.
|
||||||
|
|
||||||
|
Being a dick includes - but is not limited to - the following instances:
|
||||||
|
|
||||||
|
1a. Outright copyright infringement - Don't just copy this and change the name.
|
||||||
|
1b. Selling the unmodified original with no work done what-so-ever, that's REALLY being a dick.
|
||||||
|
1c. Modifying the original work to contain hidden harmful content. That would make you a PROPER dick.
|
||||||
|
|
||||||
|
2. If you become rich through modifications, related works/services, or supporting the original work,
|
||||||
|
share the love. Only a dick would make loads off this work and not buy the original work's
|
||||||
|
creator(s) a pint.
|
||||||
|
|
||||||
|
3. Code is provided with no warranty. Using somebody else's code and bitching when it goes wrong makes
|
||||||
|
you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.
|
@ -1,89 +0,0 @@
|
|||||||
#include "example.h"
|
|
||||||
#include "ui_example.h"
|
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
|
||||||
{
|
|
||||||
QApplication app (argc, argv);
|
|
||||||
app.setApplicationName ("QSimpleUpdater Example");
|
|
||||||
|
|
||||||
// Create the dialog and show it
|
|
||||||
Example example;
|
|
||||||
example.show();
|
|
||||||
|
|
||||||
// Run the app
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
Example::Example (QWidget *parent) : QDialog (parent), ui (new Ui::Example)
|
|
||||||
{
|
|
||||||
// Create and configure the user interface
|
|
||||||
ui->setupUi (this);
|
|
||||||
ui->versionLineEdit->setText ("0.1");
|
|
||||||
ui->versionLineEdit->setPlaceholderText ("0.1");
|
|
||||||
ui->changelogTextEdit->setPlainText ("Click the \"Check for updates\" button to download the change log");
|
|
||||||
|
|
||||||
// Close the dialog when the close button is clicked
|
|
||||||
connect (ui->closeButton, SIGNAL (clicked()), this, SLOT (close()));
|
|
||||||
|
|
||||||
// Check for updates when the updates button is clicked
|
|
||||||
connect (ui->updatesButton, SIGNAL (clicked()), this, SLOT (checkForUpdates()));
|
|
||||||
|
|
||||||
// Initialize the updater
|
|
||||||
updater = new QSimpleUpdater (this);
|
|
||||||
|
|
||||||
// When the updater finishes checking for updates, show a message box
|
|
||||||
// and show the change log of the latest version
|
|
||||||
connect (updater, SIGNAL (checkingFinished()), this, SLOT (onCheckingFinished()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Example::~Example()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Example::checkForUpdates()
|
|
||||||
{
|
|
||||||
// Disable the check for updates button while the updater
|
|
||||||
// is checking for updates
|
|
||||||
ui->updatesButton->setEnabled (false);
|
|
||||||
ui->updatesButton->setText ("Checking for updates...");
|
|
||||||
|
|
||||||
// If the user changed the text of the versionLineEdit, then change the
|
|
||||||
// application version in the updater too
|
|
||||||
if (!ui->versionLineEdit->text().isEmpty())
|
|
||||||
updater->setApplicationVersion (ui->versionLineEdit->text());
|
|
||||||
|
|
||||||
// If the versionLineEdit is empty, then set the application version
|
|
||||||
// to "0.1"
|
|
||||||
else
|
|
||||||
updater->setApplicationVersion ("0.1");
|
|
||||||
|
|
||||||
// Tell the updater where we should download the changelog, note that
|
|
||||||
// the changelog can be any file you want,
|
|
||||||
// such as an HTML page or (as in this example), a text file
|
|
||||||
updater->setChangelogUrl ("https://raw.githubusercontent.com/alex-97/"
|
|
||||||
"QSimpleUpdater/Files-for-example-project/changelog.txt");
|
|
||||||
|
|
||||||
// Tell the updater where we can find the file that tells us the latest version
|
|
||||||
// of the application
|
|
||||||
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://codeload.github.com/alex-97/QSimpleUpdater/zip/master");
|
|
||||||
|
|
||||||
// Show the progress dialog and show messages when checking is finished
|
|
||||||
updater->setSilent (false);
|
|
||||||
updater->setShowNewestVersionMessage (true);
|
|
||||||
|
|
||||||
// Finally, check for updates...
|
|
||||||
updater->checkForUpdates();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Example::onCheckingFinished()
|
|
||||||
{
|
|
||||||
// Enable the updatesButton and change its text to let the user know
|
|
||||||
// that he/she can check for updates again
|
|
||||||
ui->updatesButton->setEnabled (true);
|
|
||||||
ui->updatesButton->setText ("Check for updates");
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef EXAMPLE_H
|
|
||||||
#define EXAMPLE_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QSimpleUpdater>
|
|
||||||
|
|
||||||
namespace Ui
|
|
||||||
{
|
|
||||||
class Example;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Example : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Example (QWidget *parent = 0);
|
|
||||||
~Example();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void checkForUpdates();
|
|
||||||
void onCheckingFinished();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::Example *ui;
|
|
||||||
|
|
||||||
QString m_installed_version;
|
|
||||||
QSimpleUpdater *updater;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
22
Example/example.pro
Executable file → Normal file
22
Example/example.pro
Executable file → Normal file
@ -1,10 +1,16 @@
|
|||||||
# Include the QSimpleUpdater files
|
#
|
||||||
include($$PWD/../QSimpleUpdater/QSimpleUpdater.pri)
|
# Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
#
|
||||||
|
# This work is free. You can redistribute it and/or modify it under the
|
||||||
|
# terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||||
|
# as published by Sam Hocevar. See the COPYING file for more details.
|
||||||
|
#
|
||||||
|
|
||||||
# Include the QtWidgets module
|
TEMPLATE = app
|
||||||
QT += widgets
|
|
||||||
|
|
||||||
# Define the source code
|
FORMS += $$PWD/src/Window.ui
|
||||||
FORMS += example.ui
|
HEADERS += $$PWD/src/Window.h
|
||||||
HEADERS += example.h
|
SOURCES += $$PWD/src/Window.cpp \
|
||||||
SOURCES += example.cpp
|
$$PWD/src/main.cpp
|
||||||
|
|
||||||
|
include ($$PWD/../QSimpleUpdater.pri)
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Example</class>
|
|
||||||
<widget class="QDialog" name="Example">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>400</width>
|
|
||||||
<height>300</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>QSimpleUpdater Example</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="versionLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Set installed version (latest version is 1.0)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="versionLineEdit">
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>0.1 (default)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="changelogLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Changelog of latest version</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPlainTextEdit" name="changelogTextEdit">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Courier</family>
|
|
||||||
<pointsize>11</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="autoFillBackground">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="undoRedoEnabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="backgroundVisible">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="widget" native="true">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="closeButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Close</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="updatesButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Check for updates</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
95
Example/src/Window.cpp
Normal file
95
Example/src/Window.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
*
|
||||||
|
* This work is free. You can redistribute it and/or modify it under the
|
||||||
|
* terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||||
|
* as published by Sam Hocevar. See the COPYING file for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Window.h"
|
||||||
|
#include "ui_Window.h"
|
||||||
|
|
||||||
|
#include <QSimpleUpdater.h>
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Define the URL of the Update Definitions file
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
static const QString DEFS_URL = "http://pastebin.com/raw/FGs1sTs0";
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Window::Window
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
Window::Window (QWidget* parent) : QMainWindow (parent) {
|
||||||
|
m_ui = new Ui::Window;
|
||||||
|
m_ui->setupUi (this);
|
||||||
|
|
||||||
|
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)));
|
||||||
|
|
||||||
|
/* React to button clicks */
|
||||||
|
connect (m_ui->resetButton, SIGNAL (clicked()),
|
||||||
|
this, SLOT (resetFields()));
|
||||||
|
connect (m_ui->closeButton, SIGNAL (clicked()),
|
||||||
|
this, SLOT (close()));
|
||||||
|
connect (m_ui->checkButton, SIGNAL (clicked()),
|
||||||
|
this, SLOT (checkForUpdates()));
|
||||||
|
|
||||||
|
/* Resize the dialog to fit */
|
||||||
|
setFixedSize (minimumSizeHint());
|
||||||
|
|
||||||
|
/* Reset the UI state */
|
||||||
|
resetFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Window::~Window
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
Window::~Window() {
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Window::checkForUpdates
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Window::resetFields() {
|
||||||
|
m_ui->installedVersion->setText ("0.1");
|
||||||
|
m_ui->enableDownloader->setChecked (true);
|
||||||
|
m_ui->showAllNotifcations->setChecked (false);
|
||||||
|
m_ui->showUpdateNotifications->setChecked (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Window::checkForUpdates
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Window::checkForUpdates() {
|
||||||
|
/* Get settings from the UI */
|
||||||
|
QString version = m_ui->installedVersion->text();
|
||||||
|
bool downloaderEnabled = m_ui->enableDownloader->isChecked();
|
||||||
|
bool notifyOnFinish = m_ui->showAllNotifcations->isChecked();
|
||||||
|
bool notifyOnUpdate = m_ui->showUpdateNotifications->isChecked();
|
||||||
|
|
||||||
|
/* Apply the settings */
|
||||||
|
m_updater->setModuleVersion (DEFS_URL, version);
|
||||||
|
m_updater->setNotifyOnFinish (DEFS_URL, notifyOnFinish);
|
||||||
|
m_updater->setNotifyOnUpdate (DEFS_URL, notifyOnUpdate);
|
||||||
|
m_updater->setDownloaderEnabled (DEFS_URL, downloaderEnabled);
|
||||||
|
|
||||||
|
/* Check for updates */
|
||||||
|
m_updater->checkForUpdates (DEFS_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Window::updateChangelog
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Window::updateChangelog (QString url) {
|
||||||
|
m_ui->changelogText->setText (m_updater->getChangelog (url));
|
||||||
|
}
|
38
Example/src/Window.h
Normal file
38
Example/src/Window.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
*
|
||||||
|
* This work is free. You can redistribute it and/or modify it under the
|
||||||
|
* terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||||
|
* as published by Sam Hocevar. See the COPYING file for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WINDOW_H
|
||||||
|
#define _WINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Window;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QSimpleUpdater;
|
||||||
|
|
||||||
|
class Window : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Window (QWidget* parent = 0);
|
||||||
|
~Window();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void resetFields();
|
||||||
|
void checkForUpdates();
|
||||||
|
void updateChangelog (QString url);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Window* m_ui;
|
||||||
|
QSimpleUpdater* m_updater;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
221
Example/src/Window.ui
Normal file
221
Example/src/Window.ui
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Window</class>
|
||||||
|
<widget class="QMainWindow" name="Window">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>496</width>
|
||||||
|
<height>487</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>QSimpleUpdater Example</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_2">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../../etc/resources/qsimpleupdater.qrc">:/icons/update.png</pixmap>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_3">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string><h1><i>QSimpleUpdater</i></h1></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string><i>A simpler way to update your Qt applications...</i></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Updater Options</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QCheckBox" name="enableDownloader">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable integrated downloader</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="showUpdateNotifications">
|
||||||
|
<property name="text">
|
||||||
|
<string>Notify me when an update is available</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="showAllNotifcations">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show all notifications</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Set installed version (latest version is 1.0)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="installedVersion">
|
||||||
|
<property name="text">
|
||||||
|
<string>0.1</string>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Write a version string...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Changelog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QTextBrowser" name="changelogText">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="html">
|
||||||
|
<string><!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 &quot;Check for Updates&quot; to update this field...</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="resetButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset Fields</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="closeButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="checkButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check for Updates</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../../etc/resources/qsimpleupdater.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
20
Example/src/main.cpp
Normal file
20
Example/src/main.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
*
|
||||||
|
* This work is free. You can redistribute it and/or modify it under the
|
||||||
|
* terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||||
|
* as published by Sam Hocevar. See the COPYING file for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
|
int main (int argc, char** argv) {
|
||||||
|
QApplication app (argc, argv);
|
||||||
|
app.setApplicationVersion ("1.0");
|
||||||
|
app.setApplicationName ("Application");
|
||||||
|
|
||||||
|
Window window;
|
||||||
|
window.show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
47
QSimpleUpdater.pri
Normal file
47
QSimpleUpdater.pri
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
#
|
||||||
|
# This file is part of the QSimpleUpdater library, which is released under
|
||||||
|
# the DBAD license, you can read a copy of it below:
|
||||||
|
#
|
||||||
|
# DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
|
||||||
|
# AND MODIFICATION:
|
||||||
|
#
|
||||||
|
# Do whatever you like with the original work, just don't be a dick.
|
||||||
|
# Being a dick includes - but is not limited to - the following instances:
|
||||||
|
#
|
||||||
|
# 1a. Outright copyright infringement - Don't just copy this and change the
|
||||||
|
# name.
|
||||||
|
# 1b. Selling the unmodified original with no work done what-so-ever, that's
|
||||||
|
# REALLY being a dick.
|
||||||
|
# 1c. Modifying the original work to contain hidden harmful content.
|
||||||
|
# That would make you a PROPER dick.
|
||||||
|
#
|
||||||
|
# If you become rich through modifications, related works/services, or
|
||||||
|
# supporting the original work, share the love.
|
||||||
|
# Only a dick would make loads off this work and not buy the original works
|
||||||
|
# creator(s) a pint.
|
||||||
|
#
|
||||||
|
# Code is provided with no warranty. Using somebody else's code and bitching
|
||||||
|
# when it goes wrong makes you a DONKEY dick.
|
||||||
|
# Fix the problem yourself. A non-dick would submit the fix back.
|
||||||
|
|
||||||
|
QT += gui
|
||||||
|
QT += core
|
||||||
|
QT += network
|
||||||
|
QT += widgets
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/include
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/src/Updater.cpp \
|
||||||
|
$$PWD/src/Downloader.cpp \
|
||||||
|
$$PWD/src/QSimpleUpdater.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/include/QSimpleUpdater.h \
|
||||||
|
$$PWD/src/Updater.h \
|
||||||
|
$$PWD/src/Downloader.h
|
||||||
|
|
||||||
|
FORMS += $$PWD/src/Downloader.ui
|
||||||
|
RESOURCES += $$PWD/etc/resources/qsimpleupdater.qrc
|
31
QSimpleUpdater.pro
Normal file
31
QSimpleUpdater.pro
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
#
|
||||||
|
# This file is part of the QSimpleUpdater library, which is released under
|
||||||
|
# the DBAD license, you can read a copy of it below:
|
||||||
|
#
|
||||||
|
# DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
|
||||||
|
# AND MODIFICATION:
|
||||||
|
#
|
||||||
|
# Do whatever you like with the original work, just don't be a dick.
|
||||||
|
# Being a dick includes - but is not limited to - the following instances:
|
||||||
|
#
|
||||||
|
# 1a. Outright copyright infringement - Don't just copy this and change the
|
||||||
|
# name.
|
||||||
|
# 1b. Selling the unmodified original with no work done what-so-ever, that's
|
||||||
|
# REALLY being a dick.
|
||||||
|
# 1c. Modifying the original work to contain hidden harmful content.
|
||||||
|
# That would make you a PROPER dick.
|
||||||
|
#
|
||||||
|
# If you become rich through modifications, related works/services, or
|
||||||
|
# supporting the original work, share the love.
|
||||||
|
# Only a dick would make loads off this work and not buy the original works
|
||||||
|
# creator(s) a pint.
|
||||||
|
#
|
||||||
|
# Code is provided with no warranty. Using somebody else's code and bitching
|
||||||
|
# when it goes wrong makes you a DONKEY dick.
|
||||||
|
# Fix the problem yourself. A non-dick would submit the fix back.
|
||||||
|
|
||||||
|
TEMPLATE = lib
|
||||||
|
DEFINES += QSU_SHARED
|
||||||
|
include ($$PWD/QSimpleUpdater.pri)
|
@ -1,14 +0,0 @@
|
|||||||
# Project info
|
|
||||||
project = QSimpleUpdater
|
|
||||||
url = http://qsimpleupdater.sf.net/doc
|
|
||||||
description = A simple auto-updating system for Qt projects
|
|
||||||
|
|
||||||
# Import sources and headers
|
|
||||||
headerdirs = ../src
|
|
||||||
sourcedirs = ../src
|
|
||||||
sources.fileextensions = "*.cpp *.qdoc *.mm *.qml"
|
|
||||||
headers.fileextensions = "*.h *.ch *.h++ *.hh *.hpp *.hxx"
|
|
||||||
|
|
||||||
# Output as HTML
|
|
||||||
outputdir = doc-html
|
|
||||||
outputformats = HTML
|
|
@ -1,165 +0,0 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
@ -1,36 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is part of QSimpleUpdater
|
|
||||||
#
|
|
||||||
# Copyright (c) 2014 Alex Spataru <alex_spataru@outlook.com>
|
|
||||||
#
|
|
||||||
# Please check the license.txt file for more information.
|
|
||||||
#
|
|
||||||
|
|
||||||
QT += gui
|
|
||||||
QT += widgets
|
|
||||||
QT += network
|
|
||||||
|
|
||||||
HEADERS += $$PWD/src/qsimpleupdater.h \
|
|
||||||
$$PWD/src/dialogs/download_dialog.h \
|
|
||||||
$$PWD/src/dialogs/progress_dialog.h
|
|
||||||
|
|
||||||
SOURCES += $$PWD/src/qsimpleupdater.cpp \
|
|
||||||
$$PWD/src/dialogs/download_dialog.cpp \
|
|
||||||
$$PWD/src/dialogs/progress_dialog.cpp
|
|
||||||
|
|
||||||
OTHER_FILES += $$PWD/src/QSimpleUpdater
|
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/src
|
|
||||||
|
|
||||||
unix:!android {
|
|
||||||
LIBS += -lcrypto -lssl
|
|
||||||
}
|
|
||||||
|
|
||||||
win32* {
|
|
||||||
LIBS += -LC:/OpenSSL-Win32/lib -llibeay32
|
|
||||||
}
|
|
||||||
|
|
||||||
RESOURCES += $$PWD/res/qsu_resources.qrc
|
|
||||||
|
|
||||||
FORMS += $$PWD/src/dialogs/download_dialog.ui \
|
|
||||||
$$PWD/src/dialogs/progress_dialog.ui
|
|
@ -1 +0,0 @@
|
|||||||
#include "qsimpleupdater.h"
|
|
@ -1,271 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C) Copyright 2014 Alex Spataru
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the GNU Lesser General Public License
|
|
||||||
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
|
||||||
* http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "download_dialog.h"
|
|
||||||
#include "ui_download_dialog.h"
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
|
|
||||||
DownloadDialog::DownloadDialog (QWidget *parent)
|
|
||||||
: QWidget (parent)
|
|
||||||
, ui (new Ui::DownloadDialog)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Setup the UI
|
|
||||||
ui->setupUi (this);
|
|
||||||
|
|
||||||
// Make the window look like a dialog
|
|
||||||
QIcon _blank;
|
|
||||||
setWindowIcon (_blank);
|
|
||||||
setWindowModality (Qt::WindowModal);
|
|
||||||
setWindowFlags (Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
|
|
||||||
|
|
||||||
// Connect SIGNALS/SLOTS
|
|
||||||
connect (ui->stopButton, SIGNAL (clicked()), this, SLOT (cancelDownload()));
|
|
||||||
connect (ui->openButton, SIGNAL (clicked()), this, SLOT (installUpdate()));
|
|
||||||
|
|
||||||
// Configure open button
|
|
||||||
ui->openButton->setEnabled (false);
|
|
||||||
ui->openButton->setVisible (false);
|
|
||||||
|
|
||||||
// Initialize the network access manager
|
|
||||||
m_manager = new QNetworkAccessManager (this);
|
|
||||||
|
|
||||||
// Avoid SSL issues
|
|
||||||
connect (m_manager, SIGNAL (sslErrors (QNetworkReply *, QList<QSslError>)), this,
|
|
||||||
SLOT (ignoreSslErrors (QNetworkReply *, QList<QSslError>)));
|
|
||||||
}
|
|
||||||
|
|
||||||
DownloadDialog::~DownloadDialog (void)
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DownloadDialog::beginDownload (const QUrl& url)
|
|
||||||
{
|
|
||||||
Q_ASSERT (!url.isEmpty());
|
|
||||||
|
|
||||||
// Reset the UI
|
|
||||||
ui->progressBar->setValue (0);
|
|
||||||
ui->stopButton->setText (tr ("Stop"));
|
|
||||||
ui->downloadLabel->setText (tr ("Downloading updates"));
|
|
||||||
ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("unknown"));
|
|
||||||
|
|
||||||
// Begin the download
|
|
||||||
m_reply = m_manager->get (QNetworkRequest (url));
|
|
||||||
m_start_time = QDateTime::currentDateTime().toTime_t();
|
|
||||||
|
|
||||||
// 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::installUpdate (void)
|
|
||||||
{
|
|
||||||
QMessageBox msg;
|
|
||||||
msg.setIcon (QMessageBox::Question);
|
|
||||||
msg.setText ("<b>" +
|
|
||||||
tr ("To apply the update(s), you must first quit %1")
|
|
||||||
.arg (qApp->applicationName()) +
|
|
||||||
"</b>");
|
|
||||||
msg.setInformativeText (tr ("Do you want to quit %1 now?").arg (qApp->applicationName()));
|
|
||||||
msg.setStandardButtons (QMessageBox::Yes | QMessageBox::No);
|
|
||||||
|
|
||||||
if (msg.exec() == QMessageBox::Yes)
|
|
||||||
{
|
|
||||||
openDownload();
|
|
||||||
qApp->closeAllWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->openButton->setEnabled (true);
|
|
||||||
ui->openButton->setVisible (true);
|
|
||||||
ui->timeLabel->setText (tr ("Click the \"Open\" button to apply the update"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DownloadDialog::openDownload (void)
|
|
||||||
{
|
|
||||||
if (!m_path.isEmpty())
|
|
||||||
{
|
|
||||||
QString url = m_path;
|
|
||||||
|
|
||||||
if (url.startsWith ("/"))
|
|
||||||
url = "file://" + url;
|
|
||||||
|
|
||||||
else
|
|
||||||
url = "file:///" + url;
|
|
||||||
|
|
||||||
QDesktopServices::openUrl (url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DownloadDialog::cancelDownload (void)
|
|
||||||
{
|
|
||||||
if (!m_reply->isFinished())
|
|
||||||
{
|
|
||||||
QMessageBox _message;
|
|
||||||
_message.setWindowTitle (tr ("Updater"));
|
|
||||||
_message.setIcon (QMessageBox::Question);
|
|
||||||
_message.setStandardButtons (QMessageBox::Yes | QMessageBox::No);
|
|
||||||
_message.setText (tr ("Are you sure you want to cancel the download?"));
|
|
||||||
|
|
||||||
if (_message.exec() == QMessageBox::Yes)
|
|
||||||
{
|
|
||||||
hide();
|
|
||||||
m_reply->abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DownloadDialog::downloadFinished (void)
|
|
||||||
{
|
|
||||||
ui->stopButton->setText (tr ("Close"));
|
|
||||||
ui->downloadLabel->setText (tr ("Download complete!"));
|
|
||||||
ui->timeLabel->setText (tr ("The installer will open in a separate window..."));
|
|
||||||
|
|
||||||
QByteArray data = m_reply->readAll();
|
|
||||||
|
|
||||||
if (!data.isEmpty())
|
|
||||||
{
|
|
||||||
QStringList list = m_reply->url().toString().split ("/");
|
|
||||||
QFile file (QDir::tempPath() + "/" + list.at (list.count() - 1));
|
|
||||||
QMutex _mutex;
|
|
||||||
|
|
||||||
if (file.open (QIODevice::WriteOnly))
|
|
||||||
{
|
|
||||||
_mutex.lock();
|
|
||||||
file.write (data);
|
|
||||||
m_path = file.fileName();
|
|
||||||
file.close();
|
|
||||||
_mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
installUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DownloadDialog::updateProgress (qint64 received, qint64 total)
|
|
||||||
{
|
|
||||||
// We know the size of the download, so we can calculate the progress....
|
|
||||||
if (total > 0 && received > 0)
|
|
||||||
{
|
|
||||||
ui->progressBar->setMinimum (0);
|
|
||||||
ui->progressBar->setMaximum (100);
|
|
||||||
|
|
||||||
int _progress = (int) ((received * 100) / total);
|
|
||||||
ui->progressBar->setValue (_progress);
|
|
||||||
|
|
||||||
QString _total_string;
|
|
||||||
QString _received_string;
|
|
||||||
|
|
||||||
float _total = total;
|
|
||||||
float _received = received;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->downloadLabel->setText (tr ("Downloading updates") + " (" + _received_string + " " + tr ("of") + " " + _total_string + ")");
|
|
||||||
|
|
||||||
uint _diff = QDateTime::currentDateTime().toTime_t() - m_start_time;
|
|
||||||
|
|
||||||
if (_diff > 0)
|
|
||||||
{
|
|
||||||
QString _time_string;
|
|
||||||
float _time_remaining = total / (received / _diff);
|
|
||||||
|
|
||||||
if (_time_remaining > 7200)
|
|
||||||
{
|
|
||||||
_time_remaining /= 3600;
|
|
||||||
_time_string = tr ("About %1 hours").arg (int (_time_remaining + 0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (_time_remaining > 60)
|
|
||||||
{
|
|
||||||
_time_remaining /= 60;
|
|
||||||
_time_string = tr ("About %1 minutes").arg (int (_time_remaining + 0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (_time_remaining <= 60)
|
|
||||||
_time_string = tr ("%1 seconds").arg (int (_time_remaining + 0.5));
|
|
||||||
|
|
||||||
ui->timeLabel->setText (tr ("Time remaining") + ": " + _time_string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do not know the size of the download, so we avoid scaring the shit out
|
|
||||||
// of the user
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->progressBar->setValue (-1);
|
|
||||||
ui->progressBar->setMinimum (0);
|
|
||||||
ui->progressBar->setMaximum (0);
|
|
||||||
ui->downloadLabel->setText (tr ("Downloading updates"));
|
|
||||||
ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("Unknown"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DownloadDialog::ignoreSslErrors (QNetworkReply *reply,
|
|
||||||
const QList<QSslError>& error)
|
|
||||||
{
|
|
||||||
#ifndef Q_OS_IOS
|
|
||||||
reply->ignoreSslErrors (error);
|
|
||||||
#else
|
|
||||||
Q_UNUSED (reply);
|
|
||||||
Q_UNUSED (error);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
float DownloadDialog::roundNumber (const float& input)
|
|
||||||
{
|
|
||||||
return roundf (input * 100) / 100;
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C) Copyright 2014 Alex Spataru
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the GNU Lesser General Public License
|
|
||||||
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
|
||||||
* http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DOWNLOAD_DIALOG_H
|
|
||||||
#define DOWNLOAD_DIALOG_H
|
|
||||||
|
|
||||||
#include <QDir>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
namespace Ui
|
|
||||||
{
|
|
||||||
class DownloadDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DownloadDialog : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit DownloadDialog (QWidget *parent = 0);
|
|
||||||
~DownloadDialog (void);
|
|
||||||
|
|
||||||
void beginDownload (const QUrl& url);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void openDownload (void);
|
|
||||||
void installUpdate (void);
|
|
||||||
void cancelDownload (void);
|
|
||||||
void downloadFinished (void);
|
|
||||||
void updateProgress (qint64 received, qint64 total);
|
|
||||||
void ignoreSslErrors (QNetworkReply *reply, const QList<QSslError>& error);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::DownloadDialog *ui;
|
|
||||||
|
|
||||||
QString m_path;
|
|
||||||
bool m_download_paused;
|
|
||||||
|
|
||||||
QNetworkReply *m_reply;
|
|
||||||
QNetworkAccessManager *m_manager;
|
|
||||||
|
|
||||||
uint m_start_time;
|
|
||||||
|
|
||||||
float roundNumber (const float& input);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because one or more lines are too long
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C) Copyright 2014 Alex Spataru
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the GNU Lesser General Public License
|
|
||||||
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
|
||||||
* http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "progress_dialog.h"
|
|
||||||
#include "ui_progress_dialog.h"
|
|
||||||
|
|
||||||
ProgressDialog::ProgressDialog (QWidget *parent) : QDialog (parent), ui (new Ui::ProgressDialog)
|
|
||||||
{
|
|
||||||
// Create and configure UI
|
|
||||||
ui->setupUi (this);
|
|
||||||
|
|
||||||
// Make the window look like a dialog
|
|
||||||
QIcon _blank;
|
|
||||||
setWindowIcon (_blank);
|
|
||||||
setWindowModality (Qt::WindowModal);
|
|
||||||
setWindowFlags (Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
|
|
||||||
|
|
||||||
// Close dialog when cancel button is clicked
|
|
||||||
connect (ui->ui_cancel_button, SIGNAL (clicked()), this, SLOT (cancel()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressDialog::~ProgressDialog()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProgressDialog::cancel (void)
|
|
||||||
{
|
|
||||||
hide();
|
|
||||||
emit cancelClicked();
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C) Copyright 2014 Alex Spataru
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the GNU Lesser General Public License
|
|
||||||
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
|
||||||
* http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PROGRESS_DIALOG_H
|
|
||||||
#define PROGRESS_DIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
namespace Ui
|
|
||||||
{
|
|
||||||
class ProgressDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProgressDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ProgressDialog (QWidget *parent = 0);
|
|
||||||
~ProgressDialog();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void cancelClicked();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void cancel (void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::ProgressDialog *ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PROGRESS_DIALOG_H
|
|
@ -1,121 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>ProgressDialog</class>
|
|
||||||
<widget class="QDialog" name="ProgressDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>410</width>
|
|
||||||
<height>152</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Software Updater</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetMinimumSize</enum>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="ui_icon">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="pixmap">
|
|
||||||
<pixmap resource="../../res/qsu_resources.qrc">:/icons/update.png</pixmap>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="widget" native="true">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="ui_progress_bar">
|
|
||||||
<property name="text">
|
|
||||||
<string>Checking for updates...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QProgressBar" name="progressBar">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>250</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
<property name="invertedAppearance">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="button_widget" native="true">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="ui_cancel_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cancel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources>
|
|
||||||
<include location="../../res/qsu_resources.qrc"/>
|
|
||||||
</resources>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
@ -1,520 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C) Copyright 2014 Alex Spataru
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the GNU Lesser General Public License
|
|
||||||
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
|
||||||
* http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*! \class QSimpleUpdater
|
|
||||||
* \brief A simple auto-updater system for Qt
|
|
||||||
*
|
|
||||||
* QSimpleUpdater is an implementation of an auto-updating system to be used with Qt projects.
|
|
||||||
* Aside from notifying you if there's a newer version, it allows you to download the change log in any
|
|
||||||
* format (such as HTML or RTF) and download the updates directly from your application using a dialog.
|
|
||||||
* QSimpleUpdater is free and open source LGPL software,
|
|
||||||
* which means that you can use it for both open source and proprietary applications.
|
|
||||||
*
|
|
||||||
* \chapter Installation
|
|
||||||
*
|
|
||||||
* \list
|
|
||||||
* \o Copy the QSimpleUpdater folder in your "3rd-party" folder.
|
|
||||||
* \o Include the QSimpleUpdater project include (pri) file using the include() function.
|
|
||||||
* \o That's all! Check the example project as a reference for your project.
|
|
||||||
* \endlist
|
|
||||||
*
|
|
||||||
* \chapter Running the example project
|
|
||||||
*
|
|
||||||
* \list
|
|
||||||
* \o Navigate to the Example folder and open example.pro with Qt Creator.
|
|
||||||
* \o Compile the project and play with it :)
|
|
||||||
* \endlist
|
|
||||||
*
|
|
||||||
* \chapter Warnings
|
|
||||||
* Many websites today use the HTTP Secure protocol, which means that you will need SSL
|
|
||||||
* in order to communicate with them.
|
|
||||||
* If your project needs to access such a webiste (for example GitHub),
|
|
||||||
* you will need to carefully read the following information in order to ensure that
|
|
||||||
* QSimpleUpdater works with those websites (both in your machine and in the final users' machine).
|
|
||||||
*
|
|
||||||
* This section is extremely important for any developers wishing to deploy their applications under
|
|
||||||
* the Windows platform, because the application will depend on the OpenSSL libaries in order to work.
|
|
||||||
*
|
|
||||||
* \bold {Linux}
|
|
||||||
*
|
|
||||||
* Make sure that you have installed the following libraries in your system:
|
|
||||||
*
|
|
||||||
* \list
|
|
||||||
* \o lssl
|
|
||||||
* \o lcrypto
|
|
||||||
* \endlist
|
|
||||||
*
|
|
||||||
* \bold {Mac OS X}
|
|
||||||
*
|
|
||||||
* The libraries required by QSimpleUpdater are the same as Linux, however, these libraries
|
|
||||||
* are installed by default in most Mac OS X installations.
|
|
||||||
*
|
|
||||||
* \bold {Microsoft Windows}
|
|
||||||
*
|
|
||||||
* QSimpleUpdater makes use of the OpenSSL-Win32 project, make sure that have it installed
|
|
||||||
* and that the project knows where to find them (the default location is C:/OpenSSL-Win32).
|
|
||||||
* Finally, deploy the following libraries with your compiled project:
|
|
||||||
*
|
|
||||||
* \list
|
|
||||||
* \o libeay32.dll
|
|
||||||
* \o ssleay32.dll
|
|
||||||
* \endlist
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*! \fn QSimpleUpdater::checkingFinished (void)
|
|
||||||
* This signal is triggered when the updater system finishes downloading
|
|
||||||
* and proccessing the version data and changelog data.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qsimpleupdater.h"
|
|
||||||
|
|
||||||
/*! \internal
|
|
||||||
* Initializes and configures the class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
QSimpleUpdater::QSimpleUpdater (QObject *parent)
|
|
||||||
: QObject (parent)
|
|
||||||
, m_silent (false)
|
|
||||||
, m_show_newest_version (true)
|
|
||||||
, m_show_update_available (true)
|
|
||||||
, m_new_version_available (false)
|
|
||||||
{
|
|
||||||
|
|
||||||
m_progressDialog = new ProgressDialog();
|
|
||||||
m_downloadDialog = new DownloadDialog();
|
|
||||||
|
|
||||||
m_manager = new QNetworkAccessManager (this);
|
|
||||||
connect (m_manager, SIGNAL (finished (QNetworkReply *)), this,
|
|
||||||
SLOT (checkDownloadedVersion (QNetworkReply *)));
|
|
||||||
connect (m_manager, SIGNAL (sslErrors (QNetworkReply *, QList<QSslError>)),
|
|
||||||
this, SLOT (ignoreSslErrors (QNetworkReply *, QList<QSslError>)));
|
|
||||||
|
|
||||||
connect (m_progressDialog, SIGNAL (cancelClicked()), this, SLOT (cancel()));
|
|
||||||
connect (this, SIGNAL (checkingFinished()), this, SLOT (onCheckingFinished()));
|
|
||||||
|
|
||||||
setApplicationVersion (qApp->applicationVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the downloaded change log as a \c QString.
|
|
||||||
*
|
|
||||||
* \sa setChangelogUrl()
|
|
||||||
*/
|
|
||||||
|
|
||||||
QString QSimpleUpdater::changeLog() const
|
|
||||||
{
|
|
||||||
return m_changelog;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Checks for updates and calls the appropiate functions
|
|
||||||
* when finished.
|
|
||||||
*
|
|
||||||
* \sa setDownloadUrl(), setReferenceUrl()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::checkForUpdates (void)
|
|
||||||
{
|
|
||||||
if (!m_reference_url.isEmpty())
|
|
||||||
{
|
|
||||||
m_manager->get (QNetworkRequest (m_reference_url));
|
|
||||||
|
|
||||||
if (!silent())
|
|
||||||
m_progressDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
qDebug() << "QSimpleUpdater: Invalid reference URL";
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Opens the download link in a web browser.
|
|
||||||
*
|
|
||||||
* \sa setDownloadUrl()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::openDownloadLink (void)
|
|
||||||
{
|
|
||||||
if (!m_download_url.isEmpty())
|
|
||||||
QDesktopServices::openUrl (m_download_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the latest version as a \c QString.
|
|
||||||
*
|
|
||||||
* \sa setReferenceUrl(), checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
QString QSimpleUpdater::latestVersion() const
|
|
||||||
{
|
|
||||||
return m_latest_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the local version of the application.
|
|
||||||
*
|
|
||||||
* \sa setApplicationVersion()
|
|
||||||
*/
|
|
||||||
|
|
||||||
QString QSimpleUpdater::installedVersion() const
|
|
||||||
{
|
|
||||||
return m_installed_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Downloads the latest version of the application
|
|
||||||
* and displays download info in a dialog.
|
|
||||||
*
|
|
||||||
* \sa setDownloadUrl(), checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::downloadLatestVersion (void)
|
|
||||||
{
|
|
||||||
if (!m_download_url.isEmpty())
|
|
||||||
m_downloadDialog->beginDownload (m_download_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns \c true if the system detected that there is
|
|
||||||
* a newer version of the application available online.
|
|
||||||
*
|
|
||||||
* \sa setReferenceUrl(), checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool QSimpleUpdater::newerVersionAvailable() const
|
|
||||||
{
|
|
||||||
return m_new_version_available;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns \c true if the system is set to
|
|
||||||
* hide the progress dialog.
|
|
||||||
*
|
|
||||||
* \sa setSilent()
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool QSimpleUpdater::silent() const
|
|
||||||
{
|
|
||||||
return m_silent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Tells the system from where to download the update packages
|
|
||||||
* with the \a url parameter.
|
|
||||||
*
|
|
||||||
* Its recommended to use fixed URLs if you
|
|
||||||
* want to automatically download and install your updates using
|
|
||||||
* the bundled download dialog.
|
|
||||||
*
|
|
||||||
* \sa downloadLatestVersion(), openDownloadLink()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::setDownloadUrl (const QString& url)
|
|
||||||
{
|
|
||||||
Q_ASSERT (!url.isEmpty());
|
|
||||||
m_download_url.setUrl (url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Tells the updater system from where to download the file
|
|
||||||
* that indicates the latest version using the \a url parameter.
|
|
||||||
*
|
|
||||||
* The reference file should contain \bold {ONLY} the latest version
|
|
||||||
* in a plain text format. For example:
|
|
||||||
*
|
|
||||||
* \list
|
|
||||||
* \o 1
|
|
||||||
* \o 0.1
|
|
||||||
* \o 1.0.1
|
|
||||||
* \o 2.2.12
|
|
||||||
* \o etc
|
|
||||||
* \endlist
|
|
||||||
*
|
|
||||||
* \sa latestVersion()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::setReferenceUrl (const QString& url)
|
|
||||||
{
|
|
||||||
Q_ASSERT (!url.isEmpty());
|
|
||||||
m_reference_url.setUrl (url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Tells the updater system from where to download the
|
|
||||||
* change log using the \a url parameter.
|
|
||||||
* The change log can be any file you like, however,
|
|
||||||
* its recommended to write it in plain text,
|
|
||||||
* such as TXT, HTML and RTF files.
|
|
||||||
*
|
|
||||||
* \sa changeLog()
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void QSimpleUpdater::setChangelogUrl (const QString& url)
|
|
||||||
{
|
|
||||||
Q_ASSERT (!url.isEmpty());
|
|
||||||
m_changelog_url.setUrl (url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Tells the updater the version of the installed
|
|
||||||
* copy of your application using the \a version parameter.
|
|
||||||
*
|
|
||||||
* Calling this function is optional, as the default
|
|
||||||
* values are loaded from QApplication class.
|
|
||||||
*
|
|
||||||
* \sa installedVersion(), checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void QSimpleUpdater::setApplicationVersion (const QString& version)
|
|
||||||
{
|
|
||||||
Q_ASSERT (!version.isEmpty());
|
|
||||||
m_installed_version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
*
|
|
||||||
* \list
|
|
||||||
* \o If \a silent is set to \c true, no dialogs will be shown while checking
|
|
||||||
* for updates or when a newer version of the application is found.
|
|
||||||
* \o If \a silent is set to \c false, a dialog will be shown while checking for
|
|
||||||
* updates or when a newer version of the application is found.
|
|
||||||
* \endlist
|
|
||||||
*
|
|
||||||
* \sa silent()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::setSilent (bool silent)
|
|
||||||
{
|
|
||||||
m_silent = silent;
|
|
||||||
|
|
||||||
if (m_silent)
|
|
||||||
setShowNewestVersionMessage (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* If the \a show parameter is set to \c true, the updater system will show a
|
|
||||||
* message box notifying the user when there's an update available.
|
|
||||||
*
|
|
||||||
* \sa checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::setShowUpdateAvailableMessage (bool show)
|
|
||||||
{
|
|
||||||
m_show_update_available = show;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* If the \a show parameter is set to \c true, the updater system will show a
|
|
||||||
* message box notifying the user when the latest version is already installed.
|
|
||||||
*
|
|
||||||
* For example, this configuration is useful when the user manually calls this function.
|
|
||||||
* \i {Eg:} when he or she clicks the "Check for updates" menu item.
|
|
||||||
*
|
|
||||||
* \sa checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::setShowNewestVersionMessage (bool show)
|
|
||||||
{
|
|
||||||
m_show_newest_version = show;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \internal
|
|
||||||
* Disconnects the network access manager when the user
|
|
||||||
* clicks on the "cancel" button in the progress dialog.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::cancel (void)
|
|
||||||
{
|
|
||||||
m_manager->disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \internal
|
|
||||||
* Alerts the user when the download of version information
|
|
||||||
* data is corrupted.
|
|
||||||
*
|
|
||||||
* \sa checkDownloadedVersion()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::showErrorMessage (void)
|
|
||||||
{
|
|
||||||
if (!silent())
|
|
||||||
{
|
|
||||||
m_progressDialog->hide();
|
|
||||||
QMessageBox::warning (NULL, tr ("Software Updater"),
|
|
||||||
tr ("An unknown error occured while checking for updates"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \internal
|
|
||||||
* Informs the user if there's a newer version available for download
|
|
||||||
* or if he or she is running the latest version of the application.
|
|
||||||
*
|
|
||||||
* \sa checkDownloadedVersion()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::onCheckingFinished (void)
|
|
||||||
{
|
|
||||||
// Hide the progress dialog
|
|
||||||
m_progressDialog->hide();
|
|
||||||
|
|
||||||
// Get the application icon as a pixmap
|
|
||||||
QPixmap _icon = qApp->windowIcon().pixmap (
|
|
||||||
qApp->windowIcon().actualSize (QSize (96, 96)));
|
|
||||||
|
|
||||||
// If the icon is invalid, use default icon
|
|
||||||
if (_icon.isNull())
|
|
||||||
_icon = QPixmap (":/icons/update.png");
|
|
||||||
|
|
||||||
QMessageBox _message;
|
|
||||||
_message.setIconPixmap (_icon);
|
|
||||||
|
|
||||||
// Ask user if he/she wants to download newer version
|
|
||||||
if (newerVersionAvailable() && m_show_update_available)
|
|
||||||
{
|
|
||||||
_message.setDetailedText (changeLog());
|
|
||||||
_message.setStandardButtons (QMessageBox::Yes | QMessageBox::No);
|
|
||||||
_message.setText ("<b>" + tr ("A new version of %1 is available!").arg (qApp->applicationName()) + "</b>");
|
|
||||||
_message.setInformativeText (tr ("%1 %2 is available - you have %3. Would you like to download it now?")
|
|
||||||
.arg (qApp->applicationName())
|
|
||||||
.arg (latestVersion())
|
|
||||||
.arg (installedVersion()));
|
|
||||||
|
|
||||||
if (_message.exec() == QMessageBox::Yes)
|
|
||||||
downloadLatestVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell user that he/she is up to date (only if necessary)
|
|
||||||
else if (!silent() && m_show_newest_version && !m_latest_version.isEmpty())
|
|
||||||
{
|
|
||||||
_message.setStandardButtons (QMessageBox::Ok);
|
|
||||||
_message.setText ("<b>" + tr ("You're up-to-date!") +
|
|
||||||
" </b>");
|
|
||||||
_message.setInformativeText (
|
|
||||||
tr ("%1 %2 is currently the newest version available")
|
|
||||||
.arg (qApp->applicationName())
|
|
||||||
.arg (installedVersion()));
|
|
||||||
|
|
||||||
_message.exec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \internal
|
|
||||||
* Compares downloaded version information with local version information
|
|
||||||
* and decides if there's a newer version available.
|
|
||||||
*
|
|
||||||
* Finally, the function downloads the changelog if there's a newer version
|
|
||||||
* available online.
|
|
||||||
*
|
|
||||||
* \sa checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::checkDownloadedVersion (QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
bool _new_update = false;
|
|
||||||
|
|
||||||
QString _reply = QString::fromUtf8 (reply->readAll());
|
|
||||||
_reply.replace (" ", "");
|
|
||||||
_reply.replace ("\n", "");
|
|
||||||
|
|
||||||
if (!_reply.isEmpty())
|
|
||||||
{
|
|
||||||
m_latest_version = _reply;
|
|
||||||
|
|
||||||
QStringList _download = m_latest_version.split (".");
|
|
||||||
QStringList _installed = m_installed_version.split (".");
|
|
||||||
|
|
||||||
for (int i = 0; i <= _download.count() - 1; ++i)
|
|
||||||
{
|
|
||||||
if (_download.count() - 1 >= i && _installed.count() - 1 >= i)
|
|
||||||
{
|
|
||||||
if (_download.at (i) > _installed.at (i))
|
|
||||||
{
|
|
||||||
_new_update = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_installed.count() < _download.count())
|
|
||||||
{
|
|
||||||
if (_installed.at (i - 1) == _download.at (i - 1))
|
|
||||||
break;
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_new_update = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
showErrorMessage();
|
|
||||||
|
|
||||||
m_new_version_available = _new_update;
|
|
||||||
|
|
||||||
if (!m_changelog_url.isEmpty() && newerVersionAvailable())
|
|
||||||
{
|
|
||||||
QNetworkAccessManager *_manager = new QNetworkAccessManager (this);
|
|
||||||
|
|
||||||
connect (_manager, SIGNAL (finished (QNetworkReply *)), this,
|
|
||||||
SLOT (processDownloadedChangelog (QNetworkReply *)));
|
|
||||||
|
|
||||||
connect (_manager, SIGNAL (sslErrors (QNetworkReply *, QList<QSslError>)),
|
|
||||||
this, SLOT (ignoreSslErrors (QNetworkReply *, QList<QSslError>)));
|
|
||||||
|
|
||||||
_manager->get (QNetworkRequest (m_changelog_url));
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
emit checkingFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \internal
|
|
||||||
* Reads the downloaded changelog data and transforms it into a QString.
|
|
||||||
*
|
|
||||||
* \sa setChangelogUrl(), changeLog()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::processDownloadedChangelog (QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
QString _reply = QString::fromUtf8 (reply->readAll());
|
|
||||||
|
|
||||||
if (!_reply.isEmpty())
|
|
||||||
m_changelog = _reply;
|
|
||||||
|
|
||||||
emit checkingFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \internal
|
|
||||||
* Allows the download process to continue even if there are SSL errors.
|
|
||||||
*
|
|
||||||
* \sa checkForUpdates()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void QSimpleUpdater::ignoreSslErrors (QNetworkReply *reply,
|
|
||||||
const QList<QSslError>& error)
|
|
||||||
{
|
|
||||||
#if SUPPORTS_SSL
|
|
||||||
reply->ignoreSslErrors (error);
|
|
||||||
#else
|
|
||||||
Q_UNUSED (reply);
|
|
||||||
Q_UNUSED (error);
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C) Copyright 2014 Alex Spataru
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the GNU Lesser General Public License
|
|
||||||
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
|
||||||
* http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef Q_SIMPLE_UPDATER_H
|
|
||||||
#define Q_SIMPLE_UPDATER_H
|
|
||||||
|
|
||||||
#define SUPPORTS_SSL !defined(Q_OS_IOS)
|
|
||||||
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
|
|
||||||
#if SUPPORTS_SSL
|
|
||||||
#include <QSsl>
|
|
||||||
#include <QSslError>
|
|
||||||
#include <QSslConfiguration>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "dialogs/download_dialog.h"
|
|
||||||
#include "dialogs/progress_dialog.h"
|
|
||||||
|
|
||||||
class QSimpleUpdater : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
QSimpleUpdater (QObject *parent = 0);
|
|
||||||
|
|
||||||
QString changeLog() const;
|
|
||||||
QString latestVersion() const;
|
|
||||||
QString installedVersion() const;
|
|
||||||
|
|
||||||
bool silent() const;
|
|
||||||
bool newerVersionAvailable() const;
|
|
||||||
|
|
||||||
void checkForUpdates (void);
|
|
||||||
void openDownloadLink (void);
|
|
||||||
void downloadLatestVersion (void);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setSilent (bool silent);
|
|
||||||
void setDownloadUrl (const QString& url);
|
|
||||||
void setReferenceUrl (const QString& url);
|
|
||||||
void setChangelogUrl (const QString& url);
|
|
||||||
void setShowNewestVersionMessage (bool show);
|
|
||||||
void setShowUpdateAvailableMessage (bool show);
|
|
||||||
void setApplicationVersion (const QString& version);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void checkingFinished (void);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void cancel (void);
|
|
||||||
void showErrorMessage (void);
|
|
||||||
void onCheckingFinished (void);
|
|
||||||
void checkDownloadedVersion (QNetworkReply *reply);
|
|
||||||
void processDownloadedChangelog (QNetworkReply *reply);
|
|
||||||
void ignoreSslErrors (QNetworkReply *reply, const QList<QSslError>& error);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_changelog;
|
|
||||||
QString m_latest_version;
|
|
||||||
QString m_installed_version;
|
|
||||||
QNetworkAccessManager *m_manager;
|
|
||||||
|
|
||||||
QUrl m_download_url;
|
|
||||||
QUrl m_reference_url;
|
|
||||||
QUrl m_changelog_url;
|
|
||||||
|
|
||||||
bool m_silent;
|
|
||||||
bool m_show_newest_version;
|
|
||||||
bool m_show_update_available;
|
|
||||||
bool m_new_version_available;
|
|
||||||
|
|
||||||
DownloadDialog *m_downloadDialog;
|
|
||||||
ProgressDialog *m_progressDialog;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
69
Readme.md
Executable file → Normal file
69
Readme.md
Executable file → Normal file
@ -1,59 +1,10 @@
|
|||||||
## QSimpleUpdater
|
# QSimpleUpdater
|
||||||
|
QSimpleUpdater is an implementation of an auto-updating system to be used with Qt projects.
|
||||||
[![OpenHub](https://www.openhub.net/p/qsimpleupdater/widgets/project_thin_badge.gif)](http://openhub.net/p/qsimpleupdater)
|
|
||||||
|
## Integrating QSimpleUpdater with your projects
|
||||||
QSimpleUpdater is an implementation of an auto-updating system to be used with Qt projects.
|
1. Copy the QSimpleUpdater folder in your "3rd-party" folder.
|
||||||
|
2. Include the QSimpleUpdater project include (*pri*) file using the include() function.
|
||||||
QSimpleUpdater is **free and open source [LGPL software](https://www.gnu.org/licenses/lgpl.html)**, which means that you can use it for both open source and proprietary applications.
|
3. That's all! Check the example project as a reference for your project.
|
||||||
|
|
||||||
## Developer Documentation
|
## License
|
||||||
|
QSimpleUpdater is free and open-source software, it is released under the [DBAD](COPYING.md) license.
|
||||||
You can find the developer documentation for QSimpleUpdater [here](http://qsimpleupdater.sourceforge.net/doc/).
|
|
||||||
|
|
||||||
## Using QSimpleUpdater
|
|
||||||
|
|
||||||
1. Copy the *QSimpleUpdater* folder in your "3rd-party" folder.
|
|
||||||
2. Include the QSimpleUpdater project include (pri) file using the include() function.
|
|
||||||
3. That's all! Check the example project as a reference for your project.
|
|
||||||
|
|
||||||
## Running the example project
|
|
||||||
|
|
||||||
1. Navigate to the *Example* folder and open *example.pro* with [Qt Creator](http://qt-project.org/wiki/Category:Tools::QtCreator).
|
|
||||||
2. Compile the project and play with it *:)*
|
|
||||||
|
|
||||||
## Warnings
|
|
||||||
|
|
||||||
Many websites today use the [HTTP Secure](http://en.wikipedia.org/wiki/HTTP_Secure) protocol, which means that you will need [SSL](https://www.globalsign.com/en/ssl-information-center/what-ssl/) in order to communicate with them. If your project needs to access such a webiste (for example GitHub), you will need to carefully read the following information in order to ensure that QSimpleUpdater works with those websites (both in your machine and in the final users' machine).
|
|
||||||
|
|
||||||
This section is extremely important for any developer wishing to deploy his or her applications under the Windows platform, because the application will depend on the libraries provided by QSimpleUpdater.
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
Make sure that you have installed the following libraries in your system:
|
|
||||||
|
|
||||||
+ lssl
|
|
||||||
+ lcrypto
|
|
||||||
|
|
||||||
### Mac OS X
|
|
||||||
|
|
||||||
The libraries required by QSimpleUpdater are the same as Linux, however, these libraries are installed by default in most Mac OS X installations.
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
QSimpleUpdater makes use of the OpenSSL-Win32 project, make sure that have it installed and that the project knows where to find them (the default location is C:/OpenSSL-Win32) and that you deploy the following libraries with your compiled project:
|
|
||||||
|
|
||||||
+ libeay32.dll
|
|
||||||
+ ssleay32.dll
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
Donate [Bitcoins](http://bitcoin.org) to the project to keep it going!
|
|
||||||
|
|
||||||
> 1FFz9TZCPGgiCD97yEqnFaauYYvZUE7f51
|
|
||||||
|
|
||||||
## Useful Links
|
|
||||||
|
|
||||||
+ [Project website](http://qsimpleupdater.sourceforge.net)
|
|
||||||
+ [OpenHub Project](http://openhub.net/p/qsimpleupdater)
|
|
||||||
+ [GitHub repository](http://github.com/alex-97/qsimpleupdater)
|
|
||||||
+ [Contact developer](mailto:alex.racotta@gmail.com)
|
|
||||||
|
0
QSimpleUpdater/res/qsu_resources.qrc → etc/resources/qsimpleupdater.qrc
Normal file → Executable file
0
QSimpleUpdater/res/qsu_resources.qrc → etc/resources/qsimpleupdater.qrc
Normal file → Executable file
0
QSimpleUpdater/res/update.png → etc/resources/update.png
Normal file → Executable file
0
QSimpleUpdater/res/update.png → etc/resources/update.png
Normal file → Executable file
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
20
etc/scripts/format-code.bat
Normal file
20
etc/scripts/format-code.bat
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
:: Description: This script changes the style format of
|
||||||
|
:: all the source code of the project.
|
||||||
|
|
||||||
|
:: Setup the command line
|
||||||
|
@echo off
|
||||||
|
title Code Formatter
|
||||||
|
|
||||||
|
:: Go to the directory where the script is run
|
||||||
|
cd /d %~dp0
|
||||||
|
|
||||||
|
:: Style and format the source code recursively
|
||||||
|
astyle --pad-oper --pad-first-paren-out --align-pointer=type --remove-brackets --convert-tabs --max-code-length=80 --style=google --lineend=windows --suffix=none --recursive ../../*.h ../../*.cpp ../../*.c
|
||||||
|
|
||||||
|
:: Notify the user that we have finished
|
||||||
|
echo.
|
||||||
|
echo Code styling complete!
|
||||||
|
echo.
|
||||||
|
|
||||||
|
:: Let the user see the output
|
||||||
|
pause
|
2
etc/scripts/format-code.sh
Normal file
2
etc/scripts/format-code.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Style and format recursively
|
||||||
|
astyle --pad-oper --pad-first-paren-out --align-pointer=type --remove-brackets --convert-tabs --max-code-length=80 --style=google --lineend=windows --suffix=none --recursive ../../*.h ../../*.cpp ../../*.c
|
13
example/COPYING
Normal file
13
example/COPYING
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
12
example/definitions/README.md
Normal file
12
example/definitions/README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# What is this?
|
||||||
|
|
||||||
|
The [updates.json](updates.json) file is the update definitions file. In other words, it lists the latest versions, changelogs and download URLs for each platform.
|
||||||
|
|
||||||
|
The example project downloads the [updates.json](updates.json) file and analyzes in order to:
|
||||||
|
|
||||||
|
- Compare the local (user set) version and the remote version (specified in [updates.json](updates.json))
|
||||||
|
- Download the change log for the current platform
|
||||||
|
- Obtain the download URLs
|
||||||
|
- Obtain the URL to open (if specified)
|
||||||
|
|
||||||
|
Check the article on this article on the [wiki](#) for more information.
|
34
example/definitions/updates.json
Normal file
34
example/definitions/updates.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"updates": {
|
||||||
|
"windows": {
|
||||||
|
"open-url": "",
|
||||||
|
"latest-version": "1.0",
|
||||||
|
"download-url": "https://github.com/alex-spataru/QSimpleUpdater/archive/master.zip",
|
||||||
|
"changelog": "This is an example changelog for Windows. Go on..."
|
||||||
|
},
|
||||||
|
"osx": {
|
||||||
|
"open-url": "",
|
||||||
|
"latest-version": "1.0",
|
||||||
|
"download-url": "https://github.com/alex-spataru/QSimpleUpdater/archive/master.zip",
|
||||||
|
"changelog": "This is an example changelog for Mac OS X. Go on..."
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"open-url": "",
|
||||||
|
"latest-version": "1.0",
|
||||||
|
"download-url": "https://github.com/alex-spataru/QSimpleUpdater/archive/master.zip",
|
||||||
|
"changelog": "This is an example changelog for Linux. Go on..."
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"open-url": "",
|
||||||
|
"latest-version": "1.0",
|
||||||
|
"download-url": "https://github.com/alex-spataru/QSimpleUpdater/archive/master.zip",
|
||||||
|
"changelog": "This is an example changelog for iOS. Go on..."
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"open-url": "",
|
||||||
|
"latest-version": "1.0",
|
||||||
|
"download-url": "https://github.com/alex-spataru/QSimpleUpdater/archive/master.zip",
|
||||||
|
"changelog": "This is an example changelog for Android. Go on..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
273
include/QSimpleUpdater.h
Normal file
273
include/QSimpleUpdater.h
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
*
|
||||||
|
* This file is part of the QSimpleUpdater library, which is released under
|
||||||
|
* the DBAD license, you can read a copy of it below:
|
||||||
|
*
|
||||||
|
* DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING,
|
||||||
|
* DISTRIBUTION AND MODIFICATION:
|
||||||
|
*
|
||||||
|
* Do whatever you like with the original work, just don't be a dick.
|
||||||
|
* Being a dick includes - but is not limited to - the following instances:
|
||||||
|
*
|
||||||
|
* 1a. Outright copyright infringement - Don't just copy this and change the
|
||||||
|
* name.
|
||||||
|
* 1b. Selling the unmodified original with no work done what-so-ever, that's
|
||||||
|
* REALLY being a dick.
|
||||||
|
* 1c. Modifying the original work to contain hidden harmful content.
|
||||||
|
* That would make you a PROPER dick.
|
||||||
|
*
|
||||||
|
* If you become rich through modifications, related works/services, or
|
||||||
|
* supporting the original work, share the love.
|
||||||
|
* Only a dick would make loads off this work and not buy the original works
|
||||||
|
* creator(s) a pint.
|
||||||
|
*
|
||||||
|
* Code is provided with no warranty. Using somebody else's code and bitching
|
||||||
|
* when it goes wrong makes you a DONKEY dick.
|
||||||
|
* Fix the problem yourself. A non-dick would submit the fix back.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QSIMPLEUPDATER_MAIN_H
|
||||||
|
#define _QSIMPLEUPDATER_MAIN_H
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QList>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#if defined (QSU_SHARED)
|
||||||
|
# define QSU_DECL Q_DECL_EXPORT
|
||||||
|
#elif defined (QSU_IMPORT)
|
||||||
|
# define QSU_DECL Q_DECL_IMPORT
|
||||||
|
#else
|
||||||
|
# define QSU_DECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Updater;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Project homepage: http://qsimpleupdater.sf.net/
|
||||||
|
/// Code repository: http://github.com/alex-spataru/qsimpleupdater
|
||||||
|
///
|
||||||
|
/// The \c QSimpleUpdater class manages the updater system and allows for
|
||||||
|
/// parallel application modules to check for updates and download them.
|
||||||
|
///
|
||||||
|
/// The behavior of each updater can be regulated by specifying the update
|
||||||
|
/// definitions URL (from where we download the individual update definitions)
|
||||||
|
/// and defining the desired options by calling the individual "setter"
|
||||||
|
/// functions (e.g. \c setNotifyOnUpdate()).
|
||||||
|
///
|
||||||
|
/// The \c QSimpleUpdater also implements an integrated downloader.
|
||||||
|
/// If you need to use a custom install procedure/code, just create a function
|
||||||
|
/// that is called when the \c downloadFinished() signal is emitted to
|
||||||
|
/// implement your own install procedures.
|
||||||
|
///
|
||||||
|
/// By default, the downloader will try to open the file as if you opened it
|
||||||
|
/// from a file manager or a web browser (with the "file:///" url).
|
||||||
|
///
|
||||||
|
class QSU_DECL QSimpleUpdater : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// Returns the only instance of the class
|
||||||
|
///
|
||||||
|
static QSimpleUpdater* getInstance();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the updater registered with the given \a url is set
|
||||||
|
/// to notify the user when it finds an available update.
|
||||||
|
///
|
||||||
|
bool getNotifyOnUpdate (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the updater registered with the given \a url is set
|
||||||
|
/// to notify the user when it finishes checking for updates
|
||||||
|
///
|
||||||
|
bool getNotifyOnFinish (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the updater registered with the given \a url has an
|
||||||
|
/// update available.
|
||||||
|
///
|
||||||
|
/// \note you should call \c checkForUpdates() for this URL first in order
|
||||||
|
/// for this function to regurn a valid value
|
||||||
|
///
|
||||||
|
bool getUpdateAvailable (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the downloader is enabled for the updater registered
|
||||||
|
/// with the given \a c url
|
||||||
|
///
|
||||||
|
bool getDownloaderEnabled (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the changelog of the updater instance with the given \c url.
|
||||||
|
///
|
||||||
|
QString getChangelog (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the URL from where we can download the update
|
||||||
|
///
|
||||||
|
QString getDownloadUrl (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the latest version online
|
||||||
|
///
|
||||||
|
QString getLatestVersion (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the platform of the updater with the given \c url.
|
||||||
|
///
|
||||||
|
QString getPlatformKey (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the application name registered for the given \c url.
|
||||||
|
///
|
||||||
|
QString getModuleName (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the application version registered for the given \c url
|
||||||
|
///
|
||||||
|
QString getModuleVersion (const QString& url) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the downloader will not attempt to install the
|
||||||
|
/// downloaded file.
|
||||||
|
///
|
||||||
|
/// This can be useful if you want to use the \c downloadFinished() signal
|
||||||
|
/// to implement your own install procedures.
|
||||||
|
///
|
||||||
|
bool usesCustomInstallProcedures (const QString& url) const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
///
|
||||||
|
/// Checks for updates by downloading the update definitions file at the
|
||||||
|
/// given \a url.
|
||||||
|
///
|
||||||
|
/// You can have more than one updater running at the same time while the
|
||||||
|
/// \a url is different. Every updater instance will have its own set of
|
||||||
|
/// settings.
|
||||||
|
///
|
||||||
|
/// This can be used - for example - when having multiple shared modules
|
||||||
|
/// (e.g. plugins) that can be updated separately.
|
||||||
|
///
|
||||||
|
void checkForUpdates (const QString& url);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the platform key which we use to get version data and download
|
||||||
|
/// link in the appcast in the given \c url.
|
||||||
|
///
|
||||||
|
/// \note By default, the updater will use the name of the current operating
|
||||||
|
/// system as its platform key.
|
||||||
|
///
|
||||||
|
void setPlatformKey (const QString& url, const QString& platform);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the application name to display in the notification messages
|
||||||
|
/// for the given appcast \a url.
|
||||||
|
///
|
||||||
|
/// This can be used - for example - when having multiple shared modules
|
||||||
|
/// (e.g. plugins) that can be updated separately.
|
||||||
|
///
|
||||||
|
/// \note By default, the updater will use the name given to the
|
||||||
|
/// \c QApplication during initialization of your application.
|
||||||
|
///
|
||||||
|
void setModuleName (const QString& url, const QString& name);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the application version to use when comparing the local and
|
||||||
|
/// remote application versions.
|
||||||
|
///
|
||||||
|
/// This can be used - for example - when having multiple shared modules
|
||||||
|
/// (e.g. plugins) that can be updated separately.
|
||||||
|
///
|
||||||
|
/// \note By default, the updater will use the version given to the
|
||||||
|
/// \c QApplication during initialization of your application.
|
||||||
|
///
|
||||||
|
void setModuleVersion (const QString& url, const QString& version);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If \c notify is set to true, the \c QSimpleUpdater will notify the user
|
||||||
|
/// when an update is available.
|
||||||
|
///
|
||||||
|
/// If \c notify is set to false, the \c QSimpleUpdater will not notify the
|
||||||
|
/// user when an update is available.
|
||||||
|
///
|
||||||
|
/// \note this feature is enabled by default
|
||||||
|
/// \note you should disable this feature if you are implementing your own
|
||||||
|
/// notification methods or update procedures in your application.
|
||||||
|
/// \note this function only changes the behavior for the updater registered
|
||||||
|
/// with the given \a url.
|
||||||
|
///
|
||||||
|
void setNotifyOnUpdate (const QString& url, const bool& notify);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If set to \c true, the updater will notify the user when it finishes
|
||||||
|
/// checking for updates (even where there are no updates available).
|
||||||
|
///
|
||||||
|
/// If set to \c false (default), the updater will only notify the user
|
||||||
|
/// when there is an update available (if setNotifyOnUpdate() is \c true).
|
||||||
|
///
|
||||||
|
/// You can enable this feature when the user triggers manually the updater
|
||||||
|
/// (e.g. by clicking on the "Check for Updates..." action on the menu).
|
||||||
|
///
|
||||||
|
/// \note this feature is disabled by default
|
||||||
|
/// \note you should disable this feature if you are implementing your own
|
||||||
|
/// notification methods or update procedures in your application.
|
||||||
|
/// \note this function only changes the behavior for the updater registered
|
||||||
|
/// with the given \a url.
|
||||||
|
///
|
||||||
|
void setNotifyOnFinish (const QString& url, const bool& notify);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If set to true, the updater will allow the user to choose whenever to
|
||||||
|
/// download the update directly from the application (instead of opening
|
||||||
|
/// the given download link through a browser).
|
||||||
|
///
|
||||||
|
/// \note this feature is enabled by default
|
||||||
|
/// \note you should disable this if you are implementing your own update
|
||||||
|
/// procedures in your application.
|
||||||
|
/// \note this function only changes the behavior for the updater registered
|
||||||
|
/// with the given \a url.
|
||||||
|
///
|
||||||
|
void setDownloaderEnabled (const QString& url, const bool& enabled);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If \c custom is set to true, then the Downloader will not attempt to
|
||||||
|
/// open or install the downloaded updates. This can be useful if you want
|
||||||
|
/// to implement your own install procedures using the \c downloadFinished()
|
||||||
|
/// signal.
|
||||||
|
///
|
||||||
|
void setUseCustomInstallProcedures (const QString& url, const bool& custom);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
///
|
||||||
|
/// Emitted when the check for updates process finishes.
|
||||||
|
/// You can use this function if you are implementing your own notification
|
||||||
|
/// methods or download procedures.
|
||||||
|
///
|
||||||
|
/// \note use of this signal is not obligatory if you don't want
|
||||||
|
/// to show a custom notification or create your own downloader.
|
||||||
|
///
|
||||||
|
void checkingFinished (const QString& url);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Emitted when the download has finished.
|
||||||
|
/// You can use this to implement your own procedures to install the
|
||||||
|
/// downloaded updates.
|
||||||
|
///
|
||||||
|
void downloadFinished (const QString& url, const QString& filepath);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~QSimpleUpdater();
|
||||||
|
|
||||||
|
private:
|
||||||
|
///
|
||||||
|
/// Returns the updater object registered with the given \a url.
|
||||||
|
/// If an updater object with the given \a url is not found, then this
|
||||||
|
/// function will create it and configure it.
|
||||||
|
///
|
||||||
|
Updater* getUpdater (const QString& url) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
165
lgpl3.txt
165
lgpl3.txt
@ -1,165 +0,0 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
314
src/Downloader.cpp
Executable file
314
src/Downloader.cpp
Executable file
@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
* (C) Copyright 2014 Alex Spataru
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the GNU Lesser General Public License
|
||||||
|
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
||||||
|
* http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Class includes
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "Downloader.h"
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// System includes
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::Downloader
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
Downloader::Downloader (QWidget* parent) : QWidget (parent) {
|
||||||
|
m_ui = new Ui::Downloader;
|
||||||
|
m_ui->setupUi (this);
|
||||||
|
|
||||||
|
/* Initialize private members */
|
||||||
|
m_manager = new QNetworkAccessManager();
|
||||||
|
|
||||||
|
/* Initialize internal values */
|
||||||
|
m_filePath = "";
|
||||||
|
m_startTime = 0;
|
||||||
|
m_useCustomProcedures = false;
|
||||||
|
|
||||||
|
/* Make the window look like a modal dialog */
|
||||||
|
setWindowIcon (QIcon ());
|
||||||
|
setWindowFlags (Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
|
||||||
|
|
||||||
|
/* Configure the appearance and behavior of the buttons */
|
||||||
|
m_ui->openButton->setEnabled (false);
|
||||||
|
m_ui->openButton->setVisible (false);
|
||||||
|
connect (m_ui->stopButton, SIGNAL (clicked()),
|
||||||
|
this, SLOT (cancelDownload()));
|
||||||
|
connect (m_ui->openButton, SIGNAL (clicked()),
|
||||||
|
this, SLOT (installUpdate()));
|
||||||
|
|
||||||
|
/* Resize to fit */
|
||||||
|
setFixedSize (minimumSizeHint());
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::~Downloader
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
Downloader::~Downloader() {
|
||||||
|
delete m_ui;
|
||||||
|
delete m_reply;
|
||||||
|
delete m_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::useCustomInstallProcedures
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool Downloader::useCustomInstallProcedures() const {
|
||||||
|
return m_useCustomProcedures;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::startDownload
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::startDownload (const QUrl& url) {
|
||||||
|
/* Reset UI */
|
||||||
|
m_ui->progressBar->setValue (0);
|
||||||
|
m_ui->stopButton->setText (tr ("Stop"));
|
||||||
|
m_ui->downloadLabel->setText (tr ("Downloading updates"));
|
||||||
|
m_ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("unknown"));
|
||||||
|
|
||||||
|
/* Start download */
|
||||||
|
m_startTime = QDateTime::currentDateTime().toTime_t();
|
||||||
|
m_reply = m_manager->get (QNetworkRequest (url));
|
||||||
|
|
||||||
|
/* Update UI when download progress changes or download finishes */
|
||||||
|
connect (m_reply, SIGNAL (downloadProgress (qint64, qint64)),
|
||||||
|
this, SLOT (updateProgress (qint64, qint64)));
|
||||||
|
connect (m_reply, SIGNAL (finished()),
|
||||||
|
this, SLOT (onDownloadFinished()));
|
||||||
|
|
||||||
|
showNormal();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::openDownload
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::openDownload() {
|
||||||
|
if (!m_filePath.isEmpty()) {
|
||||||
|
QString url = m_filePath;
|
||||||
|
|
||||||
|
if (url.startsWith ("/"))
|
||||||
|
url = "file://" + url;
|
||||||
|
else
|
||||||
|
url = "file:///" + url;
|
||||||
|
|
||||||
|
hide();
|
||||||
|
QDesktopServices::openUrl (url);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
QMessageBox::critical (this,
|
||||||
|
tr ("Error"),
|
||||||
|
tr ("Cannot find downloaded update!"),
|
||||||
|
QMessageBox::Close);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::installUpdate
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::installUpdate() {
|
||||||
|
if (useCustomInstallProcedures())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QMessageBox box;
|
||||||
|
box.setIcon (QMessageBox::Question);
|
||||||
|
box.setDefaultButton (QMessageBox::Ok);
|
||||||
|
box.setStandardButtons (QMessageBox::Ok | QMessageBox::Cancel);
|
||||||
|
box.setInformativeText (tr ("Click \"OK\" to begin installing the update"));
|
||||||
|
box.setText ("<h3>" +
|
||||||
|
tr ("In order to install the update, you may need to "
|
||||||
|
"quit the application.")
|
||||||
|
+ "</h3>");
|
||||||
|
|
||||||
|
if (box.exec() == QMessageBox::Ok) {
|
||||||
|
if (!useCustomInstallProcedures())
|
||||||
|
openDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
m_ui->openButton->setEnabled (true);
|
||||||
|
m_ui->openButton->setVisible (true);
|
||||||
|
m_ui->timeLabel->setText (tr ("Click the \"Open\" button to "
|
||||||
|
"apply the update"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::cancelDownload
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::cancelDownload() {
|
||||||
|
if (!m_reply->isFinished()) {
|
||||||
|
QMessageBox box;
|
||||||
|
box.setWindowTitle (tr ("Updater"));
|
||||||
|
box.setIcon (QMessageBox::Question);
|
||||||
|
box.setStandardButtons (QMessageBox::Yes | QMessageBox::No);
|
||||||
|
box.setText (tr ("Are you sure you want to cancel the download?"));
|
||||||
|
|
||||||
|
if (box.exec() == QMessageBox::Yes) {
|
||||||
|
hide();
|
||||||
|
m_reply->abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::onDownloadFinished
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::onDownloadFinished() {
|
||||||
|
m_ui->stopButton->setText (tr ("Close"));
|
||||||
|
m_ui->downloadLabel->setText (tr ("Download complete!"));
|
||||||
|
m_ui->timeLabel->setText (tr ("The installer will open separately")
|
||||||
|
+ "...");
|
||||||
|
|
||||||
|
QByteArray data = m_reply->readAll();
|
||||||
|
|
||||||
|
if (!data.isEmpty()) {
|
||||||
|
QStringList list = m_reply->url().toString().split ("/");
|
||||||
|
QFile file (QDir::tempPath() + "/" + list.at (list.count() - 1));
|
||||||
|
|
||||||
|
if (file.open (QIODevice::WriteOnly)) {
|
||||||
|
file.write (data);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
m_filePath = file.fileName();
|
||||||
|
emit downloadFinished (m_reply->url().toString(), m_filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
installUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::calculateSizes
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::calculateSizes (qint64 received, qint64 total) {
|
||||||
|
QString totalSize;
|
||||||
|
QString receivedSize;
|
||||||
|
|
||||||
|
if (total < 1024)
|
||||||
|
totalSize = tr ("%1 bytes").arg (total);
|
||||||
|
|
||||||
|
else if (total < 1048576)
|
||||||
|
totalSize = tr ("%1 KB").arg (round (total / 1024));
|
||||||
|
|
||||||
|
else
|
||||||
|
totalSize = tr ("%1 MB").arg (round (total / 1048576));
|
||||||
|
|
||||||
|
if (received < 1024)
|
||||||
|
receivedSize = tr ("%1 bytes").arg (received);
|
||||||
|
|
||||||
|
else if (received < 1048576)
|
||||||
|
receivedSize = tr ("%1 KB").arg (received / 1024);
|
||||||
|
|
||||||
|
else
|
||||||
|
receivedSize = tr ("%1 MB").arg (received / 1048576);
|
||||||
|
|
||||||
|
m_ui->downloadLabel->setText (tr ("Downloading updates")
|
||||||
|
+ " (" + receivedSize + " " + tr ("of")
|
||||||
|
+ " " + totalSize + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::updateProgress
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::updateProgress (qint64 received, qint64 total) {
|
||||||
|
if (total > 0) {
|
||||||
|
m_ui->progressBar->setMinimum (0);
|
||||||
|
m_ui->progressBar->setMaximum (100);
|
||||||
|
m_ui->progressBar->setValue ((received * 100) / total);
|
||||||
|
|
||||||
|
calculateSizes (received, total);
|
||||||
|
calculateTimeRemaining (received, total);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
m_ui->progressBar->setMinimum (0);
|
||||||
|
m_ui->progressBar->setMaximum (0);
|
||||||
|
m_ui->progressBar->setValue (-1);
|
||||||
|
m_ui->downloadLabel->setText (tr ("Downloading Updates") + "...");
|
||||||
|
m_ui->timeLabel->setText (QString ("%1: %2")
|
||||||
|
.arg (tr ("Time Remaining"))
|
||||||
|
.arg (tr ("Unknown")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::calculateTimeRemaining
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::calculateTimeRemaining (qint64 received, qint64 total) {
|
||||||
|
uint difference = QDateTime::currentDateTime().toTime_t() - m_startTime;
|
||||||
|
|
||||||
|
if (difference > 0) {
|
||||||
|
QString timeString;
|
||||||
|
float timeRemaining = total / (received / difference);
|
||||||
|
|
||||||
|
if (timeRemaining > 7200) {
|
||||||
|
timeRemaining /= 3600;
|
||||||
|
timeString = tr ("About %1 hours").arg (int (timeRemaining + 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timeRemaining > 60) {
|
||||||
|
timeRemaining /= 60;
|
||||||
|
timeString = tr ("About %1 minutes").arg (int (timeRemaining + 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timeRemaining <= 60)
|
||||||
|
timeString = tr ("%1 seconds").arg (int (timeRemaining + 0.5));
|
||||||
|
|
||||||
|
m_ui->timeLabel->setText (tr ("Time remaining") + ": " + timeString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::round
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
float Downloader::round (const float& input) {
|
||||||
|
return roundf (input * 100) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Downloader::setUseCustomInstallProcedures
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Downloader::setUseCustomInstallProcedures (const bool& custom) {
|
||||||
|
m_useCustomProcedures = custom;
|
||||||
|
}
|
91
src/Downloader.h
Executable file
91
src/Downloader.h
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* (C) Copyright 2014 Alex Spataru
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the GNU Lesser General Public License
|
||||||
|
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
||||||
|
* http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DOWNLOAD_DIALOG_H
|
||||||
|
#define DOWNLOAD_DIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <ui_Downloader.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Downloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
|
class Downloader : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Downloader (QWidget* parent = 0);
|
||||||
|
~Downloader();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the downloader will not attempt to install the
|
||||||
|
/// downloaded file.
|
||||||
|
///
|
||||||
|
/// This can be useful if you want to use the \c downloadFinished() signal
|
||||||
|
/// to implement your own install procedures.
|
||||||
|
///
|
||||||
|
bool useCustomInstallProcedures() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
///
|
||||||
|
/// Begins downloading the update
|
||||||
|
///
|
||||||
|
void startDownload (const QUrl& url);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If \c custom is set to true, then the Downloader will not attempt to
|
||||||
|
/// open or install the downloaded updates. This can be useful if you want
|
||||||
|
/// to implement your own install procedures using the \c downloadFinished()
|
||||||
|
/// signal.
|
||||||
|
///
|
||||||
|
void setUseCustomInstallProcedures (const bool& custom);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void openDownload();
|
||||||
|
void installUpdate();
|
||||||
|
void cancelDownload();
|
||||||
|
void onDownloadFinished();
|
||||||
|
void calculateSizes (qint64 received, qint64 total);
|
||||||
|
void updateProgress (qint64 received, qint64 total);
|
||||||
|
void calculateTimeRemaining (qint64 received, qint64 total);
|
||||||
|
|
||||||
|
private:
|
||||||
|
///
|
||||||
|
/// Rounds the \a input to the nearest integer
|
||||||
|
///
|
||||||
|
float round (const float& input);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
///
|
||||||
|
/// Emitted when the download has finished.
|
||||||
|
/// You can use this to implement your own procedures to install the
|
||||||
|
/// downloaded updates.
|
||||||
|
///
|
||||||
|
void downloadFinished (const QString& url, const QString& filepath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint m_startTime;
|
||||||
|
QString m_filePath;
|
||||||
|
Ui::Downloader* m_ui;
|
||||||
|
QNetworkReply* m_reply;
|
||||||
|
bool m_useCustomProcedures;
|
||||||
|
QNetworkAccessManager* m_manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
171
src/Downloader.ui
Executable file
171
src/Downloader.ui
Executable file
@ -0,0 +1,171 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Downloader</class>
|
||||||
|
<widget class="QWidget" name="Downloader">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>464</width>
|
||||||
|
<height>164</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Updater</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="updater_icon">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>96</width>
|
||||||
|
<height>96</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../etc/resources/qsimpleupdater.qrc">:/icons/update.png</pixmap>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="progressFrame" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="downloadLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Downloading updates</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>320</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="invertedAppearance">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="timeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Time remaining: 0 minutes</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="buttonFrame" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="buttonSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="openButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Open</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="stopButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Stop</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../etc/resources/qsimpleupdater.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
239
src/QSimpleUpdater.cpp
Normal file
239
src/QSimpleUpdater.cpp
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
*
|
||||||
|
* This file is part of the QSimpleUpdater library, which is released under
|
||||||
|
* the DBAD license, you can read a copy of it below:
|
||||||
|
*
|
||||||
|
* DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING,
|
||||||
|
* DISTRIBUTION AND MODIFICATION:
|
||||||
|
*
|
||||||
|
* Do whatever you like with the original work, just don't be a dick.
|
||||||
|
* Being a dick includes - but is not limited to - the following instances:
|
||||||
|
*
|
||||||
|
* 1a. Outright copyright infringement - Don't just copy this and change the
|
||||||
|
* name.
|
||||||
|
* 1b. Selling the unmodified original with no work done what-so-ever, that's
|
||||||
|
* REALLY being a dick.
|
||||||
|
* 1c. Modifying the original work to contain hidden harmful content.
|
||||||
|
* That would make you a PROPER dick.
|
||||||
|
*
|
||||||
|
* If you become rich through modifications, related works/services, or
|
||||||
|
* supporting the original work, share the love.
|
||||||
|
* Only a dick would make loads off this work and not buy the original works
|
||||||
|
* creator(s) a pint.
|
||||||
|
*
|
||||||
|
* Code is provided with no warranty. Using somebody else's code and bitching
|
||||||
|
* when it goes wrong makes you a DONKEY dick.
|
||||||
|
* Fix the problem yourself. A non-dick would submit the fix back.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Class Includes
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "Updater.h"
|
||||||
|
#include "QSimpleUpdater.h"
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Implementation hacks
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
static QList<QString> URLS;
|
||||||
|
static QList<Updater*> UPDATERS;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::~QSimpleUpdater
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QSimpleUpdater::~QSimpleUpdater() {
|
||||||
|
URLS.clear();
|
||||||
|
UPDATERS.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getInstance
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QSimpleUpdater* QSimpleUpdater::getInstance() {
|
||||||
|
static QSimpleUpdater updater;
|
||||||
|
return &updater;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getNotifyOnUpdate
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool QSimpleUpdater::getNotifyOnUpdate (const QString& url) const {
|
||||||
|
return getUpdater (url)->notifyOnUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getNotifyOnFinish
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool QSimpleUpdater::getNotifyOnFinish (const QString& url) const {
|
||||||
|
return getUpdater (url)->notifyOnFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getUpdateAvailable
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool QSimpleUpdater::getUpdateAvailable (const QString& url) const {
|
||||||
|
return getUpdater (url)->updateAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getDownloaderEnabled
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool QSimpleUpdater::getDownloaderEnabled (const QString& url) const {
|
||||||
|
return getUpdater (url)->downloaderEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getChangelog
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString QSimpleUpdater::getChangelog (const QString& url) const {
|
||||||
|
return getUpdater (url)->changelog();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getDownloadUrl
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString QSimpleUpdater::getDownloadUrl (const QString& url) const {
|
||||||
|
return getUpdater (url)->downloadUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getLatestVersion
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString QSimpleUpdater::getLatestVersion (const QString& url) const {
|
||||||
|
return getUpdater (url)->latestVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getPlatformKey
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString QSimpleUpdater::getPlatformKey (const QString& url) const {
|
||||||
|
return getUpdater (url)->platformKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getModuleName
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString QSimpleUpdater::getModuleName (const QString& url) const {
|
||||||
|
return getUpdater (url)->moduleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getModuleVersion
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString QSimpleUpdater::getModuleVersion (const QString& url) const {
|
||||||
|
return getUpdater (url)->moduleVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::usesCustomInstallProcedures
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool QSimpleUpdater::usesCustomInstallProcedures (const QString& url) const {
|
||||||
|
return getUpdater (url)->useCustomInstallProcedures();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::checkForUpdates
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::checkForUpdates (const QString& url) {
|
||||||
|
getUpdater (url)->checkForUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::setPlatformKey
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::setPlatformKey (const QString& url,
|
||||||
|
const QString& platform) {
|
||||||
|
getUpdater (url)->setPlatformKey (platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::setModuleName
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::setModuleName (const QString& url, const QString& name) {
|
||||||
|
getUpdater (url)->setModuleName (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::setModuleVersion
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::setModuleVersion (const QString& url,
|
||||||
|
const QString& version) {
|
||||||
|
getUpdater (url)->setModuleVersion (version);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::setNotifyOnUpdate
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::setNotifyOnUpdate (const QString& url,
|
||||||
|
const bool& notify) {
|
||||||
|
getUpdater (url)->setNotifyOnUpdate (notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::setNotifyOnFinish
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::setNotifyOnFinish (const QString& url,
|
||||||
|
const bool& notify) {
|
||||||
|
getUpdater (url)->setNotifyOnFinish (notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::setDownloaderEnabled
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::setDownloaderEnabled (const QString& url,
|
||||||
|
const bool& enabled) {
|
||||||
|
getUpdater (url)->setDownloaderEnabled (enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::setUseCustomInstallProcedures
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void QSimpleUpdater::setUseCustomInstallProcedures (const QString& url,
|
||||||
|
const bool& custom) {
|
||||||
|
getUpdater (url)->setUseCustomInstallProcedures (custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// QSimpleUpdater::getUpdater
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
Updater* QSimpleUpdater::getUpdater (const QString& url) const {
|
||||||
|
if (!URLS.contains (url)) {
|
||||||
|
Updater* updater = new Updater;
|
||||||
|
updater->setUrl (url);
|
||||||
|
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return UPDATERS.at (URLS.indexOf (url));
|
||||||
|
}
|
356
src/Updater.cpp
Normal file
356
src/Updater.cpp
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
*
|
||||||
|
* This file is part of the QSimpleUpdater library, which is released under
|
||||||
|
* the DBAD license, you can read a copy of it below:
|
||||||
|
*
|
||||||
|
* DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING,
|
||||||
|
* DISTRIBUTION AND MODIFICATION:
|
||||||
|
*
|
||||||
|
* Do whatever you like with the original work, just don't be a dick.
|
||||||
|
* Being a dick includes - but is not limited to - the following instances:
|
||||||
|
*
|
||||||
|
* 1a. Outright copyright infringement - Don't just copy this and change the
|
||||||
|
* name.
|
||||||
|
* 1b. Selling the unmodified original with no work done what-so-ever, that's
|
||||||
|
* REALLY being a dick.
|
||||||
|
* 1c. Modifying the original work to contain hidden harmful content.
|
||||||
|
* That would make you a PROPER dick.
|
||||||
|
*
|
||||||
|
* If you become rich through modifications, related works/services, or
|
||||||
|
* supporting the original work, share the love.
|
||||||
|
* Only a dick would make loads off this work and not buy the original works
|
||||||
|
* creator(s) a pint.
|
||||||
|
*
|
||||||
|
* Code is provided with no warranty. Using somebody else's code and bitching
|
||||||
|
* when it goes wrong makes you a DONKEY dick.
|
||||||
|
* Fix the problem yourself. A non-dick would submit the fix back.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Class includes
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "Updater.h"
|
||||||
|
#include "Downloader.h"
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// System includes
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::Updater
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
Updater::Updater() {
|
||||||
|
m_url = "";
|
||||||
|
m_openUrl = "";
|
||||||
|
m_changelog = "";
|
||||||
|
m_downloadUrl = "";
|
||||||
|
m_latestVersion = "";
|
||||||
|
m_notifyOnUpdate = true;
|
||||||
|
m_notifyOnFinish = false;
|
||||||
|
m_updateAvailable = false;
|
||||||
|
m_downloaderEnabled = true;
|
||||||
|
m_moduleName = qApp->applicationName();
|
||||||
|
m_moduleVersion = qApp->applicationVersion();
|
||||||
|
|
||||||
|
m_downloader = new Downloader();
|
||||||
|
m_manager = new QNetworkAccessManager();
|
||||||
|
|
||||||
|
#if defined Q_OS_WIN
|
||||||
|
m_platform = "windows";
|
||||||
|
#elif defined Q_OS_MAC
|
||||||
|
m_platform = "osx";
|
||||||
|
#elif defined Q_OS_LINUX
|
||||||
|
m_platform = "linux";
|
||||||
|
#elif defined Q_OS_ANDROID
|
||||||
|
m_platform = "android";
|
||||||
|
#elif defined Q_OS_IOS
|
||||||
|
m_platform = "ios";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
connect (m_downloader, SIGNAL (downloadFinished (QString, QString)),
|
||||||
|
this, SIGNAL (downloadFinished (QString, QString)));
|
||||||
|
connect (m_manager, SIGNAL (finished (QNetworkReply*)),
|
||||||
|
this, SLOT (onReply (QNetworkReply*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::~Updater
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
Updater::~Updater() {
|
||||||
|
delete m_downloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::url
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString Updater::url() const {
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::platformKey
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString Updater::platformKey() const {
|
||||||
|
return m_platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::notifyOnUpdate
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool Updater::notifyOnUpdate() const {
|
||||||
|
return m_notifyOnUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::notifyOnFinish
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool Updater::notifyOnFinish() const {
|
||||||
|
return m_notifyOnFinish;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::updateAvailable
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool Updater::updateAvailable() const {
|
||||||
|
return m_updateAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::downloaderEnabled
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool Updater::downloaderEnabled() const {
|
||||||
|
return m_downloaderEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::m_changelog
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString Updater::changelog() const {
|
||||||
|
return m_changelog;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::downloadUrl
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString Updater::downloadUrl() const {
|
||||||
|
return m_downloadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::latestVersion
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString Updater::latestVersion() const {
|
||||||
|
return m_latestVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::moduleName
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString Updater::moduleName() const {
|
||||||
|
return m_moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::moduleVersion
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
QString Updater::moduleVersion() const {
|
||||||
|
return m_moduleVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::useCustomInstallProcedures
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool Updater::useCustomInstallProcedures() const {
|
||||||
|
return m_downloader->useCustomInstallProcedures();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::checkForUpdates
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::checkForUpdates() {
|
||||||
|
m_manager->get (QNetworkRequest (url()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setUrl
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setUrl (const QString& url) {
|
||||||
|
m_url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setNotifyOnUpdate
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setNotifyOnUpdate (const bool& notify) {
|
||||||
|
m_notifyOnUpdate = notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setNotifyOnFinish
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setNotifyOnFinish (const bool& notify) {
|
||||||
|
m_notifyOnFinish = notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setPlatformKey
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setPlatformKey (const QString& platformKey) {
|
||||||
|
m_platform = platformKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setModuleName
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setModuleName (const QString& name) {
|
||||||
|
m_moduleName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setDownloaderEnabled
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setDownloaderEnabled (const bool& enabled) {
|
||||||
|
m_downloaderEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setUseCustomInstallProcedures
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setUseCustomInstallProcedures (const bool& custom) {
|
||||||
|
m_downloader->setUseCustomInstallProcedures (custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setModuleVersion
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setModuleVersion (const QString& version) {
|
||||||
|
m_moduleVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::onReply
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
emit checkingFinished (url());
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::setUpdateAvailable
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
void Updater::setUpdateAvailable (const bool& available) {
|
||||||
|
m_updateAvailable = available;
|
||||||
|
|
||||||
|
QMessageBox box;
|
||||||
|
box.setTextFormat (Qt::RichText);
|
||||||
|
box.setIcon (QMessageBox::Information);
|
||||||
|
|
||||||
|
if (updateAvailable() && (notifyOnUpdate() || notifyOnFinish())) {
|
||||||
|
QString text = tr ("Would you like to download the update now?");
|
||||||
|
QString title = "<h3>"
|
||||||
|
+ tr ("Version %1 of %2 has been released!")
|
||||||
|
.arg (latestVersion()).arg (moduleName())
|
||||||
|
+ "</h3>";
|
||||||
|
|
||||||
|
box.setText (title);
|
||||||
|
box.setInformativeText (text);
|
||||||
|
box.setStandardButtons (QMessageBox::No | QMessageBox::Yes);
|
||||||
|
box.setDefaultButton (QMessageBox::Yes);
|
||||||
|
|
||||||
|
if (box.exec() == QMessageBox::Yes) {
|
||||||
|
if (!m_openUrl.isEmpty())
|
||||||
|
QDesktopServices::openUrl (QUrl (m_openUrl));
|
||||||
|
|
||||||
|
else if (downloaderEnabled())
|
||||||
|
m_downloader->startDownload (downloadUrl());
|
||||||
|
|
||||||
|
else
|
||||||
|
QDesktopServices::openUrl (QUrl (downloadUrl()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (notifyOnFinish()) {
|
||||||
|
box.setStandardButtons (QMessageBox::Close);
|
||||||
|
box.setInformativeText (tr ("No updates are available for the moment"));
|
||||||
|
box.setText ("<h3>"
|
||||||
|
+ tr ("Congratulations! You are running the "
|
||||||
|
"latest version of %1").arg (moduleName())
|
||||||
|
+ "</h3>");
|
||||||
|
|
||||||
|
box.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Updater::compare
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
bool Updater::compare (const QString& x, const QString& y) {
|
||||||
|
QStringList versionsX = x.split (".");
|
||||||
|
QStringList versionsY = y.split (".");
|
||||||
|
|
||||||
|
int count = qMin (versionsX.count(), versionsY.count());
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
int a = QString (versionsX.at (i)).toInt();
|
||||||
|
int b = QString (versionsY.at (i)).toInt();
|
||||||
|
|
||||||
|
if (a > b)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
else if (b > a)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionsY.count() < versionsX.count();
|
||||||
|
}
|
248
src/Updater.h
Normal file
248
src/Updater.h
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Alex Spataru <alex_spataru@outlook.com>
|
||||||
|
*
|
||||||
|
* This file is part of the QSimpleUpdater library, which is released under
|
||||||
|
* the DBAD license, you can read a copy of it below:
|
||||||
|
*
|
||||||
|
* DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING,
|
||||||
|
* DISTRIBUTION AND MODIFICATION:
|
||||||
|
*
|
||||||
|
* Do whatever you like with the original work, just don't be a dick.
|
||||||
|
* Being a dick includes - but is not limited to - the following instances:
|
||||||
|
*
|
||||||
|
* 1a. Outright copyright infringement - Don't just copy this and change the
|
||||||
|
* name.
|
||||||
|
* 1b. Selling the unmodified original with no work done what-so-ever, that's
|
||||||
|
* REALLY being a dick.
|
||||||
|
* 1c. Modifying the original work to contain hidden harmful content.
|
||||||
|
* That would make you a PROPER dick.
|
||||||
|
*
|
||||||
|
* If you become rich through modifications, related works/services, or
|
||||||
|
* supporting the original work, share the love.
|
||||||
|
* Only a dick would make loads off this work and not buy the original works
|
||||||
|
* creator(s) a pint.
|
||||||
|
*
|
||||||
|
* Code is provided with no warranty. Using somebody else's code and bitching
|
||||||
|
* when it goes wrong makes you a DONKEY dick.
|
||||||
|
* Fix the problem yourself. A non-dick would submit the fix back.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QSIMPLEUPDATER_UPDATER_H
|
||||||
|
#define _QSIMPLEUPDATER_UPDATER_H
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
|
#include <QSimpleUpdater.h>
|
||||||
|
|
||||||
|
class Downloader;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The Updater class is in charge of downloading and analyzing
|
||||||
|
/// the appcast and "reacting" based on the options given by the
|
||||||
|
/// user/developer/application.
|
||||||
|
///
|
||||||
|
class QSU_DECL Updater : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Updater();
|
||||||
|
~Updater();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the AppCast URL (from which we extract the update definitions)
|
||||||
|
///
|
||||||
|
QString url() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the current platform key, which is used to differentiate the
|
||||||
|
/// different download links (and download versions) based on the current
|
||||||
|
/// operating system.
|
||||||
|
///
|
||||||
|
/// You can modify this value with the \c setPlatformKey() function
|
||||||
|
///
|
||||||
|
QString platformKey() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the class is set to notify the user when an update
|
||||||
|
/// is found online. By default this value is set to \c true.
|
||||||
|
///
|
||||||
|
bool notifyOnUpdate() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the class is set to notify the user when it finishes
|
||||||
|
/// checking for updates (even if there are no updates available).
|
||||||
|
/// By default this value is set to \c false.
|
||||||
|
///
|
||||||
|
bool notifyOnFinish() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the updater found an updated version of the
|
||||||
|
/// application/module online.
|
||||||
|
///
|
||||||
|
bool updateAvailable() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c if the updater allows the integrated downloader to download
|
||||||
|
/// and install the update (if aplicable).
|
||||||
|
///
|
||||||
|
bool downloaderEnabled() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the latest changelog
|
||||||
|
///
|
||||||
|
QString changelog() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the URL from where we can download the update
|
||||||
|
///
|
||||||
|
QString downloadUrl() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the latest version online
|
||||||
|
///
|
||||||
|
QString latestVersion() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the application name, which can be set manually or
|
||||||
|
/// automatically using the \c qApp->applicationName() function.
|
||||||
|
///
|
||||||
|
QString moduleName() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the application version, which can be set manually or
|
||||||
|
/// automatically using the \c qApp->applicationVersion() function.
|
||||||
|
///
|
||||||
|
QString moduleVersion() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns \c true if the downloader will not attempt to install the
|
||||||
|
/// downloaded file.
|
||||||
|
///
|
||||||
|
/// This can be useful if you want to use the \c downloadFinished() signal
|
||||||
|
/// to implement your own install procedures.
|
||||||
|
///
|
||||||
|
bool useCustomInstallProcedures() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
///
|
||||||
|
/// Downloads the update definitions file and analyzes it to determine the
|
||||||
|
/// latest version and the download links
|
||||||
|
///
|
||||||
|
void checkForUpdates();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the \a url from where we download the update definitions
|
||||||
|
///
|
||||||
|
void setUrl (const QString& url);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If \c notify is set to true, the \c QSimpleUpdater will notify the user
|
||||||
|
/// when an update is available.
|
||||||
|
///
|
||||||
|
/// If \c notify is set to false, the \c QSimpleUpdater will not notify the
|
||||||
|
/// user when an update is available.
|
||||||
|
///
|
||||||
|
void setNotifyOnUpdate (const bool& notify);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If set to \c true, the updater will notify the user when it finishes
|
||||||
|
/// checking for updates (even where there are no updates available).
|
||||||
|
///
|
||||||
|
/// If set to \c false (default), the updater will only notify the user
|
||||||
|
/// when there is an update available (if setNotifyOnUpdate() is \c true).
|
||||||
|
///
|
||||||
|
void setNotifyOnFinish (const bool& notify);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the name of the module, this can be useful in large applications
|
||||||
|
/// that only need to update certain components of them (e.g. plugins).
|
||||||
|
///
|
||||||
|
void setModuleName (const QString& name);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the version of the module, this can be useful in large
|
||||||
|
/// applications that only need to update certain components of them
|
||||||
|
/// (e.g. plugins).
|
||||||
|
///
|
||||||
|
void setModuleVersion (const QString& version);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If \a enabled is set to true, then the user will be able to download
|
||||||
|
/// and install updates directly from the application, without the need
|
||||||
|
/// of opening the download URL from a browser and manually installing
|
||||||
|
/// the update.
|
||||||
|
///
|
||||||
|
void setDownloaderEnabled (const bool& enabled);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the platform key/id. This can be useful if the update depends
|
||||||
|
/// on more than the underlying operating system on which the application
|
||||||
|
/// runs.
|
||||||
|
///
|
||||||
|
void setPlatformKey (const QString& platformKey);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// If \c custom is set to true, then the Downloader will not attempt to
|
||||||
|
/// open or install the downloaded updates. This can be useful if you want
|
||||||
|
/// to implement your own install procedures using the \c downloadFinished()
|
||||||
|
/// signal.
|
||||||
|
///
|
||||||
|
void setUseCustomInstallProcedures (const bool& custom);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
///
|
||||||
|
/// Emitted when the download definitions have been downloaded and analyzed.
|
||||||
|
///
|
||||||
|
void checkingFinished (const QString& url);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Emitted when the download has finished.
|
||||||
|
/// You can use this to implement your own procedures to install the
|
||||||
|
/// downloaded updates.
|
||||||
|
///
|
||||||
|
void downloadFinished (const QString& url, const QString& filepath);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
///
|
||||||
|
/// Reads and analyzes the downloaded update definition.
|
||||||
|
///
|
||||||
|
void onReply (QNetworkReply* reply);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Changes the appropiate internal values, shows notifications (if allowed)
|
||||||
|
/// and (if allowed) initializes the internal downloader.
|
||||||
|
///
|
||||||
|
void setUpdateAvailable (const bool& available);
|
||||||
|
|
||||||
|
private:
|
||||||
|
///
|
||||||
|
/// Returns \c true if version \a x is greater than version \a y.
|
||||||
|
/// This is used to determine if the online version is greater than the
|
||||||
|
/// installed version of the module.
|
||||||
|
///
|
||||||
|
bool compare (const QString& x, const QString& y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_url;
|
||||||
|
|
||||||
|
bool m_notifyOnUpdate;
|
||||||
|
bool m_notifyOnFinish;
|
||||||
|
bool m_updateAvailable;
|
||||||
|
bool m_downloaderEnabled;
|
||||||
|
|
||||||
|
QString m_openUrl;
|
||||||
|
QString m_platform;
|
||||||
|
QString m_changelog;
|
||||||
|
QString m_moduleName;
|
||||||
|
QString m_downloadUrl;
|
||||||
|
QString m_moduleVersion;
|
||||||
|
QString m_latestVersion;
|
||||||
|
|
||||||
|
Downloader* m_downloader;
|
||||||
|
QNetworkAccessManager* m_manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user