Standalone downloader + update process tweaking...

This commit is contained in:
Martin Rotter 2014-04-11 13:49:05 +02:00
parent 1f420ee5cf
commit 475ab5e0bf
10 changed files with 185 additions and 106 deletions

View File

@ -147,11 +147,6 @@ configure_file (
${CMAKE_CURRENT_BINARY_DIR}/src/definitions/definitions.h
)
configure_file (
${PROJECT_SOURCE_DIR}/src/updater/definitions.h.in
${CMAKE_CURRENT_BINARY_DIR}/src/updater/definitions.h
)
# Define some useful DEBUG for, ehrm, debug build.
if(CMAKE_BUILD_TYPE STREQUAL "release" OR CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RELEASE")
message(STATUS "[${APP_LOW_NAME}] A release build (non-debug) is chosen. Debugging outputs are silently ignored.")

View File

@ -20,12 +20,6 @@
#include <QtGlobal>
#if QT_VERSION >= 0x050000
#include <qwebkitglobal.h>
#else
#include <qwebkitversion.h>
#endif
#define CMAKE_VERSION "@CMAKE_VERSION@"
#define CMAKE_SYSTEM "@CMAKE_SYSTEM@"
@ -39,7 +33,7 @@
#define APP_URL_ISSUES "@APP_URL_ISSUES@"
#define APP_URL_ISSUES_NEW "@APP_URL_ISSUES_NEW@"
#define APP_VERSION "@APP_VERSION@"
#define APP_USERAGENT QString("@APP_NAME@/@APP_VERSION@ (@APP_URL@) on @CMAKE_SYSTEM@; Webkit/") + qWebKitVersion()
#define APP_USERAGENT QString("@APP_NAME@/@APP_VERSION@ (@APP_URL@) on @CMAKE_SYSTEM@")
#define RELEASES_LIST "https://bitbucket.org/skunkos/rssguard/raw/master/resources/text/UPDATES?at=master"
#define DEFAULT_LOCALE "en_GB"
@ -175,6 +169,8 @@
#define APP_ICON_PLAIN_PATH APP_PREFIX + QString("/share/rssguard/icons/@APP_LOW_NAME@_plain.png")
#elif defined(Q_OS_WIN) || defined(Q_OS_OS2)
#define APP_UPDATER_EXECUTABLE "rssguard_updater.exe"
#define APP_7ZA_EXECUTABLE "7za.exe"
#define APP_LANG_PATH QApplication::applicationDirPath() + QString("/l10n")
#define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/skins")
#define APP_INFO_PATH QApplication::applicationDirPath()

View File

@ -22,6 +22,7 @@
#include "miscellaneous/iconfactory.h"
#include "network-web/networkfactory.h"
#include "network-web/webfactory.h"
#include "network-web/downloader.h"
#include "gui/messagebox.h"
#include "gui/systemtrayicon.h"
@ -104,8 +105,9 @@ void FormUpdate::checkForUpdates() {
void FormUpdate::startUpdate() {
QString url_file;
bool update_for_this_system = isUpdateForThisSystem();
if (isUpdateForThisSystem()) {
if (update_for_this_system) {
url_file = m_updateInfo.m_urls.value(OS_ID).m_fileUrl;
}
else {
@ -113,57 +115,13 @@ void FormUpdate::startUpdate() {
}
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
// On Windows/OS2 we can update the application right away.
// Download the files.
QByteArray output;
QNetworkReply::NetworkError download_result = NetworkFactory::downloadFeedFile(url_file,
10 * DOWNLOAD_TIMEOUT,
output);
Downloader *down = new Downloader(this);
#if QT_VERSION >= 0x050000
QString temp_directory = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
#else
QString temp_directory = QDesktopServices::storageLocation(QDesktopServices::TempLocation);
#endif
if (!temp_directory.isEmpty()) {
QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1);
QFile output_file(temp_directory + QDir::separator() + output_file_name);
if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
output_file.write(output);
output_file.flush();
output_file.close();
// TODO: spustit updater
// pouzit qprocess, nebo neco multiplatformniho
// nebo z quiterss shellexecuter
// program obcas pada, to je mozna zpusobeny tim
// ze je otevreny modalni okno.
close();
QProcess::startDetached(APP_UPDATER_EXECUTABLE,
QStringList() << temp_directory <<qApp->applicationFilePath() << output_file.fileName());
/*
ShellExecute(0,
0,
(wchar_t *) QString(APP_UPDATER_EXECUTABLE).utf16(),
(wchar_t *) QString("\"%1\" \"%2\" \"%3\"").arg(temp_directory,
qApp->applicationFilePath(),
output_file.fileName()).utf16(),
0,
SW_SHOWNORMAL);
*/
}
else {
// TODO: chyba - nelze zapisovat do souboru
}
}
else {
// TODO: chyba - nelze ulozit soubor.
}
connect(down, SIGNAL(completed(QNetworkReply::NetworkError,QByteArray)),
this, SLOT(finish(QNetworkReply::NetworkError,QByteArray)));
// TODO: tady jen zavolat updater a ten by si to mohl stahnout sam.
down->downloadFile(url_file);
#else
if (!WebFactory::instance()->openUrlInExternalBrowser(url_file)) {
if (SystemTrayIcon::isSystemTrayActivated()) {
@ -182,3 +140,48 @@ void FormUpdate::startUpdate() {
}
#endif
}
void FormUpdate::finish(QNetworkReply::NetworkError err, QByteArray arr)
{
// TODO: presunou do updatera.
QString url_file = m_updateInfo.m_urls.value(OS_ID).m_fileUrl;;
#if QT_VERSION >= 0x050000
QString temp_directory = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
#else
QString temp_directory = QDesktopServices::storageLocation(QDesktopServices::TempLocation);
#endif
if (!temp_directory.isEmpty()) {
QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1);
QFile output_file(temp_directory + QDir::separator() + output_file_name);
if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
output_file.write(arr);
output_file.flush();
output_file.close();
close();
QProcess::startDetached(APP_UPDATER_EXECUTABLE,
QStringList() << temp_directory <<qApp->applicationFilePath() << output_file.fileName());
//ShellExecute(0,
// 0,
// (wchar_t *) QString(APP_UPDATER_EXECUTABLE).utf16(),
// (wchar_t *) QString("\"%1\" \"%2\" \"%3\"").arg(temp_directory,
// qApp->applicationFilePath(),
// output_file.fileName()).utf16(),
// 0,
// SW_SHOWNORMAL);
}
else {
// TODO: chyba - nelze zapisovat do souboru
}
}
else {
// TODO: chyba - nelze ulozit soubor.
}
}

View File

@ -47,6 +47,8 @@ class FormUpdate : public QDialog {
void checkForUpdates();
void startUpdate();
void finish(QNetworkReply::NetworkError err, QByteArray arr);
private:
Ui::FormUpdate *m_ui;
UpdateInfo m_updateInfo;

View File

@ -53,8 +53,6 @@ class MessagesToolBar : public BaseToolBar {
void loadChangeableActions(const QStringList &actions);
signals:
// TODO: sem pridat este mozna mode: wildcard, regexp, fixed text.
// na tuto udalost se navaze filtrovani
void messageSearchPatternChanged(const QString &pattern);
// Emitted if message filter is changed.

View File

@ -88,8 +88,6 @@ void ToolBarEditor::loadFromToolBar(BaseToolBar* tool_bar) {
}
void ToolBarEditor::saveToolBar() {
// TODO: ulozit actiony nastaveny v tomdl
// e nastavovacim dialogu do prirazenyho toolbaru
QStringList action_names;
for (int i = 0; i < m_ui->m_listActivatedActions->count(); i++) {

View File

@ -1,8 +1,94 @@
#include "network-web/downloader.h"
#include "network-web/silentnetworkaccessmanager.h"
Downloader::Downloader(QObject *parent) : QObject(parent) {
#include <QTimer>
Downloader::Downloader(QObject *parent)
: QObject(parent),
m_activeReply(NULL),
m_downloadManager(new SilentNetworkAccessManager(this)),
m_timer(new QTimer(this)) {
m_timer->setInterval(2000);
m_timer->setSingleShot(true);
connect(m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
connect(m_downloadManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));
}
Downloader::~Downloader() {
m_downloadManager->deleteLater();
}
void Downloader::downloadFile(const QString &url, bool protected_contents,
const QString &username, const QString &password) {
QNetworkRequest request;
QObject originatingObject;
// Set credential information as originating object.
originatingObject.setProperty("protected", protected_contents);
originatingObject.setProperty("username", username);
originatingObject.setProperty("password", password);
request.setOriginatingObject(&originatingObject);
// Set url for this reques.
request.setUrl(url);
runRequest(request);
}
void Downloader::finished(QNetworkReply *reply) {
m_timer->stop();
// In this phase, some part of downloading process is completed.
QUrl redirection_url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (redirection_url.isValid()) {
// Communication indicates that HTTP redirection is needed.
// Setup redirection URL and download again.
QNetworkRequest request = reply->request();
request.setUrl(redirection_url);
m_activeReply->deleteLater();
m_activeReply = NULL;
runRequest(request);
}
else {
// No redirection is indicated. Final file is obtained
// in our "reply" object.
// Read the data into output buffer.
QByteArray output = reply->readAll();
QNetworkReply::NetworkError reply_error = reply->error();
m_activeReply->deleteLater();
m_activeReply = NULL;
emit completed(reply_error, output);
}
}
void Downloader::progressInternal(qint64 bytes_received, qint64 bytes_total) {
if (m_timer->interval() > 0) {
m_timer->start();
}
emit progress(bytes_received, bytes_total);
}
void Downloader::timeout() {
if (m_activeReply != NULL) {
m_activeReply->abort();
}
}
void Downloader::runRequest(const QNetworkRequest &request) {
m_timer->start();
m_activeReply = m_downloadManager->get(request);
connect(m_activeReply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(progressInternal(qint64,qint64)));
}

View File

@ -3,6 +3,14 @@
#include <QObject>
#include <QNetworkReply>
#include <QSslError>
#include "definitions/definitions.h"
class SilentNetworkAccessManager;
class QTimer;
class Downloader : public QObject {
Q_OBJECT
@ -12,13 +20,37 @@ class Downloader : public QObject {
explicit Downloader(QObject *parent = 0);
virtual ~Downloader();
// TODO: zakladni downloader s timeoutem a signalem kerej informuje o prubehu
// stahovani
public slots:
// Performs asynchronous download of given file.
// Redirections are handled.
void downloadFile(const QString &url,
bool protected_contents = false,
const QString &username = QString(),
const QString &password = QString());
signals:
// Emitted when new progress is known.
void progress(qint64 bytes_received, qint64 bytes_total);
void completed(QNetworkReply::NetworkError status, QByteArray contents = QByteArray());
public slots:
private slots:
// Called when current reply is processed.
void finished(QNetworkReply *reply);
// Called when progress of downloaded file changes.
void progressInternal(qint64 bytes_received, qint64 bytes_total);
// Called when current operation times out.
void timeout();
private:
void runRequest(const QNetworkRequest &request);
private:
QNetworkReply *m_activeReply;
SilentNetworkAccessManager *m_downloadManager;
QTimer *m_timer;
};
#endif // DOWNLOADER_H

View File

@ -1,27 +0,0 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2014 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef DEFINITIONS_H_IN
#define DEFINITIONS_H_IN
#define RSSGUARD_LOW_NAME "@APP_LOW_NAME@"
#define UPDATER_QUIT_INSTANCE "app_quit"
#define UPDATER_IS_RUNNING "app_is_running"
#define EXECUTABLE_7ZA "7za.exe"
#endif // DEFINITIONS_H_IN

View File

@ -16,7 +16,7 @@
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "qtsingleapplication/qtsinglecoreapplication.h"
#include "updater/definitions.h"
#include "definitions/definitions.h"
#include <QTranslator>
#include <QDebug>
@ -86,7 +86,7 @@ bool copyPath(QString src, QString dst) {
int main(int argc, char *argv[]) {
// Instantiate base application object.
QtSingleCoreApplication application(RSSGUARD_LOW_NAME, argc, argv);
QtSingleCoreApplication application(APP_LOW_NAME, argc, argv);
if (argc != 4) {
qDebug("Insufficient arguments passed. Update process cannot proceed.");
@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
qDebug("\n===== directories & files =====\n");
// Check if main RSS Guard instance is running.
if (application.sendMessage(UPDATER_QUIT_INSTANCE)) {
if (application.sendMessage(APP_QUIT_INSTANCE)) {
qDebug("RSS Guard application is running. Quitting it.");
}
@ -127,9 +127,9 @@ int main(int argc, char *argv[]) {
qDebug().nospace() << "Running updater in thread: \'" <<
QThread::currentThreadId() << "\'.";
QString extractor_program(EXECUTABLE_7ZA);
QString extractor_program(APP_7ZA_EXECUTABLE);
QStringList arguments;
QString output_temp_directory = temp_directory + QDir::separator() + RSSGUARD_LOW_NAME;
QString output_temp_directory = temp_directory + QDir::separator() + APP_LOW_NAME;
// Remove old folders.
if (QDir(output_temp_directory).exists()) {
@ -190,10 +190,6 @@ int main(int argc, char *argv[]) {
QString rssguard_single_temp_root = rssguard_temp_root.at(0).absoluteFilePath();
// TODO: upravit copyPath aby prepisoval soubory kdyz je kopiruje
// a to udelat tak ze se ten cilovej soubor pokusi smazat
// a az pak nakopiruje.
if (!copyPath(rssguard_single_temp_root, rssguard_path)) {
qDebug("Critical error appeared during copying of application files.");
}