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 /Swift | |
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
Diffstat (limited to 'Swift')
-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 |
8 files changed, 151 insertions, 68 deletions
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,93 +1,110 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/QtUI/QtAboutWidget.h> #include <QCoreApplication> #include <QFile> #include <QIcon> #include <QLabel> +#include <QProgressBar> #include <QPushButton> #include <QTextEdit> #include <QTextStream> #include <QVBoxLayout> #include <QtGlobal> #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> #include <Swift/QtUI/SwiftUpdateFeeds.h> 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 setWindowIcon(QIcon(":/logo-icon-16.png")); resize(180, 240); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setAlignment(Qt::AlignHCenter); setLayout(mainLayout); QLabel* iconLabel = new QLabel(this); iconLabel->setPixmap(QIcon(":/logo-shaded-text.256.png").pixmap(90, 90)); iconLabel->setAlignment(Qt::AlignHCenter); mainLayout->addWidget(iconLabel); QLabel* appNameLabel = new QLabel("<center><font size='+1'><b>" + QCoreApplication::applicationName() + "</b></font></center>", this); mainLayout->addWidget(appNameLabel); QLabel* versionLabel = new QLabel((QString("<center><font size='-1'>") + tr("Version %1") + "</font></center><center><font size='-1'><br/>" + QString(tr("Built with Qt %2")) + QString("<br/>") + QString(tr("Running with Qt %3")) + "</font></center>").arg(QCoreApplication::applicationVersion()).arg(QT_VERSION_STR).arg(qVersion())); 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)); } QCoreApplication::translate("TRANSLATION_INFO", "TRANSLATION_LICENSE", "This string contains the license under which this translation is licensed. We ask you to license the translation under the BSD license. Please read http://www.opensource.org/licenses/bsd-license.php, and if you agree to release your translation under this license, use the following (untranslated) text: 'This translation is licensed under the BSD License. See http://www.opensource.org/licenses/bsd-license.php'"); #if defined(SWIFTEN_PLATFORM_WINDOWS) || defined(SWIFTEN_PLATFORM_MACOSX) QPushButton* licenseButton = new QPushButton(tr("View License"), this); mainLayout->addWidget(licenseButton); connect(licenseButton, SIGNAL(clicked()), this, SLOT(handleLicenseClicked())); QPushButton* changelogButton = new QPushButton(tr("View Changes"), this); mainLayout->addWidget(changelogButton); connect(changelogButton, SIGNAL(clicked()), this, SLOT(handleChangelogClicked())); #else // Some Linux desktops have dialog window decorations without close window buttons. // This code adds a dedicated button to close the about window dialog. QHBoxLayout* buttonLayout = new QHBoxLayout(); mainLayout->addLayout(buttonLayout); QPushButton* licenseButton = new QPushButton(tr("View License"), this); buttonLayout->addWidget(licenseButton); connect(licenseButton, SIGNAL(clicked()), this, SLOT(handleLicenseClicked())); QPushButton* changelogButton = new QPushButton(tr("View Changes"), this); buttonLayout->addWidget(changelogButton); connect(changelogButton, SIGNAL(clicked()), this, SLOT(handleChangelogClicked())); buttonLayout->addItem(new QSpacerItem(20,20)); QPushButton* closeButton = new QPushButton(tr("Close"), this); @@ -102,62 +119,98 @@ void QtAboutWidget::handleLicenseClicked() { } void QtAboutWidget::handleChangelogClicked() { openPlainTextWindow(":/ChangeLog.md"); } void QtAboutWidget::handleChangeUpdateChannelClicked() { auto feedSelectionDialog = new QtUpdateFeedSelectionDialog(settingsProvider_); feedSelectionDialog->show(); } void QtAboutWidget::openPlainTextWindow(const QString& path) { QTextEdit* text = new QTextEdit(); text->setAttribute(Qt::WA_DeleteOnClose); text->setReadOnly(true); QFile file(path); if (file.open(QIODevice::ReadOnly)) { QTextStream in(&file); in.setCodec("UTF-8"); text->setPlainText(in.readAll()); file.close(); text->resize(500, 600); text->show(); text->activateWindow(); } else { SWIFT_LOG(error) << "Failed to open " << Q2PSTRING(path) << "." << std::endl; } } -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; auto addUpdateFeedDialogLink = false; if (settingsProvider_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL) == UpdateFeeds::StableChannel) { updateFeedDescription = tr("You are receiving updates from the Stable update channel."); addUpdateFeedDialogLink = true; } else if (settingsProvider_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL) == UpdateFeeds::DevelopmentChannel) { updateFeedDescription = tr("You are receiving updates from the Development update channel."); addUpdateFeedDialogLink = true; } else if (settingsProvider_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL) == UpdateFeeds::TestingChannel) { updateFeedDescription = tr("You are receiving updates from the Testing update channel."); 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,38 +1,47 @@ /* - * 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/signals2/connection.hpp> #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(); void handleChangelogClicked(); void handleChangeUpdateChannelClicked(); 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,86 +1,86 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/QtUI/QtLoginWindow.h> #include <algorithm> #include <cassert> #include <boost/bind.hpp> #include <memory> #include <QApplication> #include <QBoxLayout> #include <QCloseEvent> #include <QComboBox> #include <QCursor> #include <QDebug> #include <QDesktopWidget> #include <QFileDialog> #include <QHBoxLayout> #include <QKeyEvent> #include <QLabel> #include <QMenuBar> #include <QMessageBox> #include <QStatusBar> #include <QToolButton> #include <Swiften/Base/Platform.h> #include <Swiften/Base/Paths.h> #include <Swift/Controllers/SettingConstants.h> #include <Swift/Controllers/Settings/SettingsProvider.h> #include <Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h> #include <Swift/Controllers/UIEvents/RequestHighlightEditorUIEvent.h> #include <Swift/Controllers/UIEvents/RequestXMLConsoleUIEvent.h> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/QtUI/QtAboutWidget.h> #include <Swift/QtUI/QtConnectionSettingsWindow.h> #include <Swift/QtUI/QtMainWindow.h> #include <Swift/QtUI/QtSwiftUtil.h> #include <Swift/QtUI/QtUISettingConstants.h> #include <Swift/QtUI/QtUtilities.h> #ifdef HAVE_SCHANNEL #include "CAPICertificateSelector.h" #include <Swiften/TLS/CAPICertificate.h> #endif #include <Swiften/TLS/PKCS12Certificate.h> 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"); #ifndef Q_OS_MAC #ifdef Q_OS_WIN32 setWindowIcon(QIcon(":/logo-icon-16-win.png")); #else setWindowIcon(QIcon(":/logo-icon-16.png")); #endif #endif QtUtilities::setX11Resource(this, "Main"); setAccessibleName(tr("Swift Login Window")); //setAccessibleDescription(tr("This window is used for providing credentials to log into your XMPP service")); resize(200, 500); setContentsMargins(0,0,0,0); QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); QBoxLayout *topLayout = new QBoxLayout(QBoxLayout::TopToBottom, centralWidget); stack_ = new QStackedWidget(centralWidget); topLayout->addWidget(stack_); topLayout->setMargin(0); loginWidgetWrapper_ = new QWidget(this); loginWidgetWrapper_->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, loginWidgetWrapper_); layout->addStretch(2); QLabel* logo = new QLabel(this); QIcon swiftWithTextLogo = QIcon(":/logo-shaded-text.png"); logo->setPixmap(swiftWithTextLogo.pixmap(QSize(192,192))); @@ -415,61 +415,61 @@ void QtLoginWindow::loginClicked() { } else { onCancelLoginRequest(); } } void QtLoginWindow::setLoginAutomatically(bool loginAutomatically) { loginAutomatically_->setChecked(loginAutomatically); } void QtLoginWindow::handleCertficateChecked(bool checked) { if (checked) { #ifdef HAVE_SCHANNEL certificateFile_ = P2QSTRING(selectCAPICertificate()); if (certificateFile_.isEmpty()) { certificateButton_->setChecked(false); } #else certificateFile_ = QFileDialog::getOpenFileName(this, tr("Select an authentication certificate"), QString(), tr("P12 files (*.cert *.p12 *.pfx);;All files (*.*)")); if (certificateFile_.isEmpty()) { certificateButton_->setChecked(false); } #endif } else { certificateFile_ = ""; } } void QtLoginWindow::handleAbout() { if (!aboutDialog_) { - aboutDialog_ = new QtAboutWidget(settings_); + aboutDialog_ = new QtAboutWidget(settings_, autoUpdater_); aboutDialog_->show(); } else { aboutDialog_->show(); aboutDialog_->raise(); aboutDialog_->activateWindow(); } } void QtLoginWindow::handleShowXMLConsole() { uiEventStream_->send(std::make_shared<RequestXMLConsoleUIEvent>()); } void QtLoginWindow::handleShowFileTransferOverview() { uiEventStream_->send(std::make_shared<RequestFileTransferListUIEvent>()); } void QtLoginWindow::handleShowHighlightEditor() { uiEventStream_->send(std::make_shared<RequestHighlightEditorUIEvent>()); } void QtLoginWindow::handleToggleSounds(bool enabled) { settings_->storeSetting(SettingConstants::PLAY_SOUNDS, enabled); } void QtLoginWindow::handleToggleNotifications(bool enabled) { settings_->storeSetting(SettingConstants::SHOW_NOTIFICATIONS, enabled); } void QtLoginWindow::handleQuit() { 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,71 +1,72 @@ /* - * 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 <QCheckBox> #include <QLineEdit> #include <QMainWindow> #include <QMenuBar> #include <QPointer> #include <QPushButton> #include <QStackedWidget> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIInterfaces/LoginWindow.h> #include <Swift/Controllers/UIInterfaces/MainWindow.h> #include <Swift/QtUI/QtAboutWidget.h> class QLabel; class QToolButton; class QComboBox; namespace Swift { + class AutoUpdater; class SettingsProvider; class TimerFactory; class QtLoginWindow : public QMainWindow, public LoginWindow { Q_OBJECT public: struct QtMenus { QtMenus(QMenu* swiftMenu, QMenu* generalMenu) : swiftMenu(swiftMenu), generalMenu(generalMenu) {} QMenu* swiftMenu; QMenu* generalMenu; }; public: - QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings, TimerFactory* timerFactory); + QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings, TimerFactory* timerFactory, AutoUpdater* autoUpdater); void morphInto(MainWindow *mainWindow); virtual void loggedOut(); virtual void setShowNotificationToggle(bool); virtual void setMessage(const std::string& message); virtual void addAvailableAccount(const std::string& defaultJID, const std::string& defaultPassword, const std::string& defaultCertificate, const ClientOptions& options); virtual void removeAvailableAccount(const std::string& jid); virtual void setLoginAutomatically(bool loginAutomatically); virtual void setIsLoggingIn(bool loggingIn); void selectUser(const std::string& user); bool askUserToTrustCertificatePermanently(const std::string& message, const std::vector<Certificate::ref>& certificate); void hide(); QtMenus getMenus() const; virtual void quit(); signals: void geometryChanged(); private slots: void loginClicked(); void handleCertficateChecked(bool); void handleQuit(); void handleShowXMLConsole(); void handleShowFileTransferOverview(); void handleShowHighlightEditor(); void handleToggleSounds(bool enabled); void handleToggleNotifications(bool enabled); void handleAbout(); void bringToFront(); void toggleBringToFront(); @@ -82,32 +83,33 @@ namespace Swift { void setInitialMenus(); QWidget* loginWidgetWrapper_; QStringList usernames_; QStringList passwords_; QStringList certificateFiles_; std::vector<ClientOptions> options_; QComboBox* username_; QLineEdit* password_; QPushButton* loginButton_; /* If you add a widget here, change setLoggingIn as well.*/ QCheckBox* remember_; QCheckBox* loginAutomatically_; QStackedWidget* stack_; QLabel* message_; QString certificateFile_; QToolButton* certificateButton_; QMenuBar* menuBar_; QMenu* swiftMenu_; QMenu* generalMenu_; QMenu* viewMenu_ = nullptr; QAction* toggleSoundsAction_; QAction* toggleNotificationsAction_; UIEventStream* uiEventStream_; QPointer<QtAboutWidget> aboutDialog_; SettingsProvider* settings_; QAction* xmlConsoleAction_; QAction* fileTransferOverviewAction_; 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 @@ -242,113 +242,126 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa #elif defined(SWIFTEN_PLATFORM_WINDOWS) notifier_ = new WindowsNotifier(SWIFT_APPLICATION_NAME, applicationPathProvider_->getResourcePath("/images/logo-icon-32.png"), systemTray->getQSystemTrayIcon()); #elif defined(SWIFTEN_PLATFORM_LINUX) notifier_ = new FreeDesktopNotifier(SWIFT_APPLICATION_NAME); #elif defined(SWIFTEN_PLATFORM_MACOSX) notifier_ = new NotificationCenterNotifier(); #else notifier_ = new NullNotifier(); #endif #if defined(SWIFTEN_PLATFORM_MACOSX) dock_ = new MacOSXDock(&cocoaApplication_); #else dock_ = new NullDock(); #endif #if defined(SWIFTEN_PLATFORM_MACOSX) uriHandler_ = new QtURIHandler(); #elif defined(SWIFTEN_PLATFORM_WIN32) uriHandler_ = new NullURIHandler(); #else uriHandler_ = new QtDBUSURIHandler(); #endif statusCache_ = new StatusCache(applicationPathProvider_); if (splitter_) { 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_, &networkFactories_, uiFactory, settingsHierachy_, systemTrays_[i], soundPlayer_, storagesFactory_, certificateStorageFactory_, dock_, notifier_, uriHandler_, &idleDetector_, emoticons, options.count("latency-debug") > 0); mainControllers_.push_back(mainController); } 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() { delete autoUpdater_; for (auto* factory : uiFactories_) { delete factory; } for (auto* controller : mainControllers_) { delete controller; } delete notifier_; for (auto* tray : systemTrays_) { delete tray; } delete tabs_; delete chatWindowFactory_; delete splitter_; delete settingsHierachy_; delete qtSettings_; delete xmlSettings_; delete statusCache_; delete uriHandler_; delete dock_; delete soundPlayer_; delete certificateStorageFactory_; delete storagesFactory_; delete applicationPathProvider_; } void QtSwift::handleAboutToQuit() { #if defined(SWIFTEN_PLATFORM_MACOSX) // This is required so Sparkle knows about the application shutting down // and can update the application in background. CocoaUIHelpers::sendCocoaApplicationWillTerminateNotification(); #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,101 +1,105 @@ /* - * 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; class QSplitter; namespace Swift { class QtUIFactory; class CertificateStorageFactory; class Dock; class Notifier; class StoragesFactory; - class AutoUpdater; class ApplicationPathProvider; class AvatarStorage; class CapsStorage; class MainController; class QtSystemTray; class QtChatTabsBase; class QtChatWindowFactory; class QtSoundPlayer; class QtMUCSearchWindowFactory; class QtUserSearchWindowFactory; class EventLoop; class URIHandler; class SettingsProviderHierachy; class XMLSettingsProvider; class StatusCache; class QtSingleWindow; class QtSwift : public QObject { Q_OBJECT public: QtSwift(const po::variables_map& options); static po::options_description getOptionsDescription(); ~QtSwift(); private slots: void handleAboutToQuit(); - void handleRecommendRestartToInstallUpdate(); + void handleAutoUpdaterStateChanged(AutoUpdater::State updatedState); private: XMLSettingsProvider* loadSettingsFile(const QString& fileName); void loadEmoticonsFile(const QString& fileName, std::map<std::string, std::string>& emoticons); static const std::string& updateChannelToFeed(const std::string& channel); private: QtEventLoop clientMainThreadCaller_; PlatformTLSFactories tlsFactories_; BoostNetworkFactories networkFactories_; QtChatWindowFactory* chatWindowFactory_; std::vector<MainController*> mainControllers_; std::vector<QtSystemTray*> systemTrays_; std::vector<QtUIFactory*> uiFactories_; QtSettingsProvider* qtSettings_; XMLSettingsProvider* xmlSettings_; SettingsProviderHierachy* settingsHierachy_; QtSingleWindow* splitter_; QtSoundPlayer* soundPlayer_; Dock* dock_; URIHandler* uriHandler_; QtChatTabsBase* tabs_; ApplicationPathProvider* applicationPathProvider_; StoragesFactory* storagesFactory_; CertificateStorageFactory* certificateStorageFactory_; - AutoUpdater* autoUpdater_; + AutoUpdater* autoUpdater_ = nullptr; Notifier* notifier_; StatusCache* statusCache_; PlatformIdleQuerier idleQuerier_; ActualIdleDetector idleDetector_; #if defined(SWIFTEN_PLATFORM_MACOSX) CocoaApplication cocoaApplication_; CocoaApplicationActivateHelper cocoaApplicationActivateHelper_; #endif }; } 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,120 +1,120 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/QtUI/QtUIFactory.h> #include <algorithm> #include <QSplitter> #include <Swiften/Whiteboard/WhiteboardSession.h> #include <Swift/Controllers/Settings/SettingsProviderHierachy.h> #include <Swift/QtUI/MUCSearch/QtMUCSearchWindow.h> #include <Swift/QtUI/QtAdHocCommandWindow.h> #include <Swift/QtUI/QtBlockListEditorWindow.h> #include <Swift/QtUI/QtChatTabs.h> #include <Swift/QtUI/QtChatTabsBase.h> #include <Swift/QtUI/QtChatWindow.h> #include <Swift/QtUI/QtChatWindowFactory.h> #include <Swift/QtUI/QtContactEditWindow.h> #include <Swift/QtUI/QtFileTransferListWidget.h> #include <Swift/QtUI/QtHighlightEditor.h> #include <Swift/QtUI/QtHistoryWindow.h> #include <Swift/QtUI/QtJoinMUCWindow.h> #include <Swift/QtUI/QtLoginWindow.h> #include <Swift/QtUI/QtMainWindow.h> #include <Swift/QtUI/QtProfileWindow.h> #include <Swift/QtUI/QtSettingsProvider.h> #include <Swift/QtUI/QtSingleWindow.h> #include <Swift/QtUI/QtSwiftUtil.h> #include <Swift/QtUI/QtSystemTray.h> #include <Swift/QtUI/QtUISettingConstants.h> #include <Swift/QtUI/QtXMLConsoleWidget.h> #include <Swift/QtUI/UserSearch/QtUserSearchWindow.h> #include <Swift/QtUI/Whiteboard/QtWhiteboardWindow.h> 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); } XMLConsoleWidget* QtUIFactory::createXMLConsoleWidget() { QtXMLConsoleWidget* widget = new QtXMLConsoleWidget(); tabsBase->addTab(widget); showTabs(); widget->show(); return widget; } HistoryWindow* QtUIFactory::createHistoryWindow(UIEventStream* uiEventStream) { QtHistoryWindow* window = new QtHistoryWindow(settings, uiEventStream); tabsBase->addTab(window); showTabs(); connect(window, SIGNAL(fontResized(int)), this, SLOT(handleHistoryWindowFontResized(int))); window->handleFontResized(historyFontSize_); window->show(); return window; } void QtUIFactory::handleHistoryWindowFontResized(int size) { historyFontSize_ = size; settings->storeSetting(QtUISettingConstants::HISTORYWINDOW_FONT_SIZE, size); } FileTransferListWidget* QtUIFactory::createFileTransferListWidget() { QtFileTransferListWidget* widget = new QtFileTransferListWidget(); tabsBase->addTab(widget); showTabs(); widget->show(); return widget; } MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) { lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_, enableAdHocCommandOnJID_); if (tabs) { tabs->setViewMenu(lastMainWindow->getMenus()[0]); } return lastMainWindow; } LoginWindow* QtUIFactory::createLoginWindow(UIEventStream* eventStream) { - loginWindow = new QtLoginWindow(eventStream, settings, timerFactory_); + loginWindow = new QtLoginWindow(eventStream, settings, timerFactory_, autoUpdater); if (netbookSplitter) { netbookSplitter->insertAtFront(loginWindow); } connect(systemTray, SIGNAL(clicked()), loginWindow, SLOT(toggleBringToFront())); #ifndef SWIFT_MOBILE QVariant loginWindowGeometryVariant = qtOnlySettings->getQSettings()->value("loginWindowGeometry"); if (loginWindowGeometryVariant.isValid()) { loginWindow->restoreGeometry(loginWindowGeometryVariant.toByteArray()); } connect(loginWindow, SIGNAL(geometryChanged()), this, SLOT(handleLoginWindowGeometryChanged())); if (startMinimized) loginWindow->hide(); #endif return loginWindow; } void QtUIFactory::handleLoginWindowGeometryChanged() { qtOnlySettings->getQSettings()->setValue("loginWindowGeometry", loginWindow->saveGeometry()); } EventWindow* QtUIFactory::createEventWindow() { return lastMainWindow->getEventWindow(); } ChatListWindow* QtUIFactory::createChatListWindow(UIEventStream*) { return lastMainWindow->getChatListWindow(); } MUCSearchWindow* QtUIFactory::createMUCSearchWindow() { return new QtMUCSearchWindow(); 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,84 +1,86 @@ /* - * 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 <vector> #include <QObject> #include <QPointer> #include <Swift/Controllers/UIInterfaces/UIFactory.h> class QSplitter; namespace Swift { + class AutoUpdater; class QtChatTabs; class QtChatTabsBase; class QtChatTheme; class QtChatWindow; class QtChatWindowFactory; class QtLoginWindow; class QtMainWindow; class QtSettingsProvider; class QtSingleWindow; class QtSystemTray; class SettingsProviderHierachy; class StatusCache; class TimerFactory; class WhiteboardSession; 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*); virtual MainWindow* createMainWindow(UIEventStream* eventStream); virtual LoginWindow* createLoginWindow(UIEventStream* eventStream); virtual EventWindow* createEventWindow(); virtual ChatListWindow* createChatListWindow(UIEventStream*); virtual MUCSearchWindow* createMUCSearchWindow(); virtual ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream); virtual UserSearchWindow* createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream, const std::set<std::string>& groups); virtual JoinMUCWindow* createJoinMUCWindow(UIEventStream* uiEventStream); virtual ProfileWindow* createProfileWindow(); virtual ContactEditWindow* createContactEditWindow(); virtual FileTransferListWidget* createFileTransferListWidget(); virtual WhiteboardWindow* createWhiteboardWindow(std::shared_ptr<WhiteboardSession> whiteboardSession); virtual HighlightEditorWindow* createHighlightEditorWindow(); virtual BlockListEditorWidget* createBlockListEditorWidget(); virtual AdHocCommandWindow* createAdHocCommandWindow(std::shared_ptr<OutgoingAdHocCommandSession> command); private slots: void handleLoginWindowGeometryChanged(); void handleChatWindowFontResized(int); void handleHistoryWindowFontResized(int); private: void showTabs(); private: SettingsProviderHierachy* settings; QtSettingsProvider* qtOnlySettings; QtChatTabsBase* tabsBase; QtChatTabs* tabs; QtSingleWindow* netbookSplitter; QtSystemTray* systemTray; QtChatWindowFactory* chatWindowFactory; TimerFactory* timerFactory_; QtMainWindow* lastMainWindow; QtLoginWindow* loginWindow; StatusCache* statusCache; + AutoUpdater* autoUpdater; std::vector<QPointer<QtChatWindow> > chatWindows; bool startMinimized; int chatFontSize; int historyFontSize_; bool emoticonsExist_; bool enableAdHocCommandOnJID_; }; } |