From 74e51310d27e9d9a66d2d790360549c48abec8d1 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Tue, 8 Mar 2016 13:36:27 +0000 Subject: Refactored keyword highlighting This commit changes the ChatWindow/ChatView APIs to not pass highlights actions as additional parameters but instead they are now part of the ChatWindow::ChatMessage and its parts. This allows the controllers to do highlighting in one single place and play sound actions on the highlighted message in a single place. On a highlighted message only unique sounds are played and they are played in sequence of the rules that matched the message. Test-Information: Adjusted the existing unit tests accordingly. Added unit tests that check reduplication of highlight action sounds and that the sound actions are emitted correctly. Manually verified that highlight sound actions with and without duplicated sounds are audible on OS X 10.11.3. Change-Id: I68c88e0d285d79d87b2997ed29d92b140480b394 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 me } } -void ChatController::postHandleIncomingMessage(boost::shared_ptr messageEvent, const HighlightAction& highlight) { +void ChatController::postHandleIncomingMessage(boost::shared_ptr 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 = sentStanza->getPayload(); if (replace) { eraseIf(unackedStanzas_, PairSecondEquals, 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(), 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(), 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) SWIFTEN_OVERRIDE; virtual void postSendMessage(const std::string &body, boost::shared_ptr sentStanza) SWIFTEN_OVERRIDE; virtual void preHandleIncomingMessage(boost::shared_ptr messageEvent) SWIFTEN_OVERRIDE; - virtual void postHandleIncomingMessage(boost::shared_ptr messageEvent, const HighlightAction&) SWIFTEN_OVERRIDE; + virtual void postHandleIncomingMessage(boost::shared_ptr messageEvent, const ChatWindow::ChatMessage& chatMessage) SWIFTEN_OVERRIDE; virtual void preSendMessageRequest(boost::shared_ptr) 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 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 playedSounds; + if (chatMessage.getFullMessageHighlightAction().playSound()) { + highlighter_->handleHighlightAction(chatMessage.getFullMessageHighlightAction()); + playedSounds.insert(chatMessage.getFullMessageHighlightAction().getSoundFile()); + } + foreach(boost::shared_ptr part, chatMessage.getParts()) { + boost::shared_ptr highlightMessage = boost::dynamic_pointer_cast(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 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 m targetedUnreadMessages_.push_back(messageEvent); } } + boost::shared_ptr message = messageEvent->getStanza(); - std::string body = message->getBody().get_value_or(""); - HighlightAction highlight; + ChatWindow::ChatMessage chatMessage; + boost::optional 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())); @@ -280,22 +313,25 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr 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 = message->getPayload(); + 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::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 m chatWindow_->show(); chatWindow_->setUnreadMessageCount(boost::numeric_cast(unreadMessages_.size())); onUnreadCountChanged(); - postHandleIncomingMessage(messageEvent, highlight); + postHandleIncomingMessage(messageEvent, chatMessage); } -void ChatControllerBase::addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr 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 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 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 info); void handleIncomingMessage(boost::shared_ptr message); - std::string addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr 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 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) = 0; virtual void preHandleIncomingMessage(boost::shared_ptr) {} - virtual void addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr label, const boost::posix_time::ptime& time, const HighlightAction& highlight); - virtual void postHandleIncomingMessage(boost::shared_ptr, const HighlightAction&) {} + virtual void addMessageHandleIncomingMessage(const JID& from, const ChatWindow::ChatMessage& message, bool senderIsSelf, boost::shared_ptr label, const boost::posix_time::ptime& time); + virtual void postHandleIncomingMessage(boost::shared_ptr, const ChatWindow::ChatMessage&) {} virtual void preSendMessageRequest(boost::shared_ptr) {} virtual bool isFromContact(const JID& from); virtual boost::optional getMessageTimestamp(boost::shared_ptr) 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, 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 -#include #include +#include -#include #include +#include #include #include #include - namespace Swift { ChatMessageParser::ChatMessageParser(const std::map& emoticons, HighlightRulesListPtr highlightRules, bool mucMode) @@ -170,8 +169,7 @@ namespace Swift { } boost::shared_ptr highlightPart = boost::make_shared(); 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 mes } } -void MUCController::addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr 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 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, const HighlightAction& highlight) { +void MUCController::postHandleIncomingMessage(boost::shared_ptr messageEvent, const ChatWindow::ChatMessage& chatMessage) { boost::shared_ptr message = messageEvent->getStanza(); if (joined_ && messageEvent->getStanza()->getFrom().getResource() != nick_ && !message->getPayload()) { 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(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(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 getMessageTimestamp(boost::shared_ptr message) const SWIFTEN_OVERRIDE; virtual void preHandleIncomingMessage(boost::shared_ptr) SWIFTEN_OVERRIDE; - virtual void addMessageHandleIncomingMessage(const JID& from, const std::string& message, bool senderIsSelf, boost::shared_ptr label, const boost::posix_time::ptime& time, const HighlightAction& highlight) SWIFTEN_OVERRIDE; - virtual void postHandleIncomingMessage(boost::shared_ptr, const HighlightAction&) SWIFTEN_OVERRIDE; + virtual void addMessageHandleIncomingMessage(const JID& from, const ChatWindow::ChatMessage& message, bool senderIsSelf, boost::shared_ptr label, const boost::posix_time::ptime& time) SWIFTEN_OVERRIDE; + virtual void postHandleIncomingMessage(boost::shared_ptr, 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 part = boost::dynamic_pointer_cast(result.getParts()[index]); - CPPUNIT_ASSERT_EQUAL(text, part->text); +#define assertHighlight(RESULT, INDEX, TEXT, EXPECTED_HIGHLIGHT) \ + { \ + boost::shared_ptr part = boost::dynamic_pointer_cast(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 +#include + #include #include @@ -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(); + MockChatWindow* window = new MockChatWindow(); mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window); boost::shared_ptr message(new Message()); @@ -724,6 +732,77 @@ public: CPPUNIT_ASSERT(stanzaContactOnRoster->getPayload() != 0); } + void testChatControllerHighlightingNotificationTesting() { + HighlightRule keywordRuleA; + keywordRuleA.setMatchChat(true); + std::vector 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 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(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 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 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(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 makeDeliveryReceiptTestMessage(const JID& from, const std::string& id) { boost::shared_ptr message = boost::make_shared(); @@ -738,6 +817,13 @@ private: return static_cast(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 emoticons_; + int handledHighlightActions_; + std::set soundsPlayed_; }; CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest); diff --git a/Swift/Controllers/HighlightManager.cpp b/Swift/Controllers/HighlightManager.cpp index e5c8cef..07f8e54 100644 --- a/Swift/Controllers/HighlightManager.cpp +++ b/Swift/Controllers/HighlightManager.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2014-2015 Isode Limited. + * Copyright (c) 2014-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -49,30 +49,26 @@ namespace Swift { HighlightManager::HighlightManager(SettingsProvider* settings) : settings_(settings) - , storingSettings_(false) -{ + , storingSettings_(false) { rules_ = boost::make_shared(); loadSettings(); handleSettingChangedConnection_ = settings_->onSettingChanged.connect(boost::bind(&HighlightManager::handleSettingChanged, this, _1)); } -void HighlightManager::handleSettingChanged(const std::string& settingPath) -{ +void HighlightManager::handleSettingChanged(const std::string& settingPath) { if (!storingSettings_ && SettingConstants::HIGHLIGHT_RULES.getKey() == settingPath) { loadSettings(); } } -std::string HighlightManager::rulesToString() const -{ +std::string HighlightManager::rulesToString() const { std::stringstream stream; boost::archive::text_oarchive archive(stream); archive << rules_->list_; return stream.str(); } -std::vector HighlightManager::getDefaultRules() -{ +std::vector HighlightManager::getDefaultRules() { std::vector rules; HighlightRule chatNotificationRule; @@ -92,26 +88,22 @@ std::vector HighlightManager::getDefaultRules() return rules; } -HighlightRule HighlightManager::getRule(int index) const -{ +HighlightRule HighlightManager::getRule(int index) const { assert(index >= 0 && static_cast(index) < rules_->getSize()); return rules_->getRule(static_cast(index)); } -void HighlightManager::setRule(int index, const HighlightRule& rule) -{ +void HighlightManager::setRule(int index, const HighlightRule& rule) { assert(index >= 0 && static_cast(index) < rules_->getSize()); rules_->list_[static_cast(index)] = rule; } -void HighlightManager::insertRule(int index, const HighlightRule& rule) -{ +void HighlightManager::insertRule(int index, const HighlightRule& rule) { assert(index >= 0 && boost::numeric_cast::size_type>(index) <= rules_->getSize()); rules_->list_.insert(rules_->list_.begin() + index, rule); } -void HighlightManager::removeRule(int index) -{ +void HighlightManager::removeRule(int index) { assert(index >= 0 && boost::numeric_cast::size_type>(index) < rules_->getSize()); rules_->list_.erase(rules_->list_.begin() + index); } @@ -124,15 +116,13 @@ void HighlightManager::swapRules(const size_t first, const size_t second) { rules_->setRule(second, swap); } -void HighlightManager::storeSettings() -{ +void HighlightManager::storeSettings() { storingSettings_ = true; // don't reload settings while saving settings_->storeSetting(SettingConstants::HIGHLIGHT_RULES, rulesToString()); storingSettings_ = false; } -void HighlightManager::loadSettings() -{ +void HighlightManager::loadSettings() { std::string rulesString = settings_->getSetting(SettingConstants::HIGHLIGHT_RULES); std::stringstream stream; stream << rulesString; @@ -144,8 +134,7 @@ void HighlightManager::loadSettings() } } -Highlighter* HighlightManager::createHighlighter() -{ +Highlighter* HighlightManager::createHighlighter() { return new Highlighter(this); } diff --git a/Swift/Controllers/Highlighter.cpp b/Swift/Controllers/Highlighter.cpp index 13ee951..40f92ba 100644 --- a/Swift/Controllers/Highlighter.cpp +++ b/Swift/Controllers/Highlighter.cpp @@ -5,13 +5,15 @@ */ /* - * Copyright (c) 2014 Isode Limited. + * Copyright (c) 2014-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include #include + +#include + #include namespace Swift { @@ -28,17 +30,19 @@ void Highlighter::setMode(Mode mode) messageType_ = mode_ == ChatMode ? HighlightRule::ChatMessage : HighlightRule::MUCMessage; } -HighlightAction Highlighter::findAction(const std::string& body, const std::string& sender) const +HighlightAction Highlighter::findFirstFullMessageMatchAction(const std::string& body, const std::string& sender) const { + HighlightAction match; HighlightRulesListPtr rules = manager_->getRules(); for (size_t i = 0; i < rules->getSize(); ++i) { const HighlightRule& rule = rules->getRule(i); - if (rule.isMatch(body, sender, nick_, messageType_)) { - return rule.getAction(); + if (rule.isMatch(body, sender, nick_, messageType_) && rule.getAction().highlightWholeMessage()) { + match = rule.getAction(); + break; } } - return HighlightAction(); + return match; } void Highlighter::handleHighlightAction(const HighlightAction& action) diff --git a/Swift/Controllers/Highlighter.h b/Swift/Controllers/Highlighter.h index d5d846b..5d5f531 100644 --- a/Swift/Controllers/Highlighter.h +++ b/Swift/Controllers/Highlighter.h @@ -4,9 +4,16 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include +#include #include @@ -24,7 +31,7 @@ namespace Swift { void setNick(const std::string& nick) { nick_ = nick; } std::string getNick() const { return nick_; } - HighlightAction findAction(const std::string& body, const std::string& sender) const; + HighlightAction findFirstFullMessageMatchAction(const std::string& body, const std::string& sender) const; void handleHighlightAction(const HighlightAction& action); diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 3a1acdf..05331bb 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.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. */ @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -55,8 +56,31 @@ namespace Swift { const std::vector >& getParts() const { return parts_; } + + void setFullMessageHighlightAction(const HighlightAction& action) { + fullMessageHighlightAction_ = action; + } + + const HighlightAction& getFullMessageHighlightAction() const { + return fullMessageHighlightAction_; + } + + bool isMeCommand() const { + bool isMeCommand = false; + if (!parts_.empty()) { + boost::shared_ptr textPart = boost::dynamic_pointer_cast(parts_[0]); + if (textPart) { + if (boost::starts_with(textPart->text, "/me ")) { + isMeCommand = true; + } + } + } + return isMeCommand; + } + private: std::vector > parts_; + HighlightAction fullMessageHighlightAction_; }; class ChatTextMessagePart : public ChatMessagePart { @@ -79,8 +103,7 @@ namespace Swift { class ChatHighlightingMessagePart : public ChatMessagePart { public: - std::string foregroundColor; - std::string backgroundColor; + HighlightAction action; std::string text; }; @@ -111,11 +134,11 @@ namespace Swift { /** Add message to window. * @return id of added message (for acks). */ - virtual std::string addMessage(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr 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 label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0; /** Adds action to window. * @return id of added message (for acks); */ - virtual std::string addAction(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr 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 label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0; /** Adds system message to window * @return id of added message (for replacement) @@ -124,9 +147,9 @@ namespace Swift { virtual void addPresenceMessage(const ChatMessage& message, Direction direction) = 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 replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) = 0; virtual void replaceSystemMessage(const ChatMessage& message, const std::string& id, const TimestampBehaviour timestampBehaviour) = 0; - virtual void replaceWithAction(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) = 0; // File transfer related stuff virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) = 0; diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index dddea6c..20c51bc 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -18,12 +18,12 @@ namespace Swift { MockChatWindow() : labelsEnabled_(false), impromptuMUCSupported_(false) {} virtual ~MockChatWindow(); - virtual std::string addMessage(const ChatMessage& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) { + virtual std::string addMessage(const ChatMessage& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/) { lastMessageBody_ = bodyFromMessage(message); return "id"; } - virtual std::string addAction(const ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {return "id";} + virtual std::string addAction(const ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/) {return "id";} virtual std::string addSystemMessage(const ChatMessage& message, Direction /*direction*/) { lastAddedSystemMessage_ = message; @@ -35,8 +35,8 @@ namespace Swift { } 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 replaceMessage(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/) {} + virtual void replaceWithAction(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/) {} virtual void replaceLastMessage(const ChatMessage& message, const TimestampBehaviour /*timestampBehaviour*/) { lastReplacedMessage_ = message; } diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h index e1d2e1a..9f0df44 100644 --- a/Swift/QtUI/QtChatView.h +++ b/Swift/QtUI/QtChatView.h @@ -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. */ @@ -28,19 +28,19 @@ namespace Swift { /** Add message to window. * @return id of added message (for acks). */ - virtual std::string addMessage(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; + virtual std::string addMessage(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0; /** Adds action to window. * @return id of added message (for acks); */ - virtual std::string addAction(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; + virtual std::string addAction(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0; virtual std::string addSystemMessage(const ChatWindow::ChatMessage& message, ChatWindow::Direction direction) = 0; virtual void addPresenceMessage(const ChatWindow::ChatMessage& message, ChatWindow::Direction direction) = 0; virtual void addErrorMessage(const ChatWindow::ChatMessage& message) = 0; - virtual void replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; + virtual void replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) = 0; virtual void replaceSystemMessage(const ChatWindow::ChatMessage& message, const std::string& id, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/) = 0; - virtual void replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; + virtual void replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) = 0; virtual void replaceLastMessage(const ChatWindow::ChatMessage& message, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/) = 0; virtual void setAckState(const std::string& id, ChatWindow::AckState state) = 0; diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 5c4723d..7649256 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -866,14 +866,14 @@ void QtChatWindow::addMUCInvitation(const std::string& senderName, const JID& ji messageLog_->addMUCInvitation(senderName, jid, reason, password, direct, isImpromptu, isContinuation); } -std::string QtChatWindow::addMessage(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) { +std::string QtChatWindow::addMessage(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time) { handleAppendedToLog(); - return messageLog_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time, highlight); + return messageLog_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time); } -std::string QtChatWindow::addAction(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) { +std::string QtChatWindow::addAction(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time) { handleAppendedToLog(); - return messageLog_->addAction(message, senderName, senderIsSelf, label, avatarPath, time, highlight); + return messageLog_->addAction(message, senderName, senderIsSelf, label, avatarPath, time); } @@ -893,14 +893,14 @@ void QtChatWindow::addErrorMessage(const ChatMessage& message) { } -void QtChatWindow::replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) { +void QtChatWindow::replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) { handleAppendedToLog(); - messageLog_->replaceMessage(message, id, time, highlight); + messageLog_->replaceMessage(message, id, time); } -void QtChatWindow::replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) { +void QtChatWindow::replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) { handleAppendedToLog(); - messageLog_->replaceWithAction(message, id, time, highlight); + messageLog_->replaceWithAction(message, id, time); } std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) { diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index 121192a..8acb10c 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.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. */ @@ -80,15 +80,15 @@ namespace Swift { public: QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings, const std::map& emoticons); virtual ~QtChatWindow(); - std::string addMessage(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); - std::string addAction(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); + std::string addMessage(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time); + std::string addAction(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time); std::string addSystemMessage(const ChatMessage& message, Direction direction); void addPresenceMessage(const ChatMessage& message, Direction direction); void addErrorMessage(const ChatMessage& message); - void replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight); - void replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight); + void replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time); + void replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time); // File transfer related stuff std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description); void setFileTransferProgress(std::string id, const int percentageDone); diff --git a/Swift/QtUI/QtPlainChatView.cpp b/Swift/QtUI/QtPlainChatView.cpp index a794167..3144080 100644 --- a/Swift/QtUI/QtPlainChatView.cpp +++ b/Swift/QtUI/QtPlainChatView.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. */ @@ -74,7 +74,7 @@ QString chatMessageToString(const ChatWindow::ChatMessage& message) { return result; } -std::string QtPlainChatView::addMessage(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time, const HighlightAction& /*highlight*/) { +std::string QtPlainChatView::addMessage(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time) { QString text = "

"; if (label) { text += P2QSTRING(label->getLabel()) + "
"; @@ -89,7 +89,7 @@ std::string QtPlainChatView::addMessage(const ChatWindow::ChatMessage& message, return idx; } -std::string QtPlainChatView::addAction(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time, const HighlightAction& /*highlight*/) { +std::string QtPlainChatView::addAction(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time) { QString text = "

"; if (label) { text += P2QSTRING(label->getLabel()) + "
"; @@ -129,7 +129,7 @@ void QtPlainChatView::addErrorMessage(const ChatWindow::ChatMessage& message) log_->append(text); } -void QtPlainChatView::replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& /*highlight*/) +void QtPlainChatView::replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) { QString text = "

"; if (lastMessageLabel_[id]) { @@ -142,7 +142,7 @@ void QtPlainChatView::replaceMessage(const ChatWindow::ChatMessage& message, con log_->append(text); } -void QtPlainChatView::replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& /*highlight*/) +void QtPlainChatView::replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) { QString text = "

"; if (lastMessageLabel_[id]) { diff --git a/Swift/QtUI/QtPlainChatView.h b/Swift/QtUI/QtPlainChatView.h index aeb50b6..fc293ff 100644 --- a/Swift/QtUI/QtPlainChatView.h +++ b/Swift/QtUI/QtPlainChatView.h @@ -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. */ @@ -35,18 +35,18 @@ namespace Swift { /** Add message to window. * @return id of added message (for acks). */ - virtual std::string addMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/); + virtual std::string addMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/); /** Adds action to window. * @return id of added message (for acks); */ - virtual std::string addAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/); + virtual std::string addAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/); virtual std::string addSystemMessage(const ChatWindow::ChatMessage& /*message*/, ChatWindow::Direction /*direction*/); virtual void addPresenceMessage(const ChatWindow::ChatMessage& /*message*/, ChatWindow::Direction /*direction*/); virtual void addErrorMessage(const ChatWindow::ChatMessage& /*message*/); - virtual void replaceMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/); - virtual void replaceWithAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/); + virtual void replaceMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/); + virtual void replaceWithAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/); virtual void replaceLastMessage(const ChatWindow::ChatMessage& /*message*/, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/); virtual void replaceSystemMessage(const ChatWindow::ChatMessage& message, const std::string& id, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/); virtual void setAckState(const std::string& /*id*/, ChatWindow::AckState /*state*/); diff --git a/Swift/QtUI/QtWebKitChatView.cpp b/Swift/QtUI/QtWebKitChatView.cpp index 2a8fed6..a0c65ef 100644 --- a/Swift/QtUI/QtWebKitChatView.cpp +++ b/Swift/QtUI/QtWebKitChatView.cpp @@ -472,14 +472,13 @@ void QtWebKitChatView::resetTopInsertPoint() { } std::string QtWebKitChatView::addMessage( - const ChatWindow::ChatMessage& message, - const std::string& senderName, - bool senderIsSelf, - boost::shared_ptr label, - const std::string& avatarPath, - const boost::posix_time::ptime& time, - const HighlightAction& highlight) { - return addMessage(chatMessageToHTML(message), senderName, senderIsSelf, label, avatarPath, "", time, highlight, ChatSnippet::getDirection(message)); + const ChatWindow::ChatMessage& message, + const std::string& senderName, + bool senderIsSelf, + boost::shared_ptr label, + const std::string& avatarPath, + const boost::posix_time::ptime& time) { + return addMessage(chatMessageToHTML(message), senderName, senderIsSelf, label, avatarPath, "", time, message.getFullMessageHighlightAction(), ChatSnippet::getDirection(message)); } QString QtWebKitChatView::getHighlightSpanStart(const std::string& text, const std::string& background) { @@ -524,7 +523,7 @@ QString QtWebKitChatView::chatMessageToHTML(const ChatWindow::ChatMessage& messa continue; } if ((highlightPart = boost::dynamic_pointer_cast(part))) { - QString spanStart = getHighlightSpanStart(highlightPart->foregroundColor, highlightPart->backgroundColor); + QString spanStart = getHighlightSpanStart(highlightPart->action.getTextColor(), highlightPart->action.getTextBackground()); result += spanStart + QtUtilities::htmlEscape(P2QSTRING(highlightPart->text)) + ""; continue; } @@ -572,8 +571,8 @@ std::string QtWebKitChatView::addMessage( return id; } -std::string QtWebKitChatView::addAction(const ChatWindow::ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) { - return addMessage(" *" + chatMessageToHTML(message) + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time, highlight, ChatSnippet::getDirection(message)); +std::string QtWebKitChatView::addAction(const ChatWindow::ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time) { + return addMessage(" *" + chatMessageToHTML(message) + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time, message.getFullMessageHighlightAction(), ChatSnippet::getDirection(message)); } static QString encodeButtonArgument(const QString& str) { @@ -815,12 +814,12 @@ std::string QtWebKitChatView::addSystemMessage(const ChatWindow::ChatMessage& me return id; } -void QtWebKitChatView::replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) { - replaceMessage(" *" + chatMessageToHTML(message) + "*", id, time, "font-style:italic ", highlight); +void QtWebKitChatView::replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) { + replaceMessage(" *" + chatMessageToHTML(message) + "*", id, time, "font-style:italic ", message.getFullMessageHighlightAction()); } -void QtWebKitChatView::replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) { - replaceMessage(chatMessageToHTML(message), id, time, "", highlight); +void QtWebKitChatView::replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) { + replaceMessage(chatMessageToHTML(message), id, time, "", message.getFullMessageHighlightAction()); } void QtWebKitChatView::replaceSystemMessage(const ChatWindow::ChatMessage& message, const std::string& id, ChatWindow::TimestampBehaviour timestampBehavior) { diff --git a/Swift/QtUI/QtWebKitChatView.h b/Swift/QtUI/QtWebKitChatView.h index b4141d4..aeed53b 100644 --- a/Swift/QtUI/QtWebKitChatView.h +++ b/Swift/QtUI/QtWebKitChatView.h @@ -50,19 +50,19 @@ namespace Swift { /** Add message to window. * @return id of added message (for acks). */ - virtual std::string addMessage(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) SWIFTEN_OVERRIDE; + virtual std::string addMessage(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time) SWIFTEN_OVERRIDE; /** Adds action to window. * @return id of added message (for acks); */ - virtual std::string addAction(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) SWIFTEN_OVERRIDE; + virtual std::string addAction(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time) SWIFTEN_OVERRIDE; virtual std::string addSystemMessage(const ChatWindow::ChatMessage& message, ChatWindow::Direction direction) SWIFTEN_OVERRIDE; virtual void addPresenceMessage(const ChatWindow::ChatMessage& message, ChatWindow::Direction direction) SWIFTEN_OVERRIDE; virtual void addErrorMessage(const ChatWindow::ChatMessage& message) SWIFTEN_OVERRIDE; - virtual void replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) SWIFTEN_OVERRIDE; + virtual void replaceMessage(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) SWIFTEN_OVERRIDE; virtual void replaceSystemMessage(const ChatWindow::ChatMessage& message, const std::string& id, ChatWindow::TimestampBehaviour timestampBehaviour) SWIFTEN_OVERRIDE; - virtual void replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) SWIFTEN_OVERRIDE; + virtual void replaceWithAction(const ChatWindow::ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time) SWIFTEN_OVERRIDE; virtual void replaceLastMessage(const ChatWindow::ChatMessage& message, const ChatWindow::TimestampBehaviour timestampBehaviour) SWIFTEN_OVERRIDE; virtual void setAckState(const std::string& id, ChatWindow::AckState state) SWIFTEN_OVERRIDE; -- cgit v0.10.2-6-g49f6