summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2013-06-01 08:26:46 (GMT)
committerKevin Smith <git@kismith.co.uk>2013-08-01 09:22:45 (GMT)
commitdb698bbb6d8c7e878e2cb997e18e572f3646e11d (patch)
tree61aa3ff72c64dd8f309a2fe4b31b5b2d3f22f04b /Swift/Controllers
parentb45602bcd36fb9d2e7a22998434e31014f072d33 (diff)
downloadswift-contrib-db698bbb6d8c7e878e2cb997e18e572f3646e11d.zip
swift-contrib-db698bbb6d8c7e878e2cb997e18e572f3646e11d.tar.bz2
Refactor chat messages so parsing of links/emoticons happens in controllers.
Change-Id: I07256f23ffbb6520f5063bdfbed9111946c46746
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp36
-rw-r--r--Swift/Controllers/Chat/ChatController.h4
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp117
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.h38
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp41
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h11
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp27
-rw-r--r--Swift/Controllers/Chat/MUCController.h15
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp4
-rw-r--r--Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp7
-rw-r--r--Swift/Controllers/HighlightRule.cpp12
-rw-r--r--Swift/Controllers/MainController.cpp124
-rw-r--r--Swift/Controllers/MainController.h40
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h72
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h37
15 files changed, 384 insertions, 201 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index f5c690c..333ae93 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2013 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 <Swift/Controllers/Chat/ChatController.h>
#include <boost/bind.hpp>
@@ -11,5 +11,4 @@
#include <stdio.h>
-#include <Swift/Controllers/Intl.h>
#include <Swiften/Base/format.h>
#include <Swiften/Base/Algorithm.h>
@@ -18,12 +17,19 @@
#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 <Swiften/Base/DateTime.h>
+#include <Swiften/Elements/DeliveryReceipt.h>
+#include <Swiften/Elements/DeliveryReceiptRequest.h>
+#include <Swiften/Elements/Idle.h>
+#include <Swiften/Base/Log.h>
+#include <Swiften/Client/ClientBlockListManager.h>
+
+#include <Swift/Controllers/Intl.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
+#include <Swift/Controllers/XMPPEvents/EventController.h>
+#include <Swift/Controllers/FileTransfer/FileTransferController.h>
+#include <Swift/Controllers/StatusUtil.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
@@ -32,11 +38,7 @@
#include <Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestChangeBlockStateUIEvent.h>
-#include <Swiften/Elements/DeliveryReceipt.h>
-#include <Swiften/Elements/DeliveryReceiptRequest.h>
-#include <Swiften/Elements/Idle.h>
#include <Swift/Controllers/SettingConstants.h>
#include <Swift/Controllers/Highlighter.h>
-#include <Swiften/Base/Log.h>
-#include <Swiften/Client/ClientBlockListManager.h>
+
namespace Swift {
@@ -45,6 +47,6 @@ 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, SettingsProvider* settings, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager)
- : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings), clientBlockListManager_(clientBlockListManager) {
+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, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::map<std::string, std::string>* emoticons)
+ : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager, emoticons), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings), clientBlockListManager_(clientBlockListManager) {
isInMUC_ = isInMUC;
lastWasPresence_ = false;
@@ -78,5 +80,5 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
chatStateNotifier_->setContactIsOnline(theirPresence && theirPresence->getType() == Presence::Available);
startMessage += ".";
- chatWindow_->addSystemMessage(startMessage, ChatWindow::DefaultDirection);
+ chatWindow_->addSystemMessage(parseMessageBody(startMessage), ChatWindow::DefaultDirection);
chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_));
chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_));
@@ -444,7 +446,7 @@ void ChatController::handlePresenceChange(boost::shared_ptr<Presence> newPresenc
if (newStatusChangeString != lastStatusChangeString_) {
if (lastWasPresence_) {
- chatWindow_->replaceLastMessage(newStatusChangeString);
+ chatWindow_->replaceLastMessage(parseMessageBody(newStatusChangeString));
} else {
- chatWindow_->addPresenceMessage(newStatusChangeString, ChatWindow::DefaultDirection);
+ chatWindow_->addPresenceMessage(parseMessageBody(newStatusChangeString), ChatWindow::DefaultDirection);
}
lastStatusChangeString_ = newStatusChangeString;
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 17bfdd0..8863c3e 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -28,5 +28,5 @@ namespace Swift {
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, SettingsProvider* settings, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager);
+ 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, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::map<std::string, std::string>* emoticons);
virtual ~ChatController();
virtual void setToJID(const JID& jid);
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 621fd2d..656133c 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Swift/Controllers/Chat/ChatControllerBase.h"
+#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <sstream>
@@ -17,5 +17,4 @@
#include <boost/algorithm/string.hpp>
-#include <Swift/Controllers/Intl.h>
#include <Swiften/Base/format.h>
#include <Swiften/Base/Path.h>
@@ -26,10 +25,15 @@
#include <Swiften/Elements/MUCUserPayload.h>
#include <Swiften/Base/foreach.h>
-#include <Swift/Controllers/XMPPEvents/EventController.h>
#include <Swiften/Disco/EntityCapsProvider.h>
-#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
-#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h>
#include <Swiften/Avatars/AvatarManager.h>
+#include <Swiften/Base/Regex.h>
+
+#include <SwifTools/Linkify.h>
+
+#include <Swift/Controllers/Intl.h>
+#include <Swift/Controllers/XMPPEvents/EventController.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swift/Controllers/XMPPEvents/MUCInviteEvent.h>
#include <Swift/Controllers/HighlightManager.h>
@@ -38,5 +42,5 @@
namespace Swift {
-ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), timerFactory_(timerFactory), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry) {
+ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::map<std::string, std::string>* emoticons) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), timerFactory_(timerFactory), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry), emoticons_(*emoticons) {
chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream);
chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));
@@ -77,5 +81,5 @@ void ChatControllerBase::handleDayChangeTick() {
dateChangeTimer_->stop();
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
- chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The day is now %1%")) % std::string(boost::posix_time::to_iso_extended_string(now)).substr(0,10)), ChatWindow::DefaultDirection);
+ chatWindow_->addSystemMessage(parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "The day is now %1%")) % std::string(boost::posix_time::to_iso_extended_string(now)).substr(0,10))), ChatWindow::DefaultDirection);
dayTicked();
createDayChangeTimer();
@@ -183,7 +187,7 @@ void ChatControllerBase::activateChatWindow() {
std::string ChatControllerBase::addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, const boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) {
if (boost::starts_with(message, "/me ")) {
- return chatWindow_->addAction(String::getSplittedAtFirst(message, ' ').second, senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
+ return chatWindow_->addAction(parseMessageBody(String::getSplittedAtFirst(message, ' ').second), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
} else {
- return chatWindow_->addMessage(message, senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
+ return chatWindow_->addMessage(parseMessageBody(message), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
}
}
@@ -191,7 +195,7 @@ std::string ChatControllerBase::addMessage(const std::string& message, const std
void ChatControllerBase::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) {
if (boost::starts_with(message, "/me ")) {
- chatWindow_->replaceWithAction(String::getSplittedAtFirst(message, ' ').second, id, time, highlight);
+ chatWindow_->replaceWithAction(parseMessageBody(String::getSplittedAtFirst(message, ' ').second), id, time, highlight);
} else {
- chatWindow_->replaceMessage(message, id, time, highlight);
+ chatWindow_->replaceMessage(parseMessageBody(message), id, time, highlight);
}
}
@@ -215,5 +219,5 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
if (!message->getTo().getResource().empty()) {
std::string errorMessage = str(format(QT_TRANSLATE_NOOP("", "Couldn't send message: %1%")) % getErrorMessage(message->getPayload<ErrorPayload>()));
- chatWindow_->addErrorMessage(errorMessage);
+ chatWindow_->addErrorMessage(parseMessageBody(errorMessage));
}
}
@@ -240,5 +244,5 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
std::ostringstream s;
s << "The following message took " << (now - delayPayloads[i]->getStamp()).total_milliseconds() / 1000.0 << " seconds to be delivered from " << delayPayloads[i]->getFrom()->toString() << ".";
- chatWindow_->addSystemMessage(std::string(s.str()), ChatWindow::DefaultDirection);
+ chatWindow_->addSystemMessage(parseMessageBody(std::string(s.str())), ChatWindow::DefaultDirection);
}
boost::shared_ptr<SecurityLabel> label = message->getPayload<SecurityLabel>();
@@ -346,4 +350,89 @@ void ChatControllerBase::handleMediatedMUCInvitation(Message::ref message) {
}
+typedef std::pair<std::string, std::string> StringPair;
+
+ChatWindow::ChatMessage ChatControllerBase::parseMessageBody(const std::string& body) {
+ ChatWindow::ChatMessage parsedMessage;
+ std::string remaining = body;
+ /* Parse one, URLs */
+ while (!remaining.empty()) {
+ bool found = false;
+ std::pair<std::vector<std::string>, size_t> links = Linkify::splitLink(remaining);
+ remaining = "";
+ for (size_t i = 0; i < links.first.size(); i++) {
+ const std::string& part = links.first[i];
+ if (found) {
+ // Must be on the last part, then
+ remaining = part;
+ }
+ else {
+ if (i == links.second) {
+ found = true;
+ parsedMessage.append(boost::make_shared<ChatWindow::ChatURIMessagePart>(part));
+ }
+ else {
+ parsedMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(part));
+ }
+ }
+ }
+ }
+
+
+
+ std::string regexString;
+ /* Parse two, emoticons */
+ foreach (StringPair emoticon, emoticons_) {
+ /* Construct a regexp that finds an instance of any of the emoticons inside a group */
+ regexString += regexString.empty() ? "(" : "|";
+ regexString += Regex::escape(emoticon.first);
+ }
+ if (!regexString.empty()) {
+ regexString += ")";
+ boost::regex emoticonRegex(regexString);
+
+ ChatWindow::ChatMessage newMessage;
+ foreach (boost::shared_ptr<ChatWindow::ChatMessagePart> part, parsedMessage.getParts()) {
+ boost::shared_ptr<ChatWindow::ChatTextMessagePart> textPart;
+ if ((textPart = boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(part))) {
+ try {
+ boost::match_results<std::string::const_iterator> match;
+ const std::string& text = textPart->text;
+ std::string::const_iterator start = text.begin();
+ while (regex_search(start, text.end(), match, emoticonRegex)) {
+ std::string::const_iterator matchStart = match[0].first;
+ std::string::const_iterator matchEnd = match[0].second;
+ if (start != matchStart) {
+ /* If we're skipping over plain text since the previous emoticon, record it as plain text */
+ newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, matchStart)));
+ }
+ boost::shared_ptr<ChatWindow::ChatEmoticonMessagePart> emoticonPart = boost::make_shared<ChatWindow::ChatEmoticonMessagePart>();
+ std::map<std::string, std::string>::const_iterator emoticonIterator = emoticons_.find(match.str());
+ assert (emoticonIterator != emoticons_.end());
+ const StringPair& emoticon = *emoticonIterator;
+ emoticonPart->imagePath = emoticon.second;
+ emoticonPart->alternativeText = emoticon.first;
+ newMessage.append(emoticonPart);
+ start = matchEnd;
+ }
+ if (start != text.end()) {
+ /* If there's plain text after the last emoticon, record it */
+ newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, text.end())));
+ }
+
+ }
+ catch (std::runtime_error) {
+ /* Basically too expensive to compute the regex results and it gave up, so pass through as text */
+ newMessage.append(part);
+ }
+ }
+ else {
+ newMessage.append(part);
+ }
+ }
+ parsedMessage = newMessage;
+
+ }
+ return parsedMessage;
+}
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index 0199142..3c527ad 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -9,31 +9,33 @@
#include <map>
#include <vector>
+#include <string>
+
#include <boost/shared_ptr.hpp>
-#include "Swiften/Base/boost_bsignals.h"
#include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
-#include "Swiften/Network/Timer.h"
-#include "Swiften/Network/TimerFactory.h"
-#include "Swiften/Elements/Stanza.h"
-#include <string>
-#include "Swiften/Elements/DiscoInfo.h"
-#include "Swift/Controllers/XMPPEvents/MessageEvent.h"
+#include <Swiften/Network/Timer.h>
+#include <Swiften/Network/TimerFactory.h>
+#include <Swiften/Elements/Stanza.h>
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Elements/DiscoInfo.h>
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/SecurityLabelsCatalog.h>
+#include <Swiften/Elements/ErrorPayload.h>
+#include <Swiften/Presence/PresenceOracle.h>
+#include <Swiften/Queries/IQRouter.h>
+#include <Swiften/Base/IDGenerator.h>
+#include <Swiften/MUC/MUCRegistry.h>
+
+#include <Swift/Controllers/XMPPEvents/MessageEvent.h>
#include <Swift/Controllers/XMPPEvents/MUCInviteEvent.h>
-#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/SecurityLabelsCatalog.h"
-#include "Swiften/Elements/ErrorPayload.h"
-#include "Swiften/Presence/PresenceOracle.h"
-#include "Swiften/Queries/IQRouter.h"
-#include "Swiften/Base/IDGenerator.h"
#include <Swift/Controllers/HistoryController.h>
-#include <Swiften/MUC/MUCRegistry.h>
#include <Swift/Controllers/HighlightManager.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
namespace Swift {
class IQRouter;
class StanzaChannel;
- class ChatWindow;
class ChatWindowFactory;
class AvatarManager;
@@ -64,5 +66,5 @@ namespace Swift {
protected:
- ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager);
+ ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::map<std::string, std::string>* emoticons);
/**
@@ -85,4 +87,5 @@ namespace Swift {
virtual JID getBaseJID();
virtual void logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming) = 0;
+ ChatWindow::ChatMessage parseMessageBody(const std::string& body);
private:
@@ -121,4 +124,5 @@ namespace Swift {
MUCRegistry* mucRegistry_;
Highlighter* highlighter_;
+ const std::map<std::string, std::string>& emoticons_;
};
}
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index d6010e9..5dd53c1 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2013 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 <Swift/Controllers/Chat/ChatsManager.h>
#include <boost/bind.hpp>
@@ -12,4 +12,18 @@
#include <Swiften/Base/foreach.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 <Swiften/Avatars/AvatarManager.h>
+#include <Swiften/Elements/MUCInvitationPayload.h>
+#include <Swiften/Roster/XMPPRoster.h>
+#include <Swiften/Client/ClientBlockListManager.h>
+#include <Swiften/Client/StanzaChannel.h>
+
#include <Swift/Controllers/Chat/ChatController.h>
#include <Swift/Controllers/Chat/ChatControllerBase.h>
@@ -26,23 +40,10 @@
#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>
-#include <Swiften/Client/StanzaChannel.h>
#include <Swift/Controllers/WhiteboardManager.h>
-#include <Swiften/Client/ClientBlockListManager.h>
namespace Swift {
@@ -78,5 +79,6 @@ ChatsManager::ChatsManager(
WhiteboardManager* whiteboardManager,
HighlightManager* highlightManager,
- ClientBlockListManager* clientBlockListManager) :
+ ClientBlockListManager* clientBlockListManager,
+ std::map<std::string, std::string>* emoticons) :
jid_(jid),
joinMUCWindowFactory_(joinMUCWindowFactory),
@@ -92,5 +94,6 @@ ChatsManager::ChatsManager(
whiteboardManager_(whiteboardManager),
highlightManager_(highlightManager),
- clientBlockListManager_(clientBlockListManager) {
+ clientBlockListManager_(clientBlockListManager),
+ emoticons_(emoticons) {
timerFactory_ = timerFactory;
eventController_ = eventController;
@@ -527,5 +530,5 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &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_, settings_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_);
+ ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, emoticons_);
chatControllers_[contact] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
@@ -600,5 +603,5 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional
muc->setCreateAsReservedIfNew();
}
- MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_, highlightManager_);
+ MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_, highlightManager_, emoticons_);
mucControllers_[mucJID] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 4d7e9a8..4d1266f 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -8,8 +8,8 @@
#include <map>
+#include <string>
#include <boost/shared_ptr.hpp>
-#include <string>
#include <Swiften/Elements/DiscoInfo.h>
#include <Swiften/Elements/Message.h>
@@ -17,8 +17,10 @@
#include <Swiften/JID/JID.h>
#include <Swiften/MUC/MUCRegistry.h>
+#include <Swiften/MUC/MUCBookmark.h>
+
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIInterfaces/ChatListWindow.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
-#include <Swiften/MUC/MUCBookmark.h>
+
namespace Swift {
@@ -56,5 +58,5 @@ namespace Swift {
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* profileSettings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager);
+ 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* profileSettings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::map<std::string, std::string>* emoticons);
virtual ~ChatsManager();
void setAvatarManager(AvatarManager* avatarManager);
@@ -141,4 +143,5 @@ namespace Swift {
HighlightManager* highlightManager_;
ClientBlockListManager* clientBlockListManager_;
+ std::map<std::string, std::string>* emoticons_;
};
}
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 6bf3e5f..0033297 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -65,6 +65,7 @@ MUCController::MUCController (
HistoryController* historyController,
MUCRegistry* mucRegistry,
- HighlightManager* highlightManager) :
- ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager), muc_(muc), nick_(nick), desiredNick_(nick), password_(password), renameCounter_(0) {
+ HighlightManager* highlightManager,
+ std::map<std::string, std::string>* emoticons) :
+ ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager, emoticons), muc_(muc), nick_(nick), desiredNick_(nick), password_(password), renameCounter_(0) {
parting_ = true;
joined_ = false;
@@ -227,5 +228,5 @@ const std::string& MUCController::getNick() {
void MUCController::handleJoinTimeoutTick() {
receivedActivity();
- chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString()), ChatWindow::DefaultDirection);
+ chatWindow_->addSystemMessage(parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString())), ChatWindow::DefaultDirection);
}
@@ -278,5 +279,5 @@ void MUCController::handleJoinFailed(boost::shared_ptr<ErrorPayload> error) {
}
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Couldn't join room: %1%.")) % errorMessage);
- chatWindow_->addErrorMessage(errorMessage);
+ chatWindow_->addErrorMessage(parseMessageBody(errorMessage));
parting_ = true;
if (!rejoinNick.empty() && renameCounter_ < 10) {
@@ -295,5 +296,5 @@ void MUCController::handleJoinComplete(const std::string& nick) {
std::string joinMessage = str(format(QT_TRANSLATE_NOOP("", "You have entered room %1% as %2%.")) % toJID_.toString() % nick);
setNick(nick);
- chatWindow_->addSystemMessage(joinMessage, ChatWindow::DefaultDirection);
+ chatWindow_->addSystemMessage(parseMessageBody(joinMessage), ChatWindow::DefaultDirection);
#ifdef SWIFT_EXPERIMENTAL_HISTORY
@@ -361,5 +362,5 @@ void MUCController::handleOccupantJoined(const MUCOccupant& occupant) {
void MUCController::addPresenceMessage(const std::string& message) {
lastWasPresence_ = true;
- chatWindow_->addPresenceMessage(message, ChatWindow::DefaultDirection);
+ chatWindow_->addPresenceMessage(parseMessageBody(message), ChatWindow::DefaultDirection);
}
@@ -448,5 +449,5 @@ void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> mes
if (message->hasSubject() && message->getBody().empty()) {
- chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The room subject is now: %1%")) % message->getSubject()), ChatWindow::DefaultDirection);;
+ chatWindow_->addSystemMessage(parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "The room subject is now: %1%")) % message->getSubject())), ChatWindow::DefaultDirection);;
chatWindow_->setSubject(message->getSubject());
doneGettingHistory_ = true;
@@ -485,5 +486,5 @@ void MUCController::handleOccupantRoleChanged(const std::string& nick, const MUC
roster_->addContact(jid, realJID, nick, group, avatarManager_->getAvatarPath(jid));
roster_->getGroup(group)->setManualSort(roleToSortName(occupant.getRole()));
- chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "%1% is now a %2%")) % nick % roleToFriendlyName(occupant.getRole())), ChatWindow::DefaultDirection);
+ chatWindow_->addSystemMessage(parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "%1% is now a %2%")) % nick % roleToFriendlyName(occupant.getRole()))), ChatWindow::DefaultDirection);
if (nick == nick_) {
setAvailableRoomActions(occupant.getAffiliation(), occupant.getRole());
@@ -518,5 +519,5 @@ void MUCController::setOnline(bool online) {
if (shouldJoinOnReconnect_) {
renameCounter_ = 0;
- chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Trying to enter room %1%")) % toJID_.toString()), ChatWindow::DefaultDirection);
+ chatWindow_->addSystemMessage(parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "Trying to enter room %1%")) % toJID_.toString())), ChatWindow::DefaultDirection);
if (loginCheckTimer_) {
loginCheckTimer_->start();
@@ -616,5 +617,5 @@ boost::optional<boost::posix_time::ptime> MUCController::getMessageTimestamp(boo
void MUCController::updateJoinParts() {
- chatWindow_->replaceLastMessage(generateJoinPartString(joinParts_));
+ chatWindow_->replaceLastMessage(parseMessageBody(generateJoinPartString(joinParts_)));
}
@@ -736,5 +737,5 @@ void MUCController::handleConfigurationFailed(ErrorPayload::ref error) {
std::string errorMessage = getErrorMessage(error);
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Room configuration failed: %1%.")) % errorMessage);
- chatWindow_->addErrorMessage(errorMessage);
+ chatWindow_->addErrorMessage(parseMessageBody(errorMessage));
}
@@ -742,5 +743,5 @@ void MUCController::handleOccupantRoleChangeFailed(ErrorPayload::ref error, cons
std::string errorMessage = getErrorMessage(error);
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Occupant role change failed: %1%.")) % errorMessage);
- chatWindow_->addErrorMessage(errorMessage);
+ chatWindow_->addErrorMessage(parseMessageBody(errorMessage));
}
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 656eadb..57fd9cd 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -7,12 +7,13 @@
#pragma once
+#include <set>
+#include <string>
+#include <map>
+
#include <boost/shared_ptr.hpp>
-#include <Swiften/Base/boost_bsignals.h>
#include <boost/signals/connection.hpp>
-#include <set>
-#include <string>
+#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Network/Timer.h>
-#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/DiscoInfo.h>
@@ -20,4 +21,6 @@
#include <Swiften/MUC/MUC.h>
#include <Swiften/Elements/MUCOccupant.h>
+
+#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <Swift/Controllers/Roster/RosterItem.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
@@ -46,5 +49,5 @@ namespace Swift {
class MUCController : public ChatControllerBase {
public:
- MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager);
+ MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::map<std::string, std::string>* emoticons);
~MUCController();
boost::signal<void ()> onUserLeft;
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index 84a407c..06c1b84 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -112,5 +112,6 @@ public:
mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createChatListWindow).With(uiEventStream_).Return(chatListWindow_);
clientBlockListManager_ = new ClientBlockListManager(iqRouter_);
- 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_, NULL, wbManager_, highlightManager_, clientBlockListManager_);
+ emoticons_ = new std::map<std::string, std::string>();
+ 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_, NULL, wbManager_, highlightManager_, clientBlockListManager_, emoticons_);
manager_->setAvatarManager(avatarManager_);
@@ -489,4 +490,5 @@ private:
HighlightManager* highlightManager_;
ClientBlockListManager* clientBlockListManager_;
+ std::map<std::string, std::string>* emoticons_;
};
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index f1fcf79..287fbd3 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -68,5 +68,6 @@ public:
muc_ = boost::make_shared<MUC>(stanzaChannel_, iqRouter_, directedPresenceSender_, mucJID_, mucRegistry_);
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_->getJID(), uiEventStream_).Return(window_);
- controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL, NULL, mucRegistry_, highlightManager_);
+ emoticons_ = new std::map<std::string, std::string>();
+ controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL, NULL, mucRegistry_, highlightManager_, emoticons_);
}
@@ -87,4 +88,5 @@ public:
delete mucRegistry_;
delete avatarManager_;
+ delete emoticons_;
}
@@ -346,4 +348,5 @@ private:
DummySettingsProvider* settings_;
HighlightManager* highlightManager_;
+ std::map<std::string, std::string>* emoticons_;
};
diff --git a/Swift/Controllers/HighlightRule.cpp b/Swift/Controllers/HighlightRule.cpp
index 28f26cf..9ca7d86 100644
--- a/Swift/Controllers/HighlightRule.cpp
+++ b/Swift/Controllers/HighlightRule.cpp
@@ -10,4 +10,5 @@
#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/Regex.h>
#include <Swift/Controllers/HighlightRule.h>
@@ -25,14 +26,5 @@ HighlightRule::HighlightRule()
boost::regex HighlightRule::regexFromString(const std::string & s) const
{
- // escape regex special characters: ^.$| etc
- // these need to be escaped: [\^\$\|.........]
- // and then C++ requires '\' to be escaped, too....
- static const boost::regex esc("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\{\\}\\\\])");
- // matched character should be prepended with '\'
- // replace matched special character with \\\1
- // and escape once more for C++ rules...
- static const std::string rep("\\\\\\1");
- std::string escaped = boost::regex_replace(s , esc, rep);
-
+ std::string escaped = Regex::escape(s);
std::string word = matchWholeWords_ ? "\\b" : "";
boost::regex::flag_type flags = boost::regex::normal;
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index a661c81..f99e0ad 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -13,10 +13,11 @@
#include <Swift/Controllers/MainController.h>
+#include <stdlib.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>
@@ -24,70 +25,73 @@
#include <Swiften/Base/String.h>
#include <Swiften/StringCodecs/Base64.h>
+#include <Swiften/Network/TimerFactory.h>
+#include <Swiften/Client/Storages.h>
+#include <Swiften/VCards/VCardManager.h>
+#include <Swiften/Client/NickResolver.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 <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/Hexify.h>
+#include <Swiften/Network/NetworkFactories.h>
+#include <Swiften/FileTransfer/FileTransferManager.h>
+#include <Swiften/Client/ClientXMLTracer.h>
+#include <Swiften/Client/StanzaChannel.h>
+#include <Swiften/Client/ClientBlockListManager.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+
+#include <SwifTools/Dock/Dock.h>
+#include <SwifTools/Notifier/TogglableNotifier.h>
+#include <SwifTools/Idle/IdleDetector.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/BuildVersion.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 <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/HistoryController.h>
#include <Swift/Controllers/HistoryViewController.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 "Swift/Controllers/WhiteboardManager.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/Hexify.h"
-#include "Swift/Controllers/UIEvents/RequestChatUIEvent.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/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 <Swift/Controllers/WhiteboardManager.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
+#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
+#include <Swift/Controllers/Storages/CertificateStorageFactory.h>
+#include <Swift/Controllers/Storages/CertificateStorageTrustChecker.h>
#include <Swift/Controllers/ProfileController.h>
#include <Swift/Controllers/ShowProfileController.h>
#include <Swift/Controllers/ContactEditController.h>
#include <Swift/Controllers/XMPPURIController.h>
-#include "Swift/Controllers/AdHocManager.h"
-#include <SwifTools/Idle/IdleDetector.h>
+#include <Swift/Controllers/AdHocManager.h>
#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
-#include <Swiften/FileTransfer/FileTransferManager.h>
-#include <Swiften/Client/ClientXMLTracer.h>
#include <Swift/Controllers/SettingConstants.h>
-#include <Swiften/Client/StanzaChannel.h>
#include <Swift/Controllers/HighlightManager.h>
#include <Swift/Controllers/HighlightEditorController.h>
-#include <Swiften/Client/ClientBlockListManager.h>
#include <Swift/Controllers/BlockListController.h>
-#include <Swiften/Crypto/CryptoProvider.h>
+
namespace Swift {
@@ -110,4 +114,5 @@ MainController::MainController(
URIHandler* uriHandler,
IdleDetector* idleDetector,
+ const std::map<std::string, std::string>& emoticons,
bool useDelayForLatency) :
eventLoop_(eventLoop),
@@ -121,5 +126,6 @@ MainController::MainController(
loginWindow_(NULL) ,
useDelayForLatency_(useDelayForLatency),
- ftOverview_(NULL) {
+ ftOverview_(NULL),
+ emoticons_(emoticons) {
storages_ = NULL;
certificateStorage_ = NULL;
@@ -340,7 +346,7 @@ void MainController::handleConnected() {
historyController_ = new HistoryController(storages_->getHistoryStorage());
historyViewController_ = new HistoryViewController(jid_, uiEventStream_, historyController_, client_->getNickResolver(), client_->getAvatarManager(), client_->getPresenceOracle(), uiFactory_);
- 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_, historyController_, whiteboardManager_, highlightManager_, client_->getClientBlockListManager());
+ 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_, historyController_, whiteboardManager_, highlightManager_, client_->getClientBlockListManager(), &emoticons_);
#else
- 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_, NULL, whiteboardManager_, highlightManager_, client_->getClientBlockListManager());
+ 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_, NULL, whiteboardManager_, highlightManager_, client_->getClientBlockListManager(), &emoticons_);
#endif
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index d60805a..ba132e7 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -1,4 +1,4 @@
/*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
@@ -7,22 +7,26 @@
#pragma once
-#include <Swiften/Base/boost_bsignals.h>
-#include <boost/shared_ptr.hpp>
#include <vector>
-
-#include "Swiften/Network/Timer.h"
+#include <map>
#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"
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Network/Timer.h>
+#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 <Swiften/Elements/CapsInfo.h>
+#include <Swiften/Client/ClientXMLTracer.h>
+
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/Controllers/ProfileSettingsProvider.h>
+#include <Swift/Controllers/XMPPEvents/ErrorEvent.h>
+#include <Swift/Controllers/UIEvents/UIEvent.h>
+
namespace Swift {
@@ -92,4 +96,5 @@ namespace Swift {
URIHandler* uriHandler,
IdleDetector* idleDetector,
+ const std::map<std::string, std::string>& emoticons,
bool useDelayForLatency);
~MainController();
@@ -185,4 +190,5 @@ namespace Swift {
HighlightManager* highlightManager_;
HighlightEditorController* highlightEditorController_;
+ std::map<std::string, std::string> emoticons_;
};
}
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index a845cbe..dce852a 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -7,11 +7,12 @@
#pragma once
+#include <vector>
+#include <string>
+
#include <boost/optional.hpp>
-#include <Swiften/Base/boost_bsignals.h>
#include <boost/shared_ptr.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
-#include <vector>
-#include <string>
+#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Elements/SecurityLabelsCatalog.h>
#include <Swiften/Elements/ChatState.h>
@@ -31,6 +32,55 @@ namespace Swift {
class InviteToChatWindow;
+
class ChatWindow {
public:
+ class ChatMessagePart {
+ public:
+ virtual ~ChatMessagePart() {}
+ };
+
+ class ChatMessage {
+ public:
+ ChatMessage() {}
+ ChatMessage(const std::string& text) {
+ append(boost::make_shared<ChatTextMessagePart>(text));
+ }
+ void append(const boost::shared_ptr<ChatMessagePart>& part) {
+ parts_.push_back(part);
+ }
+
+ const std::vector<boost::shared_ptr<ChatMessagePart> >& getParts() const {
+ return parts_;
+ }
+ private:
+ std::vector<boost::shared_ptr<ChatMessagePart> > parts_;
+ };
+
+ class ChatTextMessagePart : public ChatMessagePart {
+ public:
+ ChatTextMessagePart(const std::string& text) : text(text) {}
+ std::string text;
+ };
+
+ class ChatURIMessagePart : public ChatMessagePart {
+ public:
+ ChatURIMessagePart(const std::string& target) : target(target) {}
+ std::string target;
+ };
+
+ class ChatEmoticonMessagePart : public ChatMessagePart {
+ public:
+ std::string imagePath;
+ std::string alternativeText;
+ };
+
+ class ChatHighlightingMessagePart : public ChatMessagePart {
+ public:
+ std::string foregroundColor;
+ std::string backgroundColor;
+ std::string text;
+ };
+
+
enum AckState {Pending, Received, Failed};
enum ReceiptState {ReceiptRequested, ReceiptReceived};
@@ -49,16 +99,16 @@ namespace Swift {
* @return id of added message (for acks).
*/
- virtual 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, const HighlightAction& highlight) = 0;
+ virtual std::string addMessage(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
/** Adds action to window.
* @return id of added message (for acks);
*/
- virtual 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, const HighlightAction& highlight) = 0;
+ virtual std::string addAction(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
- virtual void addSystemMessage(const std::string& message, Direction direction) = 0;
- virtual void addPresenceMessage(const std::string& message, Direction direction) = 0;
+ virtual void addSystemMessage(const ChatMessage& message, Direction direction) = 0;
+ virtual void addPresenceMessage(const ChatMessage& message, Direction direction) = 0;
- virtual void addErrorMessage(const std::string& message) = 0;
- virtual void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
- virtual void replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
+ virtual void addErrorMessage(const ChatMessage& message) = 0;
+ virtual void replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
+ virtual void replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
// File transfer related stuff
@@ -89,5 +139,5 @@ namespace Swift {
virtual void setRosterModel(Roster* model) = 0;
virtual void setTabComplete(TabComplete* completer) = 0;
- virtual void replaceLastMessage(const std::string& message) = 0;
+ virtual void replaceLastMessage(const ChatMessage& message) = 0;
virtual void setAckState(const std::string& id, AckState state) = 0;
virtual void flash() = 0;
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index 4eb3bb6..fbfea93 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -7,5 +7,9 @@
#pragma once
-#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
+#include <boost/shared_ptr.hpp>
+
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
+#include <Swiften/Base/foreach.h>
+
namespace Swift {
@@ -15,9 +19,16 @@ namespace Swift {
virtual ~MockChatWindow();
- virtual 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&, const HighlightAction&) {lastMessageBody_ = message; return "";}
- virtual 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&, const HighlightAction&) {lastMessageBody_ = message; return "";}
- virtual void addSystemMessage(const std::string& /*message*/, Direction) {}
- virtual void addErrorMessage(const std::string& /*message*/) {}
- virtual void addPresenceMessage(const std::string& /*message*/, Direction) {}
+ virtual std::string addMessage(const ChatMessage& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {
+ lastMessageBody_ = bodyFromMessage(message); return "id";};
+
+ virtual std::string addAction(const ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {return "id";};
+
+ virtual void addSystemMessage(const ChatMessage& /*message*/, Direction /*direction*/) {};
+ virtual void addPresenceMessage(const ChatMessage& /*message*/, Direction /*direction*/) {};
+
+ virtual void addErrorMessage(const ChatMessage& /*message*/) {};
+ virtual void replaceMessage(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {};
+ virtual void replaceWithAction(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {};
+ virtual void replaceLastMessage(const ChatMessage& /*message*/) {};
// File transfer related stuff
@@ -41,7 +52,5 @@ namespace Swift {
virtual void setRosterModel(Roster* /*roster*/) {}
virtual void setTabComplete(TabComplete*) {}
- virtual void replaceLastMessage(const std::string&) {}
- virtual void replaceMessage(const std::string&, const std::string&, const boost::posix_time::ptime&, const HighlightAction&) {}
- virtual void replaceWithAction(const std::string& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction&) {}
+
void setAckState(const std::string& /*id*/, AckState /*state*/) {}
virtual void flash() {}
@@ -63,4 +72,14 @@ namespace Swift {
virtual void setBlockingState(BlockingState) {}
+ std::string bodyFromMessage(const ChatMessage& message) {
+ boost::shared_ptr<ChatTextMessagePart> text;
+ foreach (boost::shared_ptr<ChatMessagePart> part, message.getParts()) {
+ if ((text = boost::dynamic_pointer_cast<ChatTextMessagePart>(part))) {
+ return text->text;
+ }
+ }
+ return "";
+ }
+
std::string name_;
std::string lastMessageBody_;