diff options
21 files changed, 305 insertions, 155 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); 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<HighlightRulesList>(); 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<HighlightRule> HighlightManager::getDefaultRules() -{ +std::vector<HighlightRule> HighlightManager::getDefaultRules() { std::vector<HighlightRule> rules; HighlightRule chatNotificationRule; @@ -92,26 +88,22 @@ std::vector<HighlightRule> HighlightManager::getDefaultRules() return rules; } -HighlightRule HighlightManager::getRule(int index) const -{ +HighlightRule HighlightManager::getRule(int index) const { assert(index >= 0 && static_cast<size_t>(index) < rules_->getSize()); return rules_->getRule(static_cast<size_t>(index)); } -void HighlightManager::setRule(int index, const HighlightRule& rule) -{ +void HighlightManager::setRule(int index, const HighlightRule& rule) { assert(index >= 0 && static_cast<size_t>(index) < rules_->getSize()); rules_->list_[static_cast<size_t>(index)] = rule; } -void HighlightManager::insertRule(int index, const HighlightRule& rule) -{ +void HighlightManager::insertRule(int index, const HighlightRule& rule) { assert(index >= 0 && boost::numeric_cast<std::vector<std::string>::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<std::vector<std::string>::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 <Swiften/Base/foreach.h> #include <Swift/Controllers/Highlighter.h> + +#include <Swiften/Base/foreach.h> + #include <Swift/Controllers/HighlightManager.h> 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 <string> +#include <vector> #include <Swift/Controllers/HighlightRule.h> @@ -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 <string> #include <vector> +#include <boost/algorithm/string.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/make_shared.hpp> #include <boost/optional.hpp> @@ -55,8 +56,31 @@ namespace Swift { const std::vector<boost::shared_ptr<ChatMessagePart> >& 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<ChatTextMessagePart> textPart = boost::dynamic_pointer_cast<ChatTextMessagePart>(parts_[0]); + if (textPart) { + if (boost::starts_with(textPart->text, "/me ")) { + isMeCommand = true; + } + } + } + return isMeCommand; + } + private: std::vector<boost::shared_ptr<ChatMessagePart> > 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<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; + virtual std::string addMessage(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 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<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; + virtual std::string addAction(const ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 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<SecurityLabel> /*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<SecurityLabel> /*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<SecurityLabel> /*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<SecurityLabel> /*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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<std::string, std::string>& emoticons); virtual ~QtChatWindow(); - std::string addMessage(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); - std::string addAction(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); + std::string addMessage(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time); + std::string addAction(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time); 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<SecurityLabel> 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<SecurityLabel> label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time) { QString text = "<p>"; if (label) { text += P2QSTRING(label->getLabel()) + "<br/>"; @@ -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<SecurityLabel> 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<SecurityLabel> label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time) { QString text = "<p>"; if (label) { text += P2QSTRING(label->getLabel()) + "<br/>"; @@ -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 = "<p>"; 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 = "<p>"; 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<SecurityLabel> /*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<SecurityLabel> /*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<SecurityLabel> /*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<SecurityLabel> /*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<SecurityLabel> 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<SecurityLabel> 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<ChatWindow::ChatHighlightingMessagePart>(part))) { - QString spanStart = getHighlightSpanStart(highlightPart->foregroundColor, highlightPart->backgroundColor); + QString spanStart = getHighlightSpanStart(highlightPart->action.getTextColor(), highlightPart->action.getTextBackground()); result += spanStart + QtUtilities::htmlEscape(P2QSTRING(highlightPart->text)) + "</span>"; 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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<SecurityLabel> 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; |