From 3a41fca4c1c2423c1f13cc3c77f9a70f767ae2dc Mon Sep 17 00:00:00 2001 From: Richard Maudsley Date: Thu, 23 Jan 2014 11:51:53 +0000 Subject: Preventing stale highlight rules by creating list encapsulation. Change-Id: I8f95d6bfd769fb104d972bd1cabfeb3ad79d308b diff --git a/Swift/Controllers/Chat/ChatMessageParser.cpp b/Swift/Controllers/Chat/ChatMessageParser.cpp index de4abb1..a43ef0e 100644 --- a/Swift/Controllers/Chat/ChatMessageParser.cpp +++ b/Swift/Controllers/Chat/ChatMessageParser.cpp @@ -20,9 +20,9 @@ namespace Swift { - ChatMessageParser::ChatMessageParser(const std::map& emoticons, const std::vector& highlightRules) - : emoticons_(emoticons), highlightRules_(highlightRules) { - + ChatMessageParser::ChatMessageParser(const std::map& emoticons, HighlightRulesListPtr highlightRules) + : emoticons_(emoticons), highlightRules_(highlightRules) + { } typedef std::pair StringPair; @@ -126,7 +126,8 @@ namespace Swift { { ChatWindow::ChatMessage parsedMessage = message; - foreach(const HighlightRule &rule, highlightRules_) { + for (size_t i = 0; i < highlightRules_->getSize(); ++i) { + const HighlightRule& rule = highlightRules_->getRule(i); foreach(const boost::regex ®ex, rule.getKeywordRegex()) { ChatWindow::ChatMessage newMessage; foreach (boost::shared_ptr part, parsedMessage.getParts()) { diff --git a/Swift/Controllers/Chat/ChatMessageParser.h b/Swift/Controllers/Chat/ChatMessageParser.h index e899246..1acb9c3 100644 --- a/Swift/Controllers/Chat/ChatMessageParser.h +++ b/Swift/Controllers/Chat/ChatMessageParser.h @@ -14,13 +14,12 @@ namespace Swift { class ChatMessageParser { public: - ChatMessageParser(const std::map& emoticons, const std::vector& highlightRules); + ChatMessageParser(const std::map& emoticons, HighlightRulesListPtr highlightRules); ChatWindow::ChatMessage parseMessageBody(const std::string& body, bool senderIsSelf = false); private: ChatWindow::ChatMessage emoticonHighlight(const ChatWindow::ChatMessage& parsedMessage); ChatWindow::ChatMessage splitHighlight(const ChatWindow::ChatMessage& parsedMessage); std::map emoticons_; - std::vector highlightRules_; - + HighlightRulesListPtr highlightRules_; }; } diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 6c5d6d9..d56f6cc 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -155,7 +155,7 @@ ChatsManager::ChatsManager( uiEventStream_ = uiEventStream; mucBookmarkManager_ = NULL; profileSettings_ = profileSettings; - chatMessageParser_ = new ChatMessageParser(emoticons, highlightManager->getRules()); + chatMessageParser_ = new ChatMessageParser(emoticons, highlightManager_->getRules()); presenceOracle_->onPresenceChange.connect(boost::bind(&ChatsManager::handlePresenceChange, this, _1)); uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&ChatsManager::handleUIEvent, this, _1)); diff --git a/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp index 4a25b50..9207846 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatMessageParserTest.cpp @@ -52,7 +52,7 @@ public: CPPUNIT_ASSERT_EQUAL(text, part->target); } - static std::vector ruleFromKeyword(const std::string& keyword, bool matchCase, bool matchWholeWord) + static HighlightRule ruleFromKeyword(const std::string& keyword, bool matchCase, bool matchWholeWord) { HighlightRule rule; std::vector keywords; @@ -60,26 +60,31 @@ public: rule.setKeywords(keywords); rule.setMatchCase(matchCase); rule.setMatchWholeWords(matchWholeWord); - std::vector rules; - rules.push_back(rule); - return rules; + return rule; } - static std::vector ruleFromKeywords(const std::vector& rules1, const std::vector& rules2) + static const HighlightRulesListPtr ruleListFromKeyword(const std::string& keyword, bool matchCase, bool matchWholeWord) { - std::vector rules = rules1; - rules.insert(rules.end(), rules2.begin(), rules2.end()); - return rules; + boost::shared_ptr list = boost::make_shared(); + list->addRule(ruleFromKeyword(keyword, matchCase, matchWholeWord)); + return list; } - void testFullBody() { + static const HighlightRulesListPtr ruleListFromKeywords(const HighlightRule &rule1, const HighlightRule &rule2) + { + boost::shared_ptr list = boost::make_shared(); + list->addRule(rule1); + list->addRule(rule2); + return list; + } + void testFullBody() { const std::string no_special_message = "a message with no special content"; - ChatMessageParser testling(emoticons_, std::vector()); + ChatMessageParser testling(emoticons_, boost::make_shared()); ChatWindow::ChatMessage result = testling.parseMessageBody(no_special_message); assertText(result, 0, no_special_message); - testling = ChatMessageParser(emoticons_, ruleFromKeyword("trigger", false, false)); + testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false)); result = testling.parseMessageBody(":) shiny :( trigger :) http://wonderland.lit/blah http://denmark.lit boom boom"); assertEmoticon(result, 0, smile1_, smile1Path_); assertText(result, 1, " shiny "); @@ -94,72 +99,72 @@ public: assertURL(result, 10, "http://denmark.lit"); assertText(result, 11, " boom boom"); - testling = ChatMessageParser(emoticons_, ruleFromKeyword("trigger", false, false)); + testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false)); result = testling.parseMessageBody("testtriggermessage"); assertText(result, 0, "test"); assertHighlight(result, 1, "trigger"); assertText(result, 2, "message"); - testling = ChatMessageParser(emoticons_, ruleFromKeyword("trigger", false, true)); + testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, true)); result = testling.parseMessageBody("testtriggermessage"); assertText(result, 0, "testtriggermessage"); - testling = ChatMessageParser(emoticons_, ruleFromKeyword("trigger", true, false)); + testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", true, false)); result = testling.parseMessageBody("TrIgGeR"); assertText(result, 0, "TrIgGeR"); - testling = ChatMessageParser(emoticons_, ruleFromKeyword("trigger", false, false)); + testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false)); result = testling.parseMessageBody("TrIgGeR"); assertHighlight(result, 0, "TrIgGeR"); - testling = ChatMessageParser(emoticons_, ruleFromKeyword("trigger", false, false)); + testling = ChatMessageParser(emoticons_, ruleListFromKeyword("trigger", false, false)); result = testling.parseMessageBody("partialTrIgGeRmatch"); assertText(result, 0, "partial"); assertHighlight(result, 1, "TrIgGeR"); assertText(result, 2, "match"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", false, false))); + 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"); assertText(result, 2, " two "); assertHighlight(result, 3, "three"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", false, false))); + 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"); assertText(result, 2, " two "); assertHighlight(result, 3, "tHrEe"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", true, false))); + 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"); assertText(result, 2, " two tHrEe"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", true, false), ruleFromKeyword("three", true, false))); + testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", true, false), ruleFromKeyword("three", true, false))); result = testling.parseMessageBody("zero oNe two tHrEe"); assertText(result, 0, "zero oNe two tHrEe"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", false, false))); + testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, false), ruleFromKeyword("three", false, false))); result = testling.parseMessageBody("zeroonetwothree"); assertText(result, 0, "zero"); assertHighlight(result, 1, "one"); assertText(result, 2, "two"); assertHighlight(result, 3, "three"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", true, false), ruleFromKeyword("three", false, false))); + testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", true, false), ruleFromKeyword("three", false, false))); result = testling.parseMessageBody("zeroOnEtwoThReE"); assertText(result, 0, "zeroOnEtwo"); assertHighlight(result, 1, "ThReE"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", false, true), ruleFromKeyword("three", false, false))); + testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, true), ruleFromKeyword("three", false, false))); result = testling.parseMessageBody("zeroonetwothree"); assertText(result, 0, "zeroonetwo"); assertHighlight(result, 1, "three"); - testling = ChatMessageParser(emoticons_, ruleFromKeywords(ruleFromKeyword("one", false, true), ruleFromKeyword("three", false, true))); + testling = ChatMessageParser(emoticons_, ruleListFromKeywords(ruleFromKeyword("one", false, true), ruleFromKeyword("three", false, true))); result = testling.parseMessageBody("zeroonetwothree"); assertText(result, 0, "zeroonetwothree"); } diff --git a/Swift/Controllers/HighlightManager.cpp b/Swift/Controllers/HighlightManager.cpp index 17ce776..2d597a7 100644 --- a/Swift/Controllers/HighlightManager.cpp +++ b/Swift/Controllers/HighlightManager.cpp @@ -43,6 +43,7 @@ HighlightManager::HighlightManager(SettingsProvider* settings) : settings_(settings) , storingSettings_(false) { + rules_ = boost::make_shared(); loadSettings(); settings_->onSettingChanged.connect(boost::bind(&HighlightManager::handleSettingChanged, this, _1)); } @@ -58,26 +59,10 @@ std::string HighlightManager::rulesToString() const { std::stringstream stream; boost::archive::text_oarchive archive(stream); - archive << rules_; + archive << rules_->list_; return stream.str(); } -std::vector HighlightManager::rulesFromString(const std::string& rulesString) -{ - std::vector rules; - if (rulesString.length()) { - std::stringstream stream; - stream << rulesString; - try { - boost::archive::text_iarchive archive(stream); - archive >> rules; - } catch (boost::archive::archive_exception&) { - /* archive corrupted */ - } - } - return rules; -} - std::vector HighlightManager::getDefaultRules() { std::vector rules; @@ -90,29 +75,26 @@ std::vector HighlightManager::getDefaultRules() HighlightRule HighlightManager::getRule(int index) const { - assert(index >= 0 && static_cast(index) < rules_.size()); - return rules_[static_cast(index)]; + assert(index >= 0 && static_cast(index) < rules_->getSize()); + return rules_->getRule(static_cast(index)); } void HighlightManager::setRule(int index, const HighlightRule& rule) { - assert(index >= 0 && static_cast(index) < rules_.size()); - rules_[static_cast(index)] = rule; - //storeSettings(); + assert(index >= 0 && static_cast(index) < rules_->getSize()); + rules_->list_[static_cast(index)] = rule; } void HighlightManager::insertRule(int index, const HighlightRule& rule) { - assert(index >= 0 && boost::numeric_cast::size_type>(index) <= rules_.size()); - rules_.insert(rules_.begin() + index, rule); - //storeSettings(); + assert(index >= 0 && boost::numeric_cast::size_type>(index) <= rules_->getSize()); + rules_->list_.insert(rules_->list_.begin() + index, rule); } void HighlightManager::removeRule(int index) { - assert(index >= 0 && boost::numeric_cast::size_type>(index) < rules_.size()); - rules_.erase(rules_.begin() + index); - //storeSettings(); + assert(index >= 0 && boost::numeric_cast::size_type>(index) < rules_->getSize()); + rules_->list_.erase(rules_->list_.begin() + index); } void HighlightManager::storeSettings() @@ -124,8 +106,18 @@ void HighlightManager::storeSettings() void HighlightManager::loadSettings() { - std::string highlightRules = settings_->getSetting(SettingConstants::HIGHLIGHT_RULES); - rules_ = rulesFromString(highlightRules); + std::string rulesString = settings_->getSetting(SettingConstants::HIGHLIGHT_RULES); + + if (rulesString.length()) { + std::stringstream stream; + stream << rulesString; + try { + boost::archive::text_iarchive archive(stream); + archive >> rules_->list_; + } catch (boost::archive::archive_exception&) { + /* archive corrupted */ + } + } } Highlighter* HighlightManager::createHighlighter() diff --git a/Swift/Controllers/HighlightManager.h b/Swift/Controllers/HighlightManager.h index e91d8ce..4f4fe6e 100644 --- a/Swift/Controllers/HighlightManager.h +++ b/Swift/Controllers/HighlightManager.h @@ -19,11 +19,26 @@ namespace Swift { class HighlightManager { public: + + class HighlightRulesList { + public: + friend class HighlightManager; + size_t getSize() const { return list_.size(); } + const HighlightRule& getRule(const size_t index) const { return list_[index]; } + void addRule(const HighlightRule &rule) { list_.push_back(rule); } + void combineRules(const HighlightRulesList &rhs) { + list_.insert(list_.end(), rhs.list_.begin(), rhs.list_.end()); + } + private: + std::vector list_; + }; + HighlightManager(SettingsProvider* settings); Highlighter* createHighlighter(); - const std::vector& getRules() const { return rules_; } + boost::shared_ptr getRules() const { return rules_; } + HighlightRule getRule(int index) const; void setRule(int index, const HighlightRule& rule); void insertRule(int index, const HighlightRule& rule); @@ -37,13 +52,14 @@ namespace Swift { void handleSettingChanged(const std::string& settingPath); std::string rulesToString() const; - static std::vector rulesFromString(const std::string&); static std::vector getDefaultRules(); SettingsProvider* settings_; bool storingSettings_; - std::vector rules_; + boost::shared_ptr rules_; }; + typedef boost::shared_ptr HighlightRulesListPtr; + } diff --git a/Swift/Controllers/Highlighter.cpp b/Swift/Controllers/Highlighter.cpp index 754641a..32d5739 100644 --- a/Swift/Controllers/Highlighter.cpp +++ b/Swift/Controllers/Highlighter.cpp @@ -24,9 +24,11 @@ void Highlighter::setMode(Mode mode) HighlightAction Highlighter::findAction(const std::string& body, const std::string& sender) const { - foreach (const HighlightRule & r, manager_->getRules()) { - if (r.isMatch(body, sender, nick_, messageType_)) { - return r.getAction(); + 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(); } } diff --git a/Swift/QtUI/QtHighlightEditor.cpp b/Swift/QtUI/QtHighlightEditor.cpp index 2221336..ab26e28 100644 --- a/Swift/QtUI/QtHighlightEditor.cpp +++ b/Swift/QtUI/QtHighlightEditor.cpp @@ -387,7 +387,9 @@ void QtHighlightEditor::selectSoundFile() void QtHighlightEditor::populateList() { ui_.listWidget->clear(); - foreach(const HighlightRule &rule, highlightManager_->getRules()) { + HighlightRulesListPtr rules = highlightManager_->getRules(); + for (size_t i = 0; i < rules->getSize(); ++i) { + const HighlightRule& rule = rules->getRule(i); QListWidgetItem *item = new QListWidgetItem(); item->setText(P2QSTRING(formatShortDescription(rule))); ui_.listWidget->addItem(item); -- cgit v0.10.2-6-g49f6