diff --git a/CMakeLists.txt b/CMakeLists.txt index 05d0a6689..394fc9401 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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.") diff --git a/src/definitions/definitions.h.in b/src/definitions/definitions.h.in index 7a6a9a6c4..dfdb781ee 100644 --- a/src/definitions/definitions.h.in +++ b/src/definitions/definitions.h.in @@ -20,12 +20,6 @@ #include -#if QT_VERSION >= 0x050000 -#include -#else -#include -#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() diff --git a/src/gui/formupdate.cpp b/src/gui/formupdate.cpp index 451f3c6f1..5e630b1db 100755 --- a/src/gui/formupdate.cpp +++ b/src/gui/formupdate.cpp @@ -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 <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 <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. + } +} diff --git a/src/gui/formupdate.h b/src/gui/formupdate.h index f978e7394..eb760f08e 100644 --- a/src/gui/formupdate.h +++ b/src/gui/formupdate.h @@ -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; diff --git a/src/gui/messagestoolbar.h b/src/gui/messagestoolbar.h index e7d46c3b2..48adedb07 100644 --- a/src/gui/messagestoolbar.h +++ b/src/gui/messagestoolbar.h @@ -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. diff --git a/src/gui/toolbareditor.cpp b/src/gui/toolbareditor.cpp index b506099e2..cb679b537 100644 --- a/src/gui/toolbareditor.cpp +++ b/src/gui/toolbareditor.cpp @@ -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++) { diff --git a/src/network-web/downloader.cpp b/src/network-web/downloader.cpp index 6025a4fe7..ad749b952 100644 --- a/src/network-web/downloader.cpp +++ b/src/network-web/downloader.cpp @@ -1,8 +1,94 @@ #include "network-web/downloader.h" +#include "network-web/silentnetworkaccessmanager.h" -Downloader::Downloader(QObject *parent) : QObject(parent) { +#include + + +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))); } diff --git a/src/network-web/downloader.h b/src/network-web/downloader.h index 3f2d941ee..0768a5666 100644 --- a/src/network-web/downloader.h +++ b/src/network-web/downloader.h @@ -3,6 +3,14 @@ #include +#include +#include + +#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 diff --git a/src/updater/definitions.h.in b/src/updater/definitions.h.in deleted file mode 100644 index c4b45fac8..000000000 --- a/src/updater/definitions.h.in +++ /dev/null @@ -1,27 +0,0 @@ -// This file is part of RSS Guard. -// -// Copyright (C) 2011-2014 by Martin Rotter -// -// 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 . - -#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 diff --git a/src/updater/main.cpp b/src/updater/main.cpp index 8af7caf70..b0c7d2967 100644 --- a/src/updater/main.cpp +++ b/src/updater/main.cpp @@ -16,7 +16,7 @@ // along with RSS Guard. If not, see . #include "qtsingleapplication/qtsinglecoreapplication.h" -#include "updater/definitions.h" +#include "definitions/definitions.h" #include #include @@ -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."); }