summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/QtUI/QtSwift.cpp')
-rw-r--r--Swift/QtUI/QtSwift.cpp567
1 files changed, 391 insertions, 176 deletions
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 183f64d..73fd733 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -1,50 +1,58 @@
/*
- * Copyright (c) 2010-2013 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
+ * Copyright (c) 2010-2019 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
*/
#include <Swift/QtUI/QtSwift.h>
-#include <string>
#include <map>
+#include <string>
#include <boost/bind.hpp>
-#include <QFile>
-#include <QMessageBox>
#include <QApplication>
+#include <QFile>
+#include <QFontDatabase>
#include <QMap>
+#include <QMessageBox>
#include <qdebug.h>
#include <Swiften/Base/Log.h>
#include <Swiften/Base/Path.h>
+#include <Swiften/Base/Paths.h>
#include <Swiften/Base/Platform.h>
-#include <Swiften/Elements/Presence.h>
+#include <Swiften/Base/String.h>
#include <Swiften/Client/Client.h>
-#include <Swiften/Base/Paths.h>
+#include <Swiften/Elements/Presence.h>
+#include <Swiften/StringCodecs/Base64.h>
+#include <Swiften/TLS/TLSContextFactory.h>
#include <SwifTools/Application/PlatformApplicationPathProvider.h>
#include <SwifTools/AutoUpdater/AutoUpdater.h>
#include <SwifTools/AutoUpdater/PlatformAutoUpdaterFactory.h>
+#include <SwifTools/EmojiMapper.h>
-#include <Swift/Controllers/Storages/CertificateFileStorageFactory.h>
-#include <Swift/Controllers/Storages/FileStoragesFactory.h>
-#include <Swift/Controllers/Settings/XMLSettingsProvider.h>
-#include <Swift/Controllers/Settings/SettingsProviderHierachy.h>
-#include <Swift/Controllers/MainController.h>
#include <Swift/Controllers/ApplicationInfo.h>
#include <Swift/Controllers/BuildVersion.h>
+#include <Swift/Controllers/AccountController.h>
+#include <Swift/Controllers/SettingConstants.h>
+#include <Swift/Controllers/Settings/SettingsProviderHierachy.h>
+#include <Swift/Controllers/Settings/XMLSettingsProvider.h>
#include <Swift/Controllers/StatusCache.h>
+#include <Swift/Controllers/Storages/CertificateFileStorageFactory.h>
+#include <Swift/Controllers/Storages/FileStoragesFactory.h>
-#include <Swift/QtUI/QtLoginWindow.h>
#include <Swift/QtUI/QtChatTabs.h>
-#include <Swift/QtUI/QtSystemTray.h>
+#include <Swift/QtUI/QtChatWindowFactory.h>
+#include <Swift/QtUI/QtLoginWindow.h>
+#include <Swift/QtUI/QtSingleWindow.h>
#include <Swift/QtUI/QtSoundPlayer.h>
#include <Swift/QtUI/QtSwiftUtil.h>
+#include <Swift/QtUI/QtSystemTray.h>
#include <Swift/QtUI/QtUIFactory.h>
-#include <Swift/QtUI/QtChatWindowFactory.h>
-#include <Swift/QtUI/QtSingleWindow.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
+#include <Swift/QtUI/SwiftUpdateFeeds.h>
#if defined(SWIFTEN_PLATFORM_WINDOWS)
#include <Swift/QtUI/WindowsNotifier.h>
@@ -52,6 +60,8 @@
#include <SwifTools/Notifier/GrowlNotifier.h>
#elif defined(SWIFTEN_PLATFORM_LINUX)
#include <Swift/QtUI/FreeDesktopNotifier.h>
+#elif defined(SWIFTEN_PLATFORM_MACOSX)
+#include <SwifTools/Notifier/NotificationCenterNotifier.h>
#else
#include <SwifTools/Notifier/NullNotifier.h>
#endif
@@ -70,198 +80,403 @@
#include <Swift/QtUI/QtDBUSURIHandler.h>
#endif
-namespace Swift{
-
#if defined(SWIFTEN_PLATFORM_MACOSX)
-//#define SWIFT_APPCAST_URL "http://swift.im/appcast/swift-mac-dev.xml"
-#else
-//#define SWIFT_APPCAST_URL ""
+#include <Swift/QtUI/CocoaUIHelpers.h>
#endif
+namespace Swift{
+
po::options_description QtSwift::getOptionsDescription() {
- po::options_description result("Options");
- result.add_options()
- ("debug", "Turn on debug logging")
- ("help", "Show this help message")
- ("version", "Show version information")
- ("netbook-mode", "Use netbook mode display (unsupported)")
- ("no-tabs", "Don't manage chat windows in tabs (unsupported)")
- ("latency-debug", "Use latency debugging (unsupported)")
- ("multi-account", po::value<int>()->default_value(1), "Number of accounts to open windows for (unsupported)")
- ("start-minimized", "Don't show the login/roster window at startup")
+ po::options_description result("Options");
+ result.add_options()
+ ("debug", "Turn on debug logging")
+ ("help", "Show this help message")
+ ("version", "Show version information")
+ ("no-tabs", "Don't manage chat windows in tabs (unsupported)")
+ ("latency-debug", "Use latency debugging (unsupported)")
+ ("enable-jid-adhocs", "Enable AdHoc commands to custom JIDs.")
#if QT_VERSION >= 0x040800
- ("language", po::value<std::string>(), "Use a specific language, instead of the system-wide one")
+ ("language", po::value<std::string>(), "Use a specific language, instead of the system-wide one")
#endif
- ;
- return result;
+ ("logfile", po::value<std::string>()->implicit_value(""), "Save all logging information to a file")
+ ("enable-future", "Enable future features (unsupported). This will persist across restarts")
+ ("disable-future", "Disable future features. This will persist across restarts")
+ ;
+ return result;
}
XMLSettingsProvider* QtSwift::loadSettingsFile(const QString& fileName) {
- QFile configFile(fileName);
- if (configFile.exists() && configFile.open(QIODevice::ReadOnly)) {
- QString xmlString;
- while (!configFile.atEnd()) {
- QByteArray line = configFile.readLine();
- xmlString += line + "\n";
- }
- return new XMLSettingsProvider(Q2PSTRING(xmlString));
- }
- return new XMLSettingsProvider("");
+ QFile configFile(fileName);
+ if (configFile.exists() && configFile.open(QIODevice::ReadOnly)) {
+ QString xmlString;
+ while (!configFile.atEnd()) {
+ QByteArray line = configFile.readLine();
+ xmlString += line + "\n";
+ }
+ return new XMLSettingsProvider(Q2PSTRING(xmlString));
+ }
+ return new XMLSettingsProvider("");
}
void QtSwift::loadEmoticonsFile(const QString& fileName, std::map<std::string, std::string>& emoticons) {
- QFile file(fileName);
- if (file.exists() && file.open(QIODevice::ReadOnly)) {
- while (!file.atEnd()) {
- QString line = file.readLine();
- line.replace("\n", "");
- line.replace("\r", "");
- QStringList tokens = line.split(" ");
- if (tokens.size() == 2) {
- QString emoticonFile = tokens[1];
- if (!emoticonFile.startsWith(":/") && !emoticonFile.startsWith("qrc:/")) {
- emoticonFile = "file://" + emoticonFile;
- }
- emoticons[Q2PSTRING(tokens[0])] = Q2PSTRING(emoticonFile);
- }
- }
- }
+ QFile file(fileName);
+ if (file.exists() && file.open(QIODevice::ReadOnly)) {
+ while (!file.atEnd()) {
+ QString line = file.readLine();
+ line.replace("\n", "");
+ line.replace("\r", "");
+ QStringList tokens = line.split(" ");
+ if (tokens.size() == 2) {
+ QString emoticonFile = tokens[1];
+ if (!emoticonFile.startsWith(":/") && !emoticonFile.startsWith("qrc:/")) {
+ emoticonFile = "file://" + emoticonFile;
+ }
+ emoticons[Q2PSTRING(tokens[0])] = Q2PSTRING(emoticonFile);
+ }
+ }
+ }
}
-QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMainThreadCaller_), autoUpdater_(NULL), idleDetector_(&idleQuerier_, networkFactories_.getTimerFactory(), 1000) {
- QCoreApplication::setApplicationName(SWIFT_APPLICATION_NAME);
- QCoreApplication::setOrganizationName(SWIFT_ORGANIZATION_NAME);
- QCoreApplication::setOrganizationDomain(SWIFT_ORGANIZATION_DOMAIN);
- QCoreApplication::setApplicationVersion(buildVersion);
-
- qtSettings_ = new QtSettingsProvider();
- xmlSettings_ = loadSettingsFile(P2QSTRING(pathToString(Paths::getExecutablePath() / "system-settings.xml")));
- settingsHierachy_ = new SettingsProviderHierachy();
- settingsHierachy_->addProviderToTopOfStack(xmlSettings_);
- settingsHierachy_->addProviderToTopOfStack(qtSettings_);
-
- std::map<std::string, std::string> emoticons;
- loadEmoticonsFile(":/emoticons/emoticons.txt", emoticons);
- loadEmoticonsFile(P2QSTRING(pathToString(Paths::getExecutablePath() / "emoticons.txt")), emoticons);
-
- if (options.count("netbook-mode")) {
- splitter_ = new QtSingleWindow(qtSettings_);
- } else {
- splitter_ = NULL;
- }
-
- int numberOfAccounts = 1;
- try {
- numberOfAccounts = options["multi-account"].as<int>();
- } catch (...) {
- /* This seems to fail on a Mac when the .app is launched directly (the usual path).*/
- numberOfAccounts = 1;
- }
-
- if (options.count("debug")) {
- Log::setLogLevel(Swift::Log::debug);
- }
-
- tabs_ = options.count("no-tabs") && !splitter_ ? NULL : new QtChatTabs(splitter_ != NULL);
- bool startMinimized = options.count("start-minimized") > 0;
- applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME);
- storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir(), networkFactories_.getCryptoProvider());
- certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory(), networkFactories_.getCryptoProvider());
- chatWindowFactory_ = new QtChatWindowFactory(splitter_, settingsHierachy_, qtSettings_, tabs_, "");
- soundPlayer_ = new QtSoundPlayer(applicationPathProvider_);
-
- // Ugly, because the dock depends on the tray, but the temporary
- // multi-account hack creates one tray per account.
- QtSystemTray* systemTray = new QtSystemTray();
- systemTrays_.push_back(systemTray);
+const std::string& QtSwift::updateChannelToFeed(const std::string& channel) {
+ static const std::string invalidChannel;
+ if (channel == UpdateFeeds::StableChannel) {
+ return UpdateFeeds::StableAppcastFeed;
+ }
+ else if (channel == UpdateFeeds::TestingChannel) {
+ return UpdateFeeds::TestingAppcastFeed;
+ }
+ else if (channel == UpdateFeeds::DevelopmentChannel) {
+ return UpdateFeeds::DevelopmentAppcastFeed;
+ }
+ else {
+ return invalidChannel;
+ }
+}
+
+QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMainThreadCaller_), autoUpdater_(nullptr), idleDetector_(&idleQuerier_, networkFactories_.getTimerFactory(), 1000) {
+ QCoreApplication::setApplicationName(SWIFT_APPLICATION_NAME);
+ QCoreApplication::setOrganizationName(SWIFT_ORGANIZATION_NAME);
+ QCoreApplication::setOrganizationDomain(SWIFT_ORGANIZATION_DOMAIN);
+ QCoreApplication::setApplicationVersion(buildVersion);
+
+ qtSettings_ = new QtSettingsProvider();
+ xmlSettings_ = loadSettingsFile(P2QSTRING(pathToString(Paths::getExecutablePath() / "system-settings.xml")));
+ settingsHierarchy_ = new SettingsProviderHierachy();
+ settingsHierarchy_->addProviderToTopOfStack(xmlSettings_);
+ settingsHierarchy_->addProviderToTopOfStack(qtSettings_);
+
+ networkFactories_.getTLSContextFactory()->setDisconnectOnCardRemoval(settingsHierarchy_->getSetting(SettingConstants::DISCONNECT_ON_CARD_REMOVAL));
+
+ loadEmoticonsFile(":/emoticons/emoticons.txt", emoticons_);
+ loadEmoticonsFile(P2QSTRING(pathToString(Paths::getExecutablePath() / "emoticons.txt")), emoticons_);
+
+ splitter_ = new QtSingleWindow(qtSettings_);
+ connect(splitter_, SIGNAL(wantsToAddAccount()), this, SLOT(handleWantsToAddAccount()));
+
+ if (options.count("debug")) {
+ Log::setLogLevel(Swift::Log::debug);
+ }
+
+ if (options.count("enable-future")) {
+ settingsHierarchy_->storeSetting(SettingConstants::FUTURE, true);
+ }
+
+ if (options.count("disable-future")) {
+ settingsHierarchy_->storeSetting(SettingConstants::FUTURE, false);
+ }
+
+ if (options.count("logfile")) {
+ try {
+ std::string fileName = options["logfile"].as<std::string>();
+ Log::setLogFile(fileName);
+ }
+ catch (...) {
+ SWIFT_LOG(error) << "Error while retrieving the specified log file name from the command line";
+ }
+ }
+ //TODO this old option can be purged
+ useDelayForLatency_ = options.count("latency-debug") > 0;
+
+ // Load fonts
+ std::vector<std::string> fontNames = {
+ "themes/Default/Lato2OFL/Lato-Black.ttf",
+ "themes/Default/Lato2OFL/Lato-BlackItalic.ttf",
+ "themes/Default/Lato2OFL/Lato-Bold.ttf",
+ "themes/Default/Lato2OFL/Lato-BoldItalic.ttf",
+ "themes/Default/Lato2OFL/Lato-Hairline.ttf",
+ "themes/Default/Lato2OFL/Lato-HairlineItalic.ttf",
+ "themes/Default/Lato2OFL/Lato-Heavy.ttf",
+ "themes/Default/Lato2OFL/Lato-HeavyItalic.ttf",
+ "themes/Default/Lato2OFL/Lato-Italic.ttf",
+ "themes/Default/Lato2OFL/Lato-Light.ttf",
+ "themes/Default/Lato2OFL/Lato-LightItalic.ttf",
+ "themes/Default/Lato2OFL/Lato-Medium.ttf",
+ "themes/Default/Lato2OFL/Lato-MediumItalic.ttf",
+ "themes/Default/Lato2OFL/Lato-Regular.ttf",
+ "themes/Default/Lato2OFL/Lato-Semibold.ttf",
+ "themes/Default/Lato2OFL/Lato-SemiboldItalic.ttf",
+ "themes/Default/Lato2OFL/Lato-Thin.ttf",
+ "themes/Default/Lato2OFL/Lato-ThinItalic.ttf"
+ };
+
+ for (auto&& fontName : fontNames) {
+ std::string fontPath = std::string(":/") + fontName;
+ int error = QFontDatabase::addApplicationFont(P2QSTRING(fontPath));
+ SWIFT_LOG_ASSERT(error != -1, error) << "Failed to load font " << fontPath;
+ }
+
+#ifdef SWIFTEN_PLATFORM_LINUX
+ std::string fontPath = std::string(":/themes/Default/Noto/NotoColorEmoji.ttf");
+ int error = QFontDatabase::addApplicationFont(P2QSTRING(fontPath));
+ SWIFT_LOG_ASSERT(error != -1, error) << "Failed to load font " << fontPath;
+ QFont::insertSubstitution(QApplication::font().family(),"NotoColorEmoji");
+#endif
+#ifdef SWIFTEN_PLATFORM_WINDOWS
+ QFont::insertSubstitution(QApplication::font().family(), "Segoe UI Emoji");
+#endif
+ enableAdHocCommandOnJID_ = options.count("enable-jid-adhocs") > 0;
+ applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME);
+ storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir(), networkFactories_.getCryptoProvider());
+ certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory(), networkFactories_.getCryptoProvider());
+ soundPlayer_ = new QtSoundPlayer(applicationPathProvider_);
+
+ // Ugly, because the dock depends on the tray, but the temporary
+ // multi-account hack creates one tray per account.
+ QtSystemTray* systemTray = new QtSystemTray();
+ systemTrays_.push_back(systemTray);
#if defined(HAVE_GROWL)
- notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME);
+ notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME);
#elif defined(SWIFTEN_PLATFORM_WINDOWS)
- notifier_ = new WindowsNotifier(SWIFT_APPLICATION_NAME, applicationPathProvider_->getResourcePath("/images/logo-icon-32.png"), systemTray->getQSystemTrayIcon());
+ 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);
+ notifier_ = new FreeDesktopNotifier(SWIFT_APPLICATION_NAME);
+#elif defined(SWIFTEN_PLATFORM_MACOSX)
+ notifier_ = new NotificationCenterNotifier();
#else
- notifier_ = new NullNotifier();
+ notifier_ = new NullNotifier();
#endif
#if defined(SWIFTEN_PLATFORM_MACOSX)
- dock_ = new MacOSXDock(&cocoaApplication_);
+ dock_ = new MacOSXDock(&cocoaApplication_);
#else
- dock_ = new NullDock();
+ dock_ = new NullDock();
#endif
#if defined(SWIFTEN_PLATFORM_MACOSX)
- uriHandler_ = new QtURIHandler();
+ uriHandler_ = new QtURIHandler();
#elif defined(SWIFTEN_PLATFORM_WIN32)
- uriHandler_ = new NullURIHandler();
+ uriHandler_ = new NullURIHandler();
#else
- uriHandler_ = new QtDBUSURIHandler();
+ uriHandler_ = new QtDBUSURIHandler();
#endif
- statusCache_ = new StatusCache(applicationPathProvider_);
-
- if (splitter_) {
- splitter_->show();
- }
-
- 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());
- 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);
- }
-
-
- // PlatformAutoUpdaterFactory autoUpdaterFactory;
- // if (autoUpdaterFactory.isSupported()) {
- // autoUpdater_ = autoUpdaterFactory.createAutoUpdater(SWIFT_APPCAST_URL);
- // autoUpdater_->checkForUpdates();
- // }
+ statusCache_ = new StatusCache(applicationPathProvider_);
+
+ splitter_->show();
+
+ PlatformAutoUpdaterFactory autoUpdaterFactory;
+ if (autoUpdaterFactory.isSupported() && settingsHierarchy_->getSetting(QtUISettingConstants::ENABLE_SOFTWARE_UPDATES)
+ && !settingsHierarchy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL).empty()) {
+ autoUpdater_ = autoUpdaterFactory.createAutoUpdater(updateChannelToFeed(settingsHierarchy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL)));
+ autoUpdater_->checkForUpdates();
+ autoUpdater_->onUpdateStateChanged.connect(boost::bind(&QtSwift::handleAutoUpdaterStateChanged, this, _1));
+
+ settingsHierarchy_->onSettingChanged.connect([&](const std::string& path) {
+ if (path == QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL.getKey()) {
+ autoUpdater_->setAppcastFeed(updateChannelToFeed(settingsHierarchy_->getSetting(QtUISettingConstants::SOFTWARE_UPDATE_CHANNEL)));
+ autoUpdater_->checkForUpdates();
+ }
+ });
+ }
+ migrateLastLoginAccount();
+ restoreAccounts();
+ connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(handleAboutToQuit()));
}
QtSwift::~QtSwift() {
- delete autoUpdater_;
- foreach (QtUIFactory* factory, uiFactories_) {
- delete factory;
- }
- foreach (MainController* controller, mainControllers_) {
- delete controller;
- }
- delete notifier_;
- foreach (QtSystemTray* tray, systemTrays_) {
- delete tray;
- }
- delete tabs_;
- delete splitter_;
- delete settingsHierachy_;
- delete qtSettings_;
- delete xmlSettings_;
- delete statusCache_;
- delete uriHandler_;
- delete dock_;
- delete soundPlayer_;
- delete chatWindowFactory_;
- delete certificateStorageFactory_;
- delete storagesFactory_;
+ delete autoUpdater_;
+ for (auto* factory : uiFactories_) {
+ delete factory;
+ }
+ for (auto* controller : accountControllers_) {
+ delete controller;
+ }
+ delete notifier_;
+ for (auto* tray : systemTrays_) {
+ delete tray;
+ }
+ delete splitter_;
+ delete settingsHierarchy_;
+ 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::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.")), "", [](){});
+ }
+}
+
+void QtSwift::handleWantsToAddAccount() {
+ auto loginWindow = addAccount();
+ if (!settingsHierarchy_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
+ for (const auto& profile : settingsHierarchy_->getAvailableProfiles()) {
+ ProfileSettingsProvider profileSettings(profile, settingsHierarchy_);
+ if (profileSettings.getIntSetting("enabled", 0)) {
+ // No point showing accounts that're already logged in
+ continue;
+ }
+ const auto& password = profileSettings.getStringSetting("pass");
+ const auto& certificate = profileSettings.getStringSetting("certificate");
+ const auto& jid = profileSettings.getStringSetting("jid");
+ const auto& clientOptions = parseClientOptions(profileSettings.getStringSetting("options"));
+ loginWindow->addAvailableAccount(jid, password, certificate, clientOptions);
+ }
+ }
+}
+
+void QtSwift::restoreAccounts() {
+ if (!settingsHierarchy_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
+ for (const auto& profile : settingsHierarchy_->getAvailableProfiles()) {
+ ProfileSettingsProvider profileSettings(profile, settingsHierarchy_);
+ if (!profileSettings.getIntSetting("enabled", 0)) {
+ continue;
+ }
+ const auto& jid = profileSettings.getStringSetting("jid");
+ const auto& password = profileSettings.getStringSetting("pass");
+ const auto& certificate = profileSettings.getStringSetting("certificate");
+ const auto& clientOptions = parseClientOptions(profileSettings.getStringSetting("options"));
+ auto loginWindow = addAccount();
+ loginWindow->addAvailableAccount(jid, password, certificate, clientOptions);
+ loginWindow->loginClicked();
+ }
+ }
+}
+
+void QtSwift::migrateLastLoginAccount() {
+ const SettingsProvider::Setting<bool> loginAutomatically = SettingsProvider::Setting<bool>("loginAutomatically", false);
+ if (settingsHierarchy_->getSetting(loginAutomatically)) {
+ auto selectedLoginJID = settingsHierarchy_->getSetting(SettingsProvider::Setting<std::string>("lastLoginJID", ""));
+ for (const auto& profile : settingsHierarchy_->getAvailableProfiles()) {
+ ProfileSettingsProvider profileSettings(profile, settingsHierarchy_);
+ if (profileSettings.getStringSetting("jid") == selectedLoginJID) {
+ profileSettings.storeInt("enabled", 1);
+ break;
+ }
+ }
+ settingsHierarchy_->storeSetting(loginAutomatically, false);
+ }
+}
+
+QtLoginWindow* QtSwift::addAccount() {
+ if (uiFactories_.size() > 0) {
+ // Don't add the first tray (see note above)
+ systemTrays_.push_back(new QtSystemTray());
+ }
+ auto tabs = new QtChatTabs(settingsHierarchy_, true);
+ QtUIFactory* uiFactory = new QtUIFactory(settingsHierarchy_, qtSettings_, tabs, splitter_, systemTrays_[systemTrays_.size() - 1], networkFactories_.getTimerFactory(), statusCache_, autoUpdater_, emoticons_, enableAdHocCommandOnJID_);
+ uiFactories_.push_back(uiFactory);
+ AccountController* accountController = new AccountController(
+ &clientMainThreadCaller_,
+ &networkFactories_,
+ uiFactory,
+ settingsHierarchy_,
+ systemTrays_[systemTrays_.size() - 1],
+ soundPlayer_,
+ storagesFactory_,
+ certificateStorageFactory_,
+ dock_,
+ notifier_,
+ uriHandler_,
+ &idleDetector_,
+ emoticons_,
+ useDelayForLatency_);
+ accountControllers_.push_back(accountController);
+
+ //FIXME - accountController has already created the window, so we can pass null here and get the old one
+ auto loginWindow = uiFactory->createLoginWindow(nullptr);
+
+ return dynamic_cast<QtLoginWindow*>(loginWindow);
+}
+
+//FIXME: Switch all this to boost::serialise
+
+#define CHECK_PARSE_LENGTH if (i >= segments.size()) {return result;}
+#define PARSE_INT_RAW(defaultValue) CHECK_PARSE_LENGTH intVal = defaultValue; try {intVal = boost::lexical_cast<int>(segments[i]);} catch(const boost::bad_lexical_cast&) {};i++;
+#define PARSE_STRING_RAW CHECK_PARSE_LENGTH stringVal = byteArrayToString(Base64::decode(segments[i]));i++;
+
+#define PARSE_BOOL(option, defaultValue) PARSE_INT_RAW(defaultValue); result.option = (intVal == 1);
+#define PARSE_INT(option, defaultValue) PARSE_INT_RAW(defaultValue); result.option = intVal;
+#define PARSE_STRING(option) PARSE_STRING_RAW; result.option = stringVal;
+#define PARSE_SAFE_STRING(option) PARSE_STRING_RAW; result.option = SafeString(createSafeByteArray(stringVal));
+#define PARSE_URL(option) {PARSE_STRING_RAW; result.option = URL::fromString(stringVal);}
+
+
+ClientOptions QtSwift::parseClientOptions(const std::string& optionString) {
+ ClientOptions result;
+ size_t i = 0;
+ int intVal = 0;
+ std::string stringVal;
+ std::vector<std::string> segments = String::split(optionString, ',');
+
+ PARSE_BOOL(useStreamCompression, 1)
+ PARSE_INT_RAW(-1)
+ switch (intVal) {
+ case 1: result.useTLS = ClientOptions::NeverUseTLS; break;
+ case 2: result.useTLS = ClientOptions::UseTLSWhenAvailable; break;
+ case 3: result.useTLS = ClientOptions::RequireTLS; break;
+ default:;
+ }
+ PARSE_BOOL(allowPLAINWithoutTLS, 0)
+ PARSE_BOOL(useStreamResumption, 0)
+ PARSE_BOOL(useAcks, 1)
+ PARSE_STRING(manualHostname)
+ PARSE_INT(manualPort, -1)
+ PARSE_INT_RAW(-1)
+ switch (intVal) {
+ case 1: result.proxyType = ClientOptions::NoProxy; break;
+ case 2: result.proxyType = ClientOptions::SystemConfiguredProxy; break;
+ case 3: result.proxyType = ClientOptions::SOCKS5Proxy; break;
+ case 4: result.proxyType = ClientOptions::HTTPConnectProxy; break;
+ }
+ PARSE_STRING(manualProxyHostname)
+ PARSE_INT(manualProxyPort, -1)
+ PARSE_URL(boshURL)
+ PARSE_URL(boshHTTPConnectProxyURL)
+ PARSE_SAFE_STRING(boshHTTPConnectProxyAuthID)
+ PARSE_SAFE_STRING(boshHTTPConnectProxyAuthPassword)
+ PARSE_BOOL(tlsOptions.schannelTLS1_0Workaround, false)
+ PARSE_BOOL(singleSignOn, false)
+
+ return result;
+}
+
+
}