summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/Controllers/Chat')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp15
-rw-r--r--Swift/Controllers/Chat/ChatController.h5
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp39
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.h22
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp10
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h4
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp41
-rw-r--r--Swift/Controllers/Chat/MUCController.h8
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp7
-rw-r--r--Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp11
-rw-r--r--Swift/Controllers/Chat/UnitTest/MockChatListWindow.h8
11 files changed, 114 insertions, 56 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 16b22fe..0ffef0c 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -32,7 +32,7 @@
#include <Swiften/Elements/DeliveryReceipt.h>
#include <Swiften/Elements/DeliveryReceiptRequest.h>
#include <Swift/Controllers/SettingConstants.h>
-
+#include <Swift/Controllers/Highlighter.h>
#include <Swiften/Base/Log.h>
namespace Swift {
@@ -40,8 +40,8 @@ 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)
- : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings) {
+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)
+ : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager), eventStream_(eventStream), userWantsReceipts_(userWantsReceipts), settings_(settings) {
isInMUC_ = isInMUC;
lastWasPresence_ = false;
chatStateNotifier_ = new ChatStateNotifier(stanzaChannel, contact, entityCapsProvider);
@@ -174,8 +174,11 @@ void ChatController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> me
}
}
-void ChatController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) {
+void ChatController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const HighlightAction& highlight) {
eventController_->handleIncomingEvent(messageEvent);
+ if (!messageEvent->getConcluded()) {
+ highlighter_->handleHighlightAction(highlight);
+ }
}
@@ -211,9 +214,9 @@ void ChatController::postSendMessage(const std::string& body, boost::shared_ptr<
boost::shared_ptr<Replace> replace = sentStanza->getPayload<Replace>();
if (replace) {
eraseIf(unackedStanzas_, PairSecondEquals<boost::shared_ptr<Stanza>, std::string>(myLastMessageUIID_));
- replaceMessage(body, myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time());
+ replaceMessage(body, myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time(), HighlightAction());
} 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());
+ 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(), HighlightAction());
}
if (stanzaChannel_->getStreamManagementEnabled() && !myLastMessageUIID_.empty() ) {
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 66ec37d..6021ec1 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -22,10 +22,11 @@ namespace Swift {
class FileTransferController;
class SettingsProvider;
class HistoryController;
+ class HighlightManager;
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);
+ 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);
virtual ~ChatController();
virtual void setToJID(const JID& jid);
virtual void setOnline(bool online);
@@ -45,7 +46,7 @@ namespace Swift {
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 postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const HighlightAction&);
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;
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 50709f7..ad7f76a 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -13,6 +13,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/numeric/conversion/cast.hpp>
#include <boost/algorithm/string.hpp>
#include <Swift/Controllers/Intl.h>
@@ -30,15 +31,18 @@
#include <Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h>
#include <Swiften/Avatars/AvatarManager.h>
#include <Swift/Controllers/XMPPEvents/MUCInviteEvent.h>
+#include <Swift/Controllers/HighlightManager.h>
+#include <Swift/Controllers/Highlighter.h>
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) : 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) : 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) {
chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream);
chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));
chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2));
chatWindow_->onLogCleared.connect(boost::bind(&ChatControllerBase::handleLogCleared, this));
entityCapsProvider_->onCapsChanged.connect(boost::bind(&ChatControllerBase::handleCapsChanged, this, _1));
+ highlighter_ = highlightManager->createHighlighter();
setOnline(stanzaChannel->isAvailable() && iqRouter->isAvailable());
createDayChangeTimer();
}
@@ -62,7 +66,7 @@ void ChatControllerBase::createDayChangeTimer() {
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
boost::posix_time::ptime midnight(now.date() + boost::gregorian::days(1));
long millisecondsUntilMidnight = (midnight - now).total_milliseconds();
- dateChangeTimer_ = boost::shared_ptr<Timer>(timerFactory_->createTimer(millisecondsUntilMidnight));
+ dateChangeTimer_ = boost::shared_ptr<Timer>(timerFactory_->createTimer(boost::numeric_cast<int>(millisecondsUntilMidnight)));
dateChangeTimer_->onTick.connect(boost::bind(&ChatControllerBase::handleDayChangeTick, this));
dateChangeTimer_->start();
}
@@ -112,7 +116,7 @@ void ChatControllerBase::handleAllMessagesRead() {
}
int ChatControllerBase::getUnreadCount() {
- return targetedUnreadMessages_.size();
+ return boost::numeric_cast<int>(targetedUnreadMessages_.size());
}
void ChatControllerBase::handleSendMessageRequest(const std::string &body, bool isCorrectionMessage) {
@@ -175,19 +179,19 @@ void ChatControllerBase::activateChatWindow() {
chatWindow_->activate();
}
-std::string ChatControllerBase::addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, const boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) {
+std::string ChatControllerBase::addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, const boost::shared_ptr<SecurityLabel> label, const std::string& 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, avatarPath, time);
+ return chatWindow_->addAction(String::getSplittedAtFirst(message, ' ').second, senderName, senderIsSelf, label, avatarPath, time, highlight);
} else {
- return chatWindow_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time);
+ return chatWindow_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time, highlight);
}
}
-void ChatControllerBase::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) {
+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);
+ chatWindow_->replaceWithAction(String::getSplittedAtFirst(message, ' ').second, id, time, highlight);
} else {
- chatWindow_->replaceMessage(message, id, time);
+ chatWindow_->replaceMessage(message, id, time, highlight);
}
}
@@ -205,6 +209,7 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
}
boost::shared_ptr<Message> message = messageEvent->getStanza();
std::string body = message->getBody();
+ HighlightAction highlight;
if (message->isError()) {
std::string errorMessage = str(format(QT_TRANSLATE_NOOP("", "Couldn't send message: %1%")) % getErrorMessage(message->getPayload<ErrorPayload>()));
chatWindow_->addErrorMessage(errorMessage);
@@ -243,6 +248,11 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
}
onActivity(body);
+ // Highlight
+ if (!isIncomingMessageFromMe(message)) {
+ highlight = highlighter_->findAction(body, senderDisplayNameFromMessage(from));
+ }
+
boost::shared_ptr<Replace> replace = message->getPayload<Replace>();
if (replace) {
std::string body = message->getBody();
@@ -250,19 +260,19 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
std::map<JID, std::string>::iterator lastMessage;
lastMessage = lastMessagesUIID_.find(from);
if (lastMessage != lastMessagesUIID_.end()) {
- replaceMessage(body, lastMessagesUIID_[from], timeStamp);
+ replaceMessage(body, lastMessagesUIID_[from], timeStamp, highlight);
}
}
else {
- lastMessagesUIID_[from] = addMessage(body, senderDisplayNameFromMessage(from), isIncomingMessageFromMe(message), label, std::string(avatarManager_->getAvatarPath(from).string()), timeStamp);
+ lastMessagesUIID_[from] = addMessage(body, senderDisplayNameFromMessage(from), isIncomingMessageFromMe(message), label, std::string(avatarManager_->getAvatarPath(from).string()), timeStamp, highlight);
}
logMessage(body, from, selfJID_, timeStamp, true);
}
chatWindow_->show();
- chatWindow_->setUnreadMessageCount(unreadMessages_.size());
+ chatWindow_->setUnreadMessageCount(boost::numeric_cast<int>(unreadMessages_.size()));
onUnreadCountChanged();
- postHandleIncomingMessage(messageEvent);
+ postHandleIncomingMessage(messageEvent, highlight);
}
std::string ChatControllerBase::getErrorMessage(boost::shared_ptr<ErrorPayload> error) {
@@ -296,13 +306,14 @@ std::string ChatControllerBase::getErrorMessage(boost::shared_ptr<ErrorPayload>
case ErrorPayload::UnexpectedRequest: return QT_TRANSLATE_NOOP("", "Unexpected request");
}
}
+ assert(false);
return defaultMessage;
}
void ChatControllerBase::handleGeneralMUCInvitation(MUCInviteEvent::ref event) {
unreadMessages_.push_back(event);
chatWindow_->show();
- chatWindow_->setUnreadMessageCount(unreadMessages_.size());
+ chatWindow_->setUnreadMessageCount(boost::numeric_cast<int>(unreadMessages_.size()));
onUnreadCountChanged();
chatWindow_->addMUCInvitation(senderDisplayNameFromMessage(event->getInviter()), event->getRoomJID(), event->getReason(), event->getPassword(), event->getDirect());
eventController_->handleIncomingEvent(event);
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index b26af02..baef9e6 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -29,6 +29,7 @@
#include "Swiften/Base/IDGenerator.h"
#include <Swift/Controllers/HistoryController.h>
#include <Swiften/MUC/MUCRegistry.h>
+#include <Swift/Controllers/HighlightManager.h>
namespace Swift {
class IQRouter;
@@ -39,6 +40,8 @@ namespace Swift {
class UIEventStream;
class EventController;
class EntityCapsProvider;
+ class HighlightManager;
+ class Highlighter;
class ChatControllerBase : public boost::bsignals::trackable {
public:
@@ -47,11 +50,11 @@ namespace Swift {
void activateChatWindow();
void setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info);
void handleIncomingMessage(boost::shared_ptr<MessageEvent> message);
- 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);
- void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time);
+ 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);
+ void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight);
virtual void setOnline(bool online);
virtual void setEnabled(bool enabled);
- virtual void setToJID(const JID& jid) {toJID_ = jid;};
+ virtual void setToJID(const JID& jid) {toJID_ = jid;}
/** Used for determining when something is recent.*/
boost::signal<void (const std::string& /*activity*/)> onActivity;
boost::signal<void ()> onUnreadCountChanged;
@@ -60,20 +63,20 @@ namespace Swift {
void handleCapsChanged(const JID& jid);
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);
+ 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);
/**
* Pass the Message appended, and the stanza used to send it.
*/
- virtual void postSendMessage(const std::string&, boost::shared_ptr<Stanza>) {};
+ virtual void postSendMessage(const std::string&, boost::shared_ptr<Stanza>) {}
virtual std::string senderDisplayNameFromMessage(const JID& from) = 0;
virtual bool isIncomingMessageFromMe(boost::shared_ptr<Message>) = 0;
- virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {};
- virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {};
- virtual void preSendMessageRequest(boost::shared_ptr<Message>) {};
+ virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {}
+ virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>, const HighlightAction&) {}
+ virtual void preSendMessageRequest(boost::shared_ptr<Message>) {}
virtual bool isFromContact(const JID& from);
virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message>) const = 0;
- virtual void dayTicked() {};
+ virtual void dayTicked() {}
virtual void handleBareJIDCapsChanged(const JID& jid) = 0;
std::string getErrorMessage(boost::shared_ptr<ErrorPayload>);
virtual void setContactIsReceivingPresence(bool /* isReceivingPresence */) {}
@@ -116,5 +119,6 @@ namespace Swift {
SecurityLabelsCatalog::Item lastLabel_;
HistoryController* historyController_;
MUCRegistry* mucRegistry_;
+ Highlighter* highlighter_;
};
}
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 1e0e9c2..dba8565 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -74,7 +74,8 @@ ChatsManager::ChatsManager(
bool eagleMode,
SettingsProvider* settings,
HistoryController* historyController,
- WhiteboardManager* whiteboardManager) :
+ WhiteboardManager* whiteboardManager,
+ HighlightManager* highlightManager) :
jid_(jid),
joinMUCWindowFactory_(joinMUCWindowFactory),
useDelayForLatency_(useDelayForLatency),
@@ -86,7 +87,8 @@ ChatsManager::ChatsManager(
eagleMode_(eagleMode),
settings_(settings),
historyController_(historyController),
- whiteboardManager_(whiteboardManager) {
+ whiteboardManager_(whiteboardManager),
+ highlightManager_(highlightManager) {
timerFactory_ = timerFactory;
eventController_ = eventController;
stanzaChannel_ = stanzaChannel;
@@ -521,7 +523,7 @@ 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_);
+ 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_);
chatControllers_[contact] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false));
@@ -594,7 +596,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional
if (createAsReservedIfNew) {
muc->setCreateAsReservedIfNew();
}
- MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_);
+ MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_, highlightManager_);
mucControllers_[mucJID] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 5b8b785..55e62b9 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -50,10 +50,11 @@ namespace Swift {
class SettingsProvider;
class WhiteboardManager;
class HistoryController;
+ class HighlightManager;
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);
+ 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);
virtual ~ChatsManager();
void setAvatarManager(AvatarManager* avatarManager);
void setOnline(bool enabled);
@@ -136,5 +137,6 @@ namespace Swift {
SettingsProvider* settings_;
HistoryController* historyController_;
WhiteboardManager* whiteboardManager_;
+ HighlightManager* highlightManager_;
};
}
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 50eee68..a61b5f0 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -24,6 +24,7 @@
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h>
+#include <Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <Swiften/Avatars/AvatarManager.h>
@@ -35,6 +36,7 @@
#include <Swift/Controllers/Roster/SetPresence.h>
#include <Swiften/Disco/EntityCapsProvider.h>
#include <Swiften/Roster/XMPPRoster.h>
+#include <Swift/Controllers/Highlighter.h>
#define MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS 60000
@@ -61,8 +63,9 @@ MUCController::MUCController (
EntityCapsProvider* entityCapsProvider,
XMPPRoster* roster,
HistoryController* historyController,
- MUCRegistry* mucRegistry) :
- ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) {
+ 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) {
parting_ = true;
joined_ = false;
lastWasPresence_ = false;
@@ -98,6 +101,8 @@ MUCController::MUCController (
muc_->onConfigurationFormReceived.connect(boost::bind(&MUCController::handleConfigurationFormReceived, this, _1));
muc_->onRoleChangeFailed.connect(boost::bind(&MUCController::handleOccupantRoleChangeFailed, this, _1, _2, _3));
muc_->onAffiliationListReceived.connect(boost::bind(&MUCController::handleAffiliationListReceived, this, _1, _2));
+ highlighter_->setMode(Highlighter::MUCMode);
+ highlighter_->setNick(nick_);
if (timerFactory) {
loginCheckTimer_ = boost::shared_ptr<Timer>(timerFactory->createTimer(MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS));
loginCheckTimer_->onTick.connect(boost::bind(&MUCController::handleJoinTimeoutTick, this));
@@ -146,6 +151,7 @@ void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item
if (muc_->getOccupant(item->getJID().getResource()).getRealJID()) {
actions.push_back(ChatWindow::AddContact);
}
+ actions.push_back(ChatWindow::ShowProfile);
}
chatWindow_->setAvailableOccupantActions(actions);
}
@@ -164,6 +170,7 @@ void MUCController::handleActionRequestedOnOccupant(ChatWindow::OccupantAction a
case ChatWindow::MakeParticipant: muc_->changeOccupantRole(mucJID, MUCOccupant::Participant);break;
case ChatWindow::MakeVisitor: muc_->changeOccupantRole(mucJID, MUCOccupant::Visitor);break;
case ChatWindow::AddContact: if (occupant.getRealJID()) events_->send(boost::make_shared<RequestAddUserDialogUIEvent>(realJID, occupant.getNick()));break;
+ case ChatWindow::ShowProfile: events_->send(boost::make_shared<ShowProfileForRosterItemUIEvent>(mucJID));break;
}
}
@@ -228,6 +235,9 @@ void MUCController::receivedActivity() {
}
}
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wswitch-enum"
+
void MUCController::handleJoinFailed(boost::shared_ptr<ErrorPayload> error) {
receivedActivity();
std::string errorMessage = QT_TRANSLATE_NOOP("", "Unable to enter this room");
@@ -270,16 +280,18 @@ void MUCController::handleJoinFailed(boost::shared_ptr<ErrorPayload> error) {
chatWindow_->addErrorMessage(errorMessage);
parting_ = true;
if (!rejoinNick.empty()) {
- nick_ = rejoinNick;
+ setNick(rejoinNick);
rejoin();
}
}
+#pragma clang diagnostic pop
+
void MUCController::handleJoinComplete(const std::string& nick) {
receivedActivity();
joined_ = true;
std::string joinMessage = str(format(QT_TRANSLATE_NOOP("", "You have entered room %1% as %2%.")) % toJID_.toString() % nick);
- nick_ = nick;
+ setNick(nick);
chatWindow_->addSystemMessage(joinMessage);
#ifdef SWIFT_EXPERIMENTAL_HISTORY
@@ -386,6 +398,7 @@ std::string MUCController::roleToFriendlyName(MUCOccupant::Role role) {
case MUCOccupant::Visitor: return QT_TRANSLATE_NOOP("", "visitor");
case MUCOccupant::NoRole: return "";
}
+ assert(false);
return "";
}
@@ -396,6 +409,7 @@ std::string MUCController::roleToSortName(MUCOccupant::Role role) {
case MUCOccupant::Visitor: return "3";
case MUCOccupant::NoRole: return "4";
}
+ assert(false);
return "5";
}
@@ -448,10 +462,13 @@ void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> mes
}
}
-void MUCController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) {
+void MUCController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const HighlightAction& highlight) {
boost::shared_ptr<Message> message = messageEvent->getStanza();
if (joined_ && messageEvent->getStanza()->getFrom().getResource() != nick_ && messageTargetsMe(message) && !message->getPayload<Delay>()) {
eventController_->handleIncomingEvent(messageEvent);
+ if (!messageEvent->getConcluded()) {
+ highlighter_->handleHighlightAction(highlight);
+ }
}
}
@@ -487,7 +504,6 @@ std::string MUCController::roleToGroupName(MUCOccupant::Role role) {
case MUCOccupant::Participant: result = QT_TRANSLATE_NOOP("", "Participants"); break;
case MUCOccupant::Visitor: result = QT_TRANSLATE_NOOP("", "Visitors"); break;
case MUCOccupant::NoRole: result = QT_TRANSLATE_NOOP("", "Occupants"); break;
- default: assert(false);
}
return result;
}
@@ -504,7 +520,7 @@ void MUCController::setOnline(bool online) {
if (loginCheckTimer_) {
loginCheckTimer_->start();
}
- nick_ = desiredNick_;
+ setNick(desiredNick_);
rejoin();
}
}
@@ -611,7 +627,8 @@ void MUCController::appendToJoinParts(std::vector<NickJoinPart>& joinParts, cons
switch (newEvent.type) {
case Join: type = (type == Part) ? PartThenJoin : Join; break;
case Part: type = (type == Join) ? JoinThenPart : Part; break;
- default: /*Nothing to see here */;break;
+ case PartThenJoin: break;
+ case JoinThenPart: break;
}
(*it).type = type;
break;
@@ -811,7 +828,7 @@ void MUCController::addRecentLogs() {
bool senderIsSelf = nick_ == message.getFromJID().getResource();
// the chatWindow uses utc timestamps
- addMessage(message.getMessage(), senderDisplayNameFromMessage(message.getFromJID()), senderIsSelf, boost::shared_ptr<SecurityLabel>(new SecurityLabel()), std::string(avatarManager_->getAvatarPath(message.getFromJID()).string()), message.getTime() - boost::posix_time::hours(message.getOffset()));
+ addMessage(message.getMessage(), senderDisplayNameFromMessage(message.getFromJID()), senderIsSelf, boost::shared_ptr<SecurityLabel>(new SecurityLabel()), std::string(avatarManager_->getAvatarPath(message.getFromJID()).string()), message.getTime() - boost::posix_time::hours(message.getOffset()), HighlightAction());
}
}
@@ -840,4 +857,10 @@ void MUCController::checkDuplicates(boost::shared_ptr<Message> newMessage) {
}
}
+void MUCController::setNick(const std::string& nick)
+{
+ nick_ = nick;
+ highlighter_->setNick(nick_);
+}
+
}
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 63893d0..11fe0ff 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -33,18 +33,19 @@ namespace Swift {
class TabComplete;
class InviteToChatWindow;
class XMPPRoster;
+ class HighlightManager;
enum JoinPart {Join, Part, JoinThenPart, PartThenJoin};
struct NickJoinPart {
- NickJoinPart(const std::string& nick, JoinPart type) : nick(nick), type(type) {};
+ NickJoinPart(const std::string& nick, JoinPart type) : nick(nick), type(type) {}
std::string nick;
JoinPart type;
};
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);
+ 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();
boost::signal<void ()> onUserLeft;
boost::signal<void ()> onUserJoined;
@@ -62,7 +63,7 @@ namespace Swift {
std::string senderDisplayNameFromMessage(const JID& from);
boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message> message) const;
void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
- void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
+ void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>, const HighlightAction&);
void cancelReplaces();
void logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming);
@@ -108,6 +109,7 @@ namespace Swift {
void handleInviteToMUCWindowCompleted();
void addRecentLogs();
void checkDuplicates(boost::shared_ptr<Message> newMessage);
+ void setNick(const std::string& nick);
private:
MUC::ref muc_;
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index 482b19c..dd90d66 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -106,14 +106,16 @@ public:
avatarManager_ = new NullAvatarManager();
wbSessionManager_ = new WhiteboardSessionManager(iqRouter_, stanzaChannel_, presenceOracle_, entityCapsManager_);
wbManager_ = new WhiteboardManager(whiteboardWindowFactory_, uiEventStream_, nickResolver_, wbSessionManager_);
+ highlightManager_ = new HighlightManager(settings_);
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, settings_, NULL, wbManager_);
+ 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_);
manager_->setAvatarManager(avatarManager_);
- };
+ }
void tearDown() {
+ delete highlightManager_;
//delete chatListWindowFactory
delete profileSettings_;
delete avatarManager_;
@@ -481,6 +483,7 @@ private:
FileTransferManager* ftManager_;
WhiteboardSessionManager* wbSessionManager_;
WhiteboardManager* wbManager_;
+ HighlightManager* highlightManager_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest);
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index 4f37229..f1fcf79 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -26,6 +26,7 @@
#include "Swiften/Network/TimerFactory.h"
#include "Swiften/Elements/MUCUserPayload.h"
#include "Swiften/Disco/DummyEntityCapsProvider.h"
+#include <Swift/Controllers/Settings/DummySettingsProvider.h>
using namespace Swift;
@@ -62,12 +63,16 @@ public:
window_ = new MockChatWindow();
mucRegistry_ = new MUCRegistry();
entityCapsProvider_ = new DummyEntityCapsProvider();
+ settings_ = new DummySettingsProvider();
+ highlightManager_ = new HighlightManager(settings_);
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_);
- };
+ controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL, NULL, mucRegistry_, highlightManager_);
+ }
void tearDown() {
+ delete highlightManager_;
+ delete settings_;
delete entityCapsProvider_;
delete controller_;
delete eventController_;
@@ -338,6 +343,8 @@ private:
MockChatWindow* window_;
MUCRegistry* mucRegistry_;
DummyEntityCapsProvider* entityCapsProvider_;
+ DummySettingsProvider* settings_;
+ HighlightManager* highlightManager_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(MUCControllerTest);
diff --git a/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h b/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h
index 5bbd490..5fa264d 100644
--- a/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h
+++ b/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h
@@ -12,12 +12,12 @@ namespace Swift {
class MockChatListWindow : public ChatListWindow {
public:
- MockChatListWindow() {};
- virtual ~MockChatListWindow() {};
+ MockChatListWindow() {}
+ virtual ~MockChatListWindow() {}
void addMUCBookmark(const MUCBookmark& /*bookmark*/) {}
void removeMUCBookmark(const MUCBookmark& /*bookmark*/) {}
- void addWhiteboardSession(const ChatListWindow::Chat& /*chat*/) {};
- void removeWhiteboardSession(const JID& /*jid*/) {};
+ void addWhiteboardSession(const ChatListWindow::Chat& /*chat*/) {}
+ void removeWhiteboardSession(const JID& /*jid*/) {}
void setBookmarksEnabled(bool /*enabled*/) {}
void setRecents(const std::list<ChatListWindow::Chat>& /*recents*/) {}
void setUnreadCount(int /*unread*/) {}