summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp19
-rw-r--r--Swift/Controllers/Chat/ChatController.h11
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp34
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h5
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp14
-rw-r--r--Swift/Controllers/MainController.cpp97
-rw-r--r--Swift/Controllers/MainController.h8
-rw-r--r--Swift/Controllers/ProfileSettingsProvider.cpp68
-rw-r--r--Swift/Controllers/ProfileSettingsProvider.h31
-rw-r--r--Swift/Controllers/Roster/RosterController.cpp27
-rw-r--r--Swift/Controllers/Roster/RosterController.h1
-rw-r--r--Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp15
-rw-r--r--Swift/Controllers/Roster/RosterGroupExpandinessPersister.h3
-rw-r--r--Swift/Controllers/SConscript4
-rw-r--r--Swift/Controllers/SettingConstants.cpp22
-rw-r--r--Swift/Controllers/SettingConstants.h26
-rw-r--r--Swift/Controllers/Settings/DummySettingsProvider.h36
-rw-r--r--Swift/Controllers/Settings/SettingsProvider.h62
-rw-r--r--Swift/Controllers/Settings/SettingsProviderHierachy.cpp95
-rw-r--r--Swift/Controllers/Settings/SettingsProviderHierachy.h46
-rw-r--r--Swift/Controllers/Settings/XMLSettingsProvider.cpp124
-rw-r--r--Swift/Controllers/Settings/XMLSettingsProvider.h56
-rw-r--r--Swift/Controllers/SoundEventController.cpp34
-rw-r--r--Swift/Controllers/SoundEventController.h13
-rw-r--r--Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h19
-rw-r--r--Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h19
-rw-r--r--Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h19
-rw-r--r--Swift/Controllers/UIEvents/ToggleSoundsUIEvent.h19
-rw-r--r--Swift/QtUI/ChatList/QtChatListWindow.cpp24
-rw-r--r--Swift/QtUI/ChatList/QtChatListWindow.h8
-rw-r--r--Swift/QtUI/QtChatWindow.cpp11
-rw-r--r--Swift/QtUI/QtChatWindow.h8
-rw-r--r--Swift/QtUI/QtChatWindowFactory.cpp16
-rw-r--r--Swift/QtUI/QtChatWindowFactory.h6
-rw-r--r--Swift/QtUI/QtLoginWindow.cpp94
-rw-r--r--Swift/QtUI/QtLoginWindow.h17
-rw-r--r--Swift/QtUI/QtMainWindow.cpp39
-rw-r--r--Swift/QtUI/QtMainWindow.h9
-rw-r--r--Swift/QtUI/QtNameWidget.cpp9
-rw-r--r--Swift/QtUI/QtNameWidget.h6
-rw-r--r--Swift/QtUI/QtRosterHeader.cpp2
-rw-r--r--Swift/QtUI/QtRosterHeader.h4
-rw-r--r--Swift/QtUI/QtSettingsProvider.cpp59
-rw-r--r--Swift/QtUI/QtSettingsProvider.h23
-rw-r--r--Swift/QtUI/QtSwift.cpp76
-rw-r--r--Swift/QtUI/QtSwift.h12
-rw-r--r--Swift/QtUI/QtUIFactory.cpp20
-rw-r--r--Swift/QtUI/QtUIFactory.h11
-rw-r--r--Swift/QtUI/QtUIPreferences.cpp27
-rw-r--r--Swift/QtUI/QtUIPreferences.h25
-rw-r--r--Swift/QtUI/QtUISettingConstants.cpp16
-rw-r--r--Swift/QtUI/QtUISettingConstants.h20
-rw-r--r--Swift/QtUI/Roster/QtOccupantListWidget.cpp4
-rw-r--r--Swift/QtUI/Roster/QtOccupantListWidget.h6
-rw-r--r--Swift/QtUI/Roster/QtRosterWidget.cpp2
-rw-r--r--Swift/QtUI/Roster/QtRosterWidget.h2
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.cpp24
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.h10
-rw-r--r--Swift/QtUI/SConscript6
59 files changed, 985 insertions, 538 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 9a56300..ea0e8ea 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -1,121 +1,122 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Swift/Controllers/Chat/ChatController.h"
#include <boost/bind.hpp>
#include <stdio.h>
#include <Swift/Controllers/Intl.h>
#include <Swiften/Base/format.h>
#include <Swiften/Base/Algorithm.h>
#include <Swiften/Avatars/AvatarManager.h>
#include <Swiften/Chat/ChatStateNotifier.h>
#include <Swiften/Chat/ChatStateTracker.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swiften/Client/NickResolver.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
#include <Swift/Controllers/FileTransfer/FileTransferController.h>
#include <Swift/Controllers/StatusUtil.h>
#include <Swiften/Disco/EntityCapsProvider.h>
#include <Swiften/Base/foreach.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <Swiften/Elements/DeliveryReceipt.h>
#include <Swiften/Elements/DeliveryReceiptRequest.h>
-#include <Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h>
+#include <Swift/Controllers/SettingConstants.h>
#include <Swiften/Base/Log.h>
namespace Swift {
/**
* The controller does not gain ownership of the stanzaChannel, nor the factory.
*/
-ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts)
- : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts) {
+ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings)
+ : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings) {
isInMUC_ = isInMUC;
lastWasPresence_ = false;
chatStateNotifier_ = new ChatStateNotifier(stanzaChannel, contact, entityCapsProvider);
chatStateTracker_ = new ChatStateTracker();
nickResolver_ = nickResolver;
presenceOracle_->onPresenceChange.connect(boost::bind(&ChatController::handlePresenceChange, this, _1));
chatStateTracker_->onChatStateChange.connect(boost::bind(&ChatWindow::setContactChatState, chatWindow_, _1));
stanzaChannel_->onStanzaAcked.connect(boost::bind(&ChatController::handleStanzaAcked, this, _1));
nickResolver_->onNickChanged.connect(boost::bind(&ChatController::handleContactNickChanged, this, _1, _2));
std::string nick = nickResolver_->jidToNick(toJID_);
chatWindow_->setName(nick);
std::string startMessage;
Presence::ref theirPresence;
if (isInMUC) {
startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% in chatroom %2%")) % nick % contact.toBare().toString());
theirPresence = presenceOracle->getLastPresence(contact);
} else {
startMessage = str(format(QT_TRANSLATE_NOOP("", "Starting chat with %1% - %2%")) % nick % contact.toBare().toString());
theirPresence = contact.isBare() ? presenceOracle->getHighestPriorityPresence(contact.toBare()) : presenceOracle->getLastPresence(contact);
}
startMessage += ": " + statusShowTypeToFriendlyName(theirPresence ? theirPresence->getShow() : StatusShow::None);
if (theirPresence && !theirPresence->getStatus().empty()) {
startMessage += " (" + theirPresence->getStatus() + ")";
}
lastShownStatus_ = theirPresence ? theirPresence->getShow() : StatusShow::None;
chatStateNotifier_->setContactIsOnline(theirPresence && theirPresence->getType() == Presence::Available);
startMessage += ".";
chatWindow_->addSystemMessage(startMessage);
chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_));
chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_));
chatWindow_->onFileTransferStart.connect(boost::bind(&ChatController::handleFileTransferStart, this, _1, _2));
chatWindow_->onFileTransferAccept.connect(boost::bind(&ChatController::handleFileTransferAccept, this, _1, _2));
chatWindow_->onFileTransferCancel.connect(boost::bind(&ChatController::handleFileTransferCancel, this, _1));
chatWindow_->onSendFileRequest.connect(boost::bind(&ChatController::handleSendFileRequest, this, _1));
handleBareJIDCapsChanged(toJID_);
- eventStream_->onUIEvent.connect(boost::bind(&ChatController::handleUIEvent, this, _1));
+
+ settings_->onSettingChanged.connect(boost::bind(&ChatController::handleSettingChanged, this, _1));
}
void ChatController::handleContactNickChanged(const JID& jid, const std::string& /*oldNick*/) {
if (jid.toBare() == toJID_.toBare()) {
chatWindow_->setName(nickResolver_->jidToNick(jid));
}
}
ChatController::~ChatController() {
- eventStream_->onUIEvent.disconnect(boost::bind(&ChatController::handleUIEvent, this, _1));
+ settings_->onSettingChanged.disconnect(boost::bind(&ChatController::handleSettingChanged, this, _1));
nickResolver_->onNickChanged.disconnect(boost::bind(&ChatController::handleContactNickChanged, this, _1, _2));
delete chatStateNotifier_;
delete chatStateTracker_;
}
void ChatController::handleBareJIDCapsChanged(const JID& /*jid*/) {
DiscoInfo::ref disco = entityCapsProvider_->getCaps(toJID_);
if (disco) {
if (disco->hasFeature(DiscoInfo::MessageCorrectionFeature)) {
chatWindow_->setCorrectionEnabled(ChatWindow::Yes);
} else {
chatWindow_->setCorrectionEnabled(ChatWindow::No);
}
if (disco->hasFeature(DiscoInfo::MessageDeliveryReceiptsFeature)) {
contactSupportsReceipts_ = ChatWindow::Yes;
} else {
contactSupportsReceipts_ = ChatWindow::No;
}
} else {
SWIFT_LOG(debug) << "No disco info :(" << std::endl;
chatWindow_->setCorrectionEnabled(ChatWindow::Maybe);
contactSupportsReceipts_ = ChatWindow::Maybe;
}
checkForDisplayingDisplayReceiptsAlert();
}
void ChatController::setToJID(const JID& jid) {
chatStateNotifier_->setContact(jid);
ChatControllerBase::setToJID(jid);
Presence::ref presence;
if (isInMUC_) {
presence = presenceOracle_->getLastPresence(jid);
} else {
presence = jid.isBare() ? presenceOracle_->getHighestPriorityPresence(jid.toBare()) : presenceOracle_->getLastPresence(jid);
}
@@ -142,73 +143,73 @@ void ChatController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> me
chatStateTracker_->handleMessageReceived(message);
chatStateNotifier_->receivedMessageFromContact(message->getPayload<ChatState>());
if (boost::shared_ptr<DeliveryReceipt> receipt = message->getPayload<DeliveryReceipt>()) {
SWIFT_LOG(debug) << "received receipt for id: " << receipt->getReceivedID() << std::endl;
if (requestedReceipts_.find(receipt->getReceivedID()) != requestedReceipts_.end()) {
chatWindow_->setMessageReceiptState(requestedReceipts_[receipt->getReceivedID()], ChatWindow::ReceiptReceived);
requestedReceipts_.erase(receipt->getReceivedID());
}
} else if (message->getPayload<DeliveryReceiptRequest>()) {
if (receivingPresenceFromUs_) {
boost::shared_ptr<Message> receiptMessage = boost::make_shared<Message>();
receiptMessage->setTo(toJID_);
receiptMessage->addPayload(boost::make_shared<DeliveryReceipt>(message->getID()));
stanzaChannel_->sendMessage(receiptMessage);
}
}
}
void ChatController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) {
eventController_->handleIncomingEvent(messageEvent);
}
void ChatController::preSendMessageRequest(boost::shared_ptr<Message> message) {
chatStateNotifier_->addChatStateRequest(message);
if (userWantsReceipts_ && (contactSupportsReceipts_ != ChatWindow::No) && message) {
message->addPayload(boost::make_shared<DeliveryReceiptRequest>());
}
}
void ChatController::setContactIsReceivingPresence(bool isReceivingPresence) {
receivingPresenceFromUs_ = isReceivingPresence;
}
-void ChatController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
- if (boost::shared_ptr<ToggleRequestDeliveryReceiptsUIEvent> toggleAllowReceipts = boost::dynamic_pointer_cast<ToggleRequestDeliveryReceiptsUIEvent>(event)) {
- userWantsReceipts_ = toggleAllowReceipts->getEnabled();
+void ChatController::handleSettingChanged(const std::string& settingPath) {
+ if (settingPath == SettingConstants::REQUEST_DELIVERYRECEIPTS.getKey()) {
+ userWantsReceipts_ = settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS);
checkForDisplayingDisplayReceiptsAlert();
}
}
void ChatController::checkForDisplayingDisplayReceiptsAlert() {
if (userWantsReceipts_ && (contactSupportsReceipts_ == ChatWindow::No)) {
chatWindow_->setAlert("This chat doesn't support delivery receipts.");
} else if (userWantsReceipts_ && (contactSupportsReceipts_ == ChatWindow::Maybe)) {
chatWindow_->setAlert("This chat may not support delivery receipts. You might not receive delivery receipts for the messages you sent.");
} else {
chatWindow_->cancelAlert();
}
}
void ChatController::postSendMessage(const std::string& body, boost::shared_ptr<Stanza> sentStanza) {
boost::shared_ptr<Replace> replace = sentStanza->getPayload<Replace>();
if (replace) {
eraseIf(unackedStanzas_, PairSecondEquals<boost::shared_ptr<Stanza>, std::string>(myLastMessageUIID_));
chatWindow_->replaceMessage(body, myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time());
} else {
myLastMessageUIID_ = addMessage(body, QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel().getLabel() : boost::shared_ptr<SecurityLabel>(), std::string(avatarManager_->getAvatarPath(selfJID_).string()), boost::posix_time::microsec_clock::universal_time());
}
if (stanzaChannel_->getStreamManagementEnabled() && !myLastMessageUIID_.empty() ) {
chatWindow_->setAckState(myLastMessageUIID_, ChatWindow::Pending);
unackedStanzas_[sentStanza] = myLastMessageUIID_;
}
if (sentStanza->getPayload<DeliveryReceiptRequest>()) {
requestedReceipts_[sentStanza->getID()] = myLastMessageUIID_;
chatWindow_->setMessageReceiptState(myLastMessageUIID_, ChatWindow::ReceiptRequested);
}
lastWasPresence_ = false;
chatStateNotifier_->userSentMessage();
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 9c01923..2a66772 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -1,76 +1,77 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
-#include "Swift/Controllers/Chat/ChatControllerBase.h"
+#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <map>
#include <string>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
namespace Swift {
class AvatarManager;
class ChatStateNotifier;
class ChatStateTracker;
class NickResolver;
class EntityCapsProvider;
class FileTransferController;
- class UIEvent;
+ class SettingsProvider;
class ChatController : public ChatControllerBase {
public:
- ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts);
+ ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, SettingsProvider* settings);
virtual ~ChatController();
virtual void setToJID(const JID& jid);
virtual void setOnline(bool online);
virtual void handleNewFileTransferController(FileTransferController* ftc);
virtual void setContactIsReceivingPresence(bool /*isReceivingPresence*/);
private:
void handlePresenceChange(boost::shared_ptr<Presence> newPresence);
std::string getStatusChangeString(boost::shared_ptr<Presence> presence);
bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);
void postSendMessage(const std::string &body, boost::shared_ptr<Stanza> sentStanza);
void preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent);
void postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent);
void preSendMessageRequest(boost::shared_ptr<Message>);
std::string senderDisplayNameFromMessage(const JID& from);
virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message>) const;
void handleStanzaAcked(boost::shared_ptr<Stanza> stanza);
void dayTicked() {lastWasPresence_ = false;}
void handleContactNickChanged(const JID& jid, const std::string& /*oldNick*/);
void handleBareJIDCapsChanged(const JID& jid);
void handleFileTransferCancel(std::string /* id */);
void handleFileTransferStart(std::string /* id */, std::string /* description */);
void handleFileTransferAccept(std::string /* id */, std::string /* filename */);
void handleSendFileRequest(std::string filename);
- void handleUIEvent(boost::shared_ptr<UIEvent> event);
+ void handleSettingChanged(const std::string& settingPath);
void checkForDisplayingDisplayReceiptsAlert();
private:
NickResolver* nickResolver_;
ChatStateNotifier* chatStateNotifier_;
ChatStateTracker* chatStateTracker_;
std::string myLastMessageUIID_;
bool isInMUC_;
bool lastWasPresence_;
std::string lastStatusChangeString_;
std::map<boost::shared_ptr<Stanza>, std::string> unackedStanzas_;
std::map<std::string, std::string> requestedReceipts_;
StatusShow::Type lastShownStatus_;
UIEventStream* eventStream_;
ChatWindow::Tristate contactSupportsReceipts_;
bool receivingPresenceFromUs_;
bool userWantsReceipts_;
std::map<std::string, FileTransferController*> ftControllers;
+ SettingsProvider* settings_;
};
}
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index c19c524..a2b286f 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -1,148 +1,155 @@
/*
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Swift/Controllers/Chat/ChatsManager.h"
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include <Swiften/Base/foreach.h>
#include <Swift/Controllers/Chat/ChatController.h>
#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <Swift/Controllers/Chat/MUCSearchController.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
#include <Swift/Controllers/Chat/MUCController.h>
#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h>
#include <Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h>
#include <Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h>
-#include <Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h>
#include <Swift/Controllers/UIInterfaces/ChatListWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/JoinMUCWindow.h>
#include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h>
#include <Swiften/Presence/PresenceSender.h>
#include <Swiften/Client/NickResolver.h>
#include <Swiften/MUC/MUCManager.h>
#include <Swiften/Elements/ChatState.h>
#include <Swiften/Elements/MUCUserPayload.h>
#include <Swiften/Elements/DeliveryReceipt.h>
#include <Swiften/Elements/DeliveryReceiptRequest.h>
#include <Swiften/MUC/MUCBookmarkManager.h>
#include <Swift/Controllers/FileTransfer/FileTransferController.h>
#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
#include <Swift/Controllers/ProfileSettingsProvider.h>
#include <Swiften/Avatars/AvatarManager.h>
#include <Swiften/Elements/MUCInvitationPayload.h>
#include <Swiften/Roster/XMPPRoster.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/Controllers/SettingConstants.h>
namespace Swift {
typedef std::pair<JID, ChatController*> JIDChatControllerPair;
typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
#define RECENT_CHATS "recent_chats"
ChatsManager::ChatsManager(
JID jid, StanzaChannel* stanzaChannel,
IQRouter* iqRouter,
EventController* eventController,
ChatWindowFactory* chatWindowFactory,
JoinMUCWindowFactory* joinMUCWindowFactory,
NickResolver* nickResolver,
PresenceOracle* presenceOracle,
PresenceSender* presenceSender,
UIEventStream* uiEventStream,
ChatListWindowFactory* chatListWindowFactory,
bool useDelayForLatency,
TimerFactory* timerFactory,
MUCRegistry* mucRegistry,
EntityCapsProvider* entityCapsProvider,
MUCManager* mucManager,
MUCSearchWindowFactory* mucSearchWindowFactory,
- ProfileSettingsProvider* settings,
+ ProfileSettingsProvider* profileSettings,
FileTransferOverview* ftOverview,
XMPPRoster* roster,
- bool eagleMode) :
+ bool eagleMode,
+ SettingsProvider* settings) :
jid_(jid),
joinMUCWindowFactory_(joinMUCWindowFactory),
useDelayForLatency_(useDelayForLatency),
mucRegistry_(mucRegistry),
entityCapsProvider_(entityCapsProvider),
mucManager(mucManager),
ftOverview_(ftOverview),
roster_(roster),
- eagleMode_(eagleMode) {
+ eagleMode_(eagleMode),
+ settings_(settings) {
timerFactory_ = timerFactory;
eventController_ = eventController;
stanzaChannel_ = stanzaChannel;
iqRouter_ = iqRouter;
chatWindowFactory_ = chatWindowFactory;
nickResolver_ = nickResolver;
presenceOracle_ = presenceOracle;
avatarManager_ = NULL;
serverDiscoInfo_ = boost::shared_ptr<DiscoInfo>(new DiscoInfo());
presenceSender_ = presenceSender;
uiEventStream_ = uiEventStream;
mucBookmarkManager_ = NULL;
- profileSettings_ = settings;
+ profileSettings_ = profileSettings;
presenceOracle_->onPresenceChange.connect(boost::bind(&ChatsManager::handlePresenceChange, this, _1));
uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&ChatsManager::handleUIEvent, this, _1));
chatListWindow_ = chatListWindowFactory->createChatListWindow(uiEventStream_);
chatListWindow_->onMUCBookmarkActivated.connect(boost::bind(&ChatsManager::handleMUCBookmarkActivated, this, _1));
chatListWindow_->onRecentActivated.connect(boost::bind(&ChatsManager::handleRecentActivated, this, _1));
chatListWindow_->onClearRecentsRequested.connect(boost::bind(&ChatsManager::handleClearRecentsRequested, this));
joinMUCWindow_ = NULL;
- mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, settings);
+ mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, profileSettings_);
mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1));
ftOverview_->onNewFileTransferController.connect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1));
roster_->onJIDAdded.connect(boost::bind(&ChatsManager::handleJIDAddedToRoster, this, _1));
roster_->onJIDRemoved.connect(boost::bind(&ChatsManager::handleJIDRemovedFromRoster, this, _1));
roster_->onJIDUpdated.connect(boost::bind(&ChatsManager::handleJIDUpdatedInRoster, this, _1));
roster_->onRosterCleared.connect(boost::bind(&ChatsManager::handleRosterCleared, this));
+
+ settings_->onSettingChanged.connect(boost::bind(&ChatsManager::handleSettingChanged, this, _1));
+
setupBookmarks();
loadRecents();
}
ChatsManager::~ChatsManager() {
+ settings_->onSettingChanged.disconnect(boost::bind(&ChatsManager::handleSettingChanged, this, _1));
roster_->onJIDAdded.disconnect(boost::bind(&ChatsManager::handleJIDAddedToRoster, this, _1));
roster_->onJIDRemoved.disconnect(boost::bind(&ChatsManager::handleJIDRemovedFromRoster, this, _1));
roster_->onJIDUpdated.disconnect(boost::bind(&ChatsManager::handleJIDUpdatedInRoster, this, _1));
roster_->onRosterCleared.disconnect(boost::bind(&ChatsManager::handleRosterCleared, this));
delete joinMUCWindow_;
foreach (JIDChatControllerPair controllerPair, chatControllers_) {
delete controllerPair.second;
}
foreach (JIDMUCControllerPair controllerPair, mucControllers_) {
delete controllerPair.second;
}
delete mucBookmarkManager_;
delete mucSearchController_;
}
void ChatsManager::saveRecents() {
std::string recents;
int i = 1;
foreach (ChatListWindow::Chat chat, recentChats_) {
std::vector<std::string> activity;
boost::split(activity, chat.activity, boost::is_any_of("\t\n"));
if (activity.empty()) {
/* Work around Boost bug https://svn.boost.org/trac/boost/ticket/4751 */
activity.push_back("");
}
std::string recent = chat.jid.toString() + "\t" + (eagleMode_ ? "" : activity[0]) + "\t" + (chat.isMUC ? "true" : "false") + "\t" + chat.nick;
recents += recent + "\n";
if (i++ > 25) {
break;
}
}
profileSettings_->storeString(RECENT_CHATS, recents);
}
void ChatsManager::handleClearRecentsRequested() {
@@ -316,91 +323,94 @@ void ChatsManager::handleUnreadCountChanged(ChatControllerBase* controller) {
}
unreadTotal += chatItem.unreadCount;
}
chatListWindow_->setRecents(recentChats_);
chatListWindow_->setUnreadCount(unreadTotal);
}
void ChatsManager::appendRecent(const ChatListWindow::Chat& chat) {
recentChats_.erase(std::remove(recentChats_.begin(), recentChats_.end(), chat), recentChats_.end());
recentChats_.push_front(chat);
}
void ChatsManager::prependRecent(const ChatListWindow::Chat& chat) {
recentChats_.erase(std::remove(recentChats_.begin(), recentChats_.end(), chat), recentChats_.end());
recentChats_.push_back(chat);
}
void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
std::map<JID, MUCController*>::iterator it;
for (it = mucControllers_.begin(); it != mucControllers_.end(); ++it) {
if ((*it).second == mucController) {
foreach (ChatListWindow::Chat& chat, recentChats_) {
if (chat.isMUC && chat.jid == (*it).first) {
chat.statusType = StatusShow::None;
chatListWindow_->setRecents(recentChats_);
break;
}
}
mucControllers_.erase(it);
delete mucController;
return;
}
}
}
+void ChatsManager::handleSettingChanged(const std::string& settingPath) {
+ if (settingPath == SettingConstants::REQUEST_DELIVERYRECEIPTS.getKey()) {
+ userWantsReceipts_ = settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS);
+ return;
+ }
+}
+
void ChatsManager::handleUIEvent(boost::shared_ptr<UIEvent> event) {
boost::shared_ptr<RequestChatUIEvent> chatEvent = boost::dynamic_pointer_cast<RequestChatUIEvent>(event);
if (chatEvent) {
handleChatRequest(chatEvent->getContact());
return;
}
boost::shared_ptr<RemoveMUCBookmarkUIEvent> removeMUCBookmarkEvent = boost::dynamic_pointer_cast<RemoveMUCBookmarkUIEvent>(event);
if (removeMUCBookmarkEvent) {
mucBookmarkManager_->removeBookmark(removeMUCBookmarkEvent->getBookmark());
return;
}
boost::shared_ptr<AddMUCBookmarkUIEvent> addMUCBookmarkEvent = boost::dynamic_pointer_cast<AddMUCBookmarkUIEvent>(event);
if (addMUCBookmarkEvent) {
mucBookmarkManager_->addBookmark(addMUCBookmarkEvent->getBookmark());
return;
}
- boost::shared_ptr<ToggleRequestDeliveryReceiptsUIEvent> toggleRequestDeliveryReceiptsEvent = boost::dynamic_pointer_cast<ToggleRequestDeliveryReceiptsUIEvent>(event);
- if (toggleRequestDeliveryReceiptsEvent) {
- userWantsReceipts_ = toggleRequestDeliveryReceiptsEvent->getEnabled();
- return;
- }
+
boost::shared_ptr<EditMUCBookmarkUIEvent> editMUCBookmarkEvent = boost::dynamic_pointer_cast<EditMUCBookmarkUIEvent>(event);
if (editMUCBookmarkEvent) {
mucBookmarkManager_->replaceBookmark(editMUCBookmarkEvent->getOldBookmark(), editMUCBookmarkEvent->getNewBookmark());
}
else if (JoinMUCUIEvent::ref joinEvent = boost::dynamic_pointer_cast<JoinMUCUIEvent>(event)) {
handleJoinMUCRequest(joinEvent->getJID(), joinEvent->getPassword(), joinEvent->getNick(), joinEvent->getShouldJoinAutomatically(), joinEvent->getCreateAsReservedRoomIfNew());
mucControllers_[joinEvent->getJID()]->activateChatWindow();
}
else if (boost::shared_ptr<RequestJoinMUCUIEvent> joinEvent = boost::dynamic_pointer_cast<RequestJoinMUCUIEvent>(event)) {
if (!joinMUCWindow_) {
joinMUCWindow_ = joinMUCWindowFactory_->createJoinMUCWindow(uiEventStream_);
joinMUCWindow_->onSearchMUC.connect(boost::bind(&ChatsManager::handleSearchMUCRequest, this));
}
joinMUCWindow_->setMUC(joinEvent->getRoom());
joinMUCWindow_->setNick(nickResolver_->jidToNick(jid_));
joinMUCWindow_->show();
}
}
/**
* If a resource goes offline, release bound chatdialog to that resource.
*/
void ChatsManager::handlePresenceChange(boost::shared_ptr<Presence> newPresence) {
if (mucRegistry_->isMUC(newPresence->getFrom().toBare())) return;
foreach (ChatListWindow::Chat& chat, recentChats_) {
if (newPresence->getFrom().toBare() == chat.jid.toBare() && !chat.isMUC) {
Presence::ref presence = presenceOracle_->getHighestPriorityPresence(chat.jid.toBare());
chat.setStatusType(presence ? presence->getShow() : StatusShow::None);
chatListWindow_->setRecents(recentChats_);
break;
}
}
@@ -457,71 +467,71 @@ void ChatsManager::setOnline(bool enabled) {
controllerPair.second->setOnline(enabled);
if (enabled) {
controllerPair.second->rejoin();
}
}
if (!enabled) {
delete mucBookmarkManager_;
mucBookmarkManager_ = NULL;
chatListWindow_->setBookmarksEnabled(false);
} else {
setupBookmarks();
}
}
void ChatsManager::handleChatRequest(const std::string &contact) {
ChatController* controller = getChatControllerOrFindAnother(JID(contact));
controller->activateChatWindow();
}
ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact) {
ChatController* controller = getChatControllerIfExists(contact);
if (!controller && !mucRegistry_->isMUC(contact.toBare())) {
foreach (JIDChatControllerPair pair, chatControllers_) {
if (pair.first.toBare() == contact.toBare()) {
controller = pair.second;
break;
}
}
}
return controller ? controller : createNewChatController(contact);
}
ChatController* ChatsManager::createNewChatController(const JID& contact) {
assert(chatControllers_.find(contact) == chatControllers_.end());
- ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_);
+ ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_);
chatControllers_[contact] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false));
controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
updatePresenceReceivingStateOnChatController(contact);
return controller;
}
ChatController* ChatsManager::getChatControllerOrCreate(const JID &contact) {
ChatController* controller = getChatControllerIfExists(contact);
return controller ? controller : createNewChatController(contact);
}
ChatController* ChatsManager::getChatControllerIfExists(const JID &contact, bool rebindIfNeeded) {
if (chatControllers_.find(contact) == chatControllers_.end()) {
if (mucRegistry_->isMUC(contact.toBare())) {
return NULL;
}
//Need to look for an unbound window to bind first
JID bare(contact.toBare());
if (chatControllers_.find(bare) != chatControllers_.end()) {
rebindControllerJID(bare, contact);
} else {
foreach (JIDChatControllerPair pair, chatControllers_) {
if (pair.first.toBare() == contact.toBare()) {
if (rebindIfNeeded) {
rebindControllerJID(pair.first, contact);
return chatControllers_[contact];
} else {
return pair.second;
}
}
}
return NULL;
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 0c7f492..4d1fc14 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -14,116 +14,119 @@
#include <Swiften/Elements/DiscoInfo.h>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/Presence.h>
#include <Swiften/JID/JID.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIInterfaces/ChatListWindow.h>
#include <Swiften/MUC/MUCBookmark.h>
namespace Swift {
class EventController;
class ChatController;
class ChatControllerBase;
class MUCController;
class MUCManager;
class ChatWindowFactory;
class JoinMUCWindow;
class JoinMUCWindowFactory;
class NickResolver;
class PresenceOracle;
class AvatarManager;
class StanzaChannel;
class IQRouter;
class PresenceSender;
class MUCBookmarkManager;
class ChatListWindowFactory;
class TimerFactory;
class EntityCapsProvider;
class DirectedPresenceSender;
class MUCSearchWindowFactory;
class ProfileSettingsProvider;
class MUCSearchController;
class FileTransferOverview;
class FileTransferController;
class XMPPRoster;
+ class SettingsProvider;
class ChatsManager {
public:
- ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* settings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode);
+ ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* settings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings);
virtual ~ChatsManager();
void setAvatarManager(AvatarManager* avatarManager);
void setOnline(bool enabled);
void setServerDiscoInfo(boost::shared_ptr<DiscoInfo> info);
void handleIncomingMessage(boost::shared_ptr<Message> message);
private:
ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity);
void handleChatRequest(const std::string& contact);
void handleJoinMUCRequest(const JID& muc, const boost::optional<std::string>& password, const boost::optional<std::string>& nick, bool addAutoJoin, bool createAsReservedIfNew);
void handleSearchMUCRequest();
void handleMUCSelectedAfterSearch(const JID&);
void rebindControllerJID(const JID& from, const JID& to);
void handlePresenceChange(boost::shared_ptr<Presence> newPresence);
void handleUIEvent(boost::shared_ptr<UIEvent> event);
void handleMUCBookmarkAdded(const MUCBookmark& bookmark);
void handleMUCBookmarkRemoved(const MUCBookmark& bookmark);
void handleUserLeftMUC(MUCController* mucController);
void handleBookmarksReady();
void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC);
void handleNewFileTransferController(FileTransferController*);
void appendRecent(const ChatListWindow::Chat& chat);
void prependRecent(const ChatListWindow::Chat& chat);
void setupBookmarks();
void loadRecents();
void saveRecents();
void handleChatMadeRecent();
void handleMUCBookmarkActivated(const MUCBookmark&);
void handleRecentActivated(const ChatListWindow::Chat&);
void handleUnreadCountChanged(ChatControllerBase* controller);
void handleAvatarChanged(const JID& jid);
void handleClearRecentsRequested();
void handleJIDAddedToRoster(const JID&);
void handleJIDRemovedFromRoster(const JID&);
void handleJIDUpdatedInRoster(const JID&);
void handleRosterCleared();
+ void handleSettingChanged(const std::string& settingPath);
void updatePresenceReceivingStateOnChatController(const JID&);
ChatController* getChatControllerOrFindAnother(const JID &contact);
ChatController* createNewChatController(const JID &contact);
ChatController* getChatControllerOrCreate(const JID &contact);
ChatController* getChatControllerIfExists(const JID &contact, bool rebindIfNeeded = true);
private:
std::map<JID, MUCController*> mucControllers_;
std::map<JID, ChatController*> chatControllers_;
EventController* eventController_;
JID jid_;
StanzaChannel* stanzaChannel_;
IQRouter* iqRouter_;
ChatWindowFactory* chatWindowFactory_;
JoinMUCWindowFactory* joinMUCWindowFactory_;
NickResolver* nickResolver_;
PresenceOracle* presenceOracle_;
AvatarManager* avatarManager_;
PresenceSender* presenceSender_;
UIEventStream* uiEventStream_;
MUCBookmarkManager* mucBookmarkManager_;
boost::shared_ptr<DiscoInfo> serverDiscoInfo_;
ChatListWindow* chatListWindow_;
JoinMUCWindow* joinMUCWindow_;
boost::bsignals::scoped_connection uiEventConnection_;
bool useDelayForLatency_;
TimerFactory* timerFactory_;
MUCRegistry* mucRegistry_;
EntityCapsProvider* entityCapsProvider_;
MUCManager* mucManager;
MUCSearchController* mucSearchController_;
std::list<ChatListWindow::Chat> recentChats_;
ProfileSettingsProvider* profileSettings_;
FileTransferOverview* ftOverview_;
XMPPRoster* roster_;
bool eagleMode_;
bool userWantsReceipts_;
+ SettingsProvider* settings_;
};
}
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index 8162bec..cd868e6 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -1,169 +1,169 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include "3rdParty/hippomocks.h"
#include <boost/bind.hpp>
#include "Swift/Controllers/Chat/ChatsManager.h"
#include "Swift/Controllers/Chat/UnitTest/MockChatListWindow.h"
#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
#include "Swift/Controllers/Settings/DummySettingsProvider.h"
#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h"
#include "Swiften/Client/Client.h"
#include "Swiften/Disco/EntityCapsManager.h"
#include "Swiften/Disco/CapsProvider.h"
#include "Swiften/MUC/MUCManager.h"
#include "Swift/Controllers/Chat/ChatController.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
#include "Swift/Controllers/Chat/MUCController.h"
#include "Swiften/Presence/StanzaChannelPresenceSender.h"
#include "Swiften/Avatars/NullAvatarManager.h"
#include "Swiften/Avatars/AvatarMemoryStorage.h"
#include "Swiften/VCards/VCardManager.h"
#include "Swiften/VCards/VCardMemoryStorage.h"
#include "Swiften/Client/NickResolver.h"
#include "Swiften/Presence/DirectedPresenceSender.h"
#include "Swiften/Roster/XMPPRosterImpl.h"
#include "Swift/Controllers/UnitTest/MockChatWindow.h"
#include "Swiften/Client/DummyStanzaChannel.h"
#include "Swiften/Queries/DummyIQChannel.h"
#include "Swiften/Presence/PresenceOracle.h"
#include "Swiften/Jingle/JingleSessionManager.h"
#include "Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h"
#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
-#include "Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h"
#include <Swift/Controllers/ProfileSettingsProvider.h>
#include "Swift/Controllers/FileTransfer/FileTransferOverview.h"
#include "Swiften/Elements/DeliveryReceiptRequest.h"
#include "Swiften/Elements/DeliveryReceipt.h"
#include <Swiften/Base/Algorithm.h>
+#include <Swift/Controllers/SettingConstants.h>
using namespace Swift;
class DummyCapsProvider : public CapsProvider {
DiscoInfo::ref getCaps(const std::string&) const {return DiscoInfo::ref(new DiscoInfo());}
};
class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ChatsManagerTest);
CPPUNIT_TEST(testFirstOpenWindowIncoming);
CPPUNIT_TEST(testSecondOpenWindowIncoming);
CPPUNIT_TEST(testFirstOpenWindowOutgoing);
CPPUNIT_TEST(testFirstOpenWindowBareToFull);
CPPUNIT_TEST(testSecondWindow);
CPPUNIT_TEST(testUnbindRebind);
CPPUNIT_TEST(testNoDuplicateUnbind);
CPPUNIT_TEST(testThreeMUCWindows);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnRemoveFromRoster);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnAddToRoster);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToBoth);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToFrom);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
mocks_ = new MockRepository();
jid_ = JID("test@test.com/resource");
stanzaChannel_ = new DummyStanzaChannel();
iqChannel_ = new DummyIQChannel();
iqRouter_ = new IQRouter(iqChannel_);
capsProvider_ = new DummyCapsProvider();
eventController_ = new EventController();
chatWindowFactory_ = mocks_->InterfaceMock<ChatWindowFactory>();
joinMUCWindowFactory_ = mocks_->InterfaceMock<JoinMUCWindowFactory>();
xmppRoster_ = new XMPPRosterImpl();
mucRegistry_ = new MUCRegistry();
nickResolver_ = new NickResolver(jid_.toBare(), xmppRoster_, NULL, mucRegistry_);
presenceOracle_ = new PresenceOracle(stanzaChannel_);
serverDiscoInfo_ = boost::shared_ptr<DiscoInfo>(new DiscoInfo());
presenceSender_ = new StanzaChannelPresenceSender(stanzaChannel_);
directedPresenceSender_ = new DirectedPresenceSender(presenceSender_);
mucManager_ = new MUCManager(stanzaChannel_, iqRouter_, directedPresenceSender_, mucRegistry_);
uiEventStream_ = new UIEventStream();
entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_);
chatListWindowFactory_ = mocks_->InterfaceMock<ChatListWindowFactory>();
mucSearchWindowFactory_ = mocks_->InterfaceMock<MUCSearchWindowFactory>();
settings_ = new DummySettingsProvider();
profileSettings_ = new ProfileSettingsProvider("a", settings_);
chatListWindow_ = new MockChatListWindow();
ftManager_ = new DummyFileTransferManager();
ftOverview_ = new FileTransferOverview(ftManager_);
mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createChatListWindow).With(uiEventStream_).Return(chatListWindow_);
- manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false);
+ manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_);
avatarManager_ = new NullAvatarManager();
manager_->setAvatarManager(avatarManager_);
};
void tearDown() {
//delete chatListWindowFactory
- delete settings_;
delete profileSettings_;
delete avatarManager_;
delete manager_;
delete ftOverview_;
delete ftManager_;
delete directedPresenceSender_;
delete presenceSender_;
delete presenceOracle_;
delete nickResolver_;
delete mucRegistry_;
delete stanzaChannel_;
delete eventController_;
delete iqRouter_;
delete iqChannel_;
delete uiEventStream_;
delete mucManager_;
delete xmppRoster_;
delete entityCapsManager_;
delete capsProvider_;
delete chatListWindow_;
delete mocks_;
+ delete settings_;
}
void testFirstOpenWindowIncoming() {
JID messageJID("testling@test.com/resource1");
MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);
boost::shared_ptr<Message> message(new Message());
message->setFrom(messageJID);
std::string body("This is a legible message. >HEH@)oeueu");
message->setBody(body);
manager_->handleIncomingMessage(message);
CPPUNIT_ASSERT_EQUAL(body, window->lastMessageBody_);
}
void testSecondOpenWindowIncoming() {
JID messageJID1("testling@test.com/resource1");
MockChatWindow* window1 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID1, uiEventStream_).Return(window1);
boost::shared_ptr<Message> message1(new Message());
message1->setFrom(messageJID1);
std::string body1("This is a legible message. >HEH@)oeueu");
message1->setBody(body1);
manager_->handleIncomingMessage(message1);
CPPUNIT_ASSERT_EQUAL(body1, window1->lastMessageBody_);
JID messageJID2("testling@test.com/resource2");
//MockChatWindow* window2 = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
//mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID2, uiEventStream_).Return(window2);
boost::shared_ptr<Message> message2(new Message());
@@ -321,130 +321,130 @@ public:
presenceOracle_->onPresenceChange(jid1Offline);
boost::shared_ptr<Presence> jid2Online(new Presence());
jid2Online->setFrom(JID(messageJID2));
boost::shared_ptr<Presence> jid2Offline(new Presence());
jid2Offline->setFrom(JID(messageJID2));
jid2Offline->setType(Presence::Unavailable);
presenceOracle_->onPresenceChange(jid2Offline);
JID messageJID3("testling@test.com/resource3");
boost::shared_ptr<Message> message3(new Message());
message3->setFrom(messageJID3);
std::string body3("This is a legible message3.");
message3->setBody(body3);
manager_->handleIncomingMessage(message3);
CPPUNIT_ASSERT_EQUAL(body3, window1->lastMessageBody_);
boost::shared_ptr<Message> message2b(new Message());
message2b->setFrom(messageJID2);
std::string body2b("This is a legible message2b.");
message2b->setBody(body2b);
manager_->handleIncomingMessage(message2b);
CPPUNIT_ASSERT_EQUAL(body2b, window1->lastMessageBody_);
}
/**
* Test that ChatController doesn't send receipts anymore after removal of the contact from the roster.
*/
void testChatControllerPresenceAccessUpdatedOnRemoveFromRoster() {
JID messageJID("testling@test.com/resource1");
xmppRoster_->addContact(messageJID, "foo", std::vector<std::string>(), RosterItemPayload::Both);
MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);
- uiEventStream_->send(boost::shared_ptr<UIEvent>(new ToggleRequestDeliveryReceiptsUIEvent(true)));
+ settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true);
boost::shared_ptr<Message> message = makeDeliveryReceiptTestMessage(messageJID, "1");
manager_->handleIncomingMessage(message);
Stanza::ref stanzaContactOnRoster = stanzaChannel_->getStanzaAtIndex<Stanza>(0);
CPPUNIT_ASSERT_EQUAL(st(1), stanzaChannel_->sentStanzas.size());
CPPUNIT_ASSERT(stanzaContactOnRoster->getPayload<DeliveryReceipt>() != 0);
xmppRoster_->removeContact(messageJID);
message->setID("2");
manager_->handleIncomingMessage(message);
CPPUNIT_ASSERT_EQUAL(st(1), stanzaChannel_->sentStanzas.size());
}
/**
* Test that ChatController sends receipts after the contact has been added to the roster.
*/
void testChatControllerPresenceAccessUpdatedOnAddToRoster() {
JID messageJID("testling@test.com/resource1");
MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);
- uiEventStream_->send(boost::shared_ptr<UIEvent>(new ToggleRequestDeliveryReceiptsUIEvent(true)));
+ settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true);
boost::shared_ptr<Message> message = makeDeliveryReceiptTestMessage(messageJID, "1");
manager_->handleIncomingMessage(message);
CPPUNIT_ASSERT_EQUAL(st(0), stanzaChannel_->sentStanzas.size());
xmppRoster_->addContact(messageJID, "foo", std::vector<std::string>(), RosterItemPayload::Both);
message->setID("2");
manager_->handleIncomingMessage(message);
CPPUNIT_ASSERT_EQUAL(st(1), stanzaChannel_->sentStanzas.size());
Stanza::ref stanzaContactOnRoster = stanzaChannel_->getStanzaAtIndex<Stanza>(0);
CPPUNIT_ASSERT(stanzaContactOnRoster->getPayload<DeliveryReceipt>() != 0);
}
/**
* Test that ChatController sends receipts if requested after change from subscription state To to subscription state Both.
*/
void testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToBoth() {
testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::To, RosterItemPayload::Both);
}
/**
* Test that ChatController sends receipts if requested after change from subscription state To to subscription state From.
*/
void testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToFrom() {
testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::To, RosterItemPayload::From);
}
void testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::Subscription from, RosterItemPayload::Subscription to) {
JID messageJID("testling@test.com/resource1");
xmppRoster_->addContact(messageJID, "foo", std::vector<std::string>(), from);
MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);
- uiEventStream_->send(boost::shared_ptr<UIEvent>(new ToggleRequestDeliveryReceiptsUIEvent(true)));
+ settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true);
boost::shared_ptr<Message> message = makeDeliveryReceiptTestMessage(messageJID, "1");
manager_->handleIncomingMessage(message);
CPPUNIT_ASSERT_EQUAL(st(0), stanzaChannel_->sentStanzas.size());
xmppRoster_->addContact(messageJID, "foo", std::vector<std::string>(), to);
message->setID("2");
manager_->handleIncomingMessage(message);
CPPUNIT_ASSERT_EQUAL(st(1), stanzaChannel_->sentStanzas.size());
Stanza::ref stanzaContactOnRoster = stanzaChannel_->getStanzaAtIndex<Stanza>(0);
CPPUNIT_ASSERT(stanzaContactOnRoster->getPayload<DeliveryReceipt>() != 0);
}
private:
boost::shared_ptr<Message> makeDeliveryReceiptTestMessage(const JID& from, const std::string& id) {
boost::shared_ptr<Message> message = boost::make_shared<Message>();
message->setFrom(from);
message->setID(id);
message->addPayload(boost::make_shared<DeliveryReceiptRequest>());
return message;
}
size_t st(int i) {
return static_cast<size_t>(i);
}
private:
JID jid_;
ChatsManager* manager_;
DummyStanzaChannel* stanzaChannel_;
IQChannel* iqChannel_;
IQRouter* iqRouter_;
EventController* eventController_;
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 6f93dd3..06f8c3a 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -1,664 +1,657 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swift/Controllers/MainController.h>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <string>
#include <stdlib.h>
#include <Swiften/Base/format.h>
#include <Swiften/Base/Algorithm.h>
#include <Swift/Controllers/Intl.h>
#include <Swift/Controllers/UIInterfaces/UIFactory.h>
#include "Swiften/Network/TimerFactory.h"
#include "Swift/Controllers/BuildVersion.h"
#include "Swiften/Client/Storages.h"
#include "Swiften/VCards/VCardManager.h"
#include "Swift/Controllers/Chat/UserSearchController.h"
#include "Swift/Controllers/Chat/ChatsManager.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
#include "Swift/Controllers/EventWindowController.h"
#include "Swift/Controllers/UIInterfaces/LoginWindow.h"
#include "Swift/Controllers/UIInterfaces/LoginWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/MainWindow.h"
#include "Swift/Controllers/Chat/MUCController.h"
#include "Swiften/Client/NickResolver.h"
#include "Swift/Controllers/Roster/RosterController.h"
#include "Swift/Controllers/SoundEventController.h"
#include "Swift/Controllers/SoundPlayer.h"
#include "Swift/Controllers/StatusTracker.h"
#include "Swift/Controllers/SystemTray.h"
#include "Swift/Controllers/SystemTrayController.h"
#include "Swift/Controllers/XMLConsoleController.h"
#include "Swift/Controllers/FileTransferListController.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swift/Controllers/PresenceNotifier.h"
#include "Swift/Controllers/EventNotifier.h"
#include "Swift/Controllers/Storages/StoragesFactory.h"
#include "SwifTools/Dock/Dock.h"
#include "SwifTools/Notifier/TogglableNotifier.h"
#include "Swiften/Base/foreach.h"
#include "Swiften/Client/Client.h"
#include "Swiften/Presence/PresenceSender.h"
#include "Swiften/Elements/ChatState.h"
#include "Swiften/Elements/Presence.h"
#include "Swiften/Elements/VCardUpdate.h"
#include "Swift/Controllers/Settings/SettingsProvider.h"
#include "Swiften/Elements/DiscoInfo.h"
#include "Swiften/Disco/CapsInfoGenerator.h"
#include "Swiften/Disco/GetDiscoInfoRequest.h"
#include "Swiften/Disco/ClientDiscoManager.h"
#include "Swiften/VCards/GetVCardRequest.h"
#include "Swiften/StringCodecs/SHA1.h"
#include "Swiften/StringCodecs/Hexify.h"
#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
-#include "Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h"
-#include "Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h"
#include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
#include "Swift/Controllers/Storages/CertificateStorageFactory.h"
#include "Swift/Controllers/Storages/CertificateStorageTrustChecker.h"
#include "Swiften/Network/NetworkFactories.h"
#include <Swift/Controllers/ProfileController.h>
#include <Swift/Controllers/ContactEditController.h>
#include <Swift/Controllers/XMPPURIController.h>
#include "Swift/Controllers/AdHocManager.h"
#include <SwifTools/Idle/IdleDetector.h>
#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
#include <Swiften/FileTransfer/FileTransferManager.h>
#include <Swiften/Client/ClientXMLTracer.h>
+#include <Swift/Controllers/SettingConstants.h>
namespace Swift {
static const std::string CLIENT_NAME = "Swift";
static const std::string CLIENT_NODE = "http://swift.im";
-static const std::string SHOW_NOTIFICATIONS = "showNotifications";
-static const std::string REQUEST_DELIVERYRECEIPTS = "requestDeliveryReceipts";
MainController::MainController(
EventLoop* eventLoop,
NetworkFactories* networkFactories,
UIFactory* uiFactories,
- SettingsProvider *settings,
+ SettingsProvider* settings,
SystemTray* systemTray,
SoundPlayer* soundPlayer,
StoragesFactory* storagesFactory,
CertificateStorageFactory* certificateStorageFactory,
Dock* dock,
Notifier* notifier,
URIHandler* uriHandler,
IdleDetector* idleDetector,
- bool useDelayForLatency,
- bool eagleMode) :
+ bool useDelayForLatency) :
eventLoop_(eventLoop),
networkFactories_(networkFactories),
uiFactory_(uiFactories),
storagesFactory_(storagesFactory),
certificateStorageFactory_(certificateStorageFactory),
settings_(settings),
uriHandler_(uriHandler),
idleDetector_(idleDetector),
loginWindow_(NULL) ,
useDelayForLatency_(useDelayForLatency),
- eagleMode_(eagleMode),
ftOverview_(NULL) {
storages_ = NULL;
certificateStorage_ = NULL;
statusTracker_ = NULL;
presenceNotifier_ = NULL;
eventNotifier_ = NULL;
rosterController_ = NULL;
chatsManager_ = NULL;
eventWindowController_ = NULL;
profileController_ = NULL;
contactEditController_ = NULL;
userSearchControllerChat_ = NULL;
userSearchControllerAdd_ = NULL;
adHocManager_ = NULL;
quitRequested_ = false;
clientInitialized_ = false;
offlineRequested_ = false;
timeBeforeNextReconnect_ = -1;
dock_ = dock;
uiEventStream_ = new UIEventStream();
notifier_ = new TogglableNotifier(notifier);
eventController_ = new EventController();
eventController_->onEventQueueLengthChange.connect(boost::bind(&MainController::handleEventQueueLengthChange, this, _1));
systemTrayController_ = new SystemTrayController(eventController_, systemTray);
loginWindow_ = uiFactory_->createLoginWindow(uiEventStream_);
loginWindow_->setShowNotificationToggle(!notifier->isExternallyConfigured());
- soundEventController_ = new SoundEventController(eventController_, soundPlayer, settings, uiEventStream_);
+ soundEventController_ = new SoundEventController(eventController_, soundPlayer, settings);
xmppURIController_ = new XMPPURIController(uriHandler_, uiEventStream_);
- std::string selectedLoginJID = settings_->getStringSetting("lastLoginJID");
- bool loginAutomatically = settings_->getBoolSetting("loginAutomatically", false);
+ std::string selectedLoginJID = settings_->getSetting(SettingConstants::LAST_LOGIN_JID);
+ bool loginAutomatically = settings_->getSetting(SettingConstants::LOGIN_AUTOMATICALLY);
std::string cachedPassword;
std::string cachedCertificate;
- if (!eagleMode_) {
+ bool eagle = settings_->getSetting(SettingConstants::FORGET_PASSWORDS);
+ if (!eagle) {
foreach (std::string profile, settings->getAvailableProfiles()) {
ProfileSettingsProvider profileSettings(profile, settings);
- std::string password = eagleMode ? "" : profileSettings.getStringSetting("pass");
+ std::string password = profileSettings.getStringSetting("pass");
std::string certificate = profileSettings.getStringSetting("certificate");
std::string jid = profileSettings.getStringSetting("jid");
loginWindow_->addAvailableAccount(jid, password, certificate);
if (jid == selectedLoginJID) {
cachedPassword = password;
cachedCertificate = certificate;
}
}
loginWindow_->selectUser(selectedLoginJID);
loginWindow_->setLoginAutomatically(loginAutomatically);
}
loginWindow_->onLoginRequest.connect(boost::bind(&MainController::handleLoginRequest, this, _1, _2, _3, _4, _5));
loginWindow_->onPurgeSavedLoginRequest.connect(boost::bind(&MainController::handlePurgeSavedLoginRequest, this, _1));
loginWindow_->onCancelLoginRequest.connect(boost::bind(&MainController::handleCancelLoginRequest, this));
loginWindow_->onQuitRequest.connect(boost::bind(&MainController::handleQuitRequest, this));
- idleDetector_->setIdleTimeSeconds(600);
+ idleDetector_->setIdleTimeSeconds(settings->getSetting(SettingConstants::IDLE_TIMEOUT));
idleDetector_->onIdleChanged.connect(boost::bind(&MainController::handleInputIdleChanged, this, _1));
xmlConsoleController_ = new XMLConsoleController(uiEventStream_, uiFactory_);
fileTransferListController_ = new FileTransferListController(uiEventStream_, uiFactory_);
- uiEventStream_->onUIEvent.connect(boost::bind(&MainController::handleUIEvent, this, _1));
- bool enabled = settings_->getBoolSetting(SHOW_NOTIFICATIONS, true);
- uiEventStream_->send(boost::shared_ptr<ToggleNotificationsUIEvent>(new ToggleNotificationsUIEvent(enabled)));
+ settings_->onSettingChanged.connect(boost::bind(&MainController::handleSettingChanged, this, _1));
if (loginAutomatically) {
profileSettings_ = new ProfileSettingsProvider(selectedLoginJID, settings_);
handleLoginRequest(selectedLoginJID, cachedPassword, cachedCertificate, true, true);
} else {
profileSettings_ = NULL;
}
}
MainController::~MainController() {
idleDetector_->onIdleChanged.disconnect(boost::bind(&MainController::handleInputIdleChanged, this, _1));
purgeCachedCredentials();
//setManagersOffline();
eventController_->disconnectAll();
resetClient();
delete fileTransferListController_;
delete xmlConsoleController_;
delete xmppURIController_;
delete soundEventController_;
delete systemTrayController_;
delete eventController_;
delete notifier_;
delete uiEventStream_;
}
void MainController::purgeCachedCredentials() {
safeClear(password_);
}
void MainController::resetClient() {
purgeCachedCredentials();
resetCurrentError();
resetPendingReconnects();
vCardPhotoHash_.clear();
delete contactEditController_;
contactEditController_ = NULL;
delete profileController_;
profileController_ = NULL;
delete eventWindowController_;
eventWindowController_ = NULL;
delete chatsManager_;
chatsManager_ = NULL;
delete ftOverview_;
ftOverview_ = NULL;
delete rosterController_;
rosterController_ = NULL;
delete eventNotifier_;
eventNotifier_ = NULL;
delete presenceNotifier_;
presenceNotifier_ = NULL;
delete certificateStorage_;
certificateStorage_ = NULL;
delete storages_;
storages_ = NULL;
delete statusTracker_;
statusTracker_ = NULL;
delete profileSettings_;
profileSettings_ = NULL;
delete userSearchControllerChat_;
userSearchControllerChat_ = NULL;
delete userSearchControllerAdd_;
userSearchControllerAdd_ = NULL;
delete adHocManager_;
adHocManager_ = NULL;
clientInitialized_ = false;
}
-void MainController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
- boost::shared_ptr<ToggleNotificationsUIEvent> notificationsEvent = boost::dynamic_pointer_cast<ToggleNotificationsUIEvent>(event);
- if (notificationsEvent) {
- bool enabled = notificationsEvent->getEnabled();
- notifier_->setPersistentEnabled(enabled);
- settings_->storeBool(SHOW_NOTIFICATIONS, enabled);
+void MainController::handleSettingChanged(const std::string& settingPath) {
+ if (settingPath == SettingConstants::SHOW_NOTIFICATIONS.getKey()) {
+ notifier_->setPersistentEnabled(settings_->getSetting(SettingConstants::SHOW_NOTIFICATIONS));
}
- boost::shared_ptr<ToggleRequestDeliveryReceiptsUIEvent> deliveryReceiptEvent = boost::dynamic_pointer_cast<ToggleRequestDeliveryReceiptsUIEvent>(event);
- if (deliveryReceiptEvent) {
- settings_->storeBool(REQUEST_DELIVERYRECEIPTS, deliveryReceiptEvent->getEnabled());
- }
-
}
void MainController::resetPendingReconnects() {
timeBeforeNextReconnect_ = -1;
if (reconnectTimer_) {
reconnectTimer_->stop();
reconnectTimer_.reset();
}
resetCurrentError();
}
void MainController::resetCurrentError() {
if (lastDisconnectError_) {
lastDisconnectError_->conclude();
lastDisconnectError_ = boost::shared_ptr<ErrorEvent>();
}
}
void MainController::handleConnected() {
boundJID_ = client_->getJID();
resetCurrentError();
resetPendingReconnects();
- if (eagleMode_) {
+ if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
purgeCachedCredentials();
}
bool freshLogin = rosterController_ == NULL;
myStatusLooksOnline_ = true;
if (freshLogin) {
profileController_ = new ProfileController(client_->getVCardManager(), uiFactory_, uiEventStream_);
srand(time(NULL));
int randomPort = 10000 + rand() % 10000;
client_->getFileTransferManager()->startListeningOnPort(randomPort);
ftOverview_ = new FileTransferOverview(client_->getFileTransferManager());
fileTransferListController_->setFileTransferOverview(ftOverview_);
rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_);
rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
contactEditController_ = new ContactEditController(rosterController_, uiFactory_, uiEventStream_);
- chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), eagleMode_);
+ chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_);
client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
chatsManager_->setAvatarManager(client_->getAvatarManager());
eventWindowController_ = new EventWindowController(eventController_, uiFactory_);
loginWindow_->morphInto(rosterController_->getWindow());
DiscoInfo discoInfo;
discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc"));
discoInfo.addFeature(DiscoInfo::ChatStatesFeature);
discoInfo.addFeature(DiscoInfo::SecurityLabelsFeature);
discoInfo.addFeature(DiscoInfo::MessageCorrectionFeature);
#ifdef SWIFT_EXPERIMENTAL_FT
discoInfo.addFeature(DiscoInfo::JingleFeature);
discoInfo.addFeature(DiscoInfo::JingleFTFeature);
discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature);
discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature);
#endif
discoInfo.addFeature(DiscoInfo::MessageDeliveryReceiptsFeature);
client_->getDiscoManager()->setCapsNode(CLIENT_NODE);
client_->getDiscoManager()->setDiscoInfo(discoInfo);
userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, uiFactory_, client_->getIQRouter(), rosterController_);
userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, uiFactory_, client_->getIQRouter(), rosterController_);
adHocManager_ = new AdHocManager(boundJID_, uiFactory_, client_->getIQRouter(), uiEventStream_, rosterController_->getWindow());
}
loginWindow_->setIsLoggingIn(false);
client_->requestRoster();
GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(boundJID_.toBare(), client_->getIQRouter());
discoInfoRequest->onResponse.connect(boost::bind(&MainController::handleServerDiscoInfoResponse, this, _1, _2));
discoInfoRequest->send();
client_->getVCardManager()->requestOwnVCard();
rosterController_->setEnabled(true);
profileController_->setAvailable(true);
contactEditController_->setAvailable(true);
/* Send presence later to catch all the incoming presences. */
sendPresence(statusTracker_->getNextPresence());
/* Enable chats last of all, so rejoining MUCs has the right sent presence */
chatsManager_->setOnline(true);
- // notify world about current delivey receipt request setting state.
- uiEventStream_->send(boost::make_shared<ToggleRequestDeliveryReceiptsUIEvent>(settings_->getBoolSetting(REQUEST_DELIVERYRECEIPTS, false)));
}
void MainController::handleEventQueueLengthChange(int count) {
dock_->setNumberOfPendingMessages(count);
}
void MainController::reconnectAfterError() {
if (reconnectTimer_) {
reconnectTimer_->stop();
}
performLoginFromCachedCredentials();
}
void MainController::handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText) {
boost::shared_ptr<Presence> presence(new Presence());
if (show == StatusShow::None) {
// Note: this is misleading, None doesn't mean unavailable on the wire.
presence->setType(Presence::Unavailable);
resetPendingReconnects();
myStatusLooksOnline_ = false;
offlineRequested_ = true;
}
else {
offlineRequested_ = false;
presence->setShow(show);
}
presence->setStatus(statusText);
statusTracker_->setRequestedPresence(presence);
if (presence->getType() != Presence::Unavailable) {
profileSettings_->storeInt("lastShow", presence->getShow());
profileSettings_->storeString("lastStatus", presence->getStatus());
}
if (presence->getType() != Presence::Unavailable && !client_->isAvailable()) {
performLoginFromCachedCredentials();
} else {
sendPresence(presence);
}
}
void MainController::sendPresence(boost::shared_ptr<Presence> presence) {
rosterController_->getWindow()->setMyStatusType(presence->getShow());
rosterController_->getWindow()->setMyStatusText(presence->getStatus());
systemTrayController_->setMyStatusType(presence->getShow());
notifier_->setTemporarilyDisabled(presence->getShow() == StatusShow::DND);
// Add information and send
if (!vCardPhotoHash_.empty()) {
presence->updatePayload(boost::shared_ptr<VCardUpdate>(new VCardUpdate(vCardPhotoHash_)));
}
client_->getPresenceSender()->sendPresence(presence);
if (presence->getType() == Presence::Unavailable) {
logout();
}
}
void MainController::handleInputIdleChanged(bool idle) {
if (!statusTracker_) {
//Haven't logged in yet.
return;
}
- if (idle) {
- if (statusTracker_->goAutoAway()) {
- if (client_ && client_->isAvailable()) {
- sendPresence(statusTracker_->getNextPresence());
- }
+
+ if (settings_->getSetting(SettingConstants::IDLE_GOES_OFFLINE)) {
+ if (idle) {
+ logout();
}
- } else {
- if (statusTracker_->goAutoUnAway()) {
- if (client_ && client_->isAvailable()) {
- sendPresence(statusTracker_->getNextPresence());
+ }
+ else {
+ if (idle) {
+ if (statusTracker_->goAutoAway()) {
+ if (client_ && client_->isAvailable()) {
+ sendPresence(statusTracker_->getNextPresence());
+ }
+ }
+ } else {
+ if (statusTracker_->goAutoUnAway()) {
+ if (client_ && client_->isAvailable()) {
+ sendPresence(statusTracker_->getNextPresence());
+ }
}
}
}
}
void MainController::handleLoginRequest(const std::string &username, const std::string &password, const std::string& certificateFile, bool remember, bool loginAutomatically) {
jid_ = JID(username);
if (!jid_.isValid() || jid_.getNode().empty()) {
loginWindow_->setMessage(QT_TRANSLATE_NOOP("", "User address invalid. User address should be of the form 'alice@wonderland.lit'"));
loginWindow_->setIsLoggingIn(false);
} else {
loginWindow_->setMessage("");
loginWindow_->setIsLoggingIn(true);
profileSettings_ = new ProfileSettingsProvider(username, settings_);
- if (!eagleMode_) {
+ if (!settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
profileSettings_->storeString("jid", username);
profileSettings_->storeString("certificate", certificateFile);
profileSettings_->storeString("pass", (remember || loginAutomatically) ? password : "");
- settings_->storeString("lastLoginJID", username);
- settings_->storeBool("loginAutomatically", loginAutomatically);
+ settings_->storeSetting(SettingConstants::LAST_LOGIN_JID, username);
+ settings_->storeSetting(SettingConstants::LOGIN_AUTOMATICALLY, loginAutomatically);
loginWindow_->addAvailableAccount(profileSettings_->getStringSetting("jid"), profileSettings_->getStringSetting("pass"), profileSettings_->getStringSetting("certificate"));
}
password_ = password;
certificateFile_ = certificateFile;
performLoginFromCachedCredentials();
}
}
void MainController::handlePurgeSavedLoginRequest(const std::string& username) {
settings_->removeProfile(username);
loginWindow_->removeAvailableAccount(username);
}
void MainController::performLoginFromCachedCredentials() {
- if (eagleMode_ && password_.empty()) {
+ if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS) && password_.empty()) {
/* Then we can't try to login again. */
return;
}
/* If we logged in with a bare JID, and we have a full bound JID, re-login with the
* bound JID to try and keep dynamically assigned resources */
JID clientJID = jid_;
if (boundJID_.isValid() && jid_.isBare() && boundJID_.toBare() == jid_) {
clientJID = boundJID_;
}
if (!statusTracker_) {
statusTracker_ = new StatusTracker();
}
if (!clientInitialized_) {
storages_ = storagesFactory_->createStorages(jid_.toBare());
certificateStorage_ = certificateStorageFactory_->createCertificateStorage(jid_.toBare());
certificateTrustChecker_ = new CertificateStorageTrustChecker(certificateStorage_);
client_ = boost::make_shared<Swift::Client>(clientJID, createSafeByteArray(password_.c_str()), networkFactories_, storages_);
clientInitialized_ = true;
client_->setCertificateTrustChecker(certificateTrustChecker_);
client_->onDataRead.connect(boost::bind(&XMLConsoleController::handleDataRead, xmlConsoleController_, _1));
client_->onDataWritten.connect(boost::bind(&XMLConsoleController::handleDataWritten, xmlConsoleController_, _1));
client_->onDisconnected.connect(boost::bind(&MainController::handleDisconnected, this, _1));
client_->onConnected.connect(boost::bind(&MainController::handleConnected, this));
client_->setSoftwareVersion(CLIENT_NAME, buildVersion);
client_->getVCardManager()->onVCardChanged.connect(boost::bind(&MainController::handleVCardReceived, this, _1, _2));
presenceNotifier_ = new PresenceNotifier(client_->getStanzaChannel(), notifier_, client_->getMUCRegistry(), client_->getAvatarManager(), client_->getNickResolver(), client_->getPresenceOracle(), networkFactories_->getTimerFactory());
presenceNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
eventNotifier_ = new EventNotifier(eventController_, notifier_, client_->getAvatarManager(), client_->getNickResolver());
eventNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
if (!certificateFile_.empty()) {
client_->setCertificate(certificateFile_);
}
boost::shared_ptr<Presence> presence(new Presence());
presence->setShow(static_cast<StatusShow::Type>(profileSettings_->getIntSetting("lastShow", StatusShow::Online)));
presence->setStatus(profileSettings_->getStringSetting("lastStatus"));
statusTracker_->setRequestedPresence(presence);
} else {
/* In case we're in the middle of another login, make sure they don't overlap */
client_->disconnect();
}
systemTrayController_->setConnecting();
if (rosterController_) {
rosterController_->getWindow()->setConnecting();
}
ClientOptions clientOptions;
- clientOptions.forgetPassword = eagleMode_;
- clientOptions.useTLS = eagleMode_ ? ClientOptions::RequireTLS : ClientOptions::UseTLSWhenAvailable;
+ bool eagle = settings_->getSetting(SettingConstants::FORGET_PASSWORDS);
+ clientOptions.forgetPassword = eagle;
+ clientOptions.useTLS = eagle ? ClientOptions::RequireTLS : ClientOptions::UseTLSWhenAvailable;
/*if (clientJID.getDomain() == "doomsong.co.uk") {
clientOptions.boshURL = URL("https", "channels.doomsong.co.uk", 11443, "http-bind/");
clientOptions.boshHTTPConnectProxyURL = URL("http", "squidproxy.doomsong.co.uk", 8123, "");
}*/
client_->connect(clientOptions);
}
void MainController::handleDisconnected(const boost::optional<ClientError>& error) {
- if (eagleMode_) {
+ if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
purgeCachedCredentials();
}
if (quitRequested_) {
resetClient();
loginWindow_->quit();
}
else if (error) {
std::string message;
std::string certificateErrorMessage;
switch(error->getType()) {
case ClientError::UnknownError: message = QT_TRANSLATE_NOOP("", "Unknown Error"); break;
case ClientError::DomainNameResolveError: message = QT_TRANSLATE_NOOP("", "Unable to find server"); break;
case ClientError::ConnectionError: message = QT_TRANSLATE_NOOP("", "Error connecting to server"); break;
case ClientError::ConnectionReadError: message = QT_TRANSLATE_NOOP("", "Error while receiving server data"); break;
case ClientError::ConnectionWriteError: message = QT_TRANSLATE_NOOP("", "Error while sending data to the server"); break;
case ClientError::XMLError: message = QT_TRANSLATE_NOOP("", "Error parsing server data"); break;
case ClientError::AuthenticationFailedError: message = QT_TRANSLATE_NOOP("", "Login/password invalid"); break;
case ClientError::CompressionFailedError: message = QT_TRANSLATE_NOOP("", "Error while compressing stream"); break;
case ClientError::ServerVerificationFailedError: message = QT_TRANSLATE_NOOP("", "Server verification failed"); break;
case ClientError::NoSupportedAuthMechanismsError: message = QT_TRANSLATE_NOOP("", "Authentication mechanisms not supported"); break;
case ClientError::UnexpectedElementError: message = QT_TRANSLATE_NOOP("", "Unexpected response"); break;
case ClientError::ResourceBindError: message = QT_TRANSLATE_NOOP("", "Error binding resource"); break;
case ClientError::SessionStartError: message = QT_TRANSLATE_NOOP("", "Error starting session"); break;
case ClientError::StreamError: message = QT_TRANSLATE_NOOP("", "Stream error"); break;
case ClientError::TLSError: message = QT_TRANSLATE_NOOP("", "Encryption error"); break;
case ClientError::ClientCertificateLoadError: message = QT_TRANSLATE_NOOP("", "Error loading certificate (Invalid password?)"); break;
case ClientError::ClientCertificateError: message = QT_TRANSLATE_NOOP("", "Certificate not authorized"); break;
case ClientError::UnknownCertificateError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Unknown certificate"); break;
case ClientError::CertificateExpiredError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has expired"); break;
case ClientError::CertificateNotYetValidError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is not yet valid"); break;
case ClientError::CertificateSelfSignedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is self-signed"); break;
case ClientError::CertificateRejectedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has been rejected"); break;
case ClientError::CertificateUntrustedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is not trusted"); break;
case ClientError::InvalidCertificatePurposeError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate cannot be used for encrypting your connection"); break;
case ClientError::CertificatePathLengthExceededError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate path length constraint exceeded"); break;
case ClientError::InvalidCertificateSignatureError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid certificate signature"); break;
case ClientError::InvalidCAError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid Certificate Authority"); break;
case ClientError::InvalidServerIdentityError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate does not match the host identity"); break;
}
bool forceReconnectAfterCertificateTrust = false;
if (!certificateErrorMessage.empty()) {
Certificate::ref certificate = certificateTrustChecker_->getLastCertificate();
if (loginWindow_->askUserToTrustCertificatePermanently(certificateErrorMessage, certificate)) {
certificateStorage_->addCertificate(certificate);
forceReconnectAfterCertificateTrust = true;
}
else {
message = QT_TRANSLATE_NOOP("", "Certificate error");
}
}
if (forceReconnectAfterCertificateTrust) {
performLoginFromCachedCredentials();
}
else if (!rosterController_) { //hasn't been logged in yet
signOut();
loginWindow_->setMessage(message);
loginWindow_->setIsLoggingIn(false);
} else {
logout();
- if (eagleMode_) {
+ if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
message = str(format(QT_TRANSLATE_NOOP("", "Disconnected from %1%: %2%. To reconnect, Sign Out and provide your password again.")) % jid_.getDomain() % message);
} else {
if (!offlineRequested_) {
setReconnectTimer();
}
if (lastDisconnectError_) {
message = str(format(QT_TRANSLATE_NOOP("", "Reconnect to %1% failed: %2%. Will retry in %3% seconds.")) % jid_.getDomain() % message % boost::lexical_cast<std::string>(timeBeforeNextReconnect_));
lastDisconnectError_->conclude();
} else {
message = str(format(QT_TRANSLATE_NOOP("", "Disconnected from %1%: %2%.")) % jid_.getDomain() % message);
}
lastDisconnectError_ = boost::shared_ptr<ErrorEvent>(new ErrorEvent(JID(jid_.getDomain()), message));
eventController_->handleIncomingEvent(lastDisconnectError_);
}
}
}
else if (!rosterController_) { //hasn't been logged in yet
loginWindow_->setIsLoggingIn(false);
}
}
void MainController::setReconnectTimer() {
if (timeBeforeNextReconnect_ < 0) {
timeBeforeNextReconnect_ = 1;
} else {
timeBeforeNextReconnect_ = timeBeforeNextReconnect_ >= 150 ? 300 : timeBeforeNextReconnect_ * 2; // Randomly selected by roll of a die, as required by 3920bis
}
if (reconnectTimer_) {
reconnectTimer_->stop();
}
reconnectTimer_ = networkFactories_->getTimerFactory()->createTimer(timeBeforeNextReconnect_ * 1000);
reconnectTimer_->onTick.connect(boost::bind(&MainController::reconnectAfterError, this));
reconnectTimer_->start();
}
void MainController::handleCancelLoginRequest() {
signOut();
}
void MainController::signOut() {
- if (eagleMode_) {
+ if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
purgeCachedCredentials();
}
eventController_->clear();
logout();
loginWindow_->loggedOut();
resetClient();
}
void MainController::logout() {
- if (eagleMode_) {
+ if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {
purgeCachedCredentials();
}
systemTrayController_->setMyStatusType(StatusShow::None);
if (clientInitialized_ /*&& client_->isAvailable()*/) {
client_->disconnect();
}
if (rosterController_ && myStatusLooksOnline_) {
rosterController_->getWindow()->setMyStatusType(StatusShow::None);
rosterController_->getWindow()->setMyStatusText("");
myStatusLooksOnline_ = false;
}
setManagersOffline();
}
void MainController::setManagersOffline() {
if (chatsManager_) {
chatsManager_->setOnline(false);
}
if (rosterController_) {
rosterController_->setEnabled(false);
}
if (profileController_) {
profileController_->setAvailable(false);
}
if (contactEditController_) {
contactEditController_->setAvailable(false);
}
}
void MainController::handleServerDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, ErrorPayload::ref error) {
if (!error) {
chatsManager_->setServerDiscoInfo(info);
adHocManager_->setServerDiscoInfo(info);
}
}
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 013f8bb..45e4ccf 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -1,37 +1,37 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <Swiften/Base/boost_bsignals.h>
#include <boost/shared_ptr.hpp>
#include <vector>
#include "Swiften/Network/Timer.h"
#include <string>
#include "Swiften/Client/ClientError.h"
#include "Swiften/JID/JID.h"
#include "Swiften/Elements/DiscoInfo.h"
#include "Swiften/Elements/VCard.h"
#include "Swiften/Elements/ErrorPayload.h"
#include "Swiften/Elements/Presence.h"
#include "Swift/Controllers/Settings/SettingsProvider.h"
#include "Swift/Controllers/ProfileSettingsProvider.h"
#include "Swiften/Elements/CapsInfo.h"
#include "Swift/Controllers/XMPPEvents/ErrorEvent.h"
#include "Swift/Controllers/UIEvents/UIEvent.h"
#include "Swiften/Client/ClientXMLTracer.h"
namespace Swift {
class IdleDetector;
class UIFactory;
class EventLoop;
class Client;
class ChatController;
class ChatsManager;
class CertificateStorageFactory;
class CertificateStorage;
class CertificateStorageTrustChecker;
@@ -52,121 +52,119 @@ namespace Swift {
class SoundEventController;
class SoundPlayer;
class XMLConsoleController;
class FileTransferListController;
class UIEventStream;
class EventWindowFactory;
class EventWindowController;
class MUCSearchController;
class UserSearchController;
class StatusTracker;
class Dock;
class Storages;
class StoragesFactory;
class NetworkFactories;
class URIHandler;
class XMPPURIController;
class AdHocManager;
class AdHocCommandWindowFactory;
class FileTransferOverview;
class MainController {
public:
MainController(
EventLoop* eventLoop,
NetworkFactories* networkFactories,
UIFactory* uiFactories,
SettingsProvider *settings,
SystemTray* systemTray,
SoundPlayer* soundPlayer,
StoragesFactory* storagesFactory,
CertificateStorageFactory* certificateStorageFactory,
Dock* dock,
Notifier* notifier,
URIHandler* uriHandler,
IdleDetector* idleDetector,
- bool useDelayForLatency,
- bool eagleMode);
+ bool useDelayForLatency);
~MainController();
private:
void resetClient();
void handleConnected();
void handleLoginRequest(const std::string& username, const std::string& password, const std::string& certificateFile, bool remember, bool loginAutomatically);
void handleCancelLoginRequest();
void handleQuitRequest();
void handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText);
void handleDisconnected(const boost::optional<ClientError>& error);
void handleServerDiscoInfoResponse(boost::shared_ptr<DiscoInfo>, ErrorPayload::ref);
void handleEventQueueLengthChange(int count);
void handleVCardReceived(const JID& j, VCard::ref vCard);
- void handleUIEvent(boost::shared_ptr<UIEvent> event);
+ void handleSettingChanged(const std::string& settingPath);
void handlePurgeSavedLoginRequest(const std::string& username);
void sendPresence(boost::shared_ptr<Presence> presence);
void handleInputIdleChanged(bool);
void logout();
void signOut();
void setReconnectTimer();
void resetPendingReconnects();
void resetCurrentError();
void performLoginFromCachedCredentials();
void reconnectAfterError();
void setManagersOffline();
void handleNotificationClicked(const JID& jid);
void handleForceQuit();
void purgeCachedCredentials();
private:
EventLoop* eventLoop_;
NetworkFactories* networkFactories_;
UIFactory* uiFactory_;
StoragesFactory* storagesFactory_;
Storages* storages_;
CertificateStorageFactory* certificateStorageFactory_;
CertificateStorage* certificateStorage_;
CertificateStorageTrustChecker* certificateTrustChecker_;
bool clientInitialized_;
boost::shared_ptr<Client> client_;
SettingsProvider *settings_;
ProfileSettingsProvider* profileSettings_;
Dock* dock_;
URIHandler* uriHandler_;
IdleDetector* idleDetector_;
TogglableNotifier* notifier_;
PresenceNotifier* presenceNotifier_;
EventNotifier* eventNotifier_;
RosterController* rosterController_;
EventController* eventController_;
EventWindowController* eventWindowController_;
AdHocManager* adHocManager_;
LoginWindow* loginWindow_;
UIEventStream* uiEventStream_;
XMLConsoleController* xmlConsoleController_;
FileTransferListController* fileTransferListController_;
ChatsManager* chatsManager_;
ProfileController* profileController_;
ContactEditController* contactEditController_;
JID jid_;
JID boundJID_;
SystemTrayController* systemTrayController_;
SoundEventController* soundEventController_;
XMPPURIController* xmppURIController_;
std::string vCardPhotoHash_;
std::string password_;
std::string certificateFile_;
boost::shared_ptr<ErrorEvent> lastDisconnectError_;
bool useDelayForLatency_;
UserSearchController* userSearchControllerChat_;
UserSearchController* userSearchControllerAdd_;
int timeBeforeNextReconnect_;
Timer::ref reconnectTimer_;
StatusTracker* statusTracker_;
bool myStatusLooksOnline_;
bool quitRequested_;
bool offlineRequested_;
static const int SecondsToWaitBeforeForceQuitting;
- bool eagleMode_;
FileTransferOverview* ftOverview_;
};
}
diff --git a/Swift/Controllers/ProfileSettingsProvider.cpp b/Swift/Controllers/ProfileSettingsProvider.cpp
new file mode 100644
index 0000000..c1b4b13
--- /dev/null
+++ b/Swift/Controllers/ProfileSettingsProvider.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010-2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swift/Controllers/ProfileSettingsProvider.h"
+
+namespace Swift {
+
+ProfileSettingsProvider::ProfileSettingsProvider(const std::string& profile, SettingsProvider* provider) :
+ profile_(profile) {
+ provider_ = provider;
+ bool found = false;
+ foreach (std::string existingProfile, provider->getAvailableProfiles()) {
+ if (existingProfile == profile) {
+ found = true;
+ }
+ }
+ if (!found) {
+ provider_->createProfile(profile);
+ }
+}
+
+ProfileSettingsProvider::~ProfileSettingsProvider() {
+}
+
+std::string ProfileSettingsProvider::getStringSetting(const std::string &settingPath) {
+ //FIXME: Remove shim
+ SettingsProvider::Setting<std::string> setting(profileSettingPath(settingPath), "");
+ return provider_->getSetting(setting);
+}
+
+void ProfileSettingsProvider::storeString(const std::string &settingPath, const std::string &settingValue) {
+ //FIXME: Remove shim
+ if (!getIsSettingFinal(settingPath)) {
+ SettingsProvider::Setting<std::string> setting(profileSettingPath(settingPath), "");
+ provider_->storeSetting(setting, settingValue);
+ }
+}
+
+int ProfileSettingsProvider::getIntSetting(const std::string& settingPath, int defaultValue) {
+ //FIXME: Remove shim
+ SettingsProvider::Setting<int> setting(profileSettingPath(settingPath), defaultValue);
+ return provider_->getSetting(setting);
+}
+void ProfileSettingsProvider::storeInt(const std::string& settingPath, int settingValue) {
+ //FIXME: Remove shim
+ if (!getIsSettingFinal(settingPath)) {
+ SettingsProvider::Setting<int> setting(profileSettingPath(settingPath), 0);
+ provider_->storeSetting(setting, settingValue);
+ }
+}
+
+bool ProfileSettingsProvider::getIsSettingFinal(const std::string& settingPath) {
+ //FIXME: Remove shim
+ SettingsProvider::Setting<int> setting(settingPath, 0);
+ return provider_->getIsSettingFinal(setting);
+}
+
+
+std::string ProfileSettingsProvider::profileSettingPath(const std::string &settingPath) {
+ return profile_ + ":" + settingPath;
+}
+
+
+}
+
diff --git a/Swift/Controllers/ProfileSettingsProvider.h b/Swift/Controllers/ProfileSettingsProvider.h
index 8ba250c..ebc515a 100644
--- a/Swift/Controllers/ProfileSettingsProvider.h
+++ b/Swift/Controllers/ProfileSettingsProvider.h
@@ -1,42 +1,33 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
-#include "Swift/Controllers/Settings/SettingsProvider.h"
+#include <Swift/Controllers/Settings/SettingsProvider.h>
#include <Swiften/Base/foreach.h>
namespace Swift {
class ProfileSettingsProvider {
public:
- ProfileSettingsProvider(const std::string& profile, SettingsProvider* provider) : profile_(profile) {
- provider_ = provider;
- bool found = false;
- foreach (std::string existingProfile, provider->getAvailableProfiles()) {
- if (existingProfile == profile) {
- found = true;
- }
- }
- if (!found) {
- provider_->createProfile(profile);
- }
- };
- virtual ~ProfileSettingsProvider() {};
- virtual std::string getStringSetting(const std::string &settingPath) {return provider_->getStringSetting(profileSettingPath(settingPath));};
- virtual void storeString(const std::string &settingPath, const std::string &settingValue) {provider_->storeString(profileSettingPath(settingPath), settingValue);};
- virtual int getIntSetting(const std::string& settingPath, int defaultValue) {return provider_->getIntSetting(settingPath, defaultValue);}
- virtual void storeInt(const std::string& settingPath, int settingValue) {provider_->storeInt(settingPath, settingValue);}
+ ProfileSettingsProvider(const std::string& profile, SettingsProvider* provider);
+ virtual ~ProfileSettingsProvider();
+ virtual std::string getStringSetting(const std::string &settingPath);
+ virtual void storeString(const std::string &settingPath, const std::string &settingValue);
+ virtual int getIntSetting(const std::string& settingPath, int defaultValue);
+ virtual void storeInt(const std::string& settingPath, int settingValue);
+ /** See @SettingsProvider::getIsSettingFinal for discussion of what this means.*/
+ virtual bool getIsSettingFinal(const std::string& settingPath);
private:
- std::string profileSettingPath(const std::string &settingPath) {return profile_ + ":" + settingPath;};
+ std::string profileSettingPath(const std::string &settingPath);
SettingsProvider* provider_;
std::string profile_;
};
}
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp
index 66948c1..d3a00dd 100644
--- a/Swift/Controllers/Roster/RosterController.cpp
+++ b/Swift/Controllers/Roster/RosterController.cpp
@@ -1,223 +1,224 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Swift/Controllers/Roster/RosterController.h"
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include "Swiften/JID/JID.h"
#include "Swiften/Base/foreach.h"
#include "Swift/Controllers/UIInterfaces/MainWindow.h"
#include "Swift/Controllers/UIInterfaces/MainWindowFactory.h"
#include "Swiften/Client/NickResolver.h"
#include "Swiften/Roster/GetRosterRequest.h"
#include "Swiften/Roster/SetRosterRequest.h"
#include "Swift/Controllers/XMPPEvents/SubscriptionRequestEvent.h"
#include "Swift/Controllers/XMPPEvents/ErrorEvent.h"
#include "Swiften/Presence/PresenceOracle.h"
#include "Swiften/Presence/SubscriptionManager.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
#include "Swiften/Queries/IQRouter.h"
#include "Swift/Controllers/Roster/Roster.h"
#include "Swift/Controllers/Roster/SetPresence.h"
#include "Swift/Controllers/Roster/AppearOffline.h"
#include "Swift/Controllers/Roster/SetAvatar.h"
#include "Swift/Controllers/Roster/SetName.h"
#include "Swift/Controllers/Roster/OfflineRosterFilter.h"
#include "Swift/Controllers/Roster/GroupRosterItem.h"
#include "Swiften/Roster/XMPPRoster.h"
#include "Swiften/Roster/XMPPRosterItem.h"
#include "Swift/Controllers/UIEvents/AddContactUIEvent.h"
#include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h"
#include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h"
#include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h"
-#include "Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h"
#include "Swift/Controllers/UIEvents/SendFileUIEvent.h"
#include <Swiften/FileTransfer/FileTransferManager.h>
#include <Swiften/Client/NickManager.h>
#include <Swift/Controllers/Intl.h>
#include <Swiften/Base/format.h>
#include <Swiften/Elements/DiscoInfo.h>
#include <Swiften/Disco/EntityCapsManager.h>
#include <Swiften/Jingle/JingleSessionManager.h>
+#include <Swift/Controllers/SettingConstants.h>
namespace Swift {
-static const std::string SHOW_OFFLINE = "showOffline";
-
/**
* The controller does not gain ownership of these parameters.
*/
RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview)
: myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview) {
assert(fileTransferOverview);
iqRouter_ = iqRouter;
presenceOracle_ = presenceOracle;
subscriptionManager_ = subscriptionManager;
eventController_ = eventController;
settings_ = settings;
expandiness_ = new RosterGroupExpandinessPersister(roster_, settings);
roster_->addFilter(offlineFilter_);
mainWindow_->setRosterModel(roster_);
changeStatusConnection_ = mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2));
signOutConnection_ = mainWindow_->onSignOutRequest.connect(boost::bind(boost::ref(onSignOutRequest)));
xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1));
xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3));
xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1));
xmppRoster_->onRosterCleared.connect(boost::bind(&RosterController::handleRosterCleared, this));
subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2));
presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handleIncomingPresence, this, _1));
uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1));
avatarManager_ = avatarManager;
avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1));
mainWindow_->setMyAvatarPath(avatarManager_->getAvatarPath(myJID_).string());
nickManager_->onOwnNickChanged.connect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1));
mainWindow_->setMyJID(jid);
mainWindow_->setMyNick(nickManager_->getOwnNick());
entityCapsManager_->onCapsChanged.connect(boost::bind(&RosterController::handleOnCapsChanged, this, _1));
- if (settings->getBoolSetting(SHOW_OFFLINE, false)) {
- uiEventStream->onUIEvent(boost::shared_ptr<UIEvent>(new ToggleShowOfflineUIEvent(true)));
- }
+ settings_->onSettingChanged.connect(boost::bind(&RosterController::handleSettingChanged, this, _1));
+
}
RosterController::~RosterController() {
+ settings_->onSettingChanged.disconnect(boost::bind(&RosterController::handleSettingChanged, this, _1));
nickManager_->onOwnNickChanged.disconnect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1));
delete offlineFilter_;
delete expandiness_;
mainWindow_->setRosterModel(NULL);
if (mainWindow_->canDelete()) {
delete mainWindow_;
}
delete roster_;
}
void RosterController::setEnabled(bool enabled) {
if (!enabled) {
roster_->applyOnItems(AppearOffline());
}
}
void RosterController::handleShowOfflineToggled(bool state) {
- if (state != settings_->getBoolSetting(SHOW_OFFLINE, false)) {
- settings_->storeBool(SHOW_OFFLINE, state);
+ if (state != settings_->getSetting(SettingConstants::SHOW_OFFLINE)) {
+ settings_->storeSetting(SettingConstants::SHOW_OFFLINE, state);
}
if (state) {
roster_->removeFilter(offlineFilter_);
} else {
roster_->addFilter(offlineFilter_);
}
}
void RosterController::handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText) {
onChangeStatusRequest(show, statusText);
}
void RosterController::handleOnJIDAdded(const JID& jid) {
std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid);
std::string name = nickResolver_->jidToNick(jid);
if (!groups.empty()) {
foreach(const std::string& group, groups) {
roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid).string());
}
}
else {
roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid).string());
}
applyAllPresenceTo(jid);
}
void RosterController::applyAllPresenceTo(const JID& jid) {
foreach (Presence::ref presence, presenceOracle_->getAllPresence(jid)) {
roster_->applyOnItems(SetPresence(presence));
}
}
void RosterController::handleRosterCleared() {
roster_->removeAll();
}
void RosterController::handleOnJIDRemoved(const JID& jid) {
roster_->removeContact(jid);
}
void RosterController::handleOnJIDUpdated(const JID& jid, const std::string& oldName, const std::vector<std::string>& passedOldGroups) {
if (oldName != xmppRoster_->getNameForJID(jid)) {
roster_->applyOnItems(SetName(nickResolver_->jidToNick(jid), jid));
}
std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid);
std::vector<std::string> oldGroups = passedOldGroups;
std::string name = nickResolver_->jidToNick(jid);
std::string contactsGroup = QT_TRANSLATE_NOOP("", "Contacts");
if (oldGroups.empty()) {
oldGroups.push_back(contactsGroup);
}
if (groups.empty()) {
groups.push_back(contactsGroup);
}
foreach(const std::string& group, groups) {
if (std::find(oldGroups.begin(), oldGroups.end(), group) == oldGroups.end()) {
roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid).string());
}
}
foreach(const std::string& group, oldGroups) {
if (std::find(groups.begin(), groups.end(), group) == groups.end()) {
roster_->removeContactFromGroup(jid, group);
if (roster_->getGroup(group)->getChildren().size() == 0) {
roster_->removeGroup(group);
}
}
}
applyAllPresenceTo(jid);
}
-void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
- if (boost::shared_ptr<ToggleShowOfflineUIEvent> showOfflineEvent = boost::dynamic_pointer_cast<ToggleShowOfflineUIEvent>(event)) {
- handleShowOfflineToggled(showOfflineEvent->getShow());
+void RosterController::handleSettingChanged(const std::string& settingPath) {
+ if (settingPath == SettingConstants::SHOW_OFFLINE.getKey()) {
+ handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE));
}
- else if (boost::shared_ptr<AddContactUIEvent> addContactEvent = boost::dynamic_pointer_cast<AddContactUIEvent>(event)) {
+}
+
+void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
+ if (boost::shared_ptr<AddContactUIEvent> addContactEvent = boost::dynamic_pointer_cast<AddContactUIEvent>(event)) {
RosterItemPayload item;
item.setName(addContactEvent->getName());
item.setJID(addContactEvent->getJID());
item.setGroups(std::vector<std::string>(addContactEvent->getGroups().begin(), addContactEvent->getGroups().end()));
boost::shared_ptr<RosterPayload> roster(new RosterPayload());
roster->addItem(item);
SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
request->send();
subscriptionManager_->requestSubscription(addContactEvent->getJID());
}
else if (boost::shared_ptr<RemoveRosterItemUIEvent> removeEvent = boost::dynamic_pointer_cast<RemoveRosterItemUIEvent>(event)) {
RosterItemPayload item(removeEvent->getJID(), "", RosterItemPayload::Remove);
boost::shared_ptr<RosterPayload> roster(new RosterPayload());
roster->addItem(item);
SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
request->send();
}
else if (boost::shared_ptr<RenameRosterItemUIEvent> renameEvent = boost::dynamic_pointer_cast<RenameRosterItemUIEvent>(event)) {
JID contact(renameEvent->getJID());
RosterItemPayload item(contact, renameEvent->getNewName(), xmppRoster_->getSubscriptionStateForJID(contact));
item.setGroups(xmppRoster_->getGroupsForJID(contact));
boost::shared_ptr<RosterPayload> roster(new RosterPayload());
roster->addItem(item);
SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
request->send();
}
else if (boost::shared_ptr<RenameGroupUIEvent> renameGroupEvent = boost::dynamic_pointer_cast<RenameGroupUIEvent>(event)) {
std::vector<XMPPRosterItem> items = xmppRoster_->getItems();
std::string group = renameGroupEvent->getGroup();
// FIXME: We should handle contacts groups specially to avoid clashes
if (group == QT_TRANSLATE_NOOP("", "Contacts")) {
diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h
index 66748ca..5e40124 100644
--- a/Swift/Controllers/Roster/RosterController.h
+++ b/Swift/Controllers/Roster/RosterController.h
@@ -42,60 +42,61 @@ namespace Swift {
class RosterController {
public:
RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, FileTransferOverview* fileTransferOverview);
~RosterController();
void showRosterWindow();
MainWindow* getWindow() {return mainWindow_;};
boost::signal<void (StatusShow::Type, const std::string&)> onChangeStatusRequest;
boost::signal<void ()> onSignOutRequest;
void handleAvatarChanged(const JID& jid);
void setEnabled(bool enabled);
boost::optional<XMPPRosterItem> getItem(const JID&) const;
std::set<std::string> getGroups() const;
void setContactGroups(const JID& jid, const std::vector<std::string>& groups);
void updateItem(const XMPPRosterItem&);
private:
void handleOnJIDAdded(const JID &jid);
void handleRosterCleared();
void handleOnJIDRemoved(const JID &jid);
void handleOnJIDUpdated(const JID &jid, const std::string& oldName, const std::vector<std::string>& oldGroups);
void handleStartChatRequest(const JID& contact);
void handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText);
void handleShowOfflineToggled(bool state);
void handleIncomingPresence(boost::shared_ptr<Presence> newPresence);
void handleSubscriptionRequest(const JID& jid, const std::string& message);
void handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event);
void handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event);
void handleUIEvent(boost::shared_ptr<UIEvent> event);
void handleRosterSetError(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload);
void applyAllPresenceTo(const JID& jid);
void handleEditProfileRequest();
void handleOnCapsChanged(const JID& jid);
+ void handleSettingChanged(const std::string& settingPath);
JID myJID_;
XMPPRoster* xmppRoster_;
MainWindowFactory* mainWindowFactory_;
MainWindow* mainWindow_;
Roster* roster_;
OfflineRosterFilter* offlineFilter_;
AvatarManager* avatarManager_;
NickManager* nickManager_;
NickResolver* nickResolver_;
PresenceOracle* presenceOracle_;
SubscriptionManager* subscriptionManager_;
EventController* eventController_;
RosterGroupExpandinessPersister* expandiness_;
IQRouter* iqRouter_;
SettingsProvider* settings_;
UIEventStream* uiEventStream_;
EntityCapsProvider* entityCapsManager_;
FileTransferOverview* ftOverview_;
boost::bsignals::scoped_connection changeStatusConnection_;
boost::bsignals::scoped_connection signOutConnection_;
boost::bsignals::scoped_connection uiEventConnection_;
};
}
diff --git a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp
index 0a242ae..81f0c12 100644
--- a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp
+++ b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.cpp
@@ -1,62 +1,63 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "RosterGroupExpandinessPersister.h"
+#include <Swift/Controllers/Roster/RosterGroupExpandinessPersister.h>
#include <boost/bind.hpp>
#include <vector>
#include <Swiften/Base/foreach.h>
-#include "Swiften/Base/String.h"
-#include "Swift/Controllers/Roster/GroupRosterItem.h"
+#include <Swiften/Base/String.h>
+#include <Swift/Controllers/Roster/GroupRosterItem.h>
+#include <Swift/Controllers/SettingConstants.h>
namespace Swift {
RosterGroupExpandinessPersister::RosterGroupExpandinessPersister(Roster* roster, SettingsProvider* settings) : roster_(roster), settings_(settings) {
load();
roster_->onGroupAdded.connect(boost::bind(&RosterGroupExpandinessPersister::handleGroupAdded, this, _1));
}
void RosterGroupExpandinessPersister::handleGroupAdded(GroupRosterItem* group) {
if (collapsed_.find(group->getDisplayName()) != collapsed_.end()) {
group->setExpanded(false);
} else {
group->setExpanded(true);
}
group->onExpandedChanged.connect(boost::bind(&RosterGroupExpandinessPersister::handleExpandedChanged, this, group, _1));
}
void RosterGroupExpandinessPersister::handleExpandedChanged(GroupRosterItem* group, bool expanded) {
if (expanded) {
std::string displayName = group->getDisplayName();
//collapsed_.erase(std::remove(collapsed_.begin(), collapsed_.end(), displayName), collapsed_.end());
collapsed_.erase(displayName);
} else {
collapsed_.insert(group->getDisplayName());
}
save();
}
void RosterGroupExpandinessPersister::save() {
std::string setting;
foreach (const std::string& group, collapsed_) {
if (!setting.empty()) {
setting += "\n";
}
setting += group;
}
- settings_->storeString(SettingPath, setting);
+ settings_->storeSetting(SettingConstants::EXPANDED_ROSTER_GROUPS, setting);
}
void RosterGroupExpandinessPersister::load() {
- std::string saved = settings_->getStringSetting(SettingPath);
+ std::string saved = settings_->getSetting(SettingConstants::EXPANDED_ROSTER_GROUPS);
std::vector<std::string> collapsed = String::split(saved, '\n');
collapsed_.insert(collapsed.begin(), collapsed.end());
}
-const std::string RosterGroupExpandinessPersister::SettingPath = "GroupExpandiness";
+
}
diff --git a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h
index 63affe4..73c4f29 100644
--- a/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h
+++ b/Swift/Controllers/Roster/RosterGroupExpandinessPersister.h
@@ -1,27 +1,26 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <set>
#include "Swift/Controllers/Roster/Roster.h"
#include "Swift/Controllers/Settings/SettingsProvider.h"
namespace Swift {
class RosterGroupExpandinessPersister {
public:
RosterGroupExpandinessPersister(Roster* roster, SettingsProvider* settings);
private:
void handleExpandedChanged(GroupRosterItem* group, bool expanded);
void handleGroupAdded(GroupRosterItem* group);
void load();
void save();
std::set<std::string> collapsed_;
Roster* roster_;
SettingsProvider* settings_;
- static const std::string SettingPath;
};
}
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index e48f382..02e212b 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -22,62 +22,66 @@ if env["SCONS_STAGE"] == "build" :
myenv.MergeFlags(env["BOOST_FLAGS"])
myenv.StaticLibrary("SwiftControllers", [
"Chat/ChatController.cpp",
"Chat/ChatControllerBase.cpp",
"Chat/ChatsManager.cpp",
"Chat/MUCController.cpp",
"Chat/MUCSearchController.cpp",
"Chat/UserSearchController.cpp",
"MainController.cpp",
"ProfileController.cpp",
"ContactEditController.cpp",
"FileTransfer/FileTransferController.cpp",
"FileTransfer/FileTransferOverview.cpp",
"FileTransfer/FileTransferProgressInfo.cpp",
"Roster/RosterController.cpp",
"Roster/RosterGroupExpandinessPersister.cpp",
"Roster/ContactRosterItem.cpp",
"Roster/GroupRosterItem.cpp",
"Roster/RosterItem.cpp",
"Roster/Roster.cpp",
"Roster/TableRoster.cpp",
"EventWindowController.cpp",
"SoundEventController.cpp",
"SystemTrayController.cpp",
"XMLConsoleController.cpp",
"FileTransferListController.cpp",
"StatusTracker.cpp",
"PresenceNotifier.cpp",
"EventNotifier.cpp",
"AdHocManager.cpp",
"XMPPEvents/EventController.cpp",
"UIEvents/UIEvent.cpp",
"UIInterfaces/XMLConsoleWidget.cpp",
"UIInterfaces/ChatListWindow.cpp",
"PreviousStatusStore.cpp",
+ "ProfileSettingsProvider.cpp",
+ "Settings/SettingsProviderHierachy.cpp",
+ "Settings/XMLSettingsProvider.cpp",
"Storages/CertificateStorageFactory.cpp",
"Storages/CertificateStorage.cpp",
"Storages/CertificateFileStorage.cpp",
"Storages/CertificateMemoryStorage.cpp",
"Storages/AvatarFileStorage.cpp",
"Storages/FileStorages.cpp",
"Storages/RosterFileStorage.cpp",
"Storages/CapsFileStorage.cpp",
"Storages/VCardFileStorage.cpp",
"StatusUtil.cpp",
"Translator.cpp",
"XMPPURIController.cpp",
"ChatMessageSummarizer.cpp",
+ "SettingConstants.cpp"
])
env.Append(UNITTEST_SOURCES = [
File("Roster/UnitTest/RosterControllerTest.cpp"),
File("Roster/UnitTest/RosterTest.cpp"),
File("Roster/UnitTest/LeastCommonSubsequenceTest.cpp"),
File("Roster/UnitTest/TableRosterTest.cpp"),
File("UnitTest/PreviousStatusStoreTest.cpp"),
File("UnitTest/PresenceNotifierTest.cpp"),
File("Chat/UnitTest/ChatsManagerTest.cpp"),
File("Chat/UnitTest/MUCControllerTest.cpp"),
File("UnitTest/MockChatWindow.cpp"),
File("UnitTest/ChatMessageSummarizerTest.cpp"),
])
diff --git a/Swift/Controllers/SettingConstants.cpp b/Swift/Controllers/SettingConstants.cpp
new file mode 100644
index 0000000..7ab4ac4
--- /dev/null
+++ b/Swift/Controllers/SettingConstants.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swift/Controllers/SettingConstants.h>
+
+namespace Swift {
+
+const SettingsProvider::Setting<bool> SettingConstants::IDLE_GOES_OFFLINE = SettingsProvider::Setting<bool>("idleGoesOffline", false);
+const SettingsProvider::Setting<int> SettingConstants::IDLE_TIMEOUT = SettingsProvider::Setting<int>("idleTimeout", 600);
+const SettingsProvider::Setting<bool> SettingConstants::SHOW_NOTIFICATIONS = SettingsProvider::Setting<bool>("showNotifications", true);
+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);
+}
diff --git a/Swift/Controllers/SettingConstants.h b/Swift/Controllers/SettingConstants.h
new file mode 100644
index 0000000..ff1ed72
--- /dev/null
+++ b/Swift/Controllers/SettingConstants.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+
+namespace Swift {
+ class SettingConstants {
+ public:
+ static const SettingsProvider::Setting<bool> IDLE_GOES_OFFLINE;
+ static const SettingsProvider::Setting<int> IDLE_TIMEOUT;
+ static const SettingsProvider::Setting<bool> SHOW_NOTIFICATIONS;
+ 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;
+ static const SettingsProvider::Setting<bool> SHOW_OFFLINE;
+ static const SettingsProvider::Setting<std::string> EXPANDED_ROSTER_GROUPS;
+ static const SettingsProvider::Setting<bool> PLAY_SOUNDS;
+ };
+}
diff --git a/Swift/Controllers/Settings/DummySettingsProvider.h b/Swift/Controllers/Settings/DummySettingsProvider.h
index 90e1921..bb7d2e6 100644
--- a/Swift/Controllers/Settings/DummySettingsProvider.h
+++ b/Swift/Controllers/Settings/DummySettingsProvider.h
@@ -1,30 +1,52 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
-#include "Swift/Controllers/Settings/SettingsProvider.h"
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+
+#include <map>
namespace Swift {
class DummySettingsProvider : public SettingsProvider {
public:
virtual ~DummySettingsProvider() {}
- virtual std::string getStringSetting(const std::string&) {return "";}
- virtual void storeString(const std::string &, const std::string &) {}
- virtual bool getBoolSetting(const std::string &, bool ) {return true;}
- virtual void storeBool(const std::string &, bool ) {}
- virtual int getIntSetting(const std::string &, int ) {return 0;}
- virtual void storeInt(const std::string &, int ) {}
+ virtual std::string getSetting(const Setting<std::string>& setting) {
+ return stringValues.find(setting.getKey()) != stringValues.end() ? stringValues[setting.getKey()] : setting.getDefaultValue();
+ };
+ virtual void storeSetting(const Setting<std::string>& setting, const std::string& value) {
+ stringValues[setting.getKey()] = value;
+ onSettingChanged(setting.getKey());
+ };
+ virtual bool getSetting(const Setting<bool>& setting) {
+ return boolValues.find(setting.getKey()) != boolValues.end() ? boolValues[setting.getKey()] : setting.getDefaultValue();
+ };
+ virtual void storeSetting(const Setting<bool>& setting, const bool& value) {
+ boolValues[setting.getKey()] = value;
+ onSettingChanged(setting.getKey());
+ };
+ virtual int getSetting(const Setting<int>& setting) {
+ return intValues.find(setting.getKey()) != intValues.end() ? intValues[setting.getKey()] : setting.getDefaultValue();
+ };
+ virtual void storeSetting(const Setting<int>& setting, const int& value) {
+ intValues[setting.getKey()] = value;
+ onSettingChanged(setting.getKey());
+ };
virtual std::vector<std::string> getAvailableProfiles() {return std::vector<std::string>();}
virtual void createProfile(const std::string& ) {}
virtual void removeProfile(const std::string& ) {}
+ virtual bool getIsSettingFinal(const std::string& ) {return false;}
+ private:
+ std::map<std::string, std::string> stringValues;
+ std::map<std::string, int> intValues;
+ std::map<std::string, bool> boolValues;
};
}
diff --git a/Swift/Controllers/Settings/SettingsProvider.h b/Swift/Controllers/Settings/SettingsProvider.h
index a5ff4eb..e884add 100644
--- a/Swift/Controllers/Settings/SettingsProvider.h
+++ b/Swift/Controllers/Settings/SettingsProvider.h
@@ -1,33 +1,73 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2012 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_SettingsProvider_H
-#define SWIFTEN_SettingsProvider_H
+#pragma once
-#include <string>
+#include <Swiften/Base/boost_bsignals.h>
+#include <string>
#include <vector>
namespace Swift {
class SettingsProvider {
+
+ public:
+ template <typename T>
+ class Setting {
+ public:
+ Setting(const std::string& key, const T& defaultValue) : key(key), defaultValue(defaultValue) {
+
+ }
+
+ const std::string& getKey() const {
+ return key;
+ }
+
+ const T& getDefaultValue() const {
+ return defaultValue;
+ }
+
+ private:
+ std::string key;
+ T defaultValue;
+ };
+
public:
virtual ~SettingsProvider() {}
- virtual std::string getStringSetting(const std::string &settingPath) = 0;
- virtual void storeString(const std::string &settingPath, const std::string &settingValue) = 0;
- virtual bool getBoolSetting(const std::string &settingPath, bool defaultValue) = 0;
- virtual void storeBool(const std::string &settingPath, bool settingValue) = 0;
- virtual int getIntSetting(const std::string &settingPath, int defaultValue) = 0;
- virtual void storeInt(const std::string &settingPath, int settingValue) = 0;
+ virtual std::string getSetting(const Setting<std::string>& setting) = 0;
+ virtual void storeSetting(const Setting<std::string>& setting, const std::string& value) = 0;
+ virtual bool getSetting(const Setting<bool>& setting) = 0;
+ virtual void storeSetting(const Setting<bool>& setting, const bool& value) = 0;
+ virtual int getSetting(const Setting<int>& setting) = 0;
+ virtual void storeSetting(const Setting<int>& setting, const int& value) = 0;
+
virtual std::vector<std::string> getAvailableProfiles() = 0;
virtual void createProfile(const std::string& profile) = 0;
virtual void removeProfile(const std::string& profile) = 0;
+ /** A final setting is one that this settings provider says may not be overriden by lower priority profiles.
+ * e.g. An Administrator-set configuration to disallow saving user passwords could not be overridden by the user.
+ */
+ template<typename T>
+ bool getIsSettingFinal(const Setting<T>& setting) {
+ return getIsSettingFinal(setting.getKey());
+ }
+
+ friend class SettingsProviderHierachy;
+ protected:
+ virtual bool getIsSettingFinal(const std::string& settingPath) = 0;
+
+ public:
+ /**
+ * Emitted when a setting is changed.
+ */
+ boost::signal<void (const std::string& /*Setting's Path*/)> onSettingChanged;
};
}
-#endif
+
diff --git a/Swift/Controllers/Settings/SettingsProviderHierachy.cpp b/Swift/Controllers/Settings/SettingsProviderHierachy.cpp
new file mode 100644
index 0000000..3b7d13c
--- /dev/null
+++ b/Swift/Controllers/Settings/SettingsProviderHierachy.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swift/Controllers/Settings/SettingsProviderHierachy.h>
+
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/Log.h>
+namespace Swift {
+
+SettingsProviderHierachy::~SettingsProviderHierachy() {
+}
+
+std::string SettingsProviderHierachy::getSetting(const Setting<std::string>& setting) {
+ foreach (SettingsProvider* provider, providers_) {
+ std::string providerSetting = provider->getSetting(setting);
+ if (providerSetting != setting.getDefaultValue()) {
+ return providerSetting;
+ }
+ }
+ return setting.getDefaultValue();
+}
+
+void SettingsProviderHierachy::storeSetting(const Setting<std::string>& setting, const std::string& settingValue) {
+ if (!getIsSettingFinal(setting.getKey())) {
+ getWritableProvider()->storeSetting(setting, settingValue);
+ }
+}
+
+bool SettingsProviderHierachy::getSetting(const Setting<bool>& setting) {
+ foreach (SettingsProvider* provider, providers_) {
+ bool providerSetting = provider->getSetting(setting);
+ if (providerSetting != setting.getDefaultValue()) {
+ return providerSetting;
+ }
+ }
+ return setting.getDefaultValue();
+}
+
+void SettingsProviderHierachy::storeSetting(const Setting<bool>& setting, const bool& settingValue) {
+ if (!getIsSettingFinal(setting.getKey())) {
+ getWritableProvider()->storeSetting(setting, settingValue);
+ }
+}
+
+int SettingsProviderHierachy::getSetting(const Setting<int>& setting) {
+ foreach (SettingsProvider* provider, providers_) {
+ int providerSetting = provider->getSetting(setting);
+ if (providerSetting != setting.getDefaultValue()) {
+ return providerSetting;
+ }
+ }
+ return setting.getDefaultValue();
+}
+
+void SettingsProviderHierachy::storeSetting(const Setting<int>& setting, const int& settingValue) {
+ if (!getIsSettingFinal(setting.getKey())) {
+ getWritableProvider()->storeSetting(setting, settingValue);
+ }
+}
+
+std::vector<std::string> SettingsProviderHierachy::getAvailableProfiles() {
+ /* Always pull profiles from the topmost */
+ return getWritableProvider()->getAvailableProfiles();
+}
+
+void SettingsProviderHierachy::createProfile(const std::string& profile) {
+ return getWritableProvider()->createProfile(profile);
+}
+
+void SettingsProviderHierachy::removeProfile(const std::string& profile) {
+ return getWritableProvider()->removeProfile(profile);
+}
+
+bool SettingsProviderHierachy::getIsSettingFinal(const std::string& settingPath) {
+ bool isFinal = false;
+ foreach (SettingsProvider* provider, providers_) {
+ isFinal |= provider->getIsSettingFinal(settingPath);
+ }
+ return isFinal;
+}
+
+SettingsProvider* SettingsProviderHierachy::getWritableProvider() {
+ return providers_.back();
+}
+
+void SettingsProviderHierachy::addProviderToTopOfStack(SettingsProvider* provider) {
+ providers_.push_back(provider);
+ provider->onSettingChanged.connect(onSettingChanged);
+}
+
+}
+
diff --git a/Swift/Controllers/Settings/SettingsProviderHierachy.h b/Swift/Controllers/Settings/SettingsProviderHierachy.h
new file mode 100644
index 0000000..b7f6961
--- /dev/null
+++ b/Swift/Controllers/Settings/SettingsProviderHierachy.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+
+namespace Swift {
+
+class SettingsProviderHierachy : public SettingsProvider {
+ public:
+ virtual ~SettingsProviderHierachy();
+ virtual std::string getSetting(const Setting<std::string>& setting);
+ virtual void storeSetting(const Setting<std::string>& setting, const std::string& value);
+ virtual bool getSetting(const Setting<bool>& setting);
+ virtual void storeSetting(const Setting<bool>& setting, const bool& value);
+ virtual int getSetting(const Setting<int>& setting);
+ virtual void storeSetting(const Setting<int>& setting, const int& value);
+ virtual std::vector<std::string> getAvailableProfiles();
+ virtual void createProfile(const std::string& profile);
+ virtual void removeProfile(const std::string& profile);
+ protected:
+ virtual bool getIsSettingFinal(const std::string& settingPath);
+
+ public:
+ /**
+ * Adds a provider less significant than any already added.
+ * This means that if an existing provider has a setting, this provider won't be asked.
+ * Any settings will be pushed into the topmost (least significant) provider.
+ * Does not take ownership of provider.
+ */
+ void addProviderToTopOfStack(SettingsProvider* provider);
+ private:
+ SettingsProvider* getWritableProvider();
+ private:
+ /* Start/Left is most significant (lowest), left overrides right.*/
+ std::vector<SettingsProvider*> providers_;
+};
+
+}
+
+
+
diff --git a/Swift/Controllers/Settings/XMLSettingsProvider.cpp b/Swift/Controllers/Settings/XMLSettingsProvider.cpp
new file mode 100644
index 0000000..6ad3170
--- /dev/null
+++ b/Swift/Controllers/Settings/XMLSettingsProvider.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swift/Controllers/Settings/XMLSettingsProvider.h>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <Swiften/Parser/PlatformXMLParserFactory.h>
+#include <Swiften/Parser/XMLParser.h>
+#include <Swiften/Base/Log.h>
+
+namespace Swift {
+
+XMLSettingsProvider::XMLSettingsProvider(const std::string& xmlConfig) : level_(0) {
+ if (!xmlConfig.empty()) {
+ PlatformXMLParserFactory factory;
+ XMLParser* parser = factory.createXMLParser(this);
+ if (parser->parse(xmlConfig)) {
+ SWIFT_LOG(debug) << "Found and parsed system config" << std::endl;
+ }
+ else {
+ SWIFT_LOG(debug) << "Found invalid system config" << std::endl;
+ }
+ delete parser;
+ }
+ else {
+ SWIFT_LOG(debug) << "No system config found" << std::endl;
+ }
+}
+
+XMLSettingsProvider::~XMLSettingsProvider() {
+
+}
+
+std::string XMLSettingsProvider::getSetting(const Setting<std::string>& setting) {
+ if (values_.find(setting.getKey()) != values_.end()) {
+ std::string value = values_[setting.getKey()];
+ return value;
+ }
+ return setting.getDefaultValue();
+}
+
+void XMLSettingsProvider::storeSetting(const Setting<std::string>& /*settingPath*/, const std::string& /*settingValue*/) {
+ assert(false);
+}
+
+bool XMLSettingsProvider::getSetting(const Setting<bool>& setting) {
+ if (values_.find(setting.getKey()) != values_.end()) {
+ std::string value = values_[setting.getKey()];
+ return boost::iequals(value, "true") || value == "1";
+ }
+ return setting.getDefaultValue();
+}
+
+void XMLSettingsProvider::storeSetting(const Setting<bool>& /*settingPath*/, const bool& /*settingValue*/) {
+ assert(false);
+}
+
+int XMLSettingsProvider::getSetting(const Setting<int>& setting) {
+ if (values_.find(setting.getKey()) != values_.end()) {
+ std::string value = values_[setting.getKey()];
+ try {
+ return value.empty() ? setting.getDefaultValue() : boost::lexical_cast<int>(value);;
+ }
+ catch(boost::bad_lexical_cast &) {}
+ }
+ return setting.getDefaultValue();
+}
+
+void XMLSettingsProvider::storeSetting(const Setting<int>& /*settingPath*/, const int& /*settingValue*/) {
+ assert(false);
+}
+
+std::vector<std::string> XMLSettingsProvider::getAvailableProfiles() {
+ assert(false);
+}
+
+void XMLSettingsProvider::createProfile(const std::string& /*profile*/) {
+ assert(false);
+}
+
+void XMLSettingsProvider::removeProfile(const std::string& /*profile*/) {
+ assert(false);
+}
+
+bool XMLSettingsProvider::getIsSettingFinal(const std::string& settingPath) {
+ return finals_.count(settingPath);
+}
+
+void XMLSettingsProvider::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) {
+ level_++;
+ if (level_ == SettingLevel) {
+ if (attributes.getBoolAttribute("final", false)) {
+ finals_.insert(element);
+ }
+ currentElement_ = element;
+ currentText_ = "";
+ }
+}
+
+void XMLSettingsProvider::handleEndElement(const std::string& /*element*/, const std::string& /*ns*/) {
+ if (level_ == SettingLevel) {
+ values_[currentElement_] = currentText_;
+ SWIFT_LOG(debug) << "Setting value of " << currentElement_ << " to " << currentText_ << std::endl;
+ }
+ level_--;
+}
+
+void XMLSettingsProvider::handleCharacterData(const std::string& data) {
+ if (level_ >= SettingLevel) {
+ currentText_ += data;
+ }
+}
+
+
+}
+
+
+
+
diff --git a/Swift/Controllers/Settings/XMLSettingsProvider.h b/Swift/Controllers/Settings/XMLSettingsProvider.h
new file mode 100644
index 0000000..61abd11
--- /dev/null
+++ b/Swift/Controllers/Settings/XMLSettingsProvider.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swiften/Parser/XMLParserClient.h>
+
+#include <map>
+#include <set>
+
+namespace Swift {
+
+class XMLSettingsProvider : public SettingsProvider, public XMLParserClient {
+ public:
+ XMLSettingsProvider(const std::string& xmlConfig);
+ virtual ~XMLSettingsProvider();
+ virtual std::string getSetting(const Setting<std::string>& setting);
+ virtual void storeSetting(const Setting<std::string>& setting, const std::string& value);
+ virtual bool getSetting(const Setting<bool>& setting);
+ virtual void storeSetting(const Setting<bool>& setting, const bool& value);
+ virtual int getSetting(const Setting<int>& setting);
+ virtual void storeSetting(const Setting<int>& setting, const int& value);
+ virtual std::vector<std::string> getAvailableProfiles();
+ virtual void createProfile(const std::string& profile);
+ virtual void removeProfile(const std::string& profile);
+
+ virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes);
+ virtual void handleEndElement(const std::string& element, const std::string& ns);
+ virtual void handleCharacterData(const std::string& data);
+
+ protected:
+ virtual bool getIsSettingFinal(const std::string& settingPath);
+ private:
+ std::map<std::string /*settingPath*/, std::string /*settingValue*/> values_;
+ /* Settings that are final*/
+ std::set<std::string /*settingPath*/> finals_;
+
+ enum Level {
+ TopLevel = 0,
+ SettingLevel = 2
+ };
+
+ int level_;
+ std::string currentElement_;
+ std::string currentText_;
+};
+
+}
+
+
+
+
diff --git a/Swift/Controllers/SoundEventController.cpp b/Swift/Controllers/SoundEventController.cpp
index 26847ed..d056990 100644
--- a/Swift/Controllers/SoundEventController.cpp
+++ b/Swift/Controllers/SoundEventController.cpp
@@ -1,53 +1,45 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swift/Controllers/SoundEventController.h"
+#include <Swift/Controllers/SoundEventController.h>
#include <boost/bind.hpp>
-#include "Swift/Controllers/XMPPEvents/EventController.h"
-#include "Swift/Controllers/SoundPlayer.h"
-#include "Swift/Controllers/UIEvents/UIEventStream.h"
-#include "Swift/Controllers/UIEvents/ToggleSoundsUIEvent.h"
+#include <Swift/Controllers/XMPPEvents/EventController.h>
+#include <Swift/Controllers/SoundPlayer.h>
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swift/Controllers/SettingConstants.h>
namespace Swift {
-SoundEventController::SoundEventController(EventController* eventController, SoundPlayer* soundPlayer, SettingsProvider* settings, UIEventStream* uiEvents) {
- uiEvents_ = uiEvents;
+SoundEventController::SoundEventController(EventController* eventController, SoundPlayer* soundPlayer, SettingsProvider* settings) {
settings_ = settings;
eventController_ = eventController;
soundPlayer_ = soundPlayer;
- uiEvents_->onUIEvent.connect(boost::bind(&SoundEventController::handleUIEvent, this, _1));
eventController_->onEventQueueEventAdded.connect(boost::bind(&SoundEventController::handleEventQueueEventAdded, this, _1));
+ settings_->onSettingChanged.connect(boost::bind(&SoundEventController::handleSettingChanged, this, _1));
- bool playSounds = settings->getBoolSetting("playSounds", true);
- playSounds_ = !playSounds;
- setPlaySounds(playSounds);
+ playSounds_ = settings->getSetting(SettingConstants::PLAY_SOUNDS);
}
void SoundEventController::handleEventQueueEventAdded(boost::shared_ptr<StanzaEvent> event) {
if (playSounds_ && !event->getConcluded()) {
soundPlayer_->playSound(SoundPlayer::MessageReceived);
}
}
void SoundEventController::setPlaySounds(bool playSounds) {
- bool transmit = playSounds != playSounds_;
playSounds_ = playSounds;
- settings_->storeBool("playSounds", playSounds);
- if (transmit) {
- uiEvents_->send(boost::shared_ptr<ToggleSoundsUIEvent>(new ToggleSoundsUIEvent(playSounds_)));
- }
+ settings_->storeSetting(SettingConstants::PLAY_SOUNDS, playSounds);
}
-void SoundEventController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
- boost::shared_ptr<ToggleSoundsUIEvent> soundEvent = boost::dynamic_pointer_cast<ToggleSoundsUIEvent>(event);
- if (soundEvent) {
- setPlaySounds(soundEvent->getEnabled());
+void SoundEventController::handleSettingChanged(const std::string& settingPath) {
+ if (SettingConstants::PLAY_SOUNDS.getKey() == settingPath) {
+ playSounds_ = settings_->getSetting(SettingConstants::PLAY_SOUNDS);
}
}
}
diff --git a/Swift/Controllers/SoundEventController.h b/Swift/Controllers/SoundEventController.h
index 5e00fc6..c6dec6f 100644
--- a/Swift/Controllers/SoundEventController.h
+++ b/Swift/Controllers/SoundEventController.h
@@ -1,33 +1,30 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/shared_ptr.hpp>
-#include "Swift/Controllers/XMPPEvents/StanzaEvent.h"
-#include "Swift/Controllers/Settings/SettingsProvider.h"
-#include "Swift/Controllers/UIEvents/UIEvent.h"
+#include <Swift/Controllers/XMPPEvents/StanzaEvent.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
namespace Swift {
class EventController;
class SoundPlayer;
- class UIEventStream;
class SoundEventController {
public:
- SoundEventController(EventController* eventController, SoundPlayer* soundPlayer, SettingsProvider* settings, UIEventStream* uiEvents);
+ SoundEventController(EventController* eventController, SoundPlayer* soundPlayer, SettingsProvider* settings);
void setPlaySounds(bool playSounds);
bool getSoundEnabled() {return playSounds_;};
private:
- void handleUIEvent(boost::shared_ptr<UIEvent> event);
+ void handleSettingChanged(const std::string& settingPath);
void handleEventQueueEventAdded(boost::shared_ptr<StanzaEvent> event);
EventController* eventController_;
SoundPlayer* soundPlayer_;
bool playSounds_;
- UIEventStream* uiEvents_;
SettingsProvider* settings_;
};
}
diff --git a/Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h b/Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h
deleted file mode 100644
index 0f7acc8..0000000
--- a/Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include "Swift/Controllers/UIEvents/UIEvent.h"
-
-namespace Swift {
- class ToggleNotificationsUIEvent : public UIEvent {
- public:
- ToggleNotificationsUIEvent(bool enable) : enabled_(enable) {};
- bool getEnabled() {return enabled_;};
- private:
- bool enabled_;
- };
-}
diff --git a/Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h b/Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h
deleted file mode 100644
index 1ea2db5..0000000
--- a/Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2011 Tobias Markmann
- * Licensed under the BSD license.
- * See http://www.opensource.org/licenses/bsd-license.php for more information.
- */
-
-#pragma once
-
-#include "Swift/Controllers/UIEvents/UIEvent.h"
-
-namespace Swift {
- class ToggleRequestDeliveryReceiptsUIEvent : public UIEvent {
- public:
- ToggleRequestDeliveryReceiptsUIEvent(bool enable) : enabled_(enable) {}
- bool getEnabled() {return enabled_;}
- private:
- bool enabled_;
- };
-}
diff --git a/Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h b/Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h
deleted file mode 100644
index b45eb83..0000000
--- a/Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include "Swift/Controllers/UIEvents/UIEvent.h"
-
-namespace Swift {
- class ToggleShowOfflineUIEvent : public UIEvent {
- public:
- ToggleShowOfflineUIEvent(bool show) : show_(show) {};
- bool getShow() {return show_;};
- private:
- bool show_;
- };
-}
diff --git a/Swift/Controllers/UIEvents/ToggleSoundsUIEvent.h b/Swift/Controllers/UIEvents/ToggleSoundsUIEvent.h
deleted file mode 100644
index 9e5cfc6..0000000
--- a/Swift/Controllers/UIEvents/ToggleSoundsUIEvent.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2010 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include "Swift/Controllers/UIEvents/UIEvent.h"
-
-namespace Swift {
- class ToggleSoundsUIEvent : public UIEvent {
- public:
- ToggleSoundsUIEvent(bool enable) : enabled_(enable) {};
- bool getEnabled() {return enabled_;};
- private:
- bool enabled_;
- };
-}
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp
index 8de5720..5181040 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.cpp
+++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp
@@ -1,91 +1,99 @@
/*
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Swift/QtUI/ChatList/QtChatListWindow.h"
+#include <Boost/bind.hpp>
+
#include <QMenu>
#include <QContextMenuEvent>
#include <Swift/QtUI/ChatList/ChatListMUCItem.h>
#include <Swift/QtUI/ChatList/ChatListRecentItem.h>
#include <Swift/QtUI/QtAddBookmarkWindow.h>
#include <Swift/QtUI/QtEditBookmarkWindow.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
#include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h>
#include <Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h>
#include <Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h>
-#include <Swift/QtUI/QtUIPreferences.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+
namespace Swift {
-QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QTreeView(parent) {
+QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, SettingsProvider* settings, QWidget* parent) : QTreeView(parent) {
eventStream_ = uiEventStream;
- uiPreferences_ = uiPreferences;
+ settings_ = settings;;
bookmarksEnabled_ = false;
model_ = new ChatListModel();
setModel(model_);
- delegate_ = new ChatListDelegate(uiPreferences_->getCompactRosters());
+ delegate_ = new ChatListDelegate(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER));
setItemDelegate(delegate_);
setHeaderHidden(true);
#ifdef SWIFT_PLATFORM_MACOSX
setAlternatingRowColors(true);
#endif
expandAll();
setAnimated(true);
setIndentation(0);
setRootIsDecorated(true);
setupContextMenus();
connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&)));
connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleClicked(const QModelIndex&)));
- connect(uiPreferences_, SIGNAL(onCompactRostersChanged(bool)), this, SLOT(handleCompactRostersToggled(bool)));
+
+ settings_->onSettingChanged.connect(boost::bind(&QtChatListWindow::handleSettingChanged, this, _1));
}
QtChatListWindow::~QtChatListWindow() {
+ settings_->onSettingChanged.disconnect(boost::bind(&QtChatListWindow::handleSettingChanged, this, _1));
delete model_;
delete delegate_;
delete mucMenu_;
delete emptyMenu_;
}
-void QtChatListWindow::handleCompactRostersToggled(bool compact) {
- delegate_->setCompact(compact);
- repaint();
+void QtChatListWindow::handleSettingChanged(const std::string& setting) {
+ if (setting == QtUISettingConstants::COMPACT_ROSTER.getKey()) {
+ delegate_->setCompact(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER));
+ repaint();
+ }
}
void QtChatListWindow::setBookmarksEnabled(bool enabled) {
bookmarksEnabled_ = enabled;
}
void QtChatListWindow::handleClicked(const QModelIndex& index) {
ChatListGroupItem* item = dynamic_cast<ChatListGroupItem*>(static_cast<ChatListItem*>(index.internalPointer()));
if (item) {
setExpanded(index, !isExpanded(index));
}
}
void QtChatListWindow::setupContextMenus() {
mucMenu_ = new QMenu();
mucMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
mucMenu_->addAction(tr("Edit Bookmark"), this, SLOT(handleEditBookmark()));
mucMenu_->addAction(tr("Remove Bookmark"), this, SLOT(handleRemoveBookmark()));
emptyMenu_ = new QMenu();
emptyMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
}
void QtChatListWindow::handleItemActivated(const QModelIndex& index) {
ChatListItem* item = model_->getItemForIndex(index);
if (ChatListMUCItem* mucItem = dynamic_cast<ChatListMUCItem*>(item)) {
if (bookmarksEnabled_) {
onMUCBookmarkActivated(mucItem->getBookmark());
}
}
else if (ChatListRecentItem* recentItem = dynamic_cast<ChatListRecentItem*>(item)) {
if (!recentItem->getChat().isMUC || bookmarksEnabled_) {
onRecentActivated(recentItem->getChat());
}
}
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.h b/Swift/QtUI/ChatList/QtChatListWindow.h
index af37015..33131ce 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.h
+++ b/Swift/QtUI/ChatList/QtChatListWindow.h
@@ -1,55 +1,55 @@
/*
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QTreeView>
#include "Swift/Controllers/UIInterfaces/ChatListWindow.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swift/QtUI/ChatList/ChatListModel.h"
#include "Swift/QtUI/ChatList/ChatListDelegate.h"
namespace Swift {
- class QtUIPreferences;
+ class SettingsProvider;
class QtChatListWindow : public QTreeView, public ChatListWindow {
Q_OBJECT
public:
- QtChatListWindow(UIEventStream *uiEventStream, QtUIPreferences* uiPreferences, QWidget* parent = NULL);
+ QtChatListWindow(UIEventStream *uiEventStream, SettingsProvider* settings, QWidget* parent = NULL);
virtual ~QtChatListWindow();
void addMUCBookmark(const MUCBookmark& bookmark);
void removeMUCBookmark(const MUCBookmark& bookmark);
void setBookmarksEnabled(bool enabled);
void setRecents(const std::list<ChatListWindow::Chat>& recents);
void setUnreadCount(int unread);
void clearBookmarks();
signals:
void onCountUpdated(int count);
private slots:
void handleItemActivated(const QModelIndex&);
void handleAddBookmark();
void handleEditBookmark();
void handleRemoveBookmark();
void handleClicked(const QModelIndex& index);
- void handleCompactRostersToggled(bool);
+ void handleSettingChanged(const std::string& setting);
protected:
void contextMenuEvent(QContextMenuEvent* event);
private:
void setupContextMenus();
bool bookmarksEnabled_;
UIEventStream* eventStream_;
ChatListModel* model_;
ChatListDelegate* delegate_;
QMenu* mucMenu_;
QMenu* emptyMenu_;
ChatListItem* contextMenuItem_;
- QtUIPreferences* uiPreferences_;
+ SettingsProvider* settings_;
};
}
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 4cf606c..dd33e28 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -1,148 +1,147 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtChatWindow.h"
#include "QtSwiftUtil.h"
#include "Swift/Controllers/Roster/Roster.h"
#include "Swift/Controllers/Roster/RosterItem.h"
#include "Swift/Controllers/Roster/ContactRosterItem.h"
#include "Roster/QtOccupantListWidget.h"
#include "SwifTools/Linkify.h"
#include "QtChatView.h"
#include "MessageSnippet.h"
#include "SystemMessageSnippet.h"
#include "QtTextEdit.h"
#include "QtSettingsProvider.h"
#include "QtScaledAvatarCache.h"
#include "SwifTools/TabComplete.h"
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include "QtFileTransferJSBridge.h"
#include <boost/cstdint.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <QLabel>
#include <QMessageBox>
#include <QInputDialog>
#include <QApplication>
#include <QBoxLayout>
#include <QCloseEvent>
#include <QComboBox>
#include <QFileInfo>
#include <QLineEdit>
#include <QSplitter>
#include <QString>
#include <QTextEdit>
#include <QTime>
#include <QUrl>
#include <QPushButton>
#include <QFileDialog>
#include <QMenu>
-#include <Swift/QtUI/QtUIPreferences.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
#include <QDebug>
namespace Swift {
-QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, QtUIPreferences* uiPreferences) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), previousMessageWasPresence_(false), previousMessageWasFileTransfer_(false), eventStream_(eventStream) {
- uiPreferences_ = uiPreferences;
+QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), previousMessageWasPresence_(false), previousMessageWasFileTransfer_(false), eventStream_(eventStream) {
+ settings_ = settings;
unreadCount_ = 0;
idCounter_ = 0;
inputEnabled_ = true;
completer_ = NULL;
affiliationEditor_ = NULL;
theme_ = theme;
isCorrection_ = false;
correctionEnabled_ = Maybe;
updateTitleWithUnreadCount();
- QtSettingsProvider settings;
#ifdef SWIFT_EXPERIMENTAL_FT
setAcceptDrops(true);
#endif
alertStyleSheet_ = "background: rgb(255, 255, 153); color: black";
QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(2);
alertWidget_ = new QWidget(this);
QHBoxLayout* alertLayout = new QHBoxLayout(alertWidget_);
layout->addWidget(alertWidget_);
alertLabel_ = new QLabel(this);
alertLayout->addWidget(alertLabel_);
alertButton_ = new QPushButton(this);
connect (alertButton_, SIGNAL(clicked()), this, SLOT(handleAlertButtonClicked()));
alertLayout->addWidget(alertButton_);
QPalette palette = alertWidget_->palette();
palette.setColor(QPalette::Window, QColor(Qt::yellow));
palette.setColor(QPalette::WindowText, QColor(Qt::black));
alertWidget_->setStyleSheet(alertStyleSheet_);
alertLabel_->setStyleSheet(alertStyleSheet_);
alertWidget_->hide();
QBoxLayout* subjectLayout = new QBoxLayout(QBoxLayout::LeftToRight);
subject_ = new QLineEdit(this);
subjectLayout->addWidget(subject_);
setSubject("");
subject_->setReadOnly(true);
actionButton_ = new QPushButton(this);
actionButton_->setIcon(QIcon(":/icons/actions.png"));
connect(actionButton_, SIGNAL(clicked()), this, SLOT(handleActionButtonClicked()));
subjectLayout->addWidget(actionButton_);
subject_->hide();
actionButton_->hide();
layout->addLayout(subjectLayout);
logRosterSplitter_ = new QSplitter(this);
logRosterSplitter_->setAutoFillBackground(true);
layout->addWidget(logRosterSplitter_);
messageLog_ = new QtChatView(theme, this);
logRosterSplitter_->addWidget(messageLog_);
- treeWidget_ = new QtOccupantListWidget(eventStream_, uiPreferences_, this);
+ treeWidget_ = new QtOccupantListWidget(eventStream_, settings_, this);
treeWidget_->hide();
logRosterSplitter_->addWidget(treeWidget_);
logRosterSplitter_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(logRosterSplitter_, SIGNAL(splitterMoved(int, int)), this, SLOT(handleSplitterMoved(int, int)));
QWidget* midBar = new QWidget(this);
layout->addWidget(midBar);
midBar->setAutoFillBackground(true);
QHBoxLayout *midBarLayout = new QHBoxLayout(midBar);
midBarLayout->setContentsMargins(0,0,0,0);
midBarLayout->setSpacing(2);
midBarLayout->addStretch();
labelsWidget_ = new QComboBox(this);
labelsWidget_->setFocusPolicy(Qt::NoFocus);
labelsWidget_->hide();
labelsWidget_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
midBarLayout->addWidget(labelsWidget_,0);
QHBoxLayout* inputBarLayout = new QHBoxLayout();
inputBarLayout->setContentsMargins(0,0,0,0);
inputBarLayout->setSpacing(2);
input_ = new QtTextEdit(this);
input_->setAcceptRichText(false);
inputBarLayout->addWidget(input_);
correctingLabel_ = new QLabel(tr("Correcting"), this);
inputBarLayout->addWidget(correctingLabel_);
correctingLabel_->hide();
layout->addLayout(inputBarLayout);
inputClearing_ = false;
contactIsTyping_ = false;
connect(input_, SIGNAL(unhandledKeyPressEvent(QKeyEvent*)), this, SLOT(handleKeyPressEvent(QKeyEvent*)));
connect(input_, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 4f997c0..9203068 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -1,75 +1,75 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
#include <Swift/QtUI/QtMUCConfigurationWindow.h>
#include <Swift/QtUI/QtAffiliationEditor.h>
#include <QtTabbable.h>
#include <SwifTools/LastLineTracker.h>
#include <map>
#include <QPointer>
class QTextEdit;
class QLineEdit;
class QComboBox;
class QLabel;
class QSplitter;
class QPushButton;
namespace Swift {
class QtChatView;
class QtOccupantListWidget;
class QtChatTheme;
class TreeWidget;
class QtTextEdit;
class UIEventStream;
class QtFileTransferJSBridge;
- class QtUIPreferences;
+ class SettingsProvider;
class QtChatWindow : public QtTabbable, public ChatWindow {
Q_OBJECT
public:
- QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, QtUIPreferences* uiPreferences);
+ QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings);
~QtChatWindow();
std::string addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time);
std::string addAction(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time);
void addSystemMessage(const std::string& message);
void addPresenceMessage(const std::string& message);
void addErrorMessage(const std::string& errorMessage);
void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time);
// File transfer related stuff
std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes);
void setFileTransferProgress(std::string id, const int percentageDone);
void setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg);
void show();
void activate();
void setUnreadMessageCount(int count);
void convertToMUC();
// TreeWidget *getTreeWidget();
void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels);
void setSecurityLabelsEnabled(bool enabled);
void setSecurityLabelsError();
SecurityLabelsCatalog::Item getSelectedSecurityLabel();
void setName(const std::string& name);
void setInputEnabled(bool enabled);
QtTabbable::AlertType getWidgetAlertState();
void setContactChatState(ChatState::ChatStateType state);
void setRosterModel(Roster* roster);
void setTabComplete(TabComplete* completer);
int getCount();
void replaceLastMessage(const std::string& message);
void setAckState(const std::string& id, AckState state);
// message receipts
void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state);
void flash();
@@ -130,38 +130,38 @@ namespace Swift {
int unreadCount_;
bool contactIsTyping_;
LastLineTracker lastLineTracker_;
QString contact_;
QString lastSentMessage_;
QtChatView* messageLog_;
QtChatTheme* theme_;
QtTextEdit* input_;
QComboBox* labelsWidget_;
QtOccupantListWidget* treeWidget_;
QLabel* correctingLabel_;
QLabel* alertLabel_;
QWidget* alertWidget_;
QPushButton* alertButton_;
TabComplete* completer_;
QLineEdit* subject_;
QPushButton* actionButton_;
std::vector<SecurityLabelsCatalog::Item> availableLabels_;
bool isCorrection_;
bool previousMessageWasSelf_;
bool previousMessageWasSystem_;
bool previousMessageWasPresence_;
bool previousMessageWasFileTransfer_;
QString previousSenderName_;
bool inputClearing_;
UIEventStream* eventStream_;
bool inputEnabled_;
QSplitter *logRosterSplitter_;
Tristate correctionEnabled_;
QString alertStyleSheet_;
std::map<QString, QString> descriptions;
QtFileTransferJSBridge* fileTransferJS;
QPointer<QtMUCConfigurationWindow> mucConfigurationWindow_;
QPointer<QtAffiliationEditor> affiliationEditor_;
int idCounter_;
- QtUIPreferences* uiPreferences_;
+ SettingsProvider* settings_;
};
}
diff --git a/Swift/QtUI/QtChatWindowFactory.cpp b/Swift/QtUI/QtChatWindowFactory.cpp
index b860dae..7610082 100644
--- a/Swift/QtUI/QtChatWindowFactory.cpp
+++ b/Swift/QtUI/QtChatWindowFactory.cpp
@@ -1,83 +1,83 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtChatWindowFactory.h"
#include <QDesktopWidget>
#include "QtChatTabs.h"
#include "QtChatWindow.h"
#include "QtSwiftUtil.h"
#include "QtChatTheme.h"
#include <qdebug.h>
namespace Swift {
static const QString SPLITTER_STATE = "mucSplitterState";
static const QString CHAT_TABS_GEOMETRY = "chatTabsGeometry";
-QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath, QtUIPreferences* uiPreferences) : themePath_(themePath) {
+QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabs* tabs, const QString& themePath) : themePath_(themePath) {
+ qtOnlySettings_ = qtSettings;
settings_ = settings;
tabs_ = tabs;
- uiPreferences_ = uiPreferences;
theme_ = NULL;
if (splitter) {
splitter->addWidget(tabs_);
} else if (tabs_) {
- QVariant chatTabsGeometryVariant = settings_->getQSettings()->value(CHAT_TABS_GEOMETRY);
+ QVariant chatTabsGeometryVariant = qtOnlySettings_->getQSettings()->value(CHAT_TABS_GEOMETRY);
if (chatTabsGeometryVariant.isValid()) {
tabs_->restoreGeometry(chatTabsGeometryVariant.toByteArray());
}
connect(tabs_, SIGNAL(geometryChanged()), this, SLOT(handleWindowGeometryChanged()));
}
}
QtChatWindowFactory::~QtChatWindowFactory() {
delete theme_;
}
ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact,UIEventStream* eventStream) {
if (!theme_) {
theme_ = new QtChatTheme(themePath_);
if (theme_->getIncomingContent().isEmpty()) {
delete theme_;
theme_ = new QtChatTheme(""); /* Use the inbuilt theme */
}
}
- QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream, uiPreferences_);
+ QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream, settings_);
connect(chatWindow, SIGNAL(splitterMoved()), this, SLOT(handleSplitterMoved()));
connect(this, SIGNAL(changeSplitterState(QByteArray)), chatWindow, SLOT(handleChangeSplitterState(QByteArray)));
- QVariant splitterState = settings_->getQSettings()->value(SPLITTER_STATE);
+ QVariant splitterState = qtOnlySettings_->getQSettings()->value(SPLITTER_STATE);
if(splitterState.isValid()) {
chatWindow->handleChangeSplitterState(splitterState.toByteArray());
}
if (tabs_) {
tabs_->addTab(chatWindow);
} else {
- QVariant chatGeometryVariant = settings_->getQSettings()->value(CHAT_TABS_GEOMETRY);
+ QVariant chatGeometryVariant = qtOnlySettings_->getQSettings()->value(CHAT_TABS_GEOMETRY);
if (chatGeometryVariant.isValid()) {
chatWindow->restoreGeometry(chatGeometryVariant.toByteArray());
}
connect(chatWindow, SIGNAL(geometryChanged()), this, SLOT(handleWindowGeometryChanged()));
}
return chatWindow;
}
void QtChatWindowFactory::handleWindowGeometryChanged() {
- settings_->getQSettings()->setValue(CHAT_TABS_GEOMETRY, qobject_cast<QWidget*>(sender())->saveGeometry());
+ qtOnlySettings_->getQSettings()->setValue(CHAT_TABS_GEOMETRY, qobject_cast<QWidget*>(sender())->saveGeometry());
}
void QtChatWindowFactory::handleSplitterMoved() {
QByteArray splitterState = qobject_cast<QtChatWindow*>(sender())->getSplitterState();
- settings_->getQSettings()->setValue(SPLITTER_STATE, QVariant(splitterState));
+ qtOnlySettings_->getQSettings()->setValue(SPLITTER_STATE, QVariant(splitterState));
emit changeSplitterState(splitterState);
}
}
diff --git a/Swift/QtUI/QtChatWindowFactory.h b/Swift/QtUI/QtChatWindowFactory.h
index f664c43..2a16c3b 100644
--- a/Swift/QtUI/QtChatWindowFactory.h
+++ b/Swift/QtUI/QtChatWindowFactory.h
@@ -1,39 +1,39 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
#include "Swiften/JID/JID.h"
#include "QtSettingsProvider.h"
#include <QObject>
#include <QSplitter>
namespace Swift {
class QtChatTabs;
class QtChatTheme;
class UIEventStream;
class QtUIPreferences;
class QtChatWindowFactory : public QObject, public ChatWindowFactory {
Q_OBJECT
public:
- QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath, QtUIPreferences* uiPreferences);
+ QtChatWindowFactory(QSplitter* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabs* tabs, const QString& themePath);
~QtChatWindowFactory();
ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream);
signals:
void changeSplitterState(QByteArray);
private slots:
void handleWindowGeometryChanged();
void handleSplitterMoved();
private:
QString themePath_;
- QtSettingsProvider* settings_;
+ SettingsProvider* settings_;
+ QtSettingsProvider* qtOnlySettings_;
QtChatTabs* tabs_;
QtChatTheme* theme_;
- QtUIPreferences* uiPreferences_;
};
}
diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp
index fc99633..aafdef8 100644
--- a/Swift/QtUI/QtLoginWindow.cpp
+++ b/Swift/QtUI/QtLoginWindow.cpp
@@ -1,80 +1,81 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtLoginWindow.h"
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <algorithm>
#include <cassert>
#include <QApplication>
#include <QBoxLayout>
#include <QComboBox>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QStatusBar>
#include <QToolButton>
#include <QLabel>
#include <QMenuBar>
#include <QHBoxLayout>
#include <qdebug.h>
#include <QCloseEvent>
#include <QCursor>
#include <QMessageBox>
#include <QKeyEvent>
-#include "Swift/Controllers/UIEvents/UIEventStream.h"
-#include "Swift/Controllers/UIEvents/RequestXMLConsoleUIEvent.h"
-#include "Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h"
-#include "Swift/Controllers/UIEvents/ToggleSoundsUIEvent.h"
-#include "Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h"
-#include "Swiften/Base/Platform.h"
-#include "Swiften/Base/Paths.h"
-
-#include "QtAboutWidget.h"
-#include "QtSwiftUtil.h"
-#include "QtMainWindow.h"
-#include "QtUtilities.h"
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swift/Controllers/UIEvents/RequestXMLConsoleUIEvent.h>
+#include <Swift/Controllers/UIEvents/RequestFileTransferListUIEvent.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/Controllers/SettingConstants.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
+#include <Swiften/Base/Platform.h>
+#include <Swiften/Base/Paths.h>
+
+#include <QtAboutWidget.h>
+#include <QtSwiftUtil.h>
+#include <QtMainWindow.h>
+#include <QtUtilities.h>
namespace Swift{
-QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, bool eagleMode) : QMainWindow(), eagleMode_(eagleMode) {
+QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings) : QMainWindow(), settings_(settings) {
uiEventStream_ = uiEventStream;
setWindowTitle("Swift");
#ifndef Q_WS_MAC
setWindowIcon(QIcon(":/logo-icon-16.png"));
#endif
QtUtilities::setX11Resource(this, "Main");
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);
logo->setPixmap(QPixmap(":/logo-shaded-text.256.png"));
logo->setScaledContents(true);
logo->setFixedSize(192,192);
QWidget *logoWidget = new QWidget(this);
QHBoxLayout *logoLayout = new QHBoxLayout();
logoLayout->setMargin(0);
logoLayout->addStretch(0);
logoLayout->addWidget(logo);
logoLayout->addStretch(0);
logoWidget->setLayout(logoLayout);
layout->addWidget(logoWidget);
@@ -167,116 +168,114 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, bool eagleMode) : QMa
xmlConsoleAction_ = new QAction(tr("&Show Debug Console"), this);
connect(xmlConsoleAction_, SIGNAL(triggered()), SLOT(handleShowXMLConsole()));
generalMenu_->addAction(xmlConsoleAction_);
#ifdef SWIFT_EXPERIMENTAL_FT
fileTransferOverviewAction_ = new QAction(tr("Show &File Transfer Overview"), this);
connect(fileTransferOverviewAction_, SIGNAL(triggered()), SLOT(handleShowFileTransferOverview()));
generalMenu_->addAction(fileTransferOverviewAction_);
#endif
toggleSoundsAction_ = new QAction(tr("&Play Sounds"), this);
toggleSoundsAction_->setCheckable(true);
toggleSoundsAction_->setChecked(true);
connect(toggleSoundsAction_, SIGNAL(toggled(bool)), SLOT(handleToggleSounds(bool)));
generalMenu_->addAction(toggleSoundsAction_);
toggleNotificationsAction_ = new QAction(tr("Display Pop-up &Notifications"), this);
toggleNotificationsAction_->setCheckable(true);
toggleNotificationsAction_->setChecked(true);
connect(toggleNotificationsAction_, SIGNAL(toggled(bool)), SLOT(handleToggleNotifications(bool)));
#ifndef SWIFTEN_PLATFORM_MACOSX
swiftMenu_->addSeparator();
#endif
#ifdef SWIFTEN_PLATFORM_MACOSX
QAction* quitAction = new QAction("&Quit", this);
#else
QAction* quitAction = new QAction(tr("&Quit"), this);
#endif
connect(quitAction, SIGNAL(triggered()), SLOT(handleQuit()));
swiftMenu_->addAction(quitAction);
setInitialMenus();
- uiEventStream_->onUIEvent.connect(boost::bind(&QtLoginWindow::handleUIEvent, this, _1));
+ settings_->onSettingChanged.connect(boost::bind(&QtLoginWindow::handleSettingChanged, this, _1));
-
- remember_->setEnabled(!eagleMode_);
- loginAutomatically_->setEnabled(!eagleMode_);
- xmlConsoleAction_->setEnabled(!eagleMode_);
- if (eagleMode_) {
+ bool eagle = settings_->getSetting(SettingConstants::FORGET_PASSWORDS);
+ remember_->setEnabled(!eagle);
+ loginAutomatically_->setEnabled(!eagle);
+ xmlConsoleAction_->setEnabled(!eagle);
+ if (eagle) {
remember_->setChecked(false);
loginAutomatically_->setChecked(false);
}
this->show();
}
void QtLoginWindow::setShowNotificationToggle(bool toggle) {
if (toggle) {
generalMenu_->addAction(toggleNotificationsAction_);
}
else {
generalMenu_->removeAction(toggleNotificationsAction_);
}
}
bool QtLoginWindow::eventFilter(QObject *obj, QEvent *event) {
if (obj == username_->view() && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Delete || keyEvent->key() == Qt::Key_Backspace) {
QString jid(username_->view()->currentIndex().data().toString());
int result = QMessageBox::question(this, tr("Remove profile"), tr("Remove the profile '%1'?").arg(jid), QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::Yes) {
onPurgeSavedLoginRequest(Q2PSTRING(jid));
}
return true;
}
}
return QObject::eventFilter(obj, event);
}
-void QtLoginWindow::handleUIEvent(boost::shared_ptr<UIEvent> event) {
- boost::shared_ptr<ToggleSoundsUIEvent> soundEvent = boost::dynamic_pointer_cast<ToggleSoundsUIEvent>(event);
- if (soundEvent) {
- toggleSoundsAction_->setChecked(soundEvent->getEnabled());
+void QtLoginWindow::handleSettingChanged(const std::string& settingPath) {
+ if (settingPath == SettingConstants::PLAY_SOUNDS.getKey()) {
+ toggleSoundsAction_->setChecked(settings_->getSetting(SettingConstants::PLAY_SOUNDS));
}
- boost::shared_ptr<ToggleNotificationsUIEvent> notificationsEvent = boost::dynamic_pointer_cast<ToggleNotificationsUIEvent>(event);
- if (notificationsEvent) {
- toggleNotificationsAction_->setChecked(notificationsEvent->getEnabled());
+ if (settingPath == SettingConstants::SHOW_NOTIFICATIONS.getKey()) {
+ toggleNotificationsAction_->setChecked(settings_->getSetting(SettingConstants::SHOW_NOTIFICATIONS));
}
}
void QtLoginWindow::selectUser(const std::string& username) {
for (int i = 0; i < usernames_.count(); i++) {
if (P2QSTRING(username) == usernames_[i]) {
username_->setCurrentIndex(i);
password_->setFocus();
break;
}
}
}
void QtLoginWindow::removeAvailableAccount(const std::string& jid) {
QString username = P2QSTRING(jid);
int index = -1;
for (int i = 0; i < usernames_.count(); i++) {
if (username == usernames_[i]) {
index = i;
}
}
if (index >= 0) {
usernames_.removeAt(index);
passwords_.removeAt(index);
certificateFiles_.removeAt(index);
username_->removeItem(index);
}
}
void QtLoginWindow::addAvailableAccount(const std::string& defaultJID, const std::string& defaultPassword, const std::string& defaultCertificate) {
QString username = P2QSTRING(defaultJID);
int index = -1;
for (int i = 0; i < usernames_.count(); i++) {
if (username == usernames_[i]) {
index = i;
@@ -291,150 +290,141 @@ void QtLoginWindow::addAvailableAccount(const std::string& defaultJID, const std
usernames_[index] = username;
passwords_[index] = P2QSTRING(defaultPassword);
certificateFiles_[index] = P2QSTRING(defaultCertificate);
}
}
void QtLoginWindow::handleUsernameTextChanged() {
QString username = username_->currentText();
for (int i = 0; i < usernames_.count(); i++) {
if (username_->currentText() == usernames_[i]) {
certificateFile_ = certificateFiles_[i];
password_->setText(passwords_[i]);
remember_->setChecked(password_->text() != "");
}
}
if (!certificateFile_.isEmpty()) {
certificateButton_->setChecked(true);
}
}
void QtLoginWindow::loggedOut() {
stack_->removeWidget(stack_->currentWidget());
stack_->addWidget(loginWidgetWrapper_);
stack_->setCurrentWidget(loginWidgetWrapper_);
setInitialMenus();
setIsLoggingIn(false);
}
void QtLoginWindow::setIsLoggingIn(bool loggingIn) {
/* Change the for loop as well if you add to this.*/
QWidget* widgets[5] = {username_, password_, remember_, loginAutomatically_, certificateButton_};
loginButton_->setText(loggingIn ? tr("Cancel") : tr("Connect"));
for (int i = 0; i < 5; i++) {
widgets[i]->setEnabled(!loggingIn);
}
- remember_->setEnabled(!eagleMode_);
- loginAutomatically_->setEnabled(!eagleMode_);
+ bool eagle = settings_->getSetting(SettingConstants::FORGET_PASSWORDS);
+ remember_->setEnabled(!eagle);
+ loginAutomatically_->setEnabled(!eagle);
}
void QtLoginWindow::loginClicked() {
if (username_->isEnabled()) {
- if (eagleMode_) {
- QString clickThroughPath(P2QSTRING((Paths::getExecutablePath() / "eagle-banner.txt").string()));
- QFile clickThroughFile(clickThroughPath);
- if (clickThroughFile.exists() && clickThroughFile.open(QIODevice::ReadOnly)) {
- QString banner;
- while (!clickThroughFile.atEnd()) {
- QByteArray line = clickThroughFile.readLine();
- banner += line + "\n";
- }
- if (!banner.isEmpty()) {
- QMessageBox msgBox;
- msgBox.setWindowTitle(tr("Confirm terms of use"));
- msgBox.setText("");
- msgBox.setInformativeText(banner);
- msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
- msgBox.setDefaultButton(QMessageBox::No);
- if (msgBox.exec() != QMessageBox::Yes) {
- return;
- }
- }
+ std::string banner = settings_->getSetting(QtUISettingConstants::CLICKTHROUGH_BANNER);
+ if (!banner.empty()) {
+ QMessageBox msgBox;
+ msgBox.setWindowTitle(tr("Confirm terms of use"));
+ msgBox.setText("");
+ msgBox.setInformativeText(P2QSTRING(banner));
+ msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+ msgBox.setDefaultButton(QMessageBox::No);
+ if (msgBox.exec() != QMessageBox::Yes) {
+ return;
}
}
onLoginRequest(Q2PSTRING(username_->currentText()), Q2PSTRING(password_->text()), Q2PSTRING(certificateFile_), remember_->isChecked(), loginAutomatically_->isChecked());
- if (eagleMode_) { /* Mustn't remember logins */
+ if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) { /* Mustn't remember logins */
username_->clearEditText();
password_->setText("");
}
} else {
onCancelLoginRequest();
}
}
void QtLoginWindow::setLoginAutomatically(bool loginAutomatically) {
loginAutomatically_->setChecked(loginAutomatically);
}
void QtLoginWindow::handleCertficateChecked(bool checked) {
if (checked) {
certificateFile_ = QFileDialog::getOpenFileName(this, tr("Select an authentication certificate"), QString(), QString("*.cert;*.p12;*.pfx"));
if (certificateFile_.isEmpty()) {
certificateButton_->setChecked(false);
}
}
else {
certificateFile_ = "";
}
}
void QtLoginWindow::handleAbout() {
if (!aboutDialog_) {
aboutDialog_ = new QtAboutWidget();
aboutDialog_->show();
}
else {
aboutDialog_->show();
aboutDialog_->raise();
aboutDialog_->activateWindow();
}
}
void QtLoginWindow::handleShowXMLConsole() {
uiEventStream_->send(boost::shared_ptr<RequestXMLConsoleUIEvent>(new RequestXMLConsoleUIEvent()));
}
void QtLoginWindow::handleShowFileTransferOverview() {
uiEventStream_->send(boost::make_shared<RequestFileTransferListUIEvent>());
}
void QtLoginWindow::handleToggleSounds(bool enabled) {
- uiEventStream_->send(boost::shared_ptr<ToggleSoundsUIEvent>(new ToggleSoundsUIEvent(enabled)));
+ settings_->storeSetting(SettingConstants::PLAY_SOUNDS, enabled);
}
void QtLoginWindow::handleToggleNotifications(bool enabled) {
- uiEventStream_->send(boost::shared_ptr<ToggleNotificationsUIEvent>(new ToggleNotificationsUIEvent(enabled)));
+ settings_->storeSetting(SettingConstants::SHOW_NOTIFICATIONS, enabled);
}
void QtLoginWindow::handleQuit() {
onQuitRequest();
}
void QtLoginWindow::quit() {
QApplication::quit();
}
void QtLoginWindow::setInitialMenus() {
menuBar_->clear();
menuBar_->addMenu(swiftMenu_);
#ifdef SWIFTEN_PLATFORM_MACOSX
menuBar_->addMenu(generalMenu_);
#endif
}
void QtLoginWindow::morphInto(MainWindow *mainWindow) {
QtMainWindow *qtMainWindow = dynamic_cast<QtMainWindow*>(mainWindow);
assert(qtMainWindow);
stack_->removeWidget(loginWidgetWrapper_);
stack_->addWidget(qtMainWindow);
stack_->setCurrentWidget(qtMainWindow);
setEnabled(true);
setInitialMenus();
foreach (QMenu* menu, qtMainWindow->getMenus()) {
menuBar_->addMenu(menu);
}
}
void QtLoginWindow::setMessage(const std::string& message) {
if (!message.empty()) {
message_->setText("<center><font color=\"red\">" + P2QSTRING(message) + "</font></center>");
}
diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h
index df133b1..dcd7c18 100644
--- a/Swift/QtUI/QtLoginWindow.h
+++ b/Swift/QtUI/QtLoginWindow.h
@@ -1,101 +1,102 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QMainWindow>
#include <QPointer>
#include <QLineEdit>
#include <QPushButton>
#include <QCheckBox>
#include <QStackedWidget>
#include <QMenuBar>
-#include "Swift/Controllers/UIInterfaces/LoginWindow.h"
-#include "Swift/Controllers/UIEvents/UIEventStream.h"
-#include "Swift/Controllers/UIInterfaces/MainWindow.h"
-#include "QtAboutWidget.h"
+#include <Swift/Controllers/UIInterfaces/LoginWindow.h>
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swift/Controllers/UIInterfaces/MainWindow.h>
+#include <QtAboutWidget.h>
class QLabel;
class QToolButton;
class QComboBox;
namespace Swift {
+ class SettingsProvider;
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, bool eagleMode);
+ QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* settings);
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);
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, 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 handleToggleSounds(bool enabled);
void handleToggleNotifications(bool enabled);
void handleAbout();
void bringToFront();
void handleUsernameTextChanged();
void resizeEvent(QResizeEvent* event);
void moveEvent(QMoveEvent* event);
- void handleUIEvent(boost::shared_ptr<UIEvent> event);
+ void handleSettingChanged(const std::string& settingPath);
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
void setInitialMenus();
QWidget* loginWidgetWrapper_;
QStringList usernames_;
QStringList passwords_;
QStringList certificateFiles_;
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_;
QAction* toggleSoundsAction_;
QAction* toggleNotificationsAction_;
UIEventStream* uiEventStream_;
QPointer<QtAboutWidget> aboutDialog_;
- bool eagleMode_;
+ SettingsProvider* settings_;
QAction* xmlConsoleAction_;
QAction* fileTransferOverviewAction_;
};
}
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 199e388..9f66b31 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -1,273 +1,268 @@
/*
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtMainWindow.h"
#include <boost/optional.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <QBoxLayout>
#include <QComboBox>
#include <QLineEdit>
#include <QListWidget>
#include <QListWidgetItem>
#include <QPushButton>
#include <QMenuBar>
#include <QToolBar>
#include <QAction>
#include <QTabWidget>
#include <Swift/QtUI/QtSwiftUtil.h>
#include <Swift/QtUI/QtTabWidget.h>
#include <Swift/QtUI/QtSettingsProvider.h>
-#include <Swift/QtUI/QtUIPreferences.h>
#include <Swift/QtUI/QtLoginWindow.h>
#include <Roster/QtRosterWidget.h>
#include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestProfileEditorUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
-#include <Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestAdHocUIEvent.h>
-#include <Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
+#include <Swift/Controllers/SettingConstants.h>
namespace Swift {
-#define CURRENT_ROSTER_TAB "current_roster_tab"
-
-QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventStream, QtUIPreferences* uiPreferences, QtLoginWindow::QtMenus loginMenus) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
+QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
uiEventStream_ = uiEventStream;
- uiPreferences_ = uiPreferences;
settings_ = settings;
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this);
mainLayout->setContentsMargins(0,0,0,0);
mainLayout->setSpacing(0);
meView_ = new QtRosterHeader(settings, this);
mainLayout->addWidget(meView_);
connect(meView_, SIGNAL(onChangeStatusRequest(StatusShow::Type, const QString&)), this, SLOT(handleStatusChanged(StatusShow::Type, const QString&)));
connect(meView_, SIGNAL(onEditProfileRequest()), this, SLOT(handleEditProfileRequest()));
tabs_ = new QtTabWidget(this);
#if QT_VERSION >= 0x040500
tabs_->setDocumentMode(true);
#endif
tabs_->setTabPosition(QTabWidget::South);
mainLayout->addWidget(tabs_);
contactsTabWidget_ = new QWidget(this);
contactsTabWidget_->setContentsMargins(0, 0, 0, 0);
QBoxLayout *contactTabLayout = new QBoxLayout(QBoxLayout::TopToBottom, contactsTabWidget_);
contactsTabWidget_->setLayout(contactTabLayout);
contactTabLayout->setSpacing(0);
contactTabLayout->setContentsMargins(0, 0, 0, 0);
- treeWidget_ = new QtRosterWidget(uiEventStream_, uiPreferences_, this);
+ treeWidget_ = new QtRosterWidget(uiEventStream_, settings_, this);
contactTabLayout->addWidget(treeWidget_);
tabs_->addTab(contactsTabWidget_, tr("&Contacts"));
eventWindow_ = new QtEventWindow(uiEventStream_);
connect(eventWindow_, SIGNAL(onNewEventCountUpdated(int)), this, SLOT(handleEventCountUpdated(int)));
- chatListWindow_ = new QtChatListWindow(uiEventStream_, uiPreferences_);
+ chatListWindow_ = new QtChatListWindow(uiEventStream_, settings_);
connect(chatListWindow_, SIGNAL(onCountUpdated(int)), this, SLOT(handleChatCountUpdated(int)));
tabs_->addTab(chatListWindow_, tr("C&hats"));
tabs_->addTab(eventWindow_, tr("&Notices"));
- tabs_->setCurrentIndex(settings_->getIntSetting(CURRENT_ROSTER_TAB, 0));
+ tabs_->setCurrentIndex(settings_->getSetting(QtUISettingConstants::CURRENT_ROSTER_TAB));
connect(tabs_, SIGNAL(currentChanged(int)), this, SLOT(handleTabChanged(int)));
this->setLayout(mainLayout);
QMenu* viewMenu = new QMenu(tr("&View"), this);
menus_.push_back(viewMenu);
showOfflineAction_ = new QAction(tr("&Show offline contacts"), this);
showOfflineAction_->setCheckable(true);
showOfflineAction_->setChecked(false);
connect(showOfflineAction_, SIGNAL(toggled(bool)), SLOT(handleShowOfflineToggled(bool)));
viewMenu->addAction(showOfflineAction_);
//QAction* compactRosterAction_ = new QAction(tr("&Compact Roster"), this);
//compactRosterAction_->setCheckable(true);
//compactRosterAction_->setChecked(false);
//connect(compactRosterAction_, SIGNAL(toggled(bool)), uiPreferences_, SLOT(setCompactRosters(bool)));
//viewMenu->addAction(compactRosterAction_);
QMenu* actionsMenu = new QMenu(tr("&Actions"), this);
menus_.push_back(actionsMenu);
QAction* editProfileAction = new QAction(tr("Edit &Profile"), this);
connect(editProfileAction, SIGNAL(triggered()), SLOT(handleEditProfileAction()));
actionsMenu->addAction(editProfileAction);
QAction* joinMUCAction = new QAction(tr("Enter &Room"), this);
connect(joinMUCAction, SIGNAL(triggered()), SLOT(handleJoinMUCAction()));
actionsMenu->addAction(joinMUCAction);
addUserAction_ = new QAction(tr("&Add Contact"), this);
connect(addUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleAddUserActionTriggered(bool)));
actionsMenu->addAction(addUserAction_);
editUserAction_ = new QAction(tr("&Edit Selected Contact"), this);
connect(editUserAction_, SIGNAL(triggered(bool)), treeWidget_, SLOT(handleEditUserActionTriggered(bool)));
actionsMenu->addAction(editUserAction_);
editUserAction_->setEnabled(false);
chatUserAction_ = new QAction(tr("Start &Chat"), this);
connect(chatUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleChatUserActionTriggered(bool)));
actionsMenu->addAction(chatUserAction_);
serverAdHocMenu_ = new QMenu(tr("Run Server Command"), this);
actionsMenu->addMenu(serverAdHocMenu_);
actionsMenu->addSeparator();
QAction* signOutAction = new QAction(tr("&Sign Out"), this);
connect(signOutAction, SIGNAL(triggered()), SLOT(handleSignOutAction()));
actionsMenu->addAction(signOutAction);
toggleRequestDeliveryReceipts_ = new QAction(tr("&Request Delivery Receipts"), this);
toggleRequestDeliveryReceipts_->setCheckable(true);
toggleRequestDeliveryReceipts_->setChecked(false);
connect(toggleRequestDeliveryReceipts_, SIGNAL(toggled(bool)), SLOT(handleToggleRequestDeliveryReceipts(bool)));
loginMenus_.generalMenu->addAction(toggleRequestDeliveryReceipts_);
treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QAction::setEnabled, editUserAction_, _1));
setAvailableAdHocCommands(std::vector<DiscoItems::Item>());
QAction* adHocAction = new QAction(tr("Collecting commands..."), this);
adHocAction->setEnabled(false);
serverAdHocMenu_->addAction(adHocAction);
serverAdHocCommandActions_.append(adHocAction);
lastOfflineState_ = false;
- uiEventStream_->onUIEvent.connect(boost::bind(&QtMainWindow::handleUIEvent, this, _1));
+
+ settings_->onSettingChanged.connect(boost::bind(&QtMainWindow::handleSettingChanged, this, _1));
}
QtMainWindow::~QtMainWindow() {
- uiEventStream_->onUIEvent.disconnect(boost::bind(&QtMainWindow::handleUIEvent, this, _1));
+ settings_->onSettingChanged.disconnect(boost::bind(&QtMainWindow::handleSettingChanged, this, _1));
}
void QtMainWindow::handleTabChanged(int index) {
- settings_->storeInt(CURRENT_ROSTER_TAB, index);
+ settings_->storeSetting(QtUISettingConstants::CURRENT_ROSTER_TAB, index);
}
void QtMainWindow::handleToggleRequestDeliveryReceipts(bool enabled) {
- uiEventStream_->send(boost::make_shared<ToggleRequestDeliveryReceiptsUIEvent>(enabled));
+ settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, enabled);
}
QtEventWindow* QtMainWindow::getEventWindow() {
return eventWindow_;
}
QtChatListWindow* QtMainWindow::getChatListWindow() {
return chatListWindow_;
}
void QtMainWindow::setRosterModel(Roster* roster) {
treeWidget_->setRosterModel(roster);
}
void QtMainWindow::handleEditProfileRequest() {
uiEventStream_->send(boost::make_shared<RequestProfileEditorUIEvent>());
}
void QtMainWindow::handleEventCountUpdated(int count) {
QColor eventTabColor = (count == 0) ? QColor() : QColor(255, 0, 0); // invalid resets to default
int eventIndex = 2;
tabs_->tabBar()->setTabTextColor(eventIndex, eventTabColor);
QString text = tr("&Notices");
if (count > 0) {
text += QString(" (%1)").arg(count);
}
tabs_->setTabText(eventIndex, text);
}
void QtMainWindow::handleChatCountUpdated(int count) {
QColor chatTabColor = (count == 0) ? QColor() : QColor(255, 0, 0); // invalid resets to default
int chatIndex = 1;
tabs_->tabBar()->setTabTextColor(chatIndex, chatTabColor);
QString text = tr("&Chats");
if (count > 0) {
text += QString(" (%1)").arg(count);
}
tabs_->setTabText(chatIndex, text);
}
void QtMainWindow::handleAddUserActionTriggered(bool /*checked*/) {
boost::shared_ptr<UIEvent> event(new RequestAddUserDialogUIEvent());
uiEventStream_->send(event);
}
void QtMainWindow::handleChatUserActionTriggered(bool /*checked*/) {
boost::shared_ptr<UIEvent> event(new RequestChatWithUserDialogUIEvent());
uiEventStream_->send(event);
}
void QtMainWindow::handleSignOutAction() {
loginMenus_.generalMenu->removeAction(toggleRequestDeliveryReceipts_);
onSignOutRequest();
}
void QtMainWindow::handleEditProfileAction() {
uiEventStream_->send(boost::make_shared<RequestProfileEditorUIEvent>());
}
void QtMainWindow::handleJoinMUCAction() {
uiEventStream_->send(boost::make_shared<RequestJoinMUCUIEvent>());
}
void QtMainWindow::handleStatusChanged(StatusShow::Type showType, const QString &statusMessage) {
onChangeStatusRequest(showType, Q2PSTRING(statusMessage));
}
-void QtMainWindow::handleUIEvent(boost::shared_ptr<UIEvent> event) {
- boost::shared_ptr<ToggleShowOfflineUIEvent> toggleEvent = boost::dynamic_pointer_cast<ToggleShowOfflineUIEvent>(event);
- if (toggleEvent) {
- handleShowOfflineToggled(toggleEvent->getShow());
+void QtMainWindow::handleSettingChanged(const std::string& settingPath) {
+ if (settingPath == SettingConstants::SHOW_OFFLINE.getKey()) {
+ handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE));
}
- boost::shared_ptr<ToggleRequestDeliveryReceiptsUIEvent> deliveryReceiptEvent = boost::dynamic_pointer_cast<ToggleRequestDeliveryReceiptsUIEvent>(event);
- if (deliveryReceiptEvent) {
- toggleRequestDeliveryReceipts_->setChecked(deliveryReceiptEvent->getEnabled());
+ if (settingPath == SettingConstants::REQUEST_DELIVERYRECEIPTS.getKey()) {
+ toggleRequestDeliveryReceipts_->setChecked(settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS));
}
}
void QtMainWindow::handleShowOfflineToggled(bool state) {
if (state != lastOfflineState_) {
lastOfflineState_ = state;
showOfflineAction_->setChecked(state);
- uiEventStream_->onUIEvent(boost::shared_ptr<UIEvent>(new ToggleShowOfflineUIEvent(state)));
+ settings_->storeSetting(SettingConstants::SHOW_OFFLINE, state);
}
}
void QtMainWindow::setMyNick(const std::string& nick) {
meView_->setNick(P2QSTRING(nick));
}
void QtMainWindow::setMyJID(const JID& jid) {
meView_->setJID(P2QSTRING(jid.toBare().toString()));
}
void QtMainWindow::setMyAvatarPath(const std::string& path) {
meView_->setAvatar(P2QSTRING(path));
}
void QtMainWindow::setMyStatusText(const std::string& status) {
meView_->setStatusText(P2QSTRING(status));
}
void QtMainWindow::setMyStatusType(StatusShow::Type type) {
meView_->setStatusType(type);
}
void QtMainWindow::setConnecting() {
meView_->setConnecting();
}
void QtMainWindow::handleAdHocActionTriggered(bool /*checked*/) {
QAction* action = qobject_cast<QAction*>(sender());
assert(action);
DiscoItems::Item command = serverAdHocCommands_[serverAdHocCommandActions_.indexOf(action)];
uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestAdHocUIEvent(command)));
}
void QtMainWindow::setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands) {
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index 3c8bdec..44f8a25 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -1,91 +1,90 @@
/*
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QWidget>
#include <QMenu>
#include <QList>
#include "Swift/Controllers/UIInterfaces/MainWindow.h"
#include "Swift/QtUI/QtRosterHeader.h"
#include "Swift/QtUI/EventViewer/QtEventWindow.h"
#include "Swift/QtUI/ChatList/QtChatListWindow.h"
#include "Swift/QtUI/QtLoginWindow.h"
#include <vector>
class QComboBox;
class QLineEdit;
class QPushButton;
class QToolBar;
class QAction;
class QMenu;
class QTabWidget;
namespace Swift {
class QtRosterWidget;
class TreeWidget;
class UIEventStream;
class QtTabWidget;
- class QtSettingsProvider;
+ class SettingsProvider;
class QtUIPreferences;
class QtMainWindow : public QWidget, public MainWindow {
Q_OBJECT
public:
- QtMainWindow(QtSettingsProvider*, UIEventStream* eventStream, QtUIPreferences* uiPreferences, QtLoginWindow::QtMenus loginMenus);
+ QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus);
virtual ~QtMainWindow();
std::vector<QMenu*> getMenus() {return menus_;}
void setMyNick(const std::string& name);
void setMyJID(const JID& jid);
void setMyAvatarPath(const std::string& path);
void setMyStatusText(const std::string& status);
void setMyStatusType(StatusShow::Type type);
void setConnecting();
QtEventWindow* getEventWindow();
QtChatListWindow* getChatListWindow();
void setRosterModel(Roster* roster);
void setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands);
private slots:
void handleStatusChanged(StatusShow::Type showType, const QString &statusMessage);
- void handleUIEvent(boost::shared_ptr<UIEvent> event);
+ void handleSettingChanged(const std::string& settingPath);
void handleShowOfflineToggled(bool);
void handleJoinMUCAction();
void handleSignOutAction();
void handleEditProfileAction();
void handleAddUserActionTriggered(bool checked);
void handleChatUserActionTriggered(bool checked);
void handleAdHocActionTriggered(bool checked);
void handleEventCountUpdated(int count);
void handleChatCountUpdated(int count);
void handleEditProfileRequest();
void handleTabChanged(int index);
void handleToggleRequestDeliveryReceipts(bool enabled);
private:
- QtSettingsProvider* settings_;
+ SettingsProvider* settings_;
QtLoginWindow::QtMenus loginMenus_;
std::vector<QMenu*> menus_;
QtRosterWidget* treeWidget_;
QtRosterHeader* meView_;
QAction* addUserAction_;
QAction* editUserAction_;
QAction* chatUserAction_;
QAction* showOfflineAction_;
QAction* toggleRequestDeliveryReceipts_;
QMenu* serverAdHocMenu_;
QtTabWidget* tabs_;
QWidget* contactsTabWidget_;
QWidget* eventsTabWidget_;
QtEventWindow* eventWindow_;
QtChatListWindow* chatListWindow_;
UIEventStream* uiEventStream_;
bool lastOfflineState_;
std::vector<DiscoItems::Item> serverAdHocCommands_;
QList<QAction*> serverAdHocCommandActions_;
- QtUIPreferences* uiPreferences_;
};
}
diff --git a/Swift/QtUI/QtNameWidget.cpp b/Swift/QtUI/QtNameWidget.cpp
index 96f9c0d..08e32f5 100644
--- a/Swift/QtUI/QtNameWidget.cpp
+++ b/Swift/QtUI/QtNameWidget.cpp
@@ -1,95 +1,96 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2012 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtNameWidget.h"
#include <QHBoxLayout>
#include <QMenu>
#include <QMouseEvent>
#include <QtDebug>
#include <Swift/QtUI/QtElidingLabel.h>
#include <Swift/QtUI/QtSettingsProvider.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
namespace Swift {
-QtNameWidget::QtNameWidget(QtSettingsProvider* settings, QWidget *parent) : QWidget(parent), settings(settings) {
+QtNameWidget::QtNameWidget(SettingsProvider* settings, QWidget *parent) : QWidget(parent), settings(settings) {
QHBoxLayout* mainLayout = new QHBoxLayout(this);
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0,0,0,0);
- mode = settings->getBoolSetting("showNickInRosterHeader", true) ? ShowNick : ShowJID;
+ mode = settings->getSetting(QtUISettingConstants::SHOW_NICK_IN_ROSTER_HEADER) ? ShowNick : ShowJID;
textLabel = new QtElidingLabel(this);
QFont font = textLabel->font();
font.setBold(true);
textLabel->setFont(font);
mainLayout->addWidget(textLabel);
}
void QtNameWidget::setNick(const QString& nick) {
this->nick = nick;
updateText();
}
void QtNameWidget::setJID(const QString& jid) {
this->jid = jid;
updateText();
}
void QtNameWidget::mousePressEvent(QMouseEvent* event) {
QMenu menu;
bool hasNick = !nick.isEmpty();
QAction* showAsNick = new QAction(hasNick ? tr("Show Nickname") : tr("(No Nickname Set)"), this);
showAsNick->setCheckable(true);
showAsNick->setEnabled(hasNick);
if (mode == ShowNick && hasNick) {
showAsNick->setChecked(true);
}
menu.addAction(showAsNick);
QAction* showAsJID = new QAction(tr("Show Address"), this);
showAsJID->setCheckable(true);
if (mode == ShowJID || !hasNick) {
showAsJID->setChecked(true);
}
menu.addAction(showAsJID);
QAction* editProfile = new QAction(tr("Edit Profile"), this);
menu.addAction(editProfile);
QAction* result = menu.exec(event->globalPos());
if (result == showAsJID) {
mode = ShowJID;
}
else if (result == showAsNick) {
mode = ShowNick;
}
else if (result == editProfile) {
emit onChangeNickRequest();
}
- settings->storeBool("showNickInRosterHeader", mode == ShowNick);
+ settings->storeSetting(QtUISettingConstants::SHOW_NICK_IN_ROSTER_HEADER, mode == ShowNick);
updateText();
}
void QtNameWidget::updateText() {
QString text;
if (mode == ShowNick && !nick.isEmpty()) {
text = nick;
}
else {
text = jid;
}
text.replace("<","&lt;");
textLabel->setText(text);
}
}
diff --git a/Swift/QtUI/QtNameWidget.h b/Swift/QtUI/QtNameWidget.h
index 674d55c..0f00c41 100644
--- a/Swift/QtUI/QtNameWidget.h
+++ b/Swift/QtUI/QtNameWidget.h
@@ -1,44 +1,44 @@
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QWidget>
namespace Swift {
class QtElidingLabel;
- class QtSettingsProvider;
+ class SettingsProvider;
class QtNameWidget : public QWidget {
Q_OBJECT
public:
- QtNameWidget(QtSettingsProvider* settings, QWidget *parent);
+ QtNameWidget(SettingsProvider* settings, QWidget *parent);
void setNick(const QString& text);
void setJID(const QString& jid);
signals:
void onChangeNickRequest();
private:
void updateText();
virtual void mousePressEvent(QMouseEvent* event);
private:
enum Mode {
ShowNick,
ShowJID,
};
- QtSettingsProvider* settings;
+ SettingsProvider* settings;
Mode mode;
QtElidingLabel* textLabel;
QString jid;
QString nick;
};
}
diff --git a/Swift/QtUI/QtRosterHeader.cpp b/Swift/QtUI/QtRosterHeader.cpp
index 5fb4d1a..98e75c2 100644
--- a/Swift/QtUI/QtRosterHeader.cpp
+++ b/Swift/QtUI/QtRosterHeader.cpp
@@ -1,61 +1,61 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtRosterHeader.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileInfo>
#include <QIcon>
#include <QSizePolicy>
#include <qdebug.h>
#include <QMouseEvent>
#include <QPainter>
#include <QBitmap>
#include "QtStatusWidget.h"
#include <Swift/QtUI/QtElidingLabel.h>
#include <Swift/QtUI/QtClickableLabel.h>
#include <Swift/QtUI/QtNameWidget.h>
#include "QtScaledAvatarCache.h"
namespace Swift {
-QtRosterHeader::QtRosterHeader(QtSettingsProvider* settings, QWidget* parent) : QWidget(parent) {
+QtRosterHeader::QtRosterHeader(SettingsProvider* settings, QWidget* parent) : QWidget(parent) {
QHBoxLayout* topLayout = new QHBoxLayout();
topLayout->setSpacing(3);
topLayout->setContentsMargins(4,4,4,4);
setLayout(topLayout);
setMinimumHeight(50);
setMaximumHeight(50);
avatarLabel_ = new QtClickableLabel(this);
avatarLabel_->setMinimumSize(avatarSize_, avatarSize_);
avatarLabel_->setMaximumSize(avatarSize_, avatarSize_);
avatarLabel_->setAlignment(Qt::AlignCenter);
setAvatar(":/icons/avatar.png");
avatarLabel_->setScaledContents(false);
topLayout->addWidget(avatarLabel_);
connect(avatarLabel_, SIGNAL(clicked()), this, SIGNAL(onEditProfileRequest()));
QVBoxLayout* rightLayout = new QVBoxLayout();
rightLayout->setSpacing(4);
rightLayout->setContentsMargins(4,0,0,0);
topLayout->addLayout(rightLayout);
nameWidget_ = new QtNameWidget(settings, this);
connect(nameWidget_, SIGNAL(onChangeNickRequest()), this, SIGNAL(onEditProfileRequest()));
rightLayout->addWidget(nameWidget_);
statusWidget_ = new QtStatusWidget(this);
connect(statusWidget_, SIGNAL(onChangeStatusRequest(StatusShow::Type, const QString&)), this, SLOT(handleChangeStatusRequest(StatusShow::Type, const QString&)));
rightLayout->addWidget(statusWidget_);
show();
}
void QtRosterHeader::handleChangeStatusRequest(StatusShow::Type type, const QString& text) {
emit onChangeStatusRequest(type, text);
}
diff --git a/Swift/QtUI/QtRosterHeader.h b/Swift/QtUI/QtRosterHeader.h
index 3380610..050460c 100644
--- a/Swift/QtUI/QtRosterHeader.h
+++ b/Swift/QtUI/QtRosterHeader.h
@@ -1,55 +1,55 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QWidget>
#include <QLabel>
#include <QPixmap>
#include <QSize>
#include <QToolBar>
#include <string>
#include "Swiften/Elements/StatusShow.h"
#include "QtTextEdit.h"
class QHBoxLayout;
namespace Swift {
class QtClickableLabel;
class QtStatusWidget;
class QtNameWidget;
- class QtSettingsProvider;
+ class SettingsProvider;
class QtRosterHeader : public QWidget {
Q_OBJECT
public:
- QtRosterHeader(QtSettingsProvider* settings, QWidget* parent = NULL);
+ QtRosterHeader(SettingsProvider* settings, QWidget* parent = NULL);
void setAvatar(const QString& path);
void setJID(const QString& jid);
void setNick(const QString& nick);
void setStatusText(const QString& statusMessage);
void setStatusType(StatusShow::Type type);
void setConnecting();
signals:
void onChangeStatusRequest(StatusShow::Type showType, const QString &statusMessage);
void onEditProfileRequest();
private slots:
void handleChangeStatusRequest(StatusShow::Type type, const QString &statusMessage);
private:
QString name_;
QtClickableLabel* avatarLabel_;
QtNameWidget* nameWidget_;
QtTextEdit* statusEdit_;
QToolBar* toolBar_;
QtStatusWidget* statusWidget_;
static const int avatarSize_;
};
}
diff --git a/Swift/QtUI/QtSettingsProvider.cpp b/Swift/QtUI/QtSettingsProvider.cpp
index b8ef9bb..0c4d49b 100644
--- a/Swift/QtUI/QtSettingsProvider.cpp
+++ b/Swift/QtUI/QtSettingsProvider.cpp
@@ -1,94 +1,119 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "QtSettingsProvider.h"
+#include <QtSettingsProvider.h>
#include <QStringList>
#include <QFile>
namespace Swift {
QtSettingsProvider::QtSettingsProvider() {
}
QtSettingsProvider::~QtSettingsProvider() {
}
-std::string QtSettingsProvider::getStringSetting(const std::string &settingPath) {
- QVariant setting = settings_.value(settingPath.c_str());
- return setting.isNull() ? "" : std::string(setting.toString().toUtf8());
+std::string QtSettingsProvider::getSetting(const Setting<std::string>& setting) {
+ QVariant variant = settings_.value(setting.getKey().c_str());
+ return variant.isNull() ? setting.getDefaultValue() : std::string(variant.toString().toUtf8());
}
-void QtSettingsProvider::storeString(const std::string &settingPath, const std::string &settingValue) {
- settings_.setValue(settingPath.c_str(), settingValue.c_str());
+void QtSettingsProvider::storeSetting(const Setting<std::string>& setting, const std::string& settingValue) {
+ bool changed = false;
+ if (getSetting(setting) != settingValue) {
+ changed = true;
+ }
+ settings_.setValue(setting.getKey().c_str(), settingValue.c_str());
+ if (changed) {
+ onSettingChanged(setting.getKey());
+ }
updatePermissions();
}
-bool QtSettingsProvider::getBoolSetting(const std::string &settingPath, bool defaultValue) {
- QVariant setting = settings_.value(settingPath.c_str());
- return setting.isNull() ? defaultValue : setting.toBool();
+bool QtSettingsProvider::getSetting(const Setting<bool>& setting) {
+ QVariant variant = settings_.value(setting.getKey().c_str());
+ return variant.isNull() ? setting.getDefaultValue() : variant.toBool();
}
-void QtSettingsProvider::storeBool(const std::string &settingPath, bool settingValue) {
- settings_.setValue(settingPath.c_str(), settingValue);
+void QtSettingsProvider::storeSetting(const Setting<bool>& setting, const bool& settingValue) {
+ bool changed = false;
+ if (getSetting(setting) != settingValue) {
+ changed = true;
+ }
+ settings_.setValue(setting.getKey().c_str(), settingValue);
+ if (changed) {
+ onSettingChanged(setting.getKey());
+ }
updatePermissions();
}
-int QtSettingsProvider::getIntSetting(const std::string &settingPath, int defaultValue) {
- QVariant setting = settings_.value(settingPath.c_str());
- return setting.isNull() ? defaultValue : setting.toInt();
+int QtSettingsProvider::getSetting(const Setting<int>& setting) {
+ QVariant variant = settings_.value(setting.getKey().c_str());
+ return variant.isNull() ? setting.getDefaultValue() : variant.toInt();
}
-void QtSettingsProvider::storeInt(const std::string &settingPath, int settingValue) {
- settings_.setValue(settingPath.c_str(), settingValue);
+void QtSettingsProvider::storeSetting(const Setting<int>& setting, const int& settingValue) {
+ bool changed = false;
+ if (getSetting(setting) != settingValue) {
+ changed = true;
+ }
+ settings_.setValue(setting.getKey().c_str(), settingValue);
+ if (changed) {
+ onSettingChanged(setting.getKey());
+ }
updatePermissions();
}
std::vector<std::string> QtSettingsProvider::getAvailableProfiles() {
std::vector<std::string> profiles;
QVariant profilesVariant = settings_.value("profileList");
foreach(QString profileQString, profilesVariant.toStringList()) {
profiles.push_back(std::string(profileQString.toUtf8()));
}
return profiles;
}
void QtSettingsProvider::createProfile(const std::string& profile) {
QStringList stringList = settings_.value("profileList").toStringList();
stringList.append(profile.c_str());
settings_.setValue("profileList", stringList);
updatePermissions();
}
void QtSettingsProvider::removeProfile(const std::string& profile) {
QString profileStart(QString(profile.c_str()) + ":");
foreach (QString key, settings_.allKeys()) {
if (key.startsWith(profileStart)) {
settings_.remove(key);
}
}
QStringList stringList = settings_.value("profileList").toStringList();
stringList.removeAll(profile.c_str());
settings_.setValue("profileList", stringList);
updatePermissions();
}
QSettings* QtSettingsProvider::getQSettings() {
return &settings_;
}
void QtSettingsProvider::updatePermissions() {
#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
QFile file(settings_.fileName());
if (file.exists()) {
file.setPermissions(QFile::ReadOwner|QFile::WriteOwner);
}
#endif
}
+bool QtSettingsProvider::getIsSettingFinal(const std::string& /*settingPath*/) {
+ return false;
+}
+
}
diff --git a/Swift/QtUI/QtSettingsProvider.h b/Swift/QtUI/QtSettingsProvider.h
index 8eeb854..ececa6e 100644
--- a/Swift/QtUI/QtSettingsProvider.h
+++ b/Swift/QtUI/QtSettingsProvider.h
@@ -1,42 +1,43 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFT_QtSettingsProvider_H
-#define SWIFT_QtSettingsProvider_H
+#pragma once
-#include "Swift/Controllers/Settings/SettingsProvider.h"
+#include <Swift/Controllers/Settings/SettingsProvider.h>
#include <QSettings>
namespace Swift {
class QtSettingsProvider : public SettingsProvider {
public:
QtSettingsProvider();
virtual ~QtSettingsProvider();
- virtual std::string getStringSetting(const std::string &settingPath);
- virtual void storeString(const std::string &settingPath, const std::string &settingValue);
- virtual bool getBoolSetting(const std::string &settingPath, bool defaultValue);
- virtual void storeBool(const std::string &settingPath, bool settingValue);
- virtual int getIntSetting(const std::string &settingPath, int defaultValue);
- virtual void storeInt(const std::string &settingPath, int settingValue);
+ virtual std::string getSetting(const Setting<std::string>& setting);
+ virtual void storeSetting(const Setting<std::string>& setting, const std::string& value);
+ virtual bool getSetting(const Setting<bool>& setting);
+ virtual void storeSetting(const Setting<bool>& setting, const bool& value);
+ virtual int getSetting(const Setting<int>& setting);
+ virtual void storeSetting(const Setting<int>& setting, const int& value);
virtual std::vector<std::string> getAvailableProfiles();
virtual void createProfile(const std::string& profile);
virtual void removeProfile(const std::string& profile);
QSettings* getQSettings();
+ protected:
+ virtual bool getIsSettingFinal(const std::string& settingPath);
private:
void updatePermissions();
private:
QSettings settings_;
};
}
-#endif
+
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index f706deb..066d22e 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -1,208 +1,228 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtSwift.h"
#include <string>
#include <QSplitter>
#include <QFile>
#include <boost/bind.hpp>
#include <QMessageBox>
#include <QApplication>
-
-#include "QtLoginWindow.h"
-#include "QtChatTabs.h"
-#include "QtSystemTray.h"
-#include "QtSoundPlayer.h"
-#include "QtSwiftUtil.h"
-#include "QtUIFactory.h"
-#include "QtChatWindowFactory.h"
+#include <qDebug.h>
+
+#include <QtLoginWindow.h>
+#include <QtChatTabs.h>
+#include <QtSystemTray.h>
+#include <QtSoundPlayer.h>
+#include <QtSwiftUtil.h>
+#include <QtUIFactory.h>
+#include <QtChatWindowFactory.h>
#include <Swiften/Base/Log.h>
#include <Swift/Controllers/Storages/CertificateFileStorageFactory.h>
-#include "Swift/Controllers/Storages/FileStoragesFactory.h"
-#include "SwifTools/Application/PlatformApplicationPathProvider.h"
+#include <Swift/Controllers/Storages/FileStoragesFactory.h>
+#include <SwifTools/Application/PlatformApplicationPathProvider.h>
#include <string>
-#include "Swiften/Base/Platform.h"
-#include "Swiften/Elements/Presence.h"
-#include "Swiften/Client/Client.h"
-#include "Swift/Controllers/MainController.h"
-#include "Swift/Controllers/ApplicationInfo.h"
-#include "Swift/Controllers/BuildVersion.h"
-#include "SwifTools/AutoUpdater/AutoUpdater.h"
-#include "SwifTools/AutoUpdater/PlatformAutoUpdaterFactory.h"
+#include <Swiften/Base/Platform.h>
+#include <Swiften/Elements/Presence.h>
+#include <Swiften/Client/Client.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 <SwifTools/AutoUpdater/AutoUpdater.h>
+#include <SwifTools/AutoUpdater/PlatformAutoUpdaterFactory.h>
+#include "Swiften/Base/Paths.h"
#if defined(SWIFTEN_PLATFORM_WINDOWS)
#include "WindowsNotifier.h"
#elif defined(HAVE_GROWL)
#include "SwifTools/Notifier/GrowlNotifier.h"
#elif defined(SWIFTEN_PLATFORM_LINUX)
#include "FreeDesktopNotifier.h"
#else
#include "SwifTools/Notifier/NullNotifier.h"
#endif
#if defined(SWIFTEN_PLATFORM_MACOSX)
#include "SwifTools/Dock/MacOSXDock.h"
#else
#include "SwifTools/Dock/NullDock.h"
#endif
#if defined(SWIFTEN_PLATFORM_MACOSX)
#include "QtURIHandler.h"
#elif defined(SWIFTEN_PLATFORM_WIN32)
#include <SwifTools/URIHandler/NullURIHandler.h>
#else
#include "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 ""
#endif
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")
- ("eagle-mode", "Settings more suitable for military/secure deployments")
;
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("");
+}
QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMainThreadCaller_), autoUpdater_(NULL), idleDetector_(&idleQuerier_, networkFactories_.getTimerFactory(), 1000) {
if (options.count("netbook-mode")) {
splitter_ = new QSplitter();
} else {
splitter_ = NULL;
}
QCoreApplication::setApplicationName(SWIFT_APPLICATION_NAME);
QCoreApplication::setOrganizationName(SWIFT_ORGANIZATION_NAME);
QCoreApplication::setOrganizationDomain(SWIFT_ORGANIZATION_DOMAIN);
QCoreApplication::setApplicationVersion(buildVersion);
+ qtSettings_ = new QtSettingsProvider();
+ xmlSettings_ = loadSettingsFile(P2QSTRING((Paths::getExecutablePath() / "system-settings.xml").string()));
+ settingsHierachy_ = new SettingsProviderHierachy();
+ settingsHierachy_->addProviderToTopOfStack(xmlSettings_);
+ settingsHierachy_->addProviderToTopOfStack(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;
}
if (options.count("debug")) {
Swift::logging = true;
}
tabs_ = options.count("no-tabs") && !(splitter_ > 0) ? NULL : new QtChatTabs();
bool startMinimized = options.count("start-minimized") > 0;
- bool eagleMode = options.count("eagle-mode") > 0;
- settings_ = new QtSettingsProvider();
applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME);
storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir());
certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory());
- chatWindowFactory_ = new QtChatWindowFactory(splitter_, settings_, tabs_, "", &uiPreferences_);
+ 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);
#if defined(HAVE_GROWL)
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());
#elif defined(SWIFTEN_PLATFORM_LINUX)
notifier_ = new FreeDesktopNotifier(SWIFT_APPLICATION_NAME);
#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
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(settings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, startMinimized, eagleMode, &uiPreferences_);
+ QtUIFactory* uiFactory = new QtUIFactory(settingsHierachy_, qtSettings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, startMinimized);
uiFactories_.push_back(uiFactory);
MainController* mainController = new MainController(
&clientMainThreadCaller_,
&networkFactories_,
uiFactory,
- settings_,
+ settingsHierachy_,
systemTrays_[i],
soundPlayer_,
storagesFactory_,
certificateStorageFactory_,
dock_,
notifier_,
uriHandler_,
&idleDetector_,
- options.count("latency-debug") > 0,
- eagleMode);
+ options.count("latency-debug") > 0);
mainControllers_.push_back(mainController);
}
// PlatformAutoUpdaterFactory autoUpdaterFactory;
// if (autoUpdaterFactory.isSupported()) {
// autoUpdater_ = autoUpdaterFactory.createAutoUpdater(SWIFT_APPCAST_URL);
// autoUpdater_->checkForUpdates();
// }
}
QtSwift::~QtSwift() {
delete notifier_;
delete autoUpdater_;
foreach (QtUIFactory* factory, uiFactories_) {
delete factory;
}
foreach (MainController* controller, mainControllers_) {
delete controller;
}
- delete settings_;
+ delete settingsHierachy_;
+ delete qtSettings_;
+ delete xmlSettings_;
foreach (QtSystemTray* tray, systemTrays_) {
delete tray;
}
delete tabs_;
delete splitter_;
delete uriHandler_;
delete dock_;
delete soundPlayer_;
delete chatWindowFactory_;
delete certificateStorageFactory_;
delete storagesFactory_;
}
}
diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h
index c808fa0..7a49fa7 100644
--- a/Swift/QtUI/QtSwift.h
+++ b/Swift/QtUI/QtSwift.h
@@ -1,84 +1,88 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/options_description.hpp>
#include <Swiften/TLS/PlatformTLSFactories.h>
#include <Swiften/Network/BoostNetworkFactories.h>
#include <string>
#include "Swiften/Base/Platform.h"
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
#include "QtSettingsProvider.h"
#if defined(SWIFTEN_PLATFORM_MACOSX)
#include "SwifTools/Application/CocoaApplication.h"
#endif
#if defined(SWIFTEN_PLATFORM_WINDOWS)
#include "WindowsNotifier.h"
#endif
#include "SwifTools/Idle/PlatformIdleQuerier.h"
#include "SwifTools/Idle/ActualIdleDetector.h"
-#include <Swift/QtUI/QtUIPreferences.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 QtChatTabs;
class QtChatWindowFactory;
class QtSoundPlayer;
class QtMUCSearchWindowFactory;
class QtUserSearchWindowFactory;
class EventLoop;
class URIHandler;
+ class SettingsProviderHierachy;
+ class XMLSettingsProvider;
class QtSwift : public QObject {
Q_OBJECT
public:
QtSwift(const po::variables_map& options);
static po::options_description getOptionsDescription();
~QtSwift();
private:
+ XMLSettingsProvider* loadSettingsFile(const QString& fileName);
+ private:
QtEventLoop clientMainThreadCaller_;
PlatformTLSFactories tlsFactories_;
BoostNetworkFactories networkFactories_;
QtChatWindowFactory* chatWindowFactory_;
std::vector<MainController*> mainControllers_;
std::vector<QtSystemTray*> systemTrays_;
std::vector<QtUIFactory*> uiFactories_;
- QtSettingsProvider *settings_;
+ QtSettingsProvider* qtSettings_;
+ XMLSettingsProvider* xmlSettings_;
+ SettingsProviderHierachy* settingsHierachy_;
QSplitter* splitter_;
QtSoundPlayer* soundPlayer_;
Dock* dock_;
URIHandler* uriHandler_;
QtChatTabs* tabs_;
ApplicationPathProvider* applicationPathProvider_;
StoragesFactory* storagesFactory_;
CertificateStorageFactory* certificateStorageFactory_;
AutoUpdater* autoUpdater_;
Notifier* notifier_;
PlatformIdleQuerier idleQuerier_;
ActualIdleDetector idleDetector_;
- QtUIPreferences uiPreferences_;
#if defined(SWIFTEN_PLATFORM_MACOSX)
CocoaApplication cocoaApplication_;
#endif
};
}
diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp
index 88da781..c686442 100644
--- a/Swift/QtUI/QtUIFactory.cpp
+++ b/Swift/QtUI/QtUIFactory.cpp
@@ -1,141 +1,141 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2012 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtUIFactory.h"
#include <QSplitter>
#include "QtXMLConsoleWidget.h"
#include "QtChatTabs.h"
#include "QtMainWindow.h"
#include "QtLoginWindow.h"
#include "QtSystemTray.h"
#include "QtSettingsProvider.h"
#include "QtMainWindow.h"
#include "QtChatWindow.h"
#include "QtJoinMUCWindow.h"
#include "QtChatWindowFactory.h"
#include "QtSwiftUtil.h"
#include "MUCSearch/QtMUCSearchWindow.h"
#include "UserSearch/QtUserSearchWindow.h"
#include "QtProfileWindow.h"
#include "QtContactEditWindow.h"
#include "QtAdHocCommandWindow.h"
#include "QtFileTransferListWidget.h"
-
-#define CHATWINDOW_FONT_SIZE "chatWindowFontSize"
+#include <Swift/Controllers/Settings/SettingsProviderHierachy.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
namespace Swift {
-QtUIFactory::QtUIFactory(QtSettingsProvider* settings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized, bool eagleMode, QtUIPreferences* uiPreferences) : settings(settings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), lastMainWindow(NULL), loginWindow(NULL), startMinimized(startMinimized), eagleMode(eagleMode), uiPreferences(uiPreferences) {
- chatFontSize = settings->getIntSetting(CHATWINDOW_FONT_SIZE, 0);
+QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized) : settings(settings), qtOnlySettings(qtOnlySettings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), lastMainWindow(NULL), loginWindow(NULL), startMinimized(startMinimized) {
+ chatFontSize = settings->getSetting(QtUISettingConstants::CHATWINDOW_FONT_SIZE);
}
XMLConsoleWidget* QtUIFactory::createXMLConsoleWidget() {
QtXMLConsoleWidget* widget = new QtXMLConsoleWidget();
tabs->addTab(widget);
if (!tabs->isVisible()) {
tabs->show();
}
widget->show();
return widget;
}
FileTransferListWidget* QtUIFactory::createFileTransferListWidget() {
QtFileTransferListWidget* widget = new QtFileTransferListWidget();
tabs->addTab(widget);
if (!tabs->isVisible()) {
tabs->show();
}
widget->show();
return widget;
}
MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) {
- lastMainWindow = new QtMainWindow(settings, eventStream, uiPreferences, loginWindow->getMenus());
+ lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus());
return lastMainWindow;
}
LoginWindow* QtUIFactory::createLoginWindow(UIEventStream* eventStream) {
- loginWindow = new QtLoginWindow(eventStream, eagleMode);
+ loginWindow = new QtLoginWindow(eventStream, settings);
if (netbookSplitter) {
netbookSplitter->insertWidget(0, loginWindow);
}
connect(systemTray, SIGNAL(clicked()), loginWindow, SLOT(bringToFront()));
#ifndef SWIFT_MOBILE
- QVariant loginWindowGeometryVariant = settings->getQSettings()->value("loginWindowGeometry");
+ 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() {
- settings->getQSettings()->setValue("loginWindowGeometry", loginWindow->saveGeometry());
+ 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();
}
ChatWindow* QtUIFactory::createChatWindow(const JID& contact, UIEventStream* eventStream) {
QtChatWindow* window = dynamic_cast<QtChatWindow*>(chatWindowFactory->createChatWindow(contact, eventStream));
chatWindows.push_back(window);
std::vector<QPointer<QtChatWindow> > deletions;
foreach (QPointer<QtChatWindow> existingWindow, chatWindows) {
if (existingWindow.isNull()) {
deletions.push_back(existingWindow);
} else {
connect(window, SIGNAL(fontResized(int)), existingWindow, SLOT(handleFontResized(int)));
connect(existingWindow, SIGNAL(fontResized(int)), window, SLOT(handleFontResized(int)));
}
}
foreach (QPointer<QtChatWindow> deletedWindow, deletions) {
chatWindows.erase(std::remove(chatWindows.begin(), chatWindows.end(), deletedWindow), chatWindows.end());
}
connect(window, SIGNAL(fontResized(int)), this, SLOT(handleChatWindowFontResized(int)));
window->handleFontResized(chatFontSize);
return window;
}
void QtUIFactory::handleChatWindowFontResized(int size) {
chatFontSize = size;
- settings->storeInt(CHATWINDOW_FONT_SIZE, size);
+ settings->storeSetting(QtUISettingConstants::CHATWINDOW_FONT_SIZE, size);
}
UserSearchWindow* QtUIFactory::createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream, const std::set<std::string>& groups) {
return new QtUserSearchWindow(eventStream, type, groups);
};
JoinMUCWindow* QtUIFactory::createJoinMUCWindow(UIEventStream* uiEventStream) {
return new QtJoinMUCWindow(uiEventStream);
}
ProfileWindow* QtUIFactory::createProfileWindow() {
return new QtProfileWindow();
}
ContactEditWindow* QtUIFactory::createContactEditWindow() {
return new QtContactEditWindow();
}
void QtUIFactory::createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command) {
new QtAdHocCommandWindow(command);
}
}
diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h
index db33365..c9e2f2e 100644
--- a/Swift/QtUI/QtUIFactory.h
+++ b/Swift/QtUI/QtUIFactory.h
@@ -1,64 +1,63 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2012 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QObject>
#include <QPointer>
#include <Swift/Controllers/UIInterfaces/UIFactory.h>
-#include <Swift/QtUI/QtUIPreferences.h>
class QSplitter;
namespace Swift {
class QtSettingsProvider;
+ class SettingsProviderHierachy;
class QtChatTabs;
class QtSystemTray;
class QtLoginWindow;
class QtMainWindow;
class QtChatTheme;
class QtChatWindowFactory;
class QtChatWindow;
class QtUIFactory : public QObject, public UIFactory {
Q_OBJECT
public:
- QtUIFactory(QtSettingsProvider* settings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized, bool eagleMode, QtUIPreferences* uiPreferences);
+ QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized);
virtual XMLConsoleWidget* createXMLConsoleWidget();
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 void createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command);
private slots:
void handleLoginWindowGeometryChanged();
void handleChatWindowFontResized(int);
private:
- QtSettingsProvider* settings;
+ SettingsProviderHierachy* settings;
+ QtSettingsProvider* qtOnlySettings;
QtChatTabs* tabs;
QSplitter* netbookSplitter;
QtSystemTray* systemTray;
QtChatWindowFactory* chatWindowFactory;
QtMainWindow* lastMainWindow;
QtLoginWindow* loginWindow;
std::vector<QPointer<QtChatWindow> > chatWindows;
bool startMinimized;
int chatFontSize;
- bool eagleMode;
- QtUIPreferences* uiPreferences;
};
}
diff --git a/Swift/QtUI/QtUIPreferences.cpp b/Swift/QtUI/QtUIPreferences.cpp
deleted file mode 100644
index 6662e71..0000000
--- a/Swift/QtUI/QtUIPreferences.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2011 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swift/QtUI/QtUIPreferences.h>
-
-namespace Swift {
-QtUIPreferences::QtUIPreferences() : compactRosters_(false) {
-
-}
-
-QtUIPreferences::~QtUIPreferences() {
-
-}
-
-void QtUIPreferences::setCompactRosters(bool compact) {
- compactRosters_ = compact;
- emit onCompactRostersChanged(compact);
-}
-
-bool QtUIPreferences::getCompactRosters() {
- return compactRosters_;
-}
-
-}
diff --git a/Swift/QtUI/QtUIPreferences.h b/Swift/QtUI/QtUIPreferences.h
deleted file mode 100644
index e537e80..0000000
--- a/Swift/QtUI/QtUIPreferences.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2011 Kevin Smith
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <QObject>
-
-namespace Swift {
- class QtUIPreferences : public QObject {
- Q_OBJECT
- public:
- QtUIPreferences();
- ~QtUIPreferences();
- bool getCompactRosters();
- public slots:
- void setCompactRosters(bool compact);
- signals:
- void onCompactRostersChanged(bool /*now*/);
- private:
- bool compactRosters_;
- };
-} \ No newline at end of file
diff --git a/Swift/QtUI/QtUISettingConstants.cpp b/Swift/QtUI/QtUISettingConstants.cpp
new file mode 100644
index 0000000..046ccc1
--- /dev/null
+++ b/Swift/QtUI/QtUISettingConstants.cpp
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swift/QtUI/QtUISettingConstants.h>
+
+namespace Swift {
+
+const SettingsProvider::Setting<bool> QtUISettingConstants::COMPACT_ROSTER("compactRoster", false);
+const SettingsProvider::Setting<std::string> QtUISettingConstants::CLICKTHROUGH_BANNER("clickthroughBanner", "");
+const SettingsProvider::Setting<int> QtUISettingConstants::CURRENT_ROSTER_TAB("currentRosterTab", 0);
+const SettingsProvider::Setting<bool> QtUISettingConstants::SHOW_NICK_IN_ROSTER_HEADER("showNickInRosterHeader", true);
+const SettingsProvider::Setting<int> QtUISettingConstants::CHATWINDOW_FONT_SIZE("chatWindowFontSize", 0);
+}
diff --git a/Swift/QtUI/QtUISettingConstants.h b/Swift/QtUI/QtUISettingConstants.h
new file mode 100644
index 0000000..82f98bb
--- /dev/null
+++ b/Swift/QtUI/QtUISettingConstants.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+
+namespace Swift {
+ class QtUISettingConstants {
+ public:
+ static const SettingsProvider::Setting<bool> COMPACT_ROSTER;
+ static const SettingsProvider::Setting<std::string> CLICKTHROUGH_BANNER;
+ static const SettingsProvider::Setting<int> CURRENT_ROSTER_TAB;
+ static const SettingsProvider::Setting<bool> SHOW_NICK_IN_ROSTER_HEADER;
+ static const SettingsProvider::Setting<int> CHATWINDOW_FONT_SIZE;
+ };
+}
diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.cpp b/Swift/QtUI/Roster/QtOccupantListWidget.cpp
index f864919..0b3722c 100644
--- a/Swift/QtUI/Roster/QtOccupantListWidget.cpp
+++ b/Swift/QtUI/Roster/QtOccupantListWidget.cpp
@@ -1,57 +1,57 @@
/*
- * Copyright (c) 2011 Kevin Smith
+ * Copyright (c) 2011-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Roster/QtOccupantListWidget.h"
#include <QContextMenuEvent>
#include <QMenu>
#include <QAction>
#include <QInputDialog>
#include "Swift/Controllers/Roster/ContactRosterItem.h"
#include "Swift/Controllers/Roster/GroupRosterItem.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "QtSwiftUtil.h"
namespace Swift {
-QtOccupantListWidget::QtOccupantListWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QtTreeWidget(eventStream, uiPreferences, parent) {
+QtOccupantListWidget::QtOccupantListWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent) : QtTreeWidget(eventStream, settings, parent) {
}
QtOccupantListWidget::~QtOccupantListWidget() {
}
void QtOccupantListWidget::setAvailableOccupantActions(const std::vector<ChatWindow::OccupantAction>& actions) {
availableOccupantActions_ = actions;
}
void QtOccupantListWidget::contextMenuEvent(QContextMenuEvent* event) {
QModelIndex index = indexAt(event->pos());
if (!index.isValid()) {
return;
}
RosterItem* item = static_cast<RosterItem*>(index.internalPointer());
ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item);
if (contact) {
onSomethingSelectedChanged(contact);
QMenu contextMenu;
if (availableOccupantActions_.empty()) {
QAction* noAction = contextMenu.addAction(tr("No actions for this user"));
noAction->setEnabled(false);
contextMenu.exec(event->globalPos());
}
else {
std::map<QAction*, ChatWindow::OccupantAction> actions;
foreach (ChatWindow::OccupantAction availableAction, availableOccupantActions_) {
QString text = "Error: missing string";
switch (availableAction) {
case ChatWindow::Kick: text = tr("Kick user"); break;
case ChatWindow::Ban: text = tr("Kick and ban user"); break;
case ChatWindow::MakeModerator: text = tr("Make moderator"); break;
diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.h b/Swift/QtUI/Roster/QtOccupantListWidget.h
index da7c463..729115a 100644
--- a/Swift/QtUI/Roster/QtOccupantListWidget.h
+++ b/Swift/QtUI/Roster/QtOccupantListWidget.h
@@ -1,31 +1,31 @@
/*
- * Copyright (c) 2011 Kevin Smith
+ * Copyright (c) 2011-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swift/QtUI/Roster/QtTreeWidget.h"
#include "Swiften/Base/boost_bsignals.h"
#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
namespace Swift {
-class QtUIPreferences;
+class SettingsProvider;
class QtOccupantListWidget : public QtTreeWidget {
Q_OBJECT
public:
- QtOccupantListWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent = 0);
+ QtOccupantListWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent = 0);
virtual ~QtOccupantListWidget();
void setAvailableOccupantActions(const std::vector<ChatWindow::OccupantAction>& actions);
boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected;
protected:
void contextMenuEvent(QContextMenuEvent* event);
private:
std::vector<ChatWindow::OccupantAction> availableOccupantActions_;
};
}
diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp
index ac4b500..e3fee24 100644
--- a/Swift/QtUI/Roster/QtRosterWidget.cpp
+++ b/Swift/QtUI/Roster/QtRosterWidget.cpp
@@ -1,61 +1,61 @@
/*
* Copyright (c) 2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Roster/QtRosterWidget.h"
#include <QContextMenuEvent>
#include <QMenu>
#include <QInputDialog>
#include <QFileDialog>
#include "Swift/Controllers/UIEvents/RequestContactEditorUIEvent.h"
#include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h"
#include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h"
#include "Swift/Controllers/UIEvents/SendFileUIEvent.h"
#include "QtContactEditWindow.h"
#include "Swift/Controllers/Roster/ContactRosterItem.h"
#include "Swift/Controllers/Roster/GroupRosterItem.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "QtSwiftUtil.h"
namespace Swift {
-QtRosterWidget::QtRosterWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QtTreeWidget(eventStream, uiPreferences, parent) {
+QtRosterWidget::QtRosterWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent) : QtTreeWidget(eventStream, settings, parent) {
}
QtRosterWidget::~QtRosterWidget() {
}
void QtRosterWidget::handleEditUserActionTriggered(bool /*checked*/) {
QModelIndexList selectedIndexList = getSelectedIndexes();
if (selectedIndexList.empty()) {
return;
}
QModelIndex index = selectedIndexList[0];
if (!index.isValid()) {
return;
}
RosterItem* item = static_cast<RosterItem*>(index.internalPointer());
if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
eventStream_->send(boost::make_shared<RequestContactEditorUIEvent>(contact->getJID()));
}
}
void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
QModelIndex index = indexAt(event->pos());
if (!index.isValid()) {
return;
}
RosterItem* item = static_cast<RosterItem*>(index.internalPointer());
QMenu contextMenu;
if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
QAction* editContact = contextMenu.addAction(tr("Edit"));
QAction* removeContact = contextMenu.addAction(tr("Remove"));
#ifdef SWIFT_EXPERIMENTAL_FT
QAction* sendFile = NULL;
if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) {
diff --git a/Swift/QtUI/Roster/QtRosterWidget.h b/Swift/QtUI/Roster/QtRosterWidget.h
index 01f4726..549fe92 100644
--- a/Swift/QtUI/Roster/QtRosterWidget.h
+++ b/Swift/QtUI/Roster/QtRosterWidget.h
@@ -1,27 +1,27 @@
/*
* Copyright (c) 2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swift/QtUI/Roster/QtTreeWidget.h"
namespace Swift {
class QtUIPreferences;
class QtRosterWidget : public QtTreeWidget {
Q_OBJECT
public:
- QtRosterWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent = 0);
+ QtRosterWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent = 0);
virtual ~QtRosterWidget();
public slots:
void handleEditUserActionTriggered(bool checked);
protected:
void contextMenuEvent(QContextMenuEvent* event);
private:
void renameGroup(GroupRosterItem* group);
};
}
diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp
index 4382125..5fdf138 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.cpp
+++ b/Swift/QtUI/Roster/QtTreeWidget.cpp
@@ -1,93 +1,99 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Roster/QtTreeWidget.h"
#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/bind.hpp>
#include <QUrl>
#include <Swiften/Base/Platform.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <QtSwiftUtil.h>
-#include <Swift/QtUI/QtUIPreferences.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/QtUI/QtUISettingConstants.h>
namespace Swift {
-QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent) : QTreeView(parent) {
+QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent) : QTreeView(parent) {
eventStream_ = eventStream;
- uiPreferences_ = uiPreferences;
+ settings_ = settings;
model_ = new RosterModel(this);
setModel(model_);
- delegate_ = new RosterDelegate(this, uiPreferences_->getCompactRosters());
+ delegate_ = new RosterDelegate(this, settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER));
setItemDelegate(delegate_);
setHeaderHidden(true);
#ifdef SWIFT_PLATFORM_MACOSX
setAlternatingRowColors(true);
#endif
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
expandAll();
setAnimated(true);
setIndentation(0);
#ifdef SWIFT_EXPERIMENTAL_FT
setAcceptDrops(true);
#endif
setRootIsDecorated(true);
connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&)));
connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool)));
connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(handleExpanded(const QModelIndex&)));
connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(handleCollapsed(const QModelIndex&)));
connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleClicked(const QModelIndex&)));
- connect(uiPreferences_, SIGNAL(onCompactRostersChanged(bool)), this, SLOT(handleCompactRostersToggled(bool)));
+
+ settings_->onSettingChanged.connect(boost::bind(&QtTreeWidget::handleSettingChanged, this, _1));
}
QtTreeWidget::~QtTreeWidget() {
+ settings_->onSettingChanged.disconnect(boost::bind(&QtTreeWidget::handleSettingChanged, this, _1));
delete model_;
delete delegate_;
}
-void QtTreeWidget::handleCompactRostersToggled(bool compact) {
- delegate_->setCompact(compact);
- repaint();
+void QtTreeWidget::handleSettingChanged(const std::string& setting) {
+ if (setting == QtUISettingConstants::COMPACT_ROSTER.getKey()) {
+ delegate_->setCompact(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER));
+ repaint();
+ }
}
void QtTreeWidget::setRosterModel(Roster* roster) {
roster_ = roster;
model_->setRoster(roster);
expandAll();
}
QtTreeWidgetItem* QtTreeWidget::getRoot() {
return treeRoot_;
}
void QtTreeWidget::handleClicked(const QModelIndex& index) {
GroupRosterItem* item = dynamic_cast<GroupRosterItem*>(static_cast<RosterItem*>(index.internalPointer()));
if (item) {
setExpanded(index, !isExpanded(index));
}
currentChanged(index, QModelIndex());
}
QModelIndexList QtTreeWidget::getSelectedIndexes() const {
// Not using selectedIndexes(), because this seems to cause a crash in Qt (4.7.0) in the
// QModelIndexList destructor.
// This is a workaround posted in http://www.qtcentre.org/threads/16933 (although this case
// was resolved by linking against the debug libs, ours isn't, and we're not alone)
QItemSelection ranges = selectionModel()->selection();
QModelIndexList selectedIndexList;
for (int i = 0; i < ranges.count(); ++i) {
QModelIndex parent = ranges.at(i).parent();
int right = ranges.at(i).model()->columnCount(parent) - 1;
if (ranges.at(i).left() == 0 && ranges.at(i).right() == right) {
for (int r = ranges.at(i).top(); r <= ranges.at(i).bottom(); ++r) {
selectedIndexList.append(ranges.at(i).model()->index(r, 0, parent));
}
}
diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h
index 705c039..7c10a6a 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.h
+++ b/Swift/QtUI/Roster/QtTreeWidget.h
@@ -1,61 +1,61 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2012 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <QTreeView>
#include <QModelIndex>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QDragMoveEvent>
#include "Swift/QtUI/Roster/RosterModel.h"
#include "Swift/QtUI/Roster/RosterDelegate.h"
namespace Swift {
class UIEventStream;
-class QtUIPreferences;
+class SettingsProvider;
class QtTreeWidget : public QTreeView{
Q_OBJECT
public:
- QtTreeWidget(UIEventStream* eventStream, QtUIPreferences* uiPreferences, QWidget* parent = 0);
+ QtTreeWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent = 0);
~QtTreeWidget();
void show();
QtTreeWidgetItem* getRoot();
void setRosterModel(Roster* roster);
Roster* getRoster() {return roster_;}
boost::signal<void (RosterItem*)> onSomethingSelectedChanged;
private slots:
void handleItemActivated(const QModelIndex&);
void handleModelItemExpanded(const QModelIndex&, bool expanded);
void handleExpanded(const QModelIndex&);
void handleCollapsed(const QModelIndex&);
void handleClicked(const QModelIndex&);
- void handleCompactRostersToggled(bool compact);
+ void handleSettingChanged(const std::string& setting);
protected:
void dragEnterEvent(QDragEnterEvent* event);
void dropEvent(QDropEvent* event);
void dragMoveEvent(QDragMoveEvent* event);
protected:
QModelIndexList getSelectedIndexes() const;
private:
void drawBranches(QPainter*, const QRect&, const QModelIndex&) const;
protected slots:
virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous);
protected:
UIEventStream* eventStream_;
private:
RosterModel* model_;
Roster* roster_;
RosterDelegate* delegate_;
QtTreeWidgetItem* treeRoot_;
- QtUIPreferences* uiPreferences_;
+ SettingsProvider* settings_;
};
}
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index 2283001..d37958f 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -40,139 +40,139 @@ if myenv.get("HAVE_SNARL", False) :
myenv.UseFlags(myenv["SNARL_FLAGS"])
myenv.Append(CPPDEFINES = ["HAVE_SNARL"])
myenv.UseFlags(myenv["PLATFORM_FLAGS"])
myenv.Tool("qt4", toolpath = ["#/BuildTools/SCons/Tools"])
myenv.Tool("nsis", toolpath = ["#/BuildTools/SCons/Tools"])
myenv.Tool("wix", toolpath = ["#/BuildTools/SCons/Tools"])
qt4modules = ['QtCore', 'QtGui', 'QtWebKit']
if env["PLATFORM"] == "posix" :
qt4modules += ["QtDBus"]
myenv.EnableQt4Modules(qt4modules, debug = False)
myenv.Append(CPPPATH = ["."])
if env["PLATFORM"] == "win32" :
#myenv["LINKFLAGS"] = ["/SUBSYSTEM:CONSOLE"]
myenv.Append(LINKFLAGS = ["/SUBSYSTEM:WINDOWS"])
myenv.Append(LIBS = "qtmain")
myenv.WriteVal("DefaultTheme.qrc", myenv.Value(generateDefaultTheme(myenv.Dir("#/Swift/resources/themes/Default"))))
sources = [
"main.cpp",
"QtAboutWidget.cpp",
"QtAvatarWidget.cpp",
"QtUIFactory.cpp",
"QtChatWindowFactory.cpp",
"QtChatWindow.cpp",
"QtClickableLabel.cpp",
"QtLoginWindow.cpp",
"QtMainWindow.cpp",
"QtProfileWindow.cpp",
"QtNameWidget.cpp",
"QtSettingsProvider.cpp",
"QtStatusWidget.cpp",
- "QtScaledAvatarCache.cpp",
+ "QtScaledAvatarCache.cpp",
"QtSwift.cpp",
"QtURIHandler.cpp",
"QtChatView.cpp",
"QtChatTheme.cpp",
"QtChatTabs.cpp",
"QtSoundPlayer.cpp",
"QtSystemTray.cpp",
"QtCachedImageScaler.cpp",
"QtTabbable.cpp",
"QtTabWidget.cpp",
"QtTextEdit.cpp",
"QtXMLConsoleWidget.cpp",
"QtFileTransferListWidget.cpp",
"QtFileTransferListItemModel.cpp",
"QtAdHocCommandWindow.cpp",
"QtUtilities.cpp",
"QtBookmarkDetailWindow.cpp",
"QtAddBookmarkWindow.cpp",
"QtEditBookmarkWindow.cpp",
"QtContactEditWindow.cpp",
"QtContactEditWidget.cpp",
"ChatSnippet.cpp",
"MessageSnippet.cpp",
"SystemMessageSnippet.cpp",
"QtElidingLabel.cpp",
"QtFormWidget.cpp",
- "QtFormResultItemModel.cpp",
+ "QtFormResultItemModel.cpp",
"QtLineEdit.cpp",
"QtJoinMUCWindow.cpp",
"Roster/RosterModel.cpp",
"Roster/QtTreeWidget.cpp",
# "Roster/QtTreeWidgetItem.cpp",
"Roster/RosterDelegate.cpp",
"Roster/GroupItemDelegate.cpp",
"Roster/DelegateCommons.cpp",
"Roster/QtRosterWidget.cpp",
"Roster/QtOccupantListWidget.cpp",
"EventViewer/EventModel.cpp",
"EventViewer/EventDelegate.cpp",
"EventViewer/TwoLineDelegate.cpp",
"EventViewer/QtEventWindow.cpp",
"EventViewer/QtEvent.cpp",
"ChatList/QtChatListWindow.cpp",
"ChatList/ChatListModel.cpp",
"ChatList/ChatListDelegate.cpp",
"ChatList/ChatListMUCItem.cpp",
"ChatList/ChatListRecentItem.cpp",
"MUCSearch/QtMUCSearchWindow.cpp",
"MUCSearch/MUCSearchModel.cpp",
"MUCSearch/MUCSearchRoomItem.cpp",
"MUCSearch/MUCSearchEmptyItem.cpp",
"MUCSearch/MUCSearchDelegate.cpp",
"UserSearch/QtUserSearchFirstPage.cpp",
"UserSearch/QtUserSearchFieldsPage.cpp",
"UserSearch/QtUserSearchResultsPage.cpp",
"UserSearch/QtUserSearchDetailsPage.cpp",
"UserSearch/QtUserSearchWindow.cpp",
"UserSearch/UserSearchModel.cpp",
"UserSearch/UserSearchDelegate.cpp",
"QtSubscriptionRequestWindow.cpp",
"QtRosterHeader.cpp",
"QtWebView.cpp",
"qrc_DefaultTheme.cc",
"qrc_Swift.cc",
"QtFileTransferJSBridge.cpp",
"QtMUCConfigurationWindow.cpp",
"QtAffiliationEditor.cpp",
- "QtUIPreferences.cpp"
+ "QtUISettingConstants.cpp"
]
myenv["SWIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift")
if env["PLATFORM"] == "win32" :
res = myenv.RES("#/Swift/resources/Windows/Swift.rc")
# For some reason, SCons isn't picking up the dependency correctly
# Adding it explicitly until i figure out why
myenv.Depends(res, "../Controllers/BuildVersion.h")
sources += [
"WindowsNotifier.cpp",
"#/Swift/resources/Windows/Swift.res"
]
if env["PLATFORM"] == "posix" :
sources += [
"FreeDesktopNotifier.cpp",
"QtDBUSURIHandler.cpp",
]
if env["PLATFORM"] == "darwin" or env["PLATFORM"] == "win32" :
swiftProgram = myenv.Program("Swift", sources)
else :
swiftProgram = myenv.Program("swift", sources)
if env["PLATFORM"] != "darwin" and env["PLATFORM"] != "win32" :
openURIProgram = myenv.Program("swift-open-uri", "swift-open-uri.cpp")
else :
openURIProgram = []
myenv.Uic4("MUCSearch/QtMUCSearchWindow.ui")
myenv.Uic4("UserSearch/QtUserSearchWizard.ui")
myenv.Uic4("UserSearch/QtUserSearchFirstPage.ui")
myenv.Uic4("UserSearch/QtUserSearchFieldsPage.ui")
myenv.Uic4("UserSearch/QtUserSearchResultsPage.ui")