diff options
Diffstat (limited to 'Swift/Controllers/Chat')
| -rw-r--r-- | Swift/Controllers/Chat/ChatController.cpp | 8 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatController.h | 4 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 72 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.h | 13 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatMessageParser.cpp | 10 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 12 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.h | 6 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp | 47 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp | 90 | 
9 files changed, 195 insertions, 67 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index a80eee5..7f62c36 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -208,10 +208,10 @@ void ChatController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> me  	}  } -void ChatController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const HighlightAction& highlight) { +void ChatController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const ChatWindow::ChatMessage& chatMessage) {  	eventController_->handleIncomingEvent(messageEvent);  	if (!messageEvent->getConcluded()) { -		highlighter_->handleHighlightAction(highlight); +		handleHighlightActions(chatMessage);  	}  } @@ -316,9 +316,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_, true, boost::posix_time::microsec_clock::universal_time(), HighlightAction()); +		replaceMessage(chatMessageParser_->parseMessageBody(body, "", true), myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time());  	} else { -		myLastMessageUIID_ = addMessage(body, QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel().getLabel() : boost::shared_ptr<SecurityLabel>(), avatarManager_->getAvatarPath(selfJID_), boost::posix_time::microsec_clock::universal_time(), HighlightAction()); +		myLastMessageUIID_ = addMessage(chatMessageParser_->parseMessageBody(body, "", true), QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel().getLabel() : boost::shared_ptr<SecurityLabel>(), avatarManager_->getAvatarPath(selfJID_), boost::posix_time::microsec_clock::universal_time());  	}  	if (stanzaChannel_->getStreamManagementEnabled() && !myLastMessageUIID_.empty() ) { diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index 9ee82eb..6ec19df 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -52,7 +52,7 @@ namespace Swift {  			virtual bool isIncomingMessageFromMe(boost::shared_ptr<Message> message) SWIFTEN_OVERRIDE;  			virtual void postSendMessage(const std::string &body, boost::shared_ptr<Stanza> sentStanza) SWIFTEN_OVERRIDE;  			virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) SWIFTEN_OVERRIDE; -			virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const HighlightAction&) SWIFTEN_OVERRIDE; +			virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const ChatWindow::ChatMessage& chatMessage) SWIFTEN_OVERRIDE;  			virtual void preSendMessageRequest(boost::shared_ptr<Message>) SWIFTEN_OVERRIDE;  			virtual std::string senderHighlightNameFromMessage(const JID& from) SWIFTEN_OVERRIDE;  			virtual std::string senderDisplayNameFromMessage(const JID& from) SWIFTEN_OVERRIDE; diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index fef3e7a..c790cce 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -208,19 +208,50 @@ bool ChatControllerBase::hasOpenWindow() const {  	return chatWindow_ && chatWindow_->isVisible();  } -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) { +ChatWindow::ChatMessage ChatControllerBase::buildChatWindowChatMessage(const std::string& message, bool senderIsSelf, const HighlightAction& fullMessageHighlightAction) { +	ChatWindow::ChatMessage chatMessage;  	if (boost::starts_with(message, "/me ")) { -		return chatWindow_->addAction(chatMessageParser_->parseMessageBody(String::getSplittedAtFirst(message, ' ').second), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight); -	} else { -		return chatWindow_->addMessage(chatMessageParser_->parseMessageBody(message,highlighter_->getNick(),senderIsSelf), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight); +		chatMessage = chatMessageParser_->parseMessageBody(String::getSplittedAtFirst(message, ' ').second); +	} +	else { +		chatMessage = chatMessageParser_->parseMessageBody(message, highlighter_->getNick(), senderIsSelf);  	} +	chatMessage.setFullMessageHighlightAction(fullMessageHighlightAction); +	return chatMessage;  } -void ChatControllerBase::replaceMessage(const std::string& message, const std::string& id, bool senderIsSelf, const boost::posix_time::ptime& time, const HighlightAction& highlight) { -	if (boost::starts_with(message, "/me ")) { -		chatWindow_->replaceWithAction(chatMessageParser_->parseMessageBody(String::getSplittedAtFirst(message, ' ').second), id, time, highlight); -	} else { -		chatWindow_->replaceMessage(chatMessageParser_->parseMessageBody(message,highlighter_->getNick(),senderIsSelf), id, time, highlight); +void ChatControllerBase::handleHighlightActions(const ChatWindow::ChatMessage& chatMessage) { +	std::set<std::string> playedSounds; +	if (chatMessage.getFullMessageHighlightAction().playSound()) { +		highlighter_->handleHighlightAction(chatMessage.getFullMessageHighlightAction()); +		playedSounds.insert(chatMessage.getFullMessageHighlightAction().getSoundFile()); +	} +	foreach(boost::shared_ptr<ChatWindow::ChatMessagePart> part, chatMessage.getParts()) { +		boost::shared_ptr<ChatWindow::ChatHighlightingMessagePart> highlightMessage = boost::dynamic_pointer_cast<ChatWindow::ChatHighlightingMessagePart>(part); +		if (highlightMessage && highlightMessage->action.playSound()) { +			if (playedSounds.find(highlightMessage->action.getSoundFile()) == playedSounds.end()) { +				highlighter_->handleHighlightAction(highlightMessage->action); +				playedSounds.insert(highlightMessage->action.getSoundFile()); +			} +		} +	} +} + +std::string ChatControllerBase::addMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& senderName, bool senderIsSelf, const boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time) { +	if (chatMessage.isMeCommand()) { +		return chatWindow_->addAction(chatMessage, senderName, senderIsSelf, label, pathToString(avatarPath), time); +	} +	else { +		return chatWindow_->addMessage(chatMessage, senderName, senderIsSelf, label, pathToString(avatarPath), time); +	} +} + +void ChatControllerBase::replaceMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& id, const boost::posix_time::ptime& time) { +	if (chatMessage.isMeCommand()) { +		chatWindow_->replaceWithAction(chatMessage, id, time); +	} +	else { +		chatWindow_->replaceMessage(chatMessage, id, time);  	}  } @@ -236,9 +267,11 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m  			targetedUnreadMessages_.push_back(messageEvent);  		}  	} +  	boost::shared_ptr<Message> message = messageEvent->getStanza(); -	std::string body = message->getBody().get_value_or(""); -	HighlightAction highlight; +	ChatWindow::ChatMessage chatMessage; +	boost::optional<std::string> optionalBody = message->getBody(); +	std::string body = optionalBody.get_value_or("");  	if (message->isError()) {  		if (!message->getTo().getResource().empty()) {  			std::string errorMessage = str(format(QT_TRANSLATE_NOOP("", "Couldn't send message: %1%")) % getErrorMessage(message->getPayload<ErrorPayload>())); @@ -280,22 +313,25 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m  		onActivity(body);  		// Highlight +		HighlightAction fullMessageHighlight;  		if (!isIncomingMessageFromMe(message)) { -			highlight = highlighter_->findAction(body, senderHighlightNameFromMessage(from)); +			fullMessageHighlight = highlighter_->findFirstFullMessageMatchAction(body, senderHighlightNameFromMessage(from));  		}  		boost::shared_ptr<Replace> replace = message->getPayload<Replace>(); +		bool senderIsSelf = isIncomingMessageFromMe(message);  		if (replace) { -			std::string body = message->getBody().get_value_or("");  			// Should check if the user has a previous message  			std::map<JID, std::string>::iterator lastMessage;  			lastMessage = lastMessagesUIID_.find(from);  			if (lastMessage != lastMessagesUIID_.end()) { -				replaceMessage(body, lastMessagesUIID_[from], isIncomingMessageFromMe(message), timeStamp, highlight); +				chatMessage = buildChatWindowChatMessage(body, senderIsSelf, fullMessageHighlight); +				replaceMessage(chatMessage, lastMessagesUIID_[from], timeStamp);  			}  		}  		else { -			addMessageHandleIncomingMessage(from, body, isIncomingMessageFromMe(message), label, timeStamp, highlight); +			chatMessage = buildChatWindowChatMessage(body, senderIsSelf, fullMessageHighlight); +			addMessageHandleIncomingMessage(from, chatMessage, senderIsSelf, label, timeStamp);  		}  		logMessage(body, from, selfJID_, timeStamp, true); @@ -303,11 +339,11 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m  	chatWindow_->show();  	chatWindow_->setUnreadMessageCount(boost::numeric_cast<int>(unreadMessages_.size()));  	onUnreadCountChanged(); -	postHandleIncomingMessage(messageEvent, highlight); +	postHandleIncomingMessage(messageEvent, chatMessage);  } -void ChatControllerBase::addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& timeStamp, const HighlightAction& highlight) { -	lastMessagesUIID_[from] = addMessage(message, senderDisplayNameFromMessage(from), senderIsSelf, label, avatarManager_->getAvatarPath(from), timeStamp, highlight); +void ChatControllerBase::addMessageHandleIncomingMessage(const JID& from, const ChatWindow::ChatMessage& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& timeStamp) { +	lastMessagesUIID_[from] = addMessage(message, senderDisplayNameFromMessage(from), senderIsSelf, label, avatarManager_->getAvatarPath(from), timeStamp);  }  std::string ChatControllerBase::getErrorMessage(boost::shared_ptr<ErrorPayload> error) { diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index 4e68a2b..98f0ab0 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -55,8 +55,8 @@ namespace Swift {  			bool hasOpenWindow() const;  			virtual 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 boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); -			void replaceMessage(const std::string& message, const std::string& id, bool senderIsSelf, const boost::posix_time::ptime& time, const HighlightAction& highlight); +			std::string addMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time); +			void replaceMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& id, const boost::posix_time::ptime& time);  			virtual void setOnline(bool online);  			void setEnabled(bool enabled);  			virtual void setToJID(const JID& jid) {toJID_ = jid;} @@ -82,8 +82,8 @@ namespace Swift {  			virtual std::string senderHighlightNameFromMessage(const JID& from) = 0;  			virtual bool isIncomingMessageFromMe(boost::shared_ptr<Message>) = 0;  			virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {} -			virtual void addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& time, const HighlightAction& highlight); -			virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>, const HighlightAction&) {} +			virtual void addMessageHandleIncomingMessage(const JID& from, const ChatWindow::ChatMessage& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& time); +			virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>, const ChatWindow::ChatMessage&) {}  			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; @@ -95,11 +95,14 @@ namespace Swift {  			/** JID any iq for account should go to - bare except for PMs */  			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 buildChatWindowChatMessage(const std::string& message, bool senderIsSelf, const HighlightAction& fullMessageHighlightAction); +			void handleHighlightActions(const ChatWindow::ChatMessage& chatMessage);  		private:  			IDGenerator idGenerator_;  			std::string lastSentMessageStanzaID_;  			void createDayChangeTimer(); +  			void handleSendMessageRequest(const std::string &body, bool isCorrectionMessage);  			void handleAllMessagesRead();  			void handleSecurityLabelsCatalogResponse(boost::shared_ptr<SecurityLabelsCatalog>, ErrorPayload::ref error); diff --git a/Swift/Controllers/Chat/ChatMessageParser.cpp b/Swift/Controllers/Chat/ChatMessageParser.cpp index 666ec2f..53c7588 100644 --- a/Swift/Controllers/Chat/ChatMessageParser.cpp +++ b/Swift/Controllers/Chat/ChatMessageParser.cpp @@ -1,23 +1,22 @@  /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */  #include <Swift/Controllers/Chat/ChatMessageParser.h> -#include <vector>  #include <utility> +#include <vector> -#include <boost/smart_ptr/make_shared.hpp>  #include <boost/algorithm/string.hpp> +#include <boost/smart_ptr/make_shared.hpp>  #include <Swiften/Base/Regex.h>  #include <Swiften/Base/foreach.h>  #include <SwifTools/Linkify.h> -  namespace Swift {  	ChatMessageParser::ChatMessageParser(const std::map<std::string, std::string>& emoticons, HighlightRulesListPtr highlightRules, bool mucMode) @@ -170,8 +169,7 @@ namespace Swift {  								}  								boost::shared_ptr<ChatWindow::ChatHighlightingMessagePart> highlightPart = boost::make_shared<ChatWindow::ChatHighlightingMessagePart>();  								highlightPart->text = match.str(); -								highlightPart->foregroundColor = rule.getAction().getTextColor(); -								highlightPart->backgroundColor = rule.getAction().getTextBackground(); +								highlightPart->action = rule.getAction();  								newMessage.append(highlightPart);  								start = matchEnd;  							} diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 409fe1f..0bb670d 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -576,23 +576,23 @@ void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> mes  	}  } -void MUCController::addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& time, const HighlightAction& highlight) { +void MUCController::addMessageHandleIncomingMessage(const JID& from, const ChatWindow::ChatMessage& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& time) {  	if (from.isBare()) { -		chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "%1%")) % message)), ChatWindow::DefaultDirection); +		chatWindow_->addSystemMessage(message, ChatWindow::DefaultDirection);  	}  	else { -		ChatControllerBase::addMessageHandleIncomingMessage(from, message, senderIsSelf, label, time, highlight); +		ChatControllerBase::addMessageHandleIncomingMessage(from, message, senderIsSelf, label, time);  	}  } -void MUCController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const HighlightAction& highlight) { +void MUCController::postHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent, const ChatWindow::ChatMessage& chatMessage) {  	boost::shared_ptr<Message> message = messageEvent->getStanza();  	if (joined_ && messageEvent->getStanza()->getFrom().getResource() != nick_ && !message->getPayload<Delay>()) {  		if (messageTargetsMe(message) || isImpromptu_) {  			eventController_->handleIncomingEvent(messageEvent);  		}  		if (!messageEvent->getConcluded()) { -			highlighter_->handleHighlightAction(highlight); +			handleHighlightActions(chatMessage);  		}  	}  } @@ -1074,7 +1074,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()), avatarManager_->getAvatarPath(message.getFromJID()), message.getTime() - boost::posix_time::hours(message.getOffset()), HighlightAction()); +		addMessage(chatMessageParser_->parseMessageBody(message.getMessage()), senderDisplayNameFromMessage(message.getFromJID()), senderIsSelf, boost::shared_ptr<SecurityLabel>(new SecurityLabel()), avatarManager_->getAvatarPath(message.getFromJID()), message.getTime() - boost::posix_time::hours(message.getOffset()));  	}  } diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index a08d541..0fb739a 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -81,8 +81,8 @@ namespace Swift {  			virtual std::string senderDisplayNameFromMessage(const JID& from) SWIFTEN_OVERRIDE;  			virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message> message) const SWIFTEN_OVERRIDE;  			virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>) SWIFTEN_OVERRIDE; -			virtual void addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& time, const HighlightAction& highlight) SWIFTEN_OVERRIDE; -			virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>, const HighlightAction&) SWIFTEN_OVERRIDE; +			virtual void addMessageHandleIncomingMessage(const JID& from, const ChatWindow::ChatMessage& message, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& time) SWIFTEN_OVERRIDE; +			virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>, const ChatWindow::ChatMessage& chatMessage) SWIFTEN_OVERRIDE;  			virtual void cancelReplaces() SWIFTEN_OVERRIDE;  			virtual void logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming) SWIFTEN_OVERRIDE; diff --git a/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp index 1b92bb6..6748b9e 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp @@ -1,5 +1,5 @@  /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -49,9 +49,11 @@ public:  		CPPUNIT_ASSERT_EQUAL(path, part->imagePath);  	} -	void assertHighlight(const ChatWindow::ChatMessage& result, size_t index, const std::string& text) { -		boost::shared_ptr<ChatWindow::ChatHighlightingMessagePart> part = boost::dynamic_pointer_cast<ChatWindow::ChatHighlightingMessagePart>(result.getParts()[index]); -		CPPUNIT_ASSERT_EQUAL(text, part->text); +#define assertHighlight(RESULT, INDEX, TEXT, EXPECTED_HIGHLIGHT) \ +	{ \ +		boost::shared_ptr<ChatWindow::ChatHighlightingMessagePart> part = boost::dynamic_pointer_cast<ChatWindow::ChatHighlightingMessagePart>(RESULT.getParts()[INDEX]); \ +		CPPUNIT_ASSERT_EQUAL(std::string(TEXT), part->text); \ +		CPPUNIT_ASSERT(EXPECTED_HIGHLIGHT == part->action); \  	}  	void assertURL(const ChatWindow::ChatMessage& result, size_t index, const std::string& text) { @@ -108,13 +110,14 @@ public:  		ChatWindow::ChatMessage result = testling.parseMessageBody(no_special_message);  		assertText(result, 0, no_special_message); -		testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false)); +		HighlightRulesListPtr highlightRuleList = ruleListFromKeyword("trigger", false, false); +		testling = ChatMessageParser(emoticons_, highlightRuleList);  		result = testling.parseMessageBody(":) shiny :( trigger :) http://wonderland.lit/blah http://denmark.lit boom boom");  		assertEmoticon(result, 0, smile1_, smile1Path_);  		assertText(result, 1, " shiny ");  		assertEmoticon(result, 2, smile2_, smile2Path_);  		assertText(result, 3, " "); -		assertHighlight(result, 4, "trigger"); +		assertHighlight(result, 4, "trigger", highlightRuleList->getRule(0).getAction());  		assertText(result, 5, " ");  		assertEmoticon(result, 6, smile1_, smile1Path_);  		assertText(result, 7, " "); @@ -126,7 +129,7 @@ public:  		testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false));  		result = testling.parseMessageBody("testtriggermessage");  		assertText(result, 0, "test"); -		assertHighlight(result, 1, "trigger"); +		assertHighlight(result, 1, "trigger", highlightRuleList->getRule(0).getAction());  		assertText(result, 2, "message");  		testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, true)); @@ -139,32 +142,32 @@ public:  		testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false));  		result = testling.parseMessageBody("TrIgGeR"); -		assertHighlight(result, 0, "TrIgGeR"); +		assertHighlight(result, 0, "TrIgGeR", highlightRuleList->getRule(0).getAction());  		testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false));  		result = testling.parseMessageBody("partialTrIgGeRmatch");  		assertText(result, 0, "partial"); -		assertHighlight(result, 1, "TrIgGeR"); +		assertHighlight(result, 1, "TrIgGeR", highlightRuleList->getRule(0).getAction());  		assertText(result, 2, "match");  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", false, false)));  		result = testling.parseMessageBody("zero one two three");  		assertText(result, 0, "zero "); -		assertHighlight(result, 1, "one"); +		assertHighlight(result, 1, "one", highlightRuleList->getRule(0).getAction());  		assertText(result, 2, " two "); -		assertHighlight(result, 3, "three"); +		assertHighlight(result, 3, "three", highlightRuleList->getRule(0).getAction());  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", false, false)));  		result = testling.parseMessageBody("zero oNe two tHrEe");  		assertText(result, 0, "zero "); -		assertHighlight(result, 1, "oNe"); +		assertHighlight(result, 1, "oNe", highlightRuleList->getRule(0).getAction());  		assertText(result, 2, " two "); -		assertHighlight(result, 3, "tHrEe"); +		assertHighlight(result, 3, "tHrEe", highlightRuleList->getRule(0).getAction());  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", true, false)));  		result = testling.parseMessageBody("zero oNe two tHrEe");  		assertText(result, 0, "zero "); -		assertHighlight(result, 1, "oNe"); +		assertHighlight(result, 1, "oNe", highlightRuleList->getRule(0).getAction());  		assertText(result, 2, " two tHrEe");  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", true, false), ruleFromKeyword("three", true, false))); @@ -174,19 +177,19 @@ public:  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", false, false)));  		result = testling.parseMessageBody("zeroonetwothree");  		assertText(result, 0, "zero"); -		assertHighlight(result, 1, "one"); +		assertHighlight(result, 1, "one", highlightRuleList->getRule(0).getAction());  		assertText(result, 2, "two"); -		assertHighlight(result, 3, "three"); +		assertHighlight(result, 3, "three", highlightRuleList->getRule(0).getAction());  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", true, false), ruleFromKeyword("three", false, false)));  		result = testling.parseMessageBody("zeroOnEtwoThReE");  		assertText(result, 0, "zeroOnEtwo"); -		assertHighlight(result, 1, "ThReE"); +		assertHighlight(result, 1, "ThReE", highlightRuleList->getRule(0).getAction());  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, true), ruleFromKeyword("three", false, false)));  		result = testling.parseMessageBody("zeroonetwothree");  		assertText(result, 0, "zeroonetwo"); -		assertHighlight(result, 1, "three"); +		assertHighlight(result, 1, "three", highlightRuleList->getRule(0).getAction());  		testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, true), ruleFromKeyword("three", false, true)));  		result = testling.parseMessageBody("zeroonetwothree"); @@ -194,7 +197,7 @@ public:  		testling = ChatMessageParser(emoticons_, ruleListWithNickHighlight());  		result = testling.parseMessageBody("Alice", "Alice"); -		assertHighlight(result, 0, "Alice"); +		assertHighlight(result, 0, "Alice", highlightRuleList->getRule(0).getAction());  		testling = ChatMessageParser(emoticons_, ruleListWithNickHighlight());  		result = testling.parseMessageBody("TextAliceText", "Alice"); @@ -203,18 +206,18 @@ public:  		testling = ChatMessageParser(emoticons_, ruleListWithNickHighlight());  		result = testling.parseMessageBody("Text Alice Text", "Alice");  		assertText(result, 0, "Text "); -		assertHighlight(result, 1, "Alice"); +		assertHighlight(result, 1, "Alice", highlightRuleList->getRule(0).getAction());  		assertText(result, 2, " Text");  		testling = ChatMessageParser(emoticons_, ruleListWithNickHighlight());  		result = testling.parseMessageBody("Alice Text", "Alice"); -		assertHighlight(result, 0, "Alice"); +		assertHighlight(result, 0, "Alice", highlightRuleList->getRule(0).getAction());  		assertText(result, 1, " Text");  		testling = ChatMessageParser(emoticons_, ruleListWithNickHighlight());  		result = testling.parseMessageBody("Text Alice", "Alice");  		assertText(result, 0, "Text "); -		assertHighlight(result, 1, "Alice"); +		assertHighlight(result, 1, "Alice", highlightRuleList->getRule(0).getAction());  	}  	void testOneEmoticon() { diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index 4f8cf5a..31d54db 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -4,6 +4,9 @@   * See the COPYING file for more information.   */ +#include <set> +#include <map> +  #include <boost/bind.hpp>  #include <cppunit/extensions/HelperMacros.h> @@ -75,6 +78,8 @@ class ChatsManagerTest : public CppUnit::TestFixture {  	CPPUNIT_TEST(testChatControllerFullJIDBindingOnTypingAndNotActive);  	CPPUNIT_TEST(testChatControllerPMPresenceHandling);  	CPPUNIT_TEST(testLocalMUCServiceDiscoveryResetOnDisconnect); +	CPPUNIT_TEST(testChatControllerHighlightingNotificationTesting); +	CPPUNIT_TEST(testChatControllerHighlightingNotificationDeduplicateSounds);  	CPPUNIT_TEST_SUITE_END();  public: @@ -110,6 +115,9 @@ public:  		wbSessionManager_ = new WhiteboardSessionManager(iqRouter_, stanzaChannel_, presenceOracle_, entityCapsProvider_);  		wbManager_ = new WhiteboardManager(whiteboardWindowFactory_, uiEventStream_, nickResolver_, wbSessionManager_);  		highlightManager_ = new HighlightManager(settings_); +		handledHighlightActions_ = 0; +		soundsPlayed_.clear(); +		highlightManager_->onHighlight.connect(boost::bind(&ChatsManagerTest::handleHighlightAction, this, _1));  		crypto_ = PlatformCryptoProvider::create();  		vcardStorage_ = new VCardMemoryStorage(crypto_); @@ -156,7 +164,7 @@ public:  	void testFirstOpenWindowIncoming() {  		JID messageJID("testling@test.com/resource1"); -		MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>(); +		MockChatWindow* window = new MockChatWindow();  		mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);  		boost::shared_ptr<Message> message(new Message()); @@ -724,6 +732,77 @@ public:  		CPPUNIT_ASSERT(stanzaContactOnRoster->getPayload<DeliveryReceipt>() != 0);  	} +	void testChatControllerHighlightingNotificationTesting() { +		HighlightRule keywordRuleA; +		keywordRuleA.setMatchChat(true); +		std::vector<std::string> keywordsA; +		keywordsA.push_back("Romeo"); +		keywordRuleA.setKeywords(keywordsA); +		keywordRuleA.getAction().setTextColor("yellow"); +		keywordRuleA.getAction().setPlaySound(true); +		highlightManager_->insertRule(0, keywordRuleA); + +		HighlightRule keywordRuleB; +		keywordRuleB.setMatchChat(true); +		std::vector<std::string> keywordsB; +		keywordsB.push_back("Juliet"); +		keywordRuleB.setKeywords(keywordsB); +		keywordRuleB.getAction().setTextColor("green"); +		keywordRuleB.getAction().setPlaySound(true); +		keywordRuleB.getAction().setSoundFile("/tmp/someotherfile.wav"); +		highlightManager_->insertRule(0, keywordRuleB); + +		JID messageJID = JID("testling@test.com"); + +		MockChatWindow* window = new MockChatWindow(); +		mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window); + +		boost::shared_ptr<Message> message(new Message()); +		message->setFrom(messageJID); +		std::string body("This message should cause two sounds: Juliet and Romeo."); +		message->setBody(body); +		manager_->handleIncomingMessage(message); + +		CPPUNIT_ASSERT_EQUAL(2, handledHighlightActions_); +		CPPUNIT_ASSERT(soundsPlayed_.find(keywordRuleA.getAction().getSoundFile()) != soundsPlayed_.end()); +		CPPUNIT_ASSERT(soundsPlayed_.find(keywordRuleB.getAction().getSoundFile()) != soundsPlayed_.end()); +	} + +	void testChatControllerHighlightingNotificationDeduplicateSounds() { +		HighlightRule keywordRuleA; +		keywordRuleA.setMatchChat(true); +		std::vector<std::string> keywordsA; +		keywordsA.push_back("Romeo"); +		keywordRuleA.setKeywords(keywordsA); +		keywordRuleA.getAction().setTextColor("yellow"); +		keywordRuleA.getAction().setPlaySound(true); +		highlightManager_->insertRule(0, keywordRuleA); + +		HighlightRule keywordRuleB; +		keywordRuleB.setMatchChat(true); +		std::vector<std::string> keywordsB; +		keywordsB.push_back("Juliet"); +		keywordRuleB.setKeywords(keywordsB); +		keywordRuleB.getAction().setTextColor("green"); +		keywordRuleB.getAction().setPlaySound(true); +		highlightManager_->insertRule(0, keywordRuleB); + +		JID messageJID = JID("testling@test.com"); + +		MockChatWindow* window = new MockChatWindow(); +		mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window); + +		boost::shared_ptr<Message> message(new Message()); +		message->setFrom(messageJID); +		std::string body("This message should cause one sound, because both actions have the same sound: Juliet and Romeo."); +		message->setBody(body); +		manager_->handleIncomingMessage(message); + +		CPPUNIT_ASSERT_EQUAL(1, handledHighlightActions_); +		CPPUNIT_ASSERT(soundsPlayed_.find(keywordRuleA.getAction().getSoundFile()) != soundsPlayed_.end()); +		CPPUNIT_ASSERT(soundsPlayed_.find(keywordRuleB.getAction().getSoundFile()) != soundsPlayed_.end()); +	} +  private:  	boost::shared_ptr<Message> makeDeliveryReceiptTestMessage(const JID& from, const std::string& id) {  		boost::shared_ptr<Message> message = boost::make_shared<Message>(); @@ -738,6 +817,13 @@ private:  		return static_cast<size_t>(i);  	} +	void handleHighlightAction(const HighlightAction& action) { +		handledHighlightActions_++; +		if (action.playSound()) { +			soundsPlayed_.insert(action.getSoundFile()); +		} +	} +  private:  	JID jid_;  	ChatsManager* manager_; @@ -775,6 +861,8 @@ private:  	CryptoProvider* crypto_;  	VCardStorage* vcardStorage_;  	std::map<std::string, std::string> emoticons_; +	int handledHighlightActions_; +	std::set<std::string> soundsPlayed_;  };  CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest);  | 
 Swift