summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/MainController.cpp93
-rw-r--r--Swift/Controllers/MainController.h3
-rw-r--r--Swift/Controllers/SettingConstants.cpp3
-rw-r--r--Swift/Controllers/SettingConstants.h11
-rw-r--r--Swift/QtUI/QtLoginWindow.h4
-rw-r--r--Swift/QtUI/QtSingleWindow.cpp71
-rw-r--r--Swift/QtUI/QtSingleWindow.h16
-rw-r--r--Swift/QtUI/QtSwift.cpp190
-rw-r--r--Swift/QtUI/QtSwift.h14
-rw-r--r--Swift/QtUI/QtUIFactory.cpp13
-rw-r--r--Swift/QtUI/QtUIFactory.h4
11 files changed, 241 insertions, 181 deletions
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index f678c0d..91140c2 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -173,36 +173,6 @@ MainController::MainController(
xmppURIController_ = new XMPPURIController(uriHandler_, uiEventStream_);
- std::string selectedLoginJID = settings_->getSetting(SettingConstants::LAST_LOGIN_JID);
- bool loginAutomatically = settings_->getSetting(SettingConstants::LOGIN_AUTOMATICALLY);
- std::string cachedPassword;
- std::string cachedCertificate;
- ClientOptions cachedOptions;
- bool eagle = settings_->getSetting(SettingConstants::FORGET_PASSWORDS);
- if (!eagle) {
- for (auto&& profile : settings->getAvailableProfiles()) {
- ProfileSettingsProvider profileSettings(profile, settings);
- std::string password = profileSettings.getStringSetting("pass");
- std::string certificate = profileSettings.getStringSetting("certificate");
- std::string jid = profileSettings.getStringSetting("jid");
- ClientOptions clientOptions = parseClientOptions(profileSettings.getStringSetting("options"));
-
-#ifdef SWIFTEN_PLATFORM_WIN32
- clientOptions.singleSignOn = settings_->getSetting(SettingConstants::SINGLE_SIGN_ON);
-#endif
-
- loginWindow_->addAvailableAccount(jid, password, certificate, clientOptions);
- if (jid == selectedLoginJID) {
- cachedPassword = password;
- cachedCertificate = certificate;
- cachedOptions = clientOptions;
- }
- }
- loginWindow_->selectUser(selectedLoginJID);
- loginWindow_->setLoginAutomatically(loginAutomatically);
- }
-
-
loginWindow_->onLoginRequest.connect(boost::bind(&MainController::handleLoginRequest, this, _1, _2, _3, _4, _5, _6, _7));
loginWindow_->onPurgeSavedLoginRequest.connect(boost::bind(&MainController::handlePurgeSavedLoginRequest, this, _1));
loginWindow_->onCancelLoginRequest.connect(boost::bind(&MainController::handleCancelLoginRequest, this));
@@ -217,13 +187,6 @@ MainController::MainController(
settings_->onSettingChanged.connect(boost::bind(&MainController::handleSettingChanged, this, _1));
- if (loginAutomatically) {
- profileSettings_ = new ProfileSettingsProvider(selectedLoginJID, settings_);
- /* FIXME: deal with autologin with a cert*/
- handleLoginRequest(selectedLoginJID, cachedPassword, cachedCertificate, CertificateWithKey::ref(), cachedOptions, true, true);
- } else {
- profileSettings_ = nullptr;
- }
}
MainController::~MainController() {
@@ -559,8 +522,7 @@ void MainController::handleLoginRequest(const std::string &username, const std::
profileSettings_->storeString("pass", (remember || loginAutomatically) ? password : "");
std::string optionString = serializeClientOptions(options);
profileSettings_->storeString("options", optionString);
- settings_->storeSetting(SettingConstants::LAST_LOGIN_JID, username);
- settings_->storeSetting(SettingConstants::LOGIN_AUTOMATICALLY, loginAutomatically);
+ profileSettings_->storeInt("enabled", 1);
loginWindow_->addAvailableAccount(profileSettings_->getStringSetting("jid"), profileSettings_->getStringSetting("pass"), profileSettings_->getStringSetting("certificate"), options);
}
@@ -760,6 +722,7 @@ void MainController::signOut() {
if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
purgeCachedCredentials();
}
+ profileSettings_->storeInt("enabled", 0);
eventController_->clear();
logout();
loginWindow_->loggedOut();
@@ -864,6 +827,8 @@ void MainController::handleQuitRequest() {
}
}
+//FIXME: Switch all this to boost::serialise
+
#define SERIALIZE_BOOL(option) result += options.option ? "1" : "0"; result += ",";
#define SERIALIZE_INT(option) result += boost::lexical_cast<std::string>(options.option); result += ",";
#define SERIALIZE_STRING(option) result += Base64::encode(createByteArray(options.option)); result += ",";
@@ -898,55 +863,7 @@ std::string MainController::serializeClientOptions(const ClientOptions& options)
SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthID);
SERIALIZE_SAFE_STRING(boshHTTPConnectProxyAuthPassword);
SERIALIZE_BOOL(tlsOptions.schannelTLS1_0Workaround);
- return result;
-}
-
-#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 MainController::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);
-
+ SERIALIZE_BOOL(singleSignOn);
return result;
}
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 8b62415..7a06a0b 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -132,7 +132,6 @@ namespace Swift {
void handleForceQuit();
void purgeCachedCredentials();
std::string serializeClientOptions(const ClientOptions& options);
- ClientOptions parseClientOptions(const std::string& optionString);
private:
EventLoop* eventLoop_;
@@ -146,7 +145,7 @@ namespace Swift {
bool clientInitialized_;
std::shared_ptr<Client> client_;
SettingsProvider *settings_;
- ProfileSettingsProvider* profileSettings_;
+ ProfileSettingsProvider* profileSettings_ = nullptr;
Dock* dock_;
URIHandler* uriHandler_;
IdleDetector* idleDetector_;
diff --git a/Swift/Controllers/SettingConstants.cpp b/Swift/Controllers/SettingConstants.cpp
index 1191c28..8336200 100644
--- a/Swift/Controllers/SettingConstants.cpp
+++ b/Swift/Controllers/SettingConstants.cpp
@@ -14,8 +14,6 @@ const SettingsProvider::Setting<bool> SettingConstants::SHOW_NOTIFICATIONS = Set
const SettingsProvider::Setting<bool> SettingConstants::REQUEST_DELIVERYRECEIPTS = SettingsProvider::Setting<bool>("requestDeliveryReceipts", false);
const SettingsProvider::Setting<bool> SettingConstants::FORGET_PASSWORDS = SettingsProvider::Setting<bool>("forgetPasswords", false);
const SettingsProvider::Setting<bool> SettingConstants::REMEMBER_RECENT_CHATS = SettingsProvider::Setting<bool>("rememberRecentChats", true);
-const SettingsProvider::Setting<std::string> SettingConstants::LAST_LOGIN_JID = SettingsProvider::Setting<std::string>("lastLoginJID", "");
-const SettingsProvider::Setting<bool> SettingConstants::LOGIN_AUTOMATICALLY = SettingsProvider::Setting<bool>("loginAutomatically", false);
const SettingsProvider::Setting<bool> SettingConstants::SHOW_OFFLINE("showOffline", false);
const SettingsProvider::Setting<std::string> SettingConstants::EXPANDED_ROSTER_GROUPS("GroupExpandiness", "");
const SettingsProvider::Setting<bool> SettingConstants::PLAY_SOUNDS("playSounds", true);
@@ -23,7 +21,6 @@ const SettingsProvider::Setting<std::string> SettingConstants::HIGHLIGHT_RULES("
const SettingsProvider::Setting<std::string> SettingConstants::HIGHLIGHT_RULES_V2("highlightRulesV2", "@");
const SettingsProvider::Setting<std::string> SettingConstants::INVITE_AUTO_ACCEPT_MODE("inviteAutoAcceptMode", "presence");
const SettingsProvider::Setting<bool> SettingConstants::DISCONNECT_ON_CARD_REMOVAL("disconnectOnCardRemoval", true);
-const SettingsProvider::Setting<bool> SettingConstants::SINGLE_SIGN_ON("singleSignOn", false);
const SettingsProvider::Setting<bool> SettingConstants::MUC_MARKING_ELISION("mucMarkingElision", true);
const SettingsProvider::Setting<bool> SettingConstants::FUTURE("future", false);
diff --git a/Swift/Controllers/SettingConstants.h b/Swift/Controllers/SettingConstants.h
index f82dfb5..68c22b7 100644
--- a/Swift/Controllers/SettingConstants.h
+++ b/Swift/Controllers/SettingConstants.h
@@ -34,8 +34,6 @@ namespace Swift {
static const SettingsProvider::Setting<bool> REQUEST_DELIVERYRECEIPTS;
static const SettingsProvider::Setting<bool> FORGET_PASSWORDS;
static const SettingsProvider::Setting<bool> REMEMBER_RECENT_CHATS;
- static const SettingsProvider::Setting<std::string> LAST_LOGIN_JID;
- static const SettingsProvider::Setting<bool> LOGIN_AUTOMATICALLY;
/**
* The #SHOW_OFFLINE setting specifies whether or not to show offline contacts in the
* roster.
@@ -85,15 +83,6 @@ namespace Swift {
*/
static const SettingsProvider::Setting<bool> DISCONNECT_ON_CARD_REMOVAL;
/**
- * The #SINGLE_SIGN_ON setting
- * specifies whether to log in using Single Sign On.
- * This is currently supported on Windows.
- *
- * If set true Swift will use GSSAPI authentication to
- * log in the user; else not.
- */
- static const SettingsProvider::Setting<bool> SINGLE_SIGN_ON;
- /**
* The #MUC_MARKING_ELISION setting
* specifies whether or not messages with the default muc
* marking display their marking, and whether unmarked messages
diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h
index 6920903..d3c2601 100644
--- a/Swift/QtUI/QtLoginWindow.h
+++ b/Swift/QtUI/QtLoginWindow.h
@@ -59,8 +59,10 @@ namespace Swift {
signals:
void geometryChanged();
- private slots:
+ public slots:
void loginClicked();
+
+ private slots:
void handleCertficateChecked(bool);
void handleQuit();
void handleShowXMLConsole();
diff --git a/Swift/QtUI/QtSingleWindow.cpp b/Swift/QtUI/QtSingleWindow.cpp
index d53f247..6881c4f 100644
--- a/Swift/QtUI/QtSingleWindow.cpp
+++ b/Swift/QtUI/QtSingleWindow.cpp
@@ -6,9 +6,13 @@
#include <Swift/QtUI/QtSingleWindow.h>
+#include <QPushButton>
+#include <QVBoxLayout>
+
#include <Swiften/Base/Platform.h>
#include <Swift/QtUI/QtChatTabs.h>
+#include <Swift/QtUI/QtLoginWindow.h>
#include <Swift/QtUI/QtSettingsProvider.h>
namespace Swift {
@@ -24,6 +28,25 @@ QtSingleWindow::QtSingleWindow(QtSettingsProvider* settings) : QSplitter() {
}
connect(this, SIGNAL(splitterMoved(int, int)), this, SLOT(handleSplitterMoved(/*int, int*/)));
setChildrenCollapsible(false);
+
+ auto left = new QWidget(this);
+ list_ = new QListWidget(left);
+ auto addButton = new QPushButton("+", left);
+ QVBoxLayout* leftLayout = new QVBoxLayout();
+ leftLayout->addWidget(list_);
+ leftLayout->addWidget(addButton);
+ left->setLayout(leftLayout);
+ QSplitter::addWidget(left);
+ loginWindows_ = new QStackedWidget(this);
+ QSplitter::addWidget(loginWindows_);
+ tabs_ = new QStackedWidget(this);
+ QSplitter::addWidget(tabs_);
+ restoreSplitters();
+ setStretchFactor(0, 0);
+ setStretchFactor(1, 0);
+ setStretchFactor(2, 1);
+ connect(list_, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(handleListItemClicked(QListWidgetItem*)));
+ connect(addButton, SIGNAL(clicked()), this, SIGNAL(wantsToAddAccount()));
#ifdef SWIFTEN_PLATFORM_MACOSX
setHandleWidth(0);
#endif
@@ -33,14 +56,6 @@ QtSingleWindow::~QtSingleWindow() {
}
-void QtSingleWindow::addWidget(QWidget* widget) {
- QtChatTabs* tabs = dynamic_cast<QtChatTabs*>(widget);
- if (tabs) {
- connect(tabs, SIGNAL(onTitleChanged(const QString&)), this, SLOT(handleTabsTitleChanged(const QString&)));
- }
- QSplitter::addWidget(widget);
-}
-
void QtSingleWindow::handleTabsTitleChanged(const QString& title) {
setWindowTitle(title);
}
@@ -55,25 +70,18 @@ void QtSingleWindow::handleSplitterMoved() {
}
void QtSingleWindow::restoreSplitters() {
- QList<QVariant> variantValues = settings_->getQSettings()->value(SINGLE_WINDOW_SPLITS).toList();
- QList<int> intValues;
- for (auto&& value : variantValues) {
- intValues.append(value.toInt());
- }
- setSizes(intValues);
-}
-
-void QtSingleWindow::insertAtFront(QWidget* widget) {
- insertWidget(0, widget);
auto splitsVariant = settings_->getQSettings()->value(SINGLE_WINDOW_SPLITS);
if (splitsVariant.isValid()) {
- restoreSplitters();
+ auto variantValues = splitsVariant.toList();
+ QList<int> intValues;
+ for (auto&& value : variantValues) {
+ intValues.append(value.toInt());
+ }
+ setSizes(intValues);
}
else {
handleSplitterMoved();
}
- setStretchFactor(0, 0);
- setStretchFactor(1, 1);
}
void QtSingleWindow::handleGeometryChanged() {
@@ -89,4 +97,25 @@ void QtSingleWindow::moveEvent(QMoveEvent*) {
handleGeometryChanged();
}
+void QtSingleWindow::addAccount(QtLoginWindow* loginWindow, QtChatTabs* tabs) {
+ if (!loginWindows_->count()) {
+ connect(tabs, SIGNAL(onTitleChanged(const QString&)), this, SLOT(handleTabsTitleChanged(const QString&)));
+ }
+ loginWindows_->addWidget(loginWindow);
+ tabs_->addWidget(tabs);
+ list_->addItem(QString("Account %1").arg(loginWindows_->count()));
+}
+
+void QtSingleWindow::handleListItemClicked(QListWidgetItem* /*item*/) {
+ //FIXME: Should use a full model/view and do this properly (and render pretty things ourselves too)
+ auto currentTabs = tabs_->widget(tabs_->currentIndex());
+ disconnect(currentTabs, SIGNAL(onTitleChanged(const QString&)), this, SLOT(handleTabsTitleChanged(const QString&)));
+ loginWindows_->setCurrentIndex(list_->currentRow());
+ tabs_->setCurrentIndex(list_->currentRow());
+ currentTabs = tabs_->widget(tabs_->currentIndex());
+ connect(currentTabs, SIGNAL(onTitleChanged(const QString&)), this, SLOT(handleTabsTitleChanged(const QString&)));
+ //TODO change the title of the window.
+ handleTabsTitleChanged(QString("Swift"));
+}
+
}
diff --git a/Swift/QtUI/QtSingleWindow.h b/Swift/QtUI/QtSingleWindow.h
index c6f22cf..9a7e475 100644
--- a/Swift/QtUI/QtSingleWindow.h
+++ b/Swift/QtUI/QtSingleWindow.h
@@ -6,9 +6,14 @@
#pragma once
+#include <QListWidget>
#include <QSplitter>
+#include <QStackedWidget>
+
namespace Swift {
+ class QtChatTabs;
+ class QtLoginWindow;
class QtSettingsProvider;
class QtSingleWindow : public QSplitter {
@@ -16,14 +21,18 @@ namespace Swift {
public:
QtSingleWindow(QtSettingsProvider* settings);
virtual ~QtSingleWindow();
- void insertAtFront(QWidget* widget);
- void addWidget(QWidget* widget);
+ void addAccount(QtLoginWindow* widget, QtChatTabs* tabs);
+
+ signals:
+ void wantsToAddAccount();
+
protected:
void resizeEvent(QResizeEvent*);
void moveEvent(QMoveEvent*);
private slots:
void handleSplitterMoved();
void handleTabsTitleChanged(const QString& title);
+ void handleListItemClicked(QListWidgetItem*);
private:
void handleGeometryChanged();
void restoreSplitters();
@@ -31,6 +40,9 @@ namespace Swift {
private:
QtSettingsProvider* settings_;
+ QListWidget* list_;
+ QStackedWidget* loginWindows_;
+ QStackedWidget* tabs_;
};
}
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 89dfa01..28c7044 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -22,8 +22,10 @@
#include <Swiften/Base/Path.h>
#include <Swiften/Base/Paths.h>
#include <Swiften/Base/Platform.h>
+#include <Swiften/Base/String.h>
#include <Swiften/Client/Client.h>
#include <Swiften/Elements/Presence.h>
+#include <Swiften/StringCodecs/Base64.h>
#include <Swiften/TLS/TLSContextFactory.h>
#include <SwifTools/Application/PlatformApplicationPathProvider.h>
@@ -92,8 +94,6 @@ po::options_description QtSwift::getOptionsDescription() {
("version", "Show version information")
("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")
("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")
@@ -167,19 +167,11 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
networkFactories_.getTLSContextFactory()->setDisconnectOnCardRemoval(settingsHierarchy_->getSetting(SettingConstants::DISCONNECT_ON_CARD_REMOVAL));
- std::map<std::string, std::string> emoticons;
- loadEmoticonsFile(":/emoticons/emoticons.txt", emoticons);
- loadEmoticonsFile(P2QSTRING(pathToString(Paths::getExecutablePath() / "emoticons.txt")), emoticons);
+ loadEmoticonsFile(":/emoticons/emoticons.txt", emoticons_);
+ loadEmoticonsFile(P2QSTRING(pathToString(Paths::getExecutablePath() / "emoticons.txt")), emoticons_);
splitter_ = new QtSingleWindow(qtSettings_);
-
- 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;
- }
+ connect(splitter_, SIGNAL(wantsToAddAccount()), this, SLOT(handleWantsToAddAccount()));
if (options.count("debug")) {
Log::setLogLevel(Swift::Log::debug);
@@ -202,6 +194,8 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
SWIFT_LOG(error) << "Error while retrieving the specified log file name from the command line" << std::endl;
}
}
+ //TODO this old option can be purged
+ useDelayForLatency_ = options.count("latency-debug") > 0;
// Load fonts
std::vector<std::string> fontNames = {
@@ -240,13 +234,10 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
#ifdef SWIFTEN_PLATFORM_WINDOWS
QFont::insertSubstitution(QApplication::font().family(), "Segoe UI Emoji");
#endif
- bool enableAdHocCommandOnJID = options.count("enable-jid-adhocs") > 0;
- tabs_ = new QtChatTabs(settingsHierarchy_, true);
- bool startMinimized = options.count("start-minimized") > 0;
+ 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());
- chatWindowFactory_ = new QtChatWindowFactory(splitter_, settingsHierarchy_, qtSettings_, tabs_, ":/themes/Default/", emoticons);
soundPlayer_ = new QtSoundPlayer(applicationPathProvider_);
// Ugly, because the dock depends on the tray, but the temporary
@@ -298,32 +289,8 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
}
});
}
-
- 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(settingsHierarchy_, 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,
- settingsHierarchy_,
- systemTrays_[i],
- soundPlayer_,
- storagesFactory_,
- certificateStorageFactory_,
- dock_,
- notifier_,
- uriHandler_,
- &idleDetector_,
- emoticons,
- options.count("latency-debug") > 0);
- mainControllers_.push_back(mainController);
- }
-
+ migrateLastLoginAccount();
+ restoreAccounts();
connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(handleAboutToQuit()));
}
@@ -339,8 +306,6 @@ QtSwift::~QtSwift() {
for (auto* tray : systemTrays_) {
delete tray;
}
- delete tabs_;
- delete chatWindowFactory_;
delete splitter_;
delete settingsHierarchy_;
delete qtSettings_;
@@ -379,4 +344,139 @@ void QtSwift::handleAutoUpdaterStateChanged(AutoUpdater::State updatedState) {
}
}
+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);
+ MainController* mainController = new MainController(
+ &clientMainThreadCaller_,
+ &networkFactories_,
+ uiFactory,
+ settingsHierarchy_,
+ systemTrays_[systemTrays_.size() - 1],
+ soundPlayer_,
+ storagesFactory_,
+ certificateStorageFactory_,
+ dock_,
+ notifier_,
+ uriHandler_,
+ &idleDetector_,
+ emoticons_,
+ useDelayForLatency_);
+ mainControllers_.push_back(mainController);
+
+ //FIXME - mainController 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;
+}
+
+
}
diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h
index f35d2cc..d876cd8 100644
--- a/Swift/QtUI/QtSwift.h
+++ b/Swift/QtUI/QtSwift.h
@@ -6,12 +6,14 @@
#pragma once
+#include <map>
#include <string>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <Swiften/Base/Platform.h>
+#include <Swiften/Client/ClientOptions.h>
#include <Swiften/EventLoop/Qt/QtEventLoop.h>
#include <Swiften/Network/BoostNetworkFactories.h>
#include <Swiften/TLS/PlatformTLSFactories.h>
@@ -68,11 +70,19 @@ namespace Swift {
private slots:
void handleAboutToQuit();
void handleAutoUpdaterStateChanged(AutoUpdater::State updatedState);
+ void handleWantsToAddAccount();
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);
+ QtLoginWindow* addAccount();
+ ClientOptions parseClientOptions(const std::string& optionString);
+ void restoreAccounts();
+ /**
+ * Upgrades the config from pre-multi-account to post-multi-account format (added in 5.0).
+ */
+ void migrateLastLoginAccount();
private:
QtEventLoop clientMainThreadCaller_;
@@ -89,7 +99,6 @@ namespace Swift {
QtSoundPlayer* soundPlayer_;
Dock* dock_;
URIHandler* uriHandler_;
- QtChatTabs* tabs_;
ApplicationPathProvider* applicationPathProvider_;
StoragesFactory* storagesFactory_;
CertificateStorageFactory* certificateStorageFactory_;
@@ -98,6 +107,9 @@ namespace Swift {
StatusCache* statusCache_;
PlatformIdleQuerier idleQuerier_;
ActualIdleDetector idleDetector_;
+ std::map<std::string, std::string> emoticons_;
+ bool enableAdHocCommandOnJID_ = false;
+ bool useDelayForLatency_;
#if defined(SWIFTEN_PLATFORM_MACOSX)
CocoaApplication cocoaApplication_;
CocoaApplicationActivateHelper cocoaApplicationActivateHelper_;
diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp
index 0b19f63..2762d68 100644
--- a/Swift/QtUI/QtUIFactory.cpp
+++ b/Swift/QtUI/QtUIFactory.cpp
@@ -40,7 +40,9 @@
namespace Swift {
-QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, AutoUpdater* autoUpdater, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID) : settings_(settings), qtOnlySettings_(qtOnlySettings), tabs_(tabs), netbookSplitter_(netbookSplitter), systemTray_(systemTray), chatWindowFactory_(chatWindowFactory), timerFactory_(timerFactory), lastMainWindow_(nullptr), loginWindow_(nullptr), statusCache_(statusCache), autoUpdater_(autoUpdater), startMinimized_(startMinimized), emoticonsExist_(emoticonsExist), enableAdHocCommandOnJID_(enableAdHocCommandOnJID) {
+QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, TimerFactory* timerFactory, StatusCache* statusCache, AutoUpdater* autoUpdater, std::map<std::string, std::string>& emoticons, bool enableAdHocCommandOnJID) : settings_(settings), qtOnlySettings_(qtOnlySettings), tabs_(tabs), netbookSplitter_(netbookSplitter), systemTray_(systemTray), timerFactory_(timerFactory), lastMainWindow_(nullptr), loginWindow_(nullptr), statusCache_(statusCache), autoUpdater_(autoUpdater), emoticons_(emoticons), enableAdHocCommandOnJID_(enableAdHocCommandOnJID) {
+ emoticonsExist_ = !emoticons_.empty();
+ chatWindowFactory_ = new QtChatWindowFactory(netbookSplitter_, settings, qtOnlySettings, tabs_, ":/themes/Default/", emoticons_);
chatFontSize_ = settings_->getSetting(QtUISettingConstants::CHATWINDOW_FONT_SIZE);
historyFontSize_ = settings_->getSetting(QtUISettingConstants::HISTORYWINDOW_FONT_SIZE);
}
@@ -50,6 +52,7 @@ QtUIFactory::~QtUIFactory() {
for (auto chat : chatWindows_) {
SWIFT_LOG_ASSERT(chat.isNull(), debug) << "QtUIFactory has active chat windows and has not been reset properly" << std::endl;
}
+ delete chatWindowFactory_;
}
XMLConsoleWidget* QtUIFactory::createXMLConsoleWidget() {
@@ -91,12 +94,12 @@ MainWindow* QtUIFactory::createMainWindow(Chattables& chattables, UIEventStream*
}
LoginWindow* QtUIFactory::createLoginWindow(UIEventStream* eventStream) {
+ if (loginWindow_) {
+ return loginWindow_;
+ }
loginWindow_ = new QtLoginWindow(eventStream, settings_, timerFactory_, autoUpdater_);
- netbookSplitter_->insertAtFront(loginWindow_);
+ netbookSplitter_->addAccount(loginWindow_, tabs_);
connect(systemTray_, SIGNAL(clicked()), loginWindow_, SLOT(toggleBringToFront()));
- if (startMinimized_) {
- loginWindow_->hide();
- }
return loginWindow_;
}
diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h
index 4013668..ad8dc1f 100644
--- a/Swift/QtUI/QtUIFactory.h
+++ b/Swift/QtUI/QtUIFactory.h
@@ -35,7 +35,7 @@ namespace Swift {
class QtUIFactory : public QObject, public UIFactory {
Q_OBJECT
public:
- QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, AutoUpdater* autoUpdater, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID);
+ QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, TimerFactory* timerFactory, StatusCache* statusCache, AutoUpdater* autoUpdater, std::map<std::string, std::string>& emoticons, bool enableAdHocCommandOnJID);
~QtUIFactory();
virtual XMLConsoleWidget* createXMLConsoleWidget();
virtual HistoryWindow* createHistoryWindow(UIEventStream*);
@@ -75,10 +75,10 @@ namespace Swift {
StatusCache* statusCache_;
AutoUpdater* autoUpdater_;
std::vector<QPointer<QtChatWindow> > chatWindows_;
- bool startMinimized_;
int chatFontSize_;
int historyFontSize_;
bool emoticonsExist_;
+ std::map<std::string, std::string>& emoticons_;
bool enableAdHocCommandOnJID_;
};
}