diff options
author | Tobias Markmann <tm@ayena.de> | 2017-02-21 13:27:42 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2017-02-22 11:15:00 (GMT) |
commit | 996ca9ecf4f226a033d161419f11e715a3f892c3 (patch) | |
tree | e332db1edf3e9ea2282814154473e3a5e57d362d | |
parent | eea861301be0bf3e3f5db6cfc3cada38d133fef2 (diff) | |
download | swift-996ca9ecf4f226a033d161419f11e715a3f892c3.zip swift-996ca9ecf4f226a033d161419f11e715a3f892c3.tar.bz2 |
Improve Swift about window regarding auto update UX
The dialog will automatically initiate a check for updates
when opened.
It will show the current state of the auto updater backend,
e.g. whether it is downloading or already at the latest
version.
This also fixes update channel selection being shown
on Windows and Linux.
Test-Information:
Ran Swift and opening the dialog shows a short progress bar
indicating it checking for updates. Afterwards it shows that
it is already running the latest version, which is sensible
for a dev build.
Change-Id: Ie08cd2a8852e468d6007122604b532fedc24bcfe
-rw-r--r-- | SwifTools/AutoUpdater/AutoUpdater.h | 16 | ||||
-rw-r--r-- | SwifTools/AutoUpdater/SparkleAutoUpdater.h | 7 | ||||
-rw-r--r-- | SwifTools/AutoUpdater/SparkleAutoUpdater.mm | 30 | ||||
-rw-r--r-- | SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.h | 12 | ||||
-rw-r--r-- | SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.mm | 32 | ||||
-rw-r--r-- | Swift/QtUI/QtAboutWidget.cpp | 95 | ||||
-rw-r--r-- | Swift/QtUI/QtAboutWidget.h | 17 | ||||
-rw-r--r-- | Swift/QtUI/QtLoginWindow.cpp | 6 | ||||
-rw-r--r-- | Swift/QtUI/QtLoginWindow.h | 6 | ||||
-rw-r--r-- | Swift/QtUI/QtSwift.cpp | 49 | ||||
-rw-r--r-- | Swift/QtUI/QtSwift.h | 34 | ||||
-rw-r--r-- | Swift/QtUI/QtUIFactory.cpp | 6 | ||||
-rw-r--r-- | Swift/QtUI/QtUIFactory.h | 6 |
13 files changed, 222 insertions, 94 deletions
diff --git a/SwifTools/AutoUpdater/AutoUpdater.h b/SwifTools/AutoUpdater/AutoUpdater.h index 274bf50..a125229 100644 --- a/SwifTools/AutoUpdater/AutoUpdater.h +++ b/SwifTools/AutoUpdater/AutoUpdater.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -13,11 +13,21 @@ namespace Swift { class AutoUpdater { public: + enum class State { + NotCheckedForUpdatesYet, + NoUpdateAvailable, + CheckingForUpdate, + ErrorCheckingForUpdate, + DownloadingUpdate, + RestartToInstallUpdate + }; + + public: virtual ~AutoUpdater(); virtual void setAppcastFeed(const std::string& appcastFeed) = 0; virtual void checkForUpdates() = 0; - virtual bool recommendRestartToUpdate() = 0; + virtual State getCurrentState() = 0; public: /** @@ -25,6 +35,6 @@ namespace Swift { * and the user needs to be notified so they can quit the app and start * the newer version. */ - boost::signals2::signal<void()> onSuggestRestartToUserToUpdate; + boost::signals2::signal<void(State)> onUpdateStateChanged; }; } diff --git a/SwifTools/AutoUpdater/SparkleAutoUpdater.h b/SwifTools/AutoUpdater/SparkleAutoUpdater.h index dd22e73..48b75e5 100644 --- a/SwifTools/AutoUpdater/SparkleAutoUpdater.h +++ b/SwifTools/AutoUpdater/SparkleAutoUpdater.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -25,7 +25,10 @@ namespace Swift { void setAppcastFeed(const std::string& appcastFeed); void checkForUpdates(); - bool recommendRestartToUpdate(); + State getCurrentState(); + + private: + void setCurrentState(State updatedState); private: class Private; diff --git a/SwifTools/AutoUpdater/SparkleAutoUpdater.mm b/SwifTools/AutoUpdater/SparkleAutoUpdater.mm index 0c296ee..4cf5837 100644 --- a/SwifTools/AutoUpdater/SparkleAutoUpdater.mm +++ b/SwifTools/AutoUpdater/SparkleAutoUpdater.mm @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Isode Limited. + * Copyright (c) 2016-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -18,7 +18,7 @@ class SparkleAutoUpdater::Private { public: SUUpdater* updater; boost::intrusive_ptr<SparkleAutoUpdaterDelegate> delegate; - bool restartToUpdate = false; + State currentState = State::NotCheckedForUpdatesYet; }; SparkleAutoUpdater::SparkleAutoUpdater(const std::string& appcastFeed) : d(new Private()) { @@ -26,9 +26,8 @@ SparkleAutoUpdater::SparkleAutoUpdater(const std::string& appcastFeed) : d(new P [d->updater retain]; d->delegate = boost::intrusive_ptr<SparkleAutoUpdaterDelegate>([[SparkleAutoUpdaterDelegate alloc] init], false); - [d->delegate.get() setUpdateDownloadFinished: [&](){ - d->restartToUpdate = true; - onSuggestRestartToUserToUpdate(); + [d->delegate.get() setOnNewUpdateState: [&](AutoUpdater::State updatedState){ + setCurrentState(updatedState); }]; [d->updater setDelegate: d->delegate.get()]; @@ -37,8 +36,7 @@ SparkleAutoUpdater::SparkleAutoUpdater(const std::string& appcastFeed) : d(new P [d->updater setUpdateCheckInterval: 86400]; [d->updater setAutomaticallyDownloadsUpdates: true]; - NSURL* nsurl = [NSURL URLWithString: std2NSString(appcastFeed)]; - [d->updater setFeedURL: nsurl]; + setAppcastFeed(appcastFeed); } SparkleAutoUpdater::~SparkleAutoUpdater() { @@ -51,12 +49,22 @@ void SparkleAutoUpdater::setAppcastFeed(const std::string& appcastFeed) { } void SparkleAutoUpdater::checkForUpdates() { - [d->updater resetUpdateCycle]; - [d->updater checkForUpdatesInBackground]; + if (!(getCurrentState() == State::CheckingForUpdate || + getCurrentState() == State::DownloadingUpdate || + getCurrentState() == State::RestartToInstallUpdate)) { + setCurrentState(State::CheckingForUpdate); + [d->updater resetUpdateCycle]; + [d->updater checkForUpdatesInBackground]; + } +} + +void SparkleAutoUpdater::setCurrentState(AutoUpdater::State updatedState) { + d->currentState = updatedState; + onUpdateStateChanged(d->currentState); } -bool SparkleAutoUpdater::recommendRestartToUpdate() { - return d->restartToUpdate; +AutoUpdater::State SparkleAutoUpdater::getCurrentState() { + return d->currentState; } } diff --git a/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.h b/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.h index 8f408de..4aa236b 100644 --- a/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.h +++ b/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Isode Limited. + * Copyright (c) 2016-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -12,12 +12,10 @@ #import <Sparkle/Sparkle.h> -namespace Swift { - class SparkleAutoUpdater; -} +#include <SwifTools/AutoUpdater/AutoUpdater.h> @interface SparkleAutoUpdaterDelegate : NSObject<SUUpdaterDelegate> -@property (atomic) std::function< void ()> updateDownloadFinished; +@property (atomic) std::function< void (Swift::AutoUpdater::State)> onNewUpdateState; - (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast; @@ -27,6 +25,10 @@ namespace Swift { - (void)updaterDidNotFindUpdate:(SUUpdater *)update; +- (void)updater:(SUUpdater *)updater willDownloadUpdate:(SUAppcastItem *)item withRequest:(NSMutableURLRequest *)request; + +- (void)updater:(SUUpdater *)updater failedToDownloadUpdate:(SUAppcastItem *)item error:(NSError *)error; + - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update; - (void)updater:(SUUpdater *)updater willInstallUpdateOnQuit:(SUAppcastItem *)item immediateInstallationInvocation:(NSInvocation *)invocation; diff --git a/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.mm b/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.mm index 6e832ba..be58355 100644 --- a/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.mm +++ b/SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.mm @@ -1,10 +1,10 @@ /* - * Copyright (c) 2016 Isode Limited. + * Copyright (c) 2016-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#import "SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.h" +#import <SwifTools/AutoUpdater/SparkleAutoUpdaterDelegate.h> #include <string> @@ -16,11 +16,12 @@ using namespace Swift; @implementation SparkleAutoUpdaterDelegate -@synthesize updateDownloadFinished; +@synthesize onNewUpdateState; - (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast { (void)updater; (void)appcast; + onNewUpdateState(AutoUpdater::State::DownloadingUpdate); } - (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update { @@ -35,6 +36,21 @@ using namespace Swift; - (void)updaterDidNotFindUpdate:(SUUpdater *)updater { (void)updater; + onNewUpdateState(AutoUpdater::State::NoUpdateAvailable); +} + +- (void)updater:(SUUpdater *)updater willDownloadUpdate:(SUAppcastItem *)item withRequest:(NSMutableURLRequest *)request { + (void)updater; + (void)item; + (void)request; + onNewUpdateState(AutoUpdater::State::DownloadingUpdate); +} + +- (void)updater:(SUUpdater *)updater failedToDownloadUpdate:(SUAppcastItem *)item error:(NSError *)error { + (void)updater; + (void)item; + SWIFT_LOG(error) << ns2StdString([error localizedDescription]) << std::endl; + onNewUpdateState(AutoUpdater::State::ErrorCheckingForUpdate); } - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update { @@ -46,12 +62,18 @@ using namespace Swift; (void)updater; (void)item; (void)invocation; - updateDownloadFinished(); + onNewUpdateState(AutoUpdater::State::RestartToInstallUpdate); } - (void)updater:(SUUpdater *)updater didAbortWithError:(NSError *)error { (void)updater; - SWIFT_LOG(error) << ns2StdString([error localizedDescription]) << std::endl; + if ([error code] == SUNoUpdateError) { + onNewUpdateState(AutoUpdater::State::NoUpdateAvailable); + } + else { + SWIFT_LOG(error) << ns2StdString([error localizedDescription]) << std::endl; + onNewUpdateState(AutoUpdater::State::ErrorCheckingForUpdate); + } } @end diff --git a/Swift/QtUI/QtAboutWidget.cpp b/Swift/QtUI/QtAboutWidget.cpp index 9047525..3bc124a 100644 --- a/Swift/QtUI/QtAboutWidget.cpp +++ b/Swift/QtUI/QtAboutWidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -10,6 +10,7 @@ #include <QFile> #include <QIcon> #include <QLabel> +#include <QProgressBar> #include <QPushButton> #include <QTextEdit> #include <QTextStream> @@ -19,6 +20,8 @@ #include <Swiften/Base/Log.h> #include <Swiften/Base/Platform.h> +#include <SwifTools/AutoUpdater/AutoUpdater.h> + #include <Swift/QtUI/QtSwiftUtil.h> #include <Swift/QtUI/QtUISettingConstants.h> #include <Swift/QtUI/QtUpdateFeedSelectionDialog.h> @@ -26,7 +29,7 @@ namespace Swift { -QtAboutWidget::QtAboutWidget(SettingsProvider* settingsProvider) : QDialog(), settingsProvider_(settingsProvider) { +QtAboutWidget::QtAboutWidget(SettingsProvider* settingsProvider, AutoUpdater* autoUpdater) : QDialog(), settingsProvider_(settingsProvider), autoUpdater_(autoUpdater) { #ifndef Q_OS_MAC setWindowTitle(QString(tr("About %1")).arg("Swift")); #endif @@ -49,18 +52,32 @@ QtAboutWidget::QtAboutWidget(SettingsProvider* settingsProvider) : QDialog(), se versionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); mainLayout->addWidget(versionLabel); - settingsChangedConnection_ = settingsProvider_->onSettingChanged.connect([&](const std::string& path) { - if (path == QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL.getKey() || path == QtUISettingConstants::ENABLE_SOFTWARE_UPDATES.getKey()) { - updateUpdateInfoLabel(); - } - }); + if (autoUpdater_) { + settingsChangedConnection_ = settingsProvider_->onSettingChanged.connect([&](const std::string& path) { + if (path == QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL.getKey() || path == QtUISettingConstants::ENABLE_SOFTWARE_UPDATES.getKey()) { + updateUpdateInfo(); + } + }); + + autoUpdaterChangeConnection_ = autoUpdater_->onUpdateStateChanged.connect([&](AutoUpdater::State /*updatedState*/) { + updateUpdateInfo(); + }); + } + + updateChannelInfoLabel_ = new QLabel("", this); + updateChannelInfoLabel_->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByMouse); + connect(updateChannelInfoLabel_, SIGNAL(linkActivated(const QString &)), this, SLOT(handleChangeUpdateChannelClicked())); + mainLayout->addWidget(updateChannelInfoLabel_); - updateInfoLabel_ = new QLabel("", this); - updateInfoLabel_->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByMouse); - connect(updateInfoLabel_, SIGNAL(linkActivated(const QString &)), this, SLOT(handleChangeUpdateChannelClicked())); - mainLayout->addWidget(updateInfoLabel_); + updateStateInfoLabel_ = new QLabel("", this); + mainLayout->addWidget(updateStateInfoLabel_); - updateUpdateInfoLabel(); + updateProgressBar_ = new QProgressBar(this); + updateProgressBar_->setMinimum(0); + updateProgressBar_->setMaximum(0); + mainLayout->addWidget(updateProgressBar_); + + updateUpdateInfo(); if (QCoreApplication::translate("TRANSLATION_INFO", "TRANSLATION_AUTHOR") != "TRANSLATION_AUTHOR") { mainLayout->addWidget(new QLabel(QString("<center><font size='-1'>") + QString(tr("Using the English translation by\n%1")).arg(QCoreApplication::translate("TRANSLATION_INFO", "TRANSLATION_AUTHOR")).replace("\n", "<br/>") + "</font></center>", this)); @@ -129,7 +146,12 @@ void QtAboutWidget::openPlainTextWindow(const QString& path) { } } -void QtAboutWidget::updateUpdateInfoLabel() { +void QtAboutWidget::updateUpdateInfo() { + updateChannelInfoLabel_->hide(); + updateStateInfoLabel_->hide(); + updateProgressBar_->hide(); + // Currently auto updating is only supported on macOS. +#ifdef SWIFTEN_PLATFORM_MACOSX if (settingsProvider_->getSetting(QtUISettingConstants::ENABLE_SOFTWARE_UPDATES)) { if (!settingsProvider_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL).empty()) { QString updateFeedDescription; @@ -147,17 +169,48 @@ void QtAboutWidget::updateUpdateInfoLabel() { addUpdateFeedDialogLink = true; } auto updateFeedDialogLink = QString( addUpdateFeedDialogLink ? "<a href=\"#\">%1</a>" : "" ).arg(tr("Change the update channel.")); - updateInfoLabel_->setText(QString("<center><font size='-1'>%1<br/>%2</font></center>").arg(updateFeedDescription, updateFeedDialogLink)); - updateInfoLabel_->show(); - } - else { - updateInfoLabel_->hide(); + updateChannelInfoLabel_->setText(QString("<center><font size='-1'>%1<br/>%2</font></center>").arg(updateFeedDescription, updateFeedDialogLink)); + updateChannelInfoLabel_->show(); + + auto currentState = autoUpdater_->getCurrentState(); + auto currentStateStringPattern = QString("<center><font size='-1'>%1</font></center>"); + switch (currentState) { + case AutoUpdater::State::NotCheckedForUpdatesYet: + // Simply not showing any current state info. + break; + case AutoUpdater::State::CheckingForUpdate: + updateStateInfoLabel_->setText(currentStateStringPattern.arg(tr("Checking for updates…"))); + updateStateInfoLabel_->show(); + updateProgressBar_->show(); + break; + case AutoUpdater::State::ErrorCheckingForUpdate: + updateStateInfoLabel_->setText(currentStateStringPattern.arg(tr("Error checking for updates!"))); + updateStateInfoLabel_->show(); + break; + case AutoUpdater::State::NoUpdateAvailable: + updateStateInfoLabel_->setText(currentStateStringPattern.arg(tr("Swift is up to date."))); + updateStateInfoLabel_->show(); + break; + case AutoUpdater::State::DownloadingUpdate: + updateStateInfoLabel_->setText(currentStateStringPattern.arg(tr("Downloading update…"))); + updateStateInfoLabel_->show(); + updateProgressBar_->show(); + break; + case AutoUpdater::State::RestartToInstallUpdate: + updateStateInfoLabel_->setText(currentStateStringPattern.arg(tr("Update will be installed when you next restart Swift."))); + updateStateInfoLabel_->show(); + break; + } } } - else { - updateInfoLabel_->hide(); - } +#endif + setFixedSize(minimumSizeHint()); +} +void QtAboutWidget::showEvent(QShowEvent*) { + if (autoUpdater_) { + autoUpdater_->checkForUpdates(); + } } } diff --git a/Swift/QtUI/QtAboutWidget.h b/Swift/QtUI/QtAboutWidget.h index fb54c6e..b07c6b0 100644 --- a/Swift/QtUI/QtAboutWidget.h +++ b/Swift/QtUI/QtAboutWidget.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -11,15 +11,17 @@ #include <QDialog> class QLabel; +class QProgressBar; namespace Swift { + class AutoUpdater; class SettingsProvider; class QtAboutWidget : public QDialog { Q_OBJECT public: - QtAboutWidget(SettingsProvider* settings); + QtAboutWidget(SettingsProvider* settings, AutoUpdater* autoUpdater); private slots: void handleLicenseClicked(); @@ -28,11 +30,18 @@ namespace Swift { private: void openPlainTextWindow(const QString& path); - void updateUpdateInfoLabel(); + void updateUpdateInfo(); + + protected: + void showEvent(QShowEvent*); private: SettingsProvider* settingsProvider_; - QLabel* updateInfoLabel_ = nullptr; + AutoUpdater* autoUpdater_; + QLabel* updateChannelInfoLabel_ = nullptr; + QLabel* updateStateInfoLabel_ = nullptr; + QProgressBar* updateProgressBar_ = nullptr; boost::signals2::scoped_connection settingsChangedConnection_; + boost::signals2::scoped_connection autoUpdaterChangeConnection_; }; } diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp index 865d8b5..654e921 100644 --- a/Swift/QtUI/QtLoginWindow.cpp +++ b/Swift/QtUI/QtLoginWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -53,7 +53,7 @@ namespace Swift{ -QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings, TimerFactory* timerFactory) : QMainWindow(), settings_(settings), timerFactory_(timerFactory) { +QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings, TimerFactory* timerFactory, AutoUpdater* autoUpdater) : QMainWindow(), settings_(settings), timerFactory_(timerFactory), autoUpdater_(autoUpdater) { uiEventStream_ = uiEventStream; setWindowTitle("Swift"); @@ -442,7 +442,7 @@ void QtLoginWindow::handleCertficateChecked(bool checked) { void QtLoginWindow::handleAbout() { if (!aboutDialog_) { - aboutDialog_ = new QtAboutWidget(settings_); + aboutDialog_ = new QtAboutWidget(settings_, autoUpdater_); aboutDialog_->show(); } else { diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h index c42d65d..674e1e3 100644 --- a/Swift/QtUI/QtLoginWindow.h +++ b/Swift/QtUI/QtLoginWindow.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -25,6 +25,7 @@ class QToolButton; class QComboBox; namespace Swift { + class AutoUpdater; class SettingsProvider; class TimerFactory; @@ -38,7 +39,7 @@ namespace Swift { }; public: - QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings, TimerFactory* timerFactory); + QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings, TimerFactory* timerFactory, AutoUpdater* autoUpdater); void morphInto(MainWindow *mainWindow); virtual void loggedOut(); @@ -109,5 +110,6 @@ namespace Swift { QAction* highlightEditorAction_; TimerFactory* timerFactory_; ClientOptions currentOptions_; + AutoUpdater* autoUpdater_; }; } diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index ee21c4f..b61147d 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -269,12 +269,27 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa splitter_->show(); } + PlatformAutoUpdaterFactory autoUpdaterFactory; + if (autoUpdaterFactory.isSupported() && settingsHierachy_->getSetting(QtUISettingConstants::ENABLE_SOFTWARE_UPDATES) + && !settingsHierachy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL).empty()) { + autoUpdater_ = autoUpdaterFactory.createAutoUpdater(updateChannelToFeed(settingsHierachy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL))); + autoUpdater_->checkForUpdates(); + autoUpdater_->onUpdateStateChanged.connect(boost::bind(&QtSwift::handleAutoUpdaterStateChanged, this, _1)); + + settingsHierachy_->onSettingChanged.connect([&](const std::string& path) { + if (path == QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL.getKey()) { + autoUpdater_->setAppcastFeed(updateChannelToFeed(settingsHierachy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL))); + autoUpdater_->checkForUpdates(); + } + }); + } + for (int i = 0; i < numberOfAccounts; i++) { if (i > 0) { // Don't add the first tray (see note above) systemTrays_.push_back(new QtSystemTray()); } - QtUIFactory* uiFactory = new QtUIFactory(settingsHierachy_, qtSettings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, networkFactories_.getTimerFactory(), statusCache_, startMinimized, !emoticons.empty(), enableAdHocCommandOnJID); + QtUIFactory* uiFactory = new QtUIFactory(settingsHierachy_, qtSettings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, networkFactories_.getTimerFactory(), statusCache_, autoUpdater_, startMinimized, !emoticons.empty(), enableAdHocCommandOnJID); uiFactories_.push_back(uiFactory); MainController* mainController = new MainController( &clientMainThreadCaller_, @@ -295,21 +310,6 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa } connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(handleAboutToQuit())); - - PlatformAutoUpdaterFactory autoUpdaterFactory; - if (autoUpdaterFactory.isSupported() && settingsHierachy_->getSetting(QtUISettingConstants::ENABLE_SOFTWARE_UPDATES) - && !settingsHierachy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL).empty()) { - autoUpdater_ = autoUpdaterFactory.createAutoUpdater(updateChannelToFeed(settingsHierachy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL))); - autoUpdater_->checkForUpdates(); - autoUpdater_->onSuggestRestartToUserToUpdate.connect(boost::bind(&QtSwift::handleRecommendRestartToInstallUpdate, this)); - - settingsHierachy_->onSettingChanged.connect([&](const std::string& path) { - if (path == QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL.getKey()) { - autoUpdater_->setAppcastFeed(updateChannelToFeed(settingsHierachy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL))); - autoUpdater_->checkForUpdates(); - } - }); - } } QtSwift::~QtSwift() { @@ -347,8 +347,21 @@ void QtSwift::handleAboutToQuit() { #endif } -void QtSwift::handleRecommendRestartToInstallUpdate() { - notifier_->showMessage(Notifier::SystemMessage, Q2PSTRING(tr("Swift Update Available")), Q2PSTRING(tr("Restart Swift to update to the new Swift version.")), "", [](){}); +void QtSwift::handleAutoUpdaterStateChanged(AutoUpdater::State updatedState) { + switch (updatedState) { + case AutoUpdater::State::NotCheckedForUpdatesYet: + break; + case AutoUpdater::State::CheckingForUpdate: + break; + case AutoUpdater::State::DownloadingUpdate: + break; + case AutoUpdater::State::ErrorCheckingForUpdate: + break; + case AutoUpdater::State::NoUpdateAvailable: + break; + case AutoUpdater::State::RestartToInstallUpdate: + notifier_->showMessage(Notifier::SystemMessage, Q2PSTRING(tr("Swift Update Available")), Q2PSTRING(tr("Restart Swift to update to the new Swift version.")), "", [](){}); + } } } diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h index 3ad5714..a7dc3cf 100644 --- a/Swift/QtUI/QtSwift.h +++ b/Swift/QtUI/QtSwift.h @@ -1,29 +1,34 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/program_options/variables_map.hpp> +#include <string> + #include <boost/program_options/options_description.hpp> +#include <boost/program_options/variables_map.hpp> -#include <Swiften/TLS/PlatformTLSFactories.h> +#include <Swiften/Base/Platform.h> +#include <Swiften/EventLoop/Qt/QtEventLoop.h> #include <Swiften/Network/BoostNetworkFactories.h> -#include <string> -#include "Swiften/Base/Platform.h" -#include "Swiften/EventLoop/Qt/QtEventLoop.h" -#include "QtSettingsProvider.h" +#include <Swiften/TLS/PlatformTLSFactories.h> + +#include <SwifTools/AutoUpdater/AutoUpdater.h> +#include <SwifTools/Idle/ActualIdleDetector.h> +#include <SwifTools/Idle/PlatformIdleQuerier.h> + +#include <Swift/QtUI/QtSettingsProvider.h> + #if defined(SWIFTEN_PLATFORM_MACOSX) -#include "SwifTools/Application/CocoaApplication.h" -#include "CocoaApplicationActivateHelper.h" +#include <SwifTools/Application/CocoaApplication.h> +#include <CocoaApplicationActivateHelper.h> #endif #if defined(SWIFTEN_PLATFORM_WINDOWS) -#include "WindowsNotifier.h" +#include <WindowsNotifier.h> #endif -#include "SwifTools/Idle/PlatformIdleQuerier.h" -#include "SwifTools/Idle/ActualIdleDetector.h" namespace po = boost::program_options; @@ -35,7 +40,6 @@ namespace Swift { class Dock; class Notifier; class StoragesFactory; - class AutoUpdater; class ApplicationPathProvider; class AvatarStorage; class CapsStorage; @@ -62,7 +66,7 @@ namespace Swift { private slots: void handleAboutToQuit(); - void handleRecommendRestartToInstallUpdate(); + void handleAutoUpdaterStateChanged(AutoUpdater::State updatedState); private: XMLSettingsProvider* loadSettingsFile(const QString& fileName); @@ -88,7 +92,7 @@ namespace Swift { ApplicationPathProvider* applicationPathProvider_; StoragesFactory* storagesFactory_; CertificateStorageFactory* certificateStorageFactory_; - AutoUpdater* autoUpdater_; + AutoUpdater* autoUpdater_ = nullptr; Notifier* notifier_; StatusCache* statusCache_; PlatformIdleQuerier idleQuerier_; diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index 9eed822..16952a0 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -40,7 +40,7 @@ namespace Swift { -QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabsBase* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID) : settings(settings), qtOnlySettings(qtOnlySettings), tabsBase(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), timerFactory_(timerFactory), lastMainWindow(nullptr), loginWindow(nullptr), statusCache(statusCache), startMinimized(startMinimized), emoticonsExist_(emoticonsExist), enableAdHocCommandOnJID_(enableAdHocCommandOnJID) { +QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabsBase* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, AutoUpdater* autoUpdater, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID) : settings(settings), qtOnlySettings(qtOnlySettings), tabsBase(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), timerFactory_(timerFactory), lastMainWindow(nullptr), loginWindow(nullptr), statusCache(statusCache), autoUpdater(autoUpdater), startMinimized(startMinimized), emoticonsExist_(emoticonsExist), enableAdHocCommandOnJID_(enableAdHocCommandOnJID) { chatFontSize = settings->getSetting(QtUISettingConstants::CHATWINDOW_FONT_SIZE); historyFontSize_ = settings->getSetting(QtUISettingConstants::HISTORYWINDOW_FONT_SIZE); this->tabs = dynamic_cast<QtChatTabs*>(tabsBase); @@ -87,7 +87,7 @@ MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) { } LoginWindow* QtUIFactory::createLoginWindow(UIEventStream* eventStream) { - loginWindow = new QtLoginWindow(eventStream, settings, timerFactory_); + loginWindow = new QtLoginWindow(eventStream, settings, timerFactory_, autoUpdater); if (netbookSplitter) { netbookSplitter->insertAtFront(loginWindow); } diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index ce3b533..18bf9fe 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -16,6 +16,7 @@ class QSplitter; namespace Swift { + class AutoUpdater; class QtChatTabs; class QtChatTabsBase; class QtChatTheme; @@ -34,7 +35,7 @@ namespace Swift { class QtUIFactory : public QObject, public UIFactory { Q_OBJECT public: - QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabsBase* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID); + QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabsBase* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, AutoUpdater* autoUpdater, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID); virtual XMLConsoleWidget* createXMLConsoleWidget(); virtual HistoryWindow* createHistoryWindow(UIEventStream*); @@ -74,6 +75,7 @@ namespace Swift { QtMainWindow* lastMainWindow; QtLoginWindow* loginWindow; StatusCache* statusCache; + AutoUpdater* autoUpdater; std::vector<QPointer<QtChatWindow> > chatWindows; bool startMinimized; int chatFontSize; |