From 683b87d0b81c354f0c32afd5da33226d27719729 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Tue, 6 Feb 2018 21:03:54 +0100 Subject: [PATCH] src: use wstring in symbol search --- .../component/controller/CodeController.cpp | 2 +- .../component/controller/SearchController.cpp | 10 +-- .../controller/UndoRedoController.cpp | 8 +- src/lib/component/view/SearchView.h | 2 +- src/lib/data/NodeType.cpp | 9 +- src/lib/data/NodeType.h | 3 +- src/lib/data/access/StorageAccess.h | 2 +- src/lib/data/access/StorageAccessProxy.cpp | 2 +- src/lib/data/access/StorageAccessProxy.h | 2 +- src/lib/data/search/SearchIndex.cpp | 69 +++++++------- src/lib/data/search/SearchIndex.h | 31 ++++--- src/lib/data/search/SearchMatch.cpp | 75 ++++++++-------- src/lib/data/search/SearchMatch.h | 30 +++---- src/lib/data/storage/PersistentStorage.cpp | 42 ++++----- src/lib/data/storage/PersistentStorage.h | 8 +- .../utility/messaging/type/MessageSearch.h | 11 ++- .../type/MessageSearchAutocomplete.h | 6 +- .../messaging/type/MessageSearchFullText.h | 6 +- src/lib/utility/utilityString.cpp | 83 ++++++++--------- src/lib/utility/utilityString.h | 14 +++ .../qt/element/QtAutocompletionList.cpp | 25 +++--- src/lib_gui/qt/element/QtHistoryList.cpp | 8 +- src/lib_gui/qt/element/QtSmartSearchBox.cpp | 90 +++++++++---------- src/lib_gui/qt/element/QtSmartSearchBox.h | 4 +- src/lib_gui/qt/view/QtSearchView.cpp | 4 +- src/lib_gui/qt/view/QtSearchView.h | 8 +- src/lib_gui/qt/window/QtMainWindow.cpp | 4 +- src/test/SearchIndexTestSuite.h | 40 ++++----- 28 files changed, 307 insertions(+), 291 deletions(-) diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index f58ee104..ada0ac7c 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -339,7 +339,7 @@ void CodeController::handleMessage(MessageSearchFullText* message) saveOrRestoreViewMode(message); - m_collection = m_storageAccess->getFullTextSearchLocations(message->searchTerm, message->caseSensitive); + m_collection = m_storageAccess->getFullTextSearchLocations(utility::encodeToUtf8(message->searchTerm), message->caseSensitive); CodeView::ScrollParams scrollParams(CodeView::ScrollParams::SCROLL_TO_DEFINITION); getView()->scrollTo(scrollParams); diff --git a/src/lib/component/controller/SearchController.cpp b/src/lib/component/controller/SearchController.cpp index 37e49c9e..f45b192a 100644 --- a/src/lib/component/controller/SearchController.cpp +++ b/src/lib/component/controller/SearchController.cpp @@ -50,12 +50,12 @@ void SearchController::handleMessage(MessageActivateTokens* message) for (const NameHierarchy& name : message->tokenNames) { - matches.push_back(SearchMatch(utility::encodeToUtf8(name.getQualifiedName()))); + matches.push_back(SearchMatch(name.getQualifiedName())); } if (!matches.size()) { - matches.push_back(SearchMatch("")); + matches.push_back(SearchMatch(L"")); } getView()->setMatches(matches); @@ -86,14 +86,14 @@ void SearchController::handleMessage(MessageSearchAutocomplete* message) return; } - LOG_INFO("autocomplete string: \"" + message->query + "\""); + LOG_INFO(L"autocomplete string: \"" + message->query + L"\""); view->setAutocompletionList(m_storageAccess->getAutocompletionMatches(message->query, message->acceptedNodeTypes)); } void SearchController::handleMessage(MessageSearchFullText* message) { - LOG_INFO("fulltext string: \"" + message->searchTerm + "\""); - std::string prefix(message->caseSensitive ? 2 : 1, SearchMatch::FULLTEXT_SEARCH_CHARACTER); + LOG_INFO(L"fulltext string: \"" + message->searchTerm + L"\""); + std::wstring prefix(message->caseSensitive ? 2 : 1, SearchMatch::FULLTEXT_SEARCH_CHARACTER); SearchMatch match(prefix + message->searchTerm); match.searchType = SearchMatch::SEARCH_FULLTEXT; diff --git a/src/lib/component/controller/UndoRedoController.cpp b/src/lib/component/controller/UndoRedoController.cpp index d2a8a65b..8d941dee 100644 --- a/src/lib/component/controller/UndoRedoController.cpp +++ b/src/lib/component/controller/UndoRedoController.cpp @@ -557,7 +557,7 @@ void UndoRedoController::updateHistory() index++; SearchMatch match = getSearchMatchForMessage(it->message.get()); - if (!match.text.size()) + if (match.text.empty()) { continue; } @@ -607,7 +607,7 @@ SearchMatch UndoRedoController::getSearchMatchForMessage(MessageBase* message) c SearchMatch match = SearchMatch::createCommand(SearchMatch::COMMAND_ALL); if (dynamic_cast(message)->acceptedNodeTypes != NodeTypeSet::all()) { - match.name = match.text = "filter"; // TODO: show acceptedNodeTypes names or at least type ids + match.name = match.text = L"filter"; // TODO: show acceptedNodeTypes names or at least type ids } return match; } @@ -621,7 +621,7 @@ SearchMatch UndoRedoController::getSearchMatchForMessage(MessageBase* message) c else if (msg->isAggregation) { SearchMatch match; - match.name = match.text = "aggregation"; // TODO: show aggregation source and target + match.name = match.text = L"aggregation"; // TODO: show aggregation source and target match.searchType = SearchMatch::SEARCH_TOKEN; match.nodeType = NodeType::NODE_TYPE; return match; @@ -630,7 +630,7 @@ SearchMatch UndoRedoController::getSearchMatchForMessage(MessageBase* message) c else if (message->getType() == MessageSearchFullText::getStaticType()) { MessageSearchFullText* msg = dynamic_cast(message); - std::string prefix(msg->caseSensitive ? 2 : 1, SearchMatch::FULLTEXT_SEARCH_CHARACTER); + std::wstring prefix(msg->caseSensitive ? 2 : 1, SearchMatch::FULLTEXT_SEARCH_CHARACTER); SearchMatch match(prefix + msg->searchTerm); match.searchType = SearchMatch::SEARCH_FULLTEXT; diff --git a/src/lib/component/view/SearchView.h b/src/lib/component/view/SearchView.h index 31939b57..6aecd3f4 100644 --- a/src/lib/component/view/SearchView.h +++ b/src/lib/component/view/SearchView.h @@ -15,7 +15,7 @@ public: virtual std::string getName() const; - virtual std::string getQuery() const = 0; + virtual std::wstring getQuery() const = 0; virtual void setMatches(const std::vector& matches) = 0; diff --git a/src/lib/data/NodeType.cpp b/src/lib/data/NodeType.cpp index 07252853..916bfaf4 100644 --- a/src/lib/data/NodeType.cpp +++ b/src/lib/data/NodeType.cpp @@ -417,12 +417,17 @@ std::string utility::getReadableTypeString(NodeType::Type type) return ""; } -NodeType::Type utility::getTypeForReadableTypeString(const std::string str) +std::wstring utility::getReadableTypeWString(NodeType::Type type) +{ + return utility::decodeFromUtf8(getReadableTypeString(type)); +} + +NodeType::Type utility::getTypeForReadableTypeString(const std::wstring str) { for (NodeType::TypeMask mask = 1; mask <= NodeType::NODE_MAX_VALUE; mask *= 2) { NodeType::Type type = intToType(mask); - if (getReadableTypeString(type) == str) + if (getReadableTypeWString(type) == str) { return type; } diff --git a/src/lib/data/NodeType.h b/src/lib/data/NodeType.h index 42525c59..eae4505b 100644 --- a/src/lib/data/NodeType.h +++ b/src/lib/data/NodeType.h @@ -119,7 +119,8 @@ namespace utility int nodeTypeToInt(NodeType::Type type); NodeType::Type intToType(int value); std::string getReadableTypeString(NodeType::Type type); - NodeType::Type getTypeForReadableTypeString(const std::string str); + std::wstring getReadableTypeWString(NodeType::Type type); + NodeType::Type getTypeForReadableTypeString(const std::wstring str); } #endif // NODE_TYPE_H diff --git a/src/lib/data/access/StorageAccess.h b/src/lib/data/access/StorageAccess.h index 2cdf612b..48c3a9f6 100644 --- a/src/lib/data/access/StorageAccess.h +++ b/src/lib/data/access/StorageAccess.h @@ -49,7 +49,7 @@ public: virtual std::shared_ptr getFullTextSearchLocations( const std::string& searchTerm, bool caseSensitive) const = 0; - virtual std::vector getAutocompletionMatches(const std::string& query, NodeTypeSet acceptedNodeTypes) const = 0; + virtual std::vector getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const = 0; virtual std::vector getSearchMatchesForTokenIds(const std::vector& tokenIds) const = 0; virtual std::shared_ptr getGraphForAll() const = 0; diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index bd73ca3d..88bf8da9 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -126,7 +126,7 @@ std::shared_ptr StorageAccessProxy::getFullTextSearchL return std::make_shared(); } -std::vector StorageAccessProxy::getAutocompletionMatches(const std::string& query, NodeTypeSet acceptedNodeTypes) const +std::vector StorageAccessProxy::getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const { if (hasSubject()) { diff --git a/src/lib/data/access/StorageAccessProxy.h b/src/lib/data/access/StorageAccessProxy.h index 75967a2b..a5e7cd60 100644 --- a/src/lib/data/access/StorageAccessProxy.h +++ b/src/lib/data/access/StorageAccessProxy.h @@ -33,7 +33,7 @@ public: virtual std::shared_ptr getFullTextSearchLocations( const std::string& searchTerm, bool caseSensitive) const override; - virtual std::vector getAutocompletionMatches(const std::string& query, NodeTypeSet acceptedNodeTypes) const override; + virtual std::vector getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const override; virtual std::vector getSearchMatchesForTokenIds(const std::vector& tokenIds) const override; virtual std::shared_ptr getGraphForAll() const override; diff --git a/src/lib/data/search/SearchIndex.cpp b/src/lib/data/search/SearchIndex.cpp index 7dfee333..fa740806 100644 --- a/src/lib/data/search/SearchIndex.cpp +++ b/src/lib/data/search/SearchIndex.cpp @@ -16,18 +16,18 @@ SearchIndex::~SearchIndex() { } -void SearchIndex::addNode(Id id, const std::string& name, NodeTypeSet typeSet) +void SearchIndex::addNode(Id id, const std::wstring& name, NodeTypeSet typeSet) { SearchNode* currentNode = m_root; - std::string remaining = name; + std::wstring remaining = name; while (remaining.size() > 0) { auto it = currentNode->edges.find(remaining[0]); if (it != currentNode->edges.end()) { SearchEdge* currentEdge = it->second; - const std::string& edgeString = currentEdge->s; + const std::wstring& edgeString = currentEdge->s; size_t matchCount = 1; for (size_t j = 1; j < edgeString.size() && j < remaining.size(); j++) @@ -72,7 +72,7 @@ void SearchIndex::addNode(Id id, const std::string& name, NodeTypeSet typeSet) currentNode->edges.emplace(e->s[0], e.get()); currentNode = n.get(); - remaining = ""; + remaining = L""; } } @@ -100,7 +100,7 @@ void SearchIndex::clear() } std::vector SearchIndex::search( - const std::string& query, NodeTypeSet acceptedNodeTypes, size_t maxResultCount, size_t maxBestScoredResultsLength) const + const std::wstring& query, NodeTypeSet acceptedNodeTypes, size_t maxResultCount, size_t maxBestScoredResultsLength) const { // find paths containing query SearchPath startPath; @@ -113,7 +113,7 @@ std::vector SearchIndex::search( std::multiset searchResults = createScoredResults(paths, acceptedNodeTypes, maxResultCount * 3); // find best scores - std::map scoresCache; + std::map scoresCache; std::multiset bestResults; for (const SearchResult& result : searchResults) { @@ -147,7 +147,7 @@ void SearchIndex::populateEdgeGate(SearchEdge* e) } void SearchIndex::searchRecursive( - const SearchPath& path, const std::string& remainingQuery, NodeTypeSet acceptedNodeTypes, + const SearchPath& path, const std::wstring& remainingQuery, NodeTypeSet acceptedNodeTypes, std::vector* results) const { if (remainingQuery.size() == 0 && (acceptedNodeTypes.intersectsWith(path.node->containedTypes))) @@ -174,7 +174,7 @@ void SearchIndex::searchRecursive( if (passesGate) { // consume characters for edge - const std::string& edgeString = currentEdge->s; + const std::wstring& edgeString = currentEdge->s; SearchPath currentPath; currentPath.node = currentEdge->target; @@ -253,9 +253,9 @@ std::multiset SearchIndex::createScoredResults( } SearchResult SearchIndex::bestScoredResult( - SearchResult result, std::map* scoresCache, size_t maxBestScoredResultsLength) + SearchResult result, std::map* scoresCache, size_t maxBestScoredResultsLength) { - std::string text = result.text; + std::wstring text = result.text; if (maxBestScoredResultsLength && result.text.size() > maxBestScoredResultsLength) { @@ -289,8 +289,8 @@ SearchResult SearchIndex::bestScoredResult( } void SearchIndex::bestScoredResultRecursive( - const std::string& lowerText, const std::vector& indices, const size_t lastIndex, const size_t indicesPos, - std::map* scoresCache, SearchResult* result) + const std::wstring& lowerText, const std::vector& indices, const size_t lastIndex, const size_t indicesPos, + std::map* scoresCache, SearchResult* result) { // left for debugging // std::cout << lowerText << std::endl; @@ -316,7 +316,7 @@ void SearchIndex::bestScoredResultRecursive( { if (lowerText[i] == lowerText[lastIndex]) { - std::string lowerTextPart = result->text.substr(0, i + 1); + std::wstring lowerTextPart = result->text.substr(0, i + 1); auto it = scoresCache->find(lowerTextPart); if (it != scoresCache->end()) @@ -380,7 +380,7 @@ void SearchIndex::bestScoredResultRecursive( } } -int SearchIndex::scoreText(const std::string& text, const std::vector& indices) +int SearchIndex::scoreText(const std::wstring& text, const std::vector& indices) { const int unmatchedLetterBonus = -1; const int consecutiveLetterBonus = 4; @@ -390,20 +390,6 @@ int SearchIndex::scoreText(const std::string& text, const std::vector& i const int delayedStartBonus = -1; const int minDelayedStartBonus = -20; - static bool isNoLetter[256] = { false }; - if (!isNoLetter[int(' ')]) - { - isNoLetter[int(' ')] = true; - isNoLetter[int('.')] = true; - isNoLetter[int(',')] = true; - isNoLetter[int('_')] = true; - isNoLetter[int(':')] = true; - isNoLetter[int('<')] = true; - isNoLetter[int('>')] = true; - isNoLetter[int('/')] = true; - isNoLetter[int('\\')] = true; - } - int unmatchedLetterScore = 0; int consecutiveLetterScore = 0; int camelCaseScore = 0; @@ -427,7 +413,7 @@ int SearchIndex::scoreText(const std::string& text, const std::vector& i firstLetterScore += firstLetterBonus; } // after no letter - else if (index != 0 && isNoLetter[ int(text[index - 1]) ]) + else if (index != 0 && isNoLetter(text[index - 1])) { noLetterScore += noLetterBonus; } @@ -462,8 +448,8 @@ int SearchIndex::scoreText(const std::string& text, const std::vector& i } SearchResult SearchIndex::rescoreText( - const std::string& fulltext, - const std::string& text, + const std::wstring& fulltext, + const std::wstring& text, const std::vector& indices, int score, size_t maxBestScoredResultsLength) @@ -514,7 +500,7 @@ SearchResult SearchIndex::rescoreText( result.score = scoreText(text, textIndices); result.indices = textIndices; - std::map scoresCache; + std::map scoresCache; result = bestScoredResult(result, &scoresCache, maxBestScoredResultsLength); for (size_t i = 0; i < result.indices.size(); i++) @@ -524,3 +510,22 @@ SearchResult SearchIndex::rescoreText( return result; } + +bool SearchIndex::isNoLetter(const wchar_t c) +{ + switch (c) + { + case L' ': + case L'.': + case L',': + case L'_': + case L':': + case L'<': + case L'>': + case L'/': + case L'\\': + return true; + } + return false; +} + diff --git a/src/lib/data/search/SearchIndex.h b/src/lib/data/search/SearchIndex.h index 886c6c9d..fbfca1b6 100644 --- a/src/lib/data/search/SearchIndex.h +++ b/src/lib/data/search/SearchIndex.h @@ -12,6 +12,7 @@ #include "data/graph/Node.h" #include "data/NodeTypeSet.h" +// SearchResult is only used as an internal type in the SearchIndex and the PersistentStorage struct SearchResult { bool operator<(const SearchResult& other) const @@ -19,7 +20,7 @@ struct SearchResult return score > other.score; } - std::string text; + std::wstring text; std::set elementIds; std::vector indices; int score; @@ -31,13 +32,13 @@ public: SearchIndex(); virtual ~SearchIndex(); - void addNode(Id id, const std::string& name, NodeTypeSet typeSet = NodeTypeSet::all()); + void addNode(Id id, const std::wstring& name, NodeTypeSet typeSet = NodeTypeSet::all()); void finishSetup(); void clear(); // maxResultCount == 0 means "no restriction". std::vector search( - const std::string& query, NodeTypeSet acceptedNodeTypes, size_t maxResultCount, size_t maxBestScoredResultsLength = 0) const; + const std::wstring& query, NodeTypeSet acceptedNodeTypes, size_t maxResultCount, size_t maxBestScoredResultsLength = 0) const; private: struct SearchEdge; @@ -46,45 +47,47 @@ private: { std::set elementIds; NodeTypeSet containedTypes; - std::map edges; + std::map edges; }; struct SearchEdge { SearchNode* target; - std::string s; - std::unordered_set gate; + std::wstring s; + std::unordered_set gate; }; struct SearchPath { - std::string text; + std::wstring text; std::vector indices; SearchNode* node; }; void populateEdgeGate(SearchEdge* e); - void searchRecursive(const SearchPath& path, const std::string& remainingQuery, NodeTypeSet acceptedNodeTypes, + void searchRecursive(const SearchPath& path, const std::wstring& remainingQuery, NodeTypeSet acceptedNodeTypes, std::vector* results) const; std::multiset createScoredResults( const std::vector& paths, NodeTypeSet acceptedNodeTypes, size_t maxResultCount) const; static SearchResult bestScoredResult( - SearchResult result, std::map* scoresCache, size_t maxBestScoredResultsLength); + SearchResult result, std::map* scoresCache, size_t maxBestScoredResultsLength); static void bestScoredResultRecursive( - const std::string& lowerText, const std::vector& indices, const size_t lastIndex, const size_t indicesPos, - std::map* scoresCache, SearchResult* result); - static int scoreText(const std::string& text, const std::vector& indices); + const std::wstring& lowerText, const std::vector& indices, const size_t lastIndex, const size_t indicesPos, + std::map* scoresCache, SearchResult* result); + static int scoreText(const std::wstring& text, const std::vector& indices); public: static SearchResult rescoreText( - const std::string& fulltext, - const std::string& text, + const std::wstring& fulltext, + const std::wstring& text, const std::vector& indices, int score, size_t maxBestScoredResultsLength); + static bool isNoLetter(const wchar_t c); + private: std::vector> m_nodes; std::vector> m_edges; diff --git a/src/lib/data/search/SearchMatch.cpp b/src/lib/data/search/SearchMatch.cpp index 80a935fe..60287c63 100644 --- a/src/lib/data/search/SearchMatch.cpp +++ b/src/lib/data/search/SearchMatch.cpp @@ -5,9 +5,9 @@ #include "data/NodeTypeSet.h" #include "utility/logging/logging.h" -void SearchMatch::log(const std::vector& matches, const std::string& query) +void SearchMatch::log(const std::vector& matches, const std::wstring& query) { - std::stringstream ss; + std::wstringstream ss; ss << std::endl << matches.size() << " matches for \"" << query << "\":" << std::endl; for (const SearchMatch& match : matches) @@ -18,30 +18,30 @@ void SearchMatch::log(const std::vector& matches, const std::string LOG_INFO(ss.str()); } -std::string SearchMatch::getSearchTypeName(SearchType type) +std::wstring SearchMatch::getSearchTypeName(SearchType type) { switch (type) { case SEARCH_NONE: - return "none"; + return L"none"; case SEARCH_TOKEN: - return "token"; + return L"token"; case SEARCH_COMMAND: - return "command"; + return L"command"; case SEARCH_OPERATOR: - return "operator"; + return L"operator"; case SEARCH_FULLTEXT: - return "fulltext"; + return L"fulltext"; } } -std::string SearchMatch::searchMatchesToString(const std::vector& matches) +std::wstring SearchMatch::searchMatchesToString(const std::vector& matches) { - std::stringstream ss; + std::wstringstream ss; for (size_t i = 0; i < matches.size(); i++) { - ss << '@' << matches[i].getFullName(); + ss << L'@' << matches[i].getFullName(); } return ss.str(); @@ -52,7 +52,7 @@ SearchMatch SearchMatch::createCommand(CommandType type) SearchMatch match; match.name = getCommandName(type); match.text = match.name; - match.typeName = "command"; + match.typeName = L"command"; match.searchType = SEARCH_COMMAND; return match; } @@ -64,9 +64,9 @@ std::vector SearchMatch::createCommandsForNodeTypes(NodeTypeSet typ for (const NodeType& type: types.getNodeTypes()) { SearchMatch match; - match.name = type.getReadableTypeString(); + match.name = type.getReadableTypeWString(); match.text = match.name; - match.typeName = "filter"; + match.typeName = L"filter"; match.searchType = SEARCH_COMMAND; match.nodeType = type; matches.push_back(match); @@ -75,33 +75,33 @@ std::vector SearchMatch::createCommandsForNodeTypes(NodeTypeSet typ return matches; } -std::string SearchMatch::getCommandName(CommandType type) +std::wstring SearchMatch::getCommandName(CommandType type) { switch (type) { case COMMAND_ALL: - return "overview"; + return L"overview"; case COMMAND_ERROR: - return "error"; + return L"error"; case COMMAND_NODE_FILTER: - return "node_filter"; + return L"node_filter"; } - return "none"; + return L"none"; } SearchMatch::SearchMatch() - : typeName("") + : typeName(L"") , nodeType(NodeType::NODE_SYMBOL) , searchType(SEARCH_NONE) , hasChildren(false) { } -SearchMatch::SearchMatch(const std::string& query) +SearchMatch::SearchMatch(const std::wstring& query) : name(query) , text(query) - , typeName("") + , typeName(L"") , nodeType(NodeType::NODE_SYMBOL) , searchType(SEARCH_NONE) , hasChildren(false) @@ -121,8 +121,8 @@ bool SearchMatch::operator<(const SearchMatch& other) const return false; } - const std::string* str = &text; - const std::string* otherStr = &other.text; + const std::wstring* str = &text; + const std::wstring* otherStr = &other.text; if (*str == *otherStr) { str = &name; @@ -179,11 +179,11 @@ bool SearchMatch::operator==(const SearchMatch& other) const return text == other.text && searchType == other.searchType; } -size_t SearchMatch::getTextSizeForSorting(const std::string* str) const +size_t SearchMatch::getTextSizeForSorting(const std::wstring* str) const { // check if templated symbol and only use size up to template stuff - size_t pos = str->find('<'); - if (pos != std::string::npos) + size_t pos = str->find(L'<'); + if (pos != std::wstring::npos) { return pos; } @@ -201,24 +201,24 @@ bool SearchMatch::isFilterCommand() const return searchType == SEARCH_COMMAND && getCommandType() == COMMAND_NODE_FILTER; } -void SearchMatch::print(std::ostream& ostream) const +void SearchMatch::print(std::wostream& ostream) const { - ostream << name << std::endl << '\t'; + ostream << name << std::endl << L'\t'; size_t i = 0; for (size_t index : indices) { while (i < index) { i++; - ostream << ' '; + ostream << L' '; } - ostream << '^'; + ostream << L'^'; i++; } ostream << std::endl; } -std::string SearchMatch::getFullName() const +std::wstring SearchMatch::getFullName() const { if (searchType == SEARCH_TOKEN && nodeType.isFile()) { @@ -228,23 +228,18 @@ std::string SearchMatch::getFullName() const return name; } -std::string SearchMatch::getNodeTypeAsUnderscoredString() const -{ - return nodeType.getUnderscoredTypeString(); -} - -std::string SearchMatch::getSearchTypeName() const +std::wstring SearchMatch::getSearchTypeName() const { return getSearchTypeName(searchType); } SearchMatch::CommandType SearchMatch::getCommandType() const { - if (name == "overview") + if (name == L"overview") { return COMMAND_ALL; } - else if (name == "error") + else if (name == L"error") { return COMMAND_ERROR; } diff --git a/src/lib/data/search/SearchMatch.h b/src/lib/data/search/SearchMatch.h index 02a32b7c..a4284f4f 100644 --- a/src/lib/data/search/SearchMatch.h +++ b/src/lib/data/search/SearchMatch.h @@ -11,6 +11,7 @@ class NodeTypeSet; +// SearchMatch is used to display the search result in the UI struct SearchMatch { enum SearchType @@ -29,44 +30,43 @@ struct SearchMatch COMMAND_NODE_FILTER }; - static void log(const std::vector& matches, const std::string& query); + static void log(const std::vector& matches, const std::wstring& query); - static std::string getSearchTypeName(SearchType type); - static std::string searchMatchesToString(const std::vector& matches); + static std::wstring getSearchTypeName(SearchType type); + static std::wstring searchMatchesToString(const std::vector& matches); static SearchMatch createCommand(CommandType type); static std::vector createCommandsForNodeTypes(NodeTypeSet types); - static std::string getCommandName(CommandType type); + static std::wstring getCommandName(CommandType type); - static const char FULLTEXT_SEARCH_CHARACTER = '?'; + static const wchar_t FULLTEXT_SEARCH_CHARACTER = L'?'; SearchMatch(); - SearchMatch(const std::string& query); + SearchMatch(const std::wstring& query); bool operator<(const SearchMatch& other) const; bool operator==(const SearchMatch& other) const; - size_t getTextSizeForSorting(const std::string* str) const; + size_t getTextSizeForSorting(const std::wstring* str) const; bool isValid() const; bool isFilterCommand() const; - void print(std::ostream& ostream) const; + void print(std::wostream& ostream) const; - std::string getFullName() const; - std::string getNodeTypeAsUnderscoredString() const; - std::string getSearchTypeName() const; + std::wstring getFullName() const; + std::wstring getSearchTypeName() const; CommandType getCommandType() const; - std::string name; + std::wstring name; std::vector tokenIds; - std::string text; - std::string subtext; + std::wstring text; + std::wstring subtext; NameDelimiterType delimiter; - std::string typeName; + std::wstring typeName; NodeType nodeType; SearchType searchType; diff --git a/src/lib/data/storage/PersistentStorage.cpp b/src/lib/data/storage/PersistentStorage.cpp index ac82d60f..a68fc031 100644 --- a/src/lib/data/storage/PersistentStorage.cpp +++ b/src/lib/data/storage/PersistentStorage.cpp @@ -36,7 +36,7 @@ PersistentStorage::PersistentStorage(const FilePath& dbPath, const FilePath& boo { if (nodeType.hasSearchFilter()) { - m_commandIndex.addNode(0, nodeType.getReadableTypeString()); + m_commandIndex.addNode(0, nodeType.getReadableTypeWString()); } } @@ -552,7 +552,7 @@ std::shared_ptr PersistentStorage::getFullTextSearchLo return collection; } -std::vector PersistentStorage::getAutocompletionMatches(const std::string& query, NodeTypeSet acceptedNodeTypes) const +std::vector PersistentStorage::getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const { TRACE(); @@ -600,7 +600,7 @@ std::vector PersistentStorage::getAutocompletionMatches(const std:: } std::vector PersistentStorage::getAutocompletionSymbolMatches( - const std::string& query, const NodeTypeSet& acceptedNodeTypes, size_t maxResultsCount, size_t maxBestScoredResultsLength) const + const std::wstring& query, const NodeTypeSet& acceptedNodeTypes, size_t maxResultsCount, size_t maxBestScoredResultsLength) const { // search in indices const std::vector results = @@ -657,11 +657,11 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( match.text = result.text; NameHierarchy name = NameHierarchy::deserialize(firstNode->serializedName); - if (utility::encodeToUtf8(name.getQualifiedName()) == match.name) + if (name.getQualifiedName() == match.name) { const size_t idx = m_hierarchyCache.getIndexOfLastVisibleParentNode(firstNode->id); - match.text = utility::encodeToUtf8(name.getRange(idx, name.size()).getQualifiedName()); - match.subtext = utility::encodeToUtf8(name.getRange(0, idx).getQualifiedName()); + match.text = name.getRange(idx, name.size()).getQualifiedName(); + match.subtext = name.getRange(0, idx).getQualifiedName(); } match.delimiter = name.getDelimiter(); @@ -669,12 +669,12 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( match.indices = result.indices; match.score = result.score; match.nodeType = utility::intToType(firstNode->type); - match.typeName = match.nodeType.getReadableTypeString(); + match.typeName = match.nodeType.getReadableTypeWString(); match.searchType = SearchMatch::SEARCH_TOKEN; if (storageSymbolMap.find(firstNode->id) == storageSymbolMap.end()) { - match.typeName = "non-indexed " + match.typeName; + match.typeName = L"non-indexed " + match.typeName; } matches.push_back(match); @@ -683,7 +683,7 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( return matches; } -std::vector PersistentStorage::getAutocompletionFileMatches(const std::string& query, size_t maxResultsCount) const +std::vector PersistentStorage::getAutocompletionFileMatches(const std::wstring& query, size_t maxResultsCount) const { const std::vector results = m_fileIndex.search( query, @@ -702,8 +702,8 @@ std::vector PersistentStorage::getAutocompletionFileMatches(const s match.tokenIds = utility::toVector(result.elementIds); const FilePath path(match.name); - match.text = path.fileName(); - match.subtext = path.str(); + match.text = path.wFileName(); + match.subtext = path.wstr(); match.delimiter = NAME_DELIMITER_FILE; @@ -711,7 +711,7 @@ std::vector PersistentStorage::getAutocompletionFileMatches(const s match.score = result.score; match.nodeType = NodeType::NODE_FILE; - match.typeName = match.nodeType.getReadableTypeString(); + match.typeName = match.nodeType.getReadableTypeWString(); match.searchType = SearchMatch::SEARCH_TOKEN; @@ -722,7 +722,7 @@ std::vector PersistentStorage::getAutocompletionFileMatches(const s } std::vector PersistentStorage::getAutocompletionCommandMatches( - const std::string& query, NodeTypeSet acceptedNodeTypes) const + const std::wstring& query, NodeTypeSet acceptedNodeTypes) const { // search in indices const std::vector results = m_commandIndex.search(query, NodeTypeSet::all(), 0); @@ -742,12 +742,12 @@ std::vector PersistentStorage::getAutocompletionCommandMatches( match.score = result.score; match.searchType = SearchMatch::SEARCH_COMMAND; - match.typeName = "command"; + match.typeName = L"command"; if (match.getCommandType() == SearchMatch::COMMAND_NODE_FILTER) { match.nodeType = utility::getTypeForReadableTypeString(match.name); - match.typeName = "filter"; + match.typeName = L"filter"; } if (acceptedNodeTypes == NodeTypeSet::all() || @@ -786,8 +786,8 @@ std::vector PersistentStorage::getSearchMatchesForTokenIds(const st SearchMatch match; const NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName); - match.name = utility::encodeToUtf8(nameHierarchy.getQualifiedName()); - match.text = utility::encodeToUtf8(nameHierarchy.getRawName()); + match.name = nameHierarchy.getQualifiedName(); + match.text = nameHierarchy.getRawName(); match.tokenIds.push_back(elementId); match.nodeType = utility::intToType(node.type); @@ -797,7 +797,7 @@ std::vector PersistentStorage::getSearchMatchesForTokenIds(const st if (match.nodeType.isFile()) { - match.text = FilePath(match.text).fileName(); + match.text = FilePath(match.text).wFileName(); } matches.push_back(match); @@ -2546,7 +2546,7 @@ void PersistentStorage::buildSearchIndex() filePath.makeRelativeTo(dbPath); } - m_fileIndex.addNode(node.id, filePath.str(), type); + m_fileIndex.addNode(node.id, filePath.wstr(), type); } } else @@ -2558,13 +2558,13 @@ void PersistentStorage::buildSearchIndex() const NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName); // we don't use the signature here, so elements with the same signature share the same node. - std::string name = utility::encodeToUtf8(nameHierarchy.getQualifiedName()); + std::wstring name = nameHierarchy.getQualifiedName(); // replace template arguments with .. to avoid clutter in search results and have different // template specializations share the same node. if (defKind == DEFINITION_NONE && nameHierarchy.getDelimiter() == NAME_DELIMITER_CXX) { - name = utility::replaceBetween(name, '<', '>', ".."); + name = utility::replaceBetween(name, L'<', L'>', L".."); } m_symbolIndex.addNode(node.id, name, type); diff --git a/src/lib/data/storage/PersistentStorage.h b/src/lib/data/storage/PersistentStorage.h index 5f5acf05..f68dc2d1 100644 --- a/src/lib/data/storage/PersistentStorage.h +++ b/src/lib/data/storage/PersistentStorage.h @@ -87,11 +87,11 @@ public: virtual std::shared_ptr getFullTextSearchLocations( const std::string& searchTerm, bool caseSensitive) const override; - virtual std::vector getAutocompletionMatches(const std::string& query, NodeTypeSet acceptedNodeTypes) const override; + virtual std::vector getAutocompletionMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const override; std::vector getAutocompletionSymbolMatches( - const std::string& query, const NodeTypeSet& acceptedNodeTypes, size_t maxResultsCount, size_t maxBestScoredResultsLength) const; - std::vector getAutocompletionFileMatches(const std::string& query, size_t maxResultsCount) const; - std::vector getAutocompletionCommandMatches(const std::string& query, NodeTypeSet acceptedNodeTypes) const; + const std::wstring& query, const NodeTypeSet& acceptedNodeTypes, size_t maxResultsCount, size_t maxBestScoredResultsLength) const; + std::vector getAutocompletionFileMatches(const std::wstring& query, size_t maxResultsCount) const; + std::vector getAutocompletionCommandMatches(const std::wstring& query, NodeTypeSet acceptedNodeTypes) const; virtual std::vector getSearchMatchesForTokenIds(const std::vector& elementIds) const override; virtual std::shared_ptr getGraphForAll() const override; diff --git a/src/lib/utility/messaging/type/MessageSearch.h b/src/lib/utility/messaging/type/MessageSearch.h index 8b16b380..fbe4bcf4 100644 --- a/src/lib/utility/messaging/type/MessageSearch.h +++ b/src/lib/utility/messaging/type/MessageSearch.h @@ -24,7 +24,7 @@ public: std::wstring getMatchesAsString() const { - std::stringstream ss; + std::wstringstream ss; for (size_t i = 0; i < m_matches.size(); i++) { @@ -37,13 +37,16 @@ public: { if (!m_matches[i].subtext.empty()) { - ss << m_matches[i].subtext << m_matches[i].delimiter; + ss << m_matches[i].subtext << nameDelimiterTypeToString(m_matches[i].delimiter) << m_matches[i].text; + } + else + { + ss << m_matches[i].name; } - ss << m_matches[i].name; } } - return utility::decodeFromUtf8(ss.str()); + return ss.str(); } const std::vector& getMatches() const diff --git a/src/lib/utility/messaging/type/MessageSearchAutocomplete.h b/src/lib/utility/messaging/type/MessageSearchAutocomplete.h index 9bedbc5a..15475337 100644 --- a/src/lib/utility/messaging/type/MessageSearchAutocomplete.h +++ b/src/lib/utility/messaging/type/MessageSearchAutocomplete.h @@ -9,7 +9,7 @@ class MessageSearchAutocomplete : public Message { public: - MessageSearchAutocomplete(const std::string& query, NodeTypeSet acceptedNodeTypes) + MessageSearchAutocomplete(const std::wstring& query, NodeTypeSet acceptedNodeTypes) : query(query) , acceptedNodeTypes(acceptedNodeTypes) { @@ -22,7 +22,7 @@ public: virtual void print(std::wostream& os) const { - os << utility::decodeFromUtf8(query) << L"["; + os << query << L"["; std::vector nodeTypeIds = acceptedNodeTypes.getNodeTypeIds(); for (size_t i = 0; i < nodeTypeIds.size(); i++) { @@ -35,7 +35,7 @@ public: os << L"]"; } - const std::string query; + const std::wstring query; const NodeTypeSet acceptedNodeTypes; }; diff --git a/src/lib/utility/messaging/type/MessageSearchFullText.h b/src/lib/utility/messaging/type/MessageSearchFullText.h index b0e06277..c98fb7f0 100644 --- a/src/lib/utility/messaging/type/MessageSearchFullText.h +++ b/src/lib/utility/messaging/type/MessageSearchFullText.h @@ -6,7 +6,7 @@ class MessageSearchFullText: public Message { public: - MessageSearchFullText(const std::string& searchTerm, bool caseSensitive = false) + MessageSearchFullText(const std::wstring& searchTerm, bool caseSensitive = false) : searchTerm(searchTerm) , caseSensitive(caseSensitive) { @@ -19,10 +19,10 @@ public: virtual void print(std::wostream& os) const { - os << utility::decodeFromUtf8(searchTerm); + os << searchTerm; } - const std::string searchTerm; + const std::wstring searchTerm; bool caseSensitive; }; diff --git a/src/lib/utility/utilityString.cpp b/src/lib/utility/utilityString.cpp index 3ea967ea..adb47eae 100644 --- a/src/lib/utility/utilityString.cpp +++ b/src/lib/utility/utilityString.cpp @@ -27,6 +27,39 @@ namespace return str; } + + template + StringType doReplaceBetween(const StringType& str, typename StringType::value_type startDelimiter, typename StringType::value_type endDelimiter, const StringType& to) + { + size_t startPos = str.find(startDelimiter); + if (startPos == StringType::npos) + { + return str; + } + + size_t depth = 1; + + for (size_t pos = startPos + 1; pos < str.size(); pos++) + { + if (str[pos] == endDelimiter && depth) + { + depth--; + + if (depth == 0) + { + StringType end = doReplaceBetween(str.substr(pos + 1), startDelimiter, endDelimiter, to); + return str.substr(0, startPos) + startDelimiter + to + endDelimiter + end; + } + } + + if (str[pos] == startDelimiter) + { + depth++; + } + } + + return str; + } } namespace utility @@ -242,22 +275,6 @@ namespace utility return out; } - bool equalsCaseInsensitive(const std::string& a, const std::string& b) - { - if (a.size() == b.size()) - { - for (size_t i = 0; i < a.size(); i++) - { - if (tolower(a[i]) != tolower(b[i])) - { - return false; - } - } - return true; - } - return false; - } - std::string replace(std::string str, const std::string& from, const std::string& to) { return doReplace(str, from, to); @@ -270,36 +287,14 @@ namespace utility std::string replaceBetween(const std::string& str, char startDelimiter, char endDelimiter, const std::string& to) { - size_t startPos = str.find(startDelimiter); - if (startPos == std::string::npos) - { - return str; - } - - size_t depth = 1; - - for (size_t pos = startPos + 1; pos < str.size(); pos++) - { - if (str[pos] == endDelimiter && depth) - { - depth--; - - if (depth == 0) - { - std::string end = replaceBetween(str.substr(pos + 1), startDelimiter, endDelimiter, to); - return str.substr(0, startPos) + startDelimiter + to + endDelimiter + end; - } - } - - if (str[pos] == startDelimiter) - { - depth++; - } - } - - return str; + return doReplaceBetween(str, startDelimiter, endDelimiter, to); } + std::wstring replaceBetween(const std::wstring& str, wchar_t startDelimiter, wchar_t endDelimiter, const std::wstring& to) + { + return doReplaceBetween(str, startDelimiter, endDelimiter, to); + } + std::string insertLineBreaksAtBlankSpaces(const std::string& s, size_t maxLineLength) { const std::vector atoms = splitToVector(s, " "); diff --git a/src/lib/utility/utilityString.h b/src/lib/utility/utilityString.h index eb2a3871..0392f0fb 100644 --- a/src/lib/utility/utilityString.h +++ b/src/lib/utility/utilityString.h @@ -55,12 +55,15 @@ namespace utility std::string toUpperCase(const std::string& in); std::string toLowerCase(const std::string& in); std::wstring toLowerCase(const std::wstring& in); + + template bool equalsCaseInsensitive(const std::string& a, const std::string& b); std::string replace(std::string str, const std::string& from, const std::string& to); std::wstring replace(std::wstring str, const std::wstring& from, const std::wstring& to); std::string replaceBetween(const std::string& str, char startDelimiter, char endDelimiter, const std::string& to); + std::wstring replaceBetween(const std::wstring& str, wchar_t startDelimiter, wchar_t endDelimiter, const std::wstring& to); std::string insertLineBreaksAtBlankSpaces(const std::string& s, size_t maxLineLength); std::string breakSignature( @@ -132,6 +135,7 @@ namespace utility return ss.str(); } + template std::wstring join(const ContainerType& list, const std::wstring& delimiter) { @@ -149,6 +153,16 @@ namespace utility } return ss.str(); } + + template + bool equalsCaseInsensitive(const StringType& a, const StringType& b) + { + if (a.size() == b.size()) + { + return toLowerCase(a) == toLowerCase(b); + } + return false; + } } #endif // UTILITY_STRING_H diff --git a/src/lib_gui/qt/element/QtAutocompletionList.cpp b/src/lib_gui/qt/element/QtAutocompletionList.cpp index f16dfb33..f265c099 100644 --- a/src/lib_gui/qt/element/QtAutocompletionList.cpp +++ b/src/lib_gui/qt/element/QtAutocompletionList.cpp @@ -8,6 +8,7 @@ #include "settings/ApplicationSettings.h" #include "settings/ColorScheme.h" #include "utility/ResourcePaths.h" +#include "utility/utilityString.h" QtAutocompletionModel::QtAutocompletionModel(QObject* parent) : QAbstractTableModel(parent) @@ -47,13 +48,13 @@ QVariant QtAutocompletionModel::data(const QModelIndex &index, int role) const switch (index.column()) { case 0: - return QString::fromStdString(match.name); + return QString::fromStdWString(match.name); case 1: - return QString::fromStdString(match.text); + return QString::fromStdWString(match.text); case 2: - return QString::fromStdString(match.subtext); + return QString::fromStdWString(match.subtext); case 3: - return QString::fromStdString(match.typeName); + return QString::fromStdWString(match.typeName); case 4: { QList indices; @@ -81,7 +82,7 @@ const SearchMatch* QtAutocompletionModel::getSearchMatchAt(int idx) const QString QtAutocompletionModel::longestText() const { - std::string str; + std::wstring str; for (const SearchMatch& match : m_matchList) { if (match.text.size() > str.size()) @@ -89,12 +90,12 @@ QString QtAutocompletionModel::longestText() const str = match.text; } } - return QString::fromStdString(str); + return QString::fromStdWString(str); } QString QtAutocompletionModel::longestSubText() const { - std::string str; + std::wstring str; for (const SearchMatch& match : m_matchList) { if (match.subtext.size() > str.size()) @@ -102,12 +103,12 @@ QString QtAutocompletionModel::longestSubText() const str = match.subtext; } } - return QString::fromStdString(str); + return QString::fromStdWString(str); } QString QtAutocompletionModel::longestType() const { - std::string str; + std::wstring str; for (const SearchMatch& match : m_matchList) { if (match.typeName.size() > str.size()) @@ -115,7 +116,7 @@ QString QtAutocompletionModel::longestType() const str = match.typeName; } } - return QString::fromStdString(str); + return QString::fromStdWString(str); } @@ -155,8 +156,8 @@ void QtAutocompletionDelegate::paint(QPainter* painter, const QStyleOptionViewIt } else { - fillColor = QColor(scheme->getSearchTypeColor(SearchMatch::getSearchTypeName(SearchMatch::SEARCH_COMMAND), "fill").c_str()); - textColor = QColor(scheme->getSearchTypeColor(SearchMatch::getSearchTypeName(SearchMatch::SEARCH_COMMAND), "text").c_str()); + fillColor = QColor(scheme->getSearchTypeColor(utility::encodeToUtf8(SearchMatch::getSearchTypeName(SearchMatch::SEARCH_COMMAND)), "fill").c_str()); + textColor = QColor(scheme->getSearchTypeColor(utility::encodeToUtf8(SearchMatch::getSearchTypeName(SearchMatch::SEARCH_COMMAND)), "text").c_str()); } int top1 = 6; diff --git a/src/lib_gui/qt/element/QtHistoryList.cpp b/src/lib_gui/qt/element/QtHistoryList.cpp index f43c35ad..05f43809 100644 --- a/src/lib_gui/qt/element/QtHistoryList.cpp +++ b/src/lib_gui/qt/element/QtHistoryList.cpp @@ -23,9 +23,9 @@ QtHistoryItem::QtHistoryItem(const SearchMatch& match, size_t index, bool isCurr layout->setContentsMargins(0, 0, 0, 0); layout->setAlignment(Qt::AlignTop); - std::string name = utility::elide(match.nodeType.isFile() ? match.text : match.name, utility::ELIDE_RIGHT, 100); + const std::wstring name = utility::elide(match.nodeType.isFile() ? match.text : match.name, utility::ELIDE_RIGHT, 100); - m_name = new QLabel(name.c_str(), this); + m_name = new QLabel(QString::fromStdWString(name), this); m_name->setAttribute(Qt::WA_MacShowFocusRect, 0); m_name->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac m_name->setObjectName(isCurrent ? "history_item_current" : "history_item"); @@ -49,8 +49,8 @@ QtHistoryItem::QtHistoryItem(const SearchMatch& match, size_t index, bool isCurr } else { - m_indicatorColor = scheme->getSearchTypeColor(match.getSearchTypeName(), "fill"); - m_indicatorHoverColor = scheme->getSearchTypeColor(match.getSearchTypeName(), "fill", "hover"); + m_indicatorColor = scheme->getSearchTypeColor(utility::encodeToUtf8(match.getSearchTypeName()), "fill"); + m_indicatorHoverColor = scheme->getSearchTypeColor(utility::encodeToUtf8(match.getSearchTypeName()), "fill", "hover"); } std::stringstream css; diff --git a/src/lib_gui/qt/element/QtSmartSearchBox.cpp b/src/lib_gui/qt/element/QtSmartSearchBox.cpp index a78b1424..14a541f3 100644 --- a/src/lib_gui/qt/element/QtSmartSearchBox.cpp +++ b/src/lib_gui/qt/element/QtSmartSearchBox.cpp @@ -32,7 +32,7 @@ void QtSmartSearchBox::search() { editTextToElement(); - if (!m_matches.size()) + if (m_matches.empty()) { return; } @@ -41,7 +41,7 @@ void QtSmartSearchBox::search() if (m_matches.size() == 1) { SearchMatch& match = m_matches.front(); - if (match.searchType == SearchMatch::SEARCH_NONE && match.name.size()) + if (match.searchType == SearchMatch::SEARCH_NONE && !match.name.empty()) { if (m_oldMatch.name == match.name) { @@ -50,7 +50,7 @@ void QtSmartSearchBox::search() } else { - QString text = QString::fromStdString(match.name); + QString text = QString::fromStdWString(match.name); if (!text.startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER)) { text = QChar(SearchMatch::FULLTEXT_SEARCH_CHARACTER) + text; @@ -73,8 +73,8 @@ void QtSmartSearchBox::search() void QtSmartSearchBox::fullTextSearch() { - std::string term = text().toStdString().substr(1); - if (!term.size()) + std::wstring term = text().toStdWString().substr(1); + if (term.empty()) { return; } @@ -83,7 +83,7 @@ void QtSmartSearchBox::fullTextSearch() if (term.at(0) == SearchMatch::FULLTEXT_SEARCH_CHARACTER) { term = term.substr(1); - if (!term.size()) + if (term.empty()) { return; } @@ -137,7 +137,7 @@ void QtSmartSearchBox::setAutocompletionList(const std::vector& aut connect(completer, &QtAutocompletionList::matchHighlighted, this, &QtSmartSearchBox::onAutocompletionHighlighted, Qt::DirectConnection); connect(completer, &QtAutocompletionList::matchActivated, this, &QtSmartSearchBox::onAutocompletionActivated, Qt::DirectConnection); - if (autocompletionList.size()) + if (!autocompletionList.empty()) { m_highlightedMatch = *completer->getSearchMatchAt(0); } @@ -194,12 +194,12 @@ bool QtSmartSearchBox::event(QEvent *event) } else if (m_highlightedMatch.hasChildren) { - setEditText((m_highlightedMatch.getFullName() + utility::encodeToUtf8(nameDelimiterTypeToString(m_highlightedMatch.delimiter))).c_str()); + setEditText(QString::fromStdWString(m_highlightedMatch.getFullName() + nameDelimiterTypeToString(m_highlightedMatch.delimiter))); requestAutoCompletions(); } else { - setEditText(m_highlightedMatch.getFullName().c_str()); + setEditText(QString::fromStdWString(m_highlightedMatch.getFullName())); requestAutoCompletions(); } } @@ -431,9 +431,9 @@ void QtSmartSearchBox::keyPressEvent(QKeyEvent* event) { if (hasSelectedElements()) { - std::string str = getSelectedString(); + std::wstring str = getSelectedString(); deleteSelectedElements(); - QApplication::clipboard()->setText(QString::fromStdString(str)); + QApplication::clipboard()->setText(QString::fromStdWString(str)); return; } } @@ -441,8 +441,8 @@ void QtSmartSearchBox::keyPressEvent(QKeyEvent* event) { if (hasSelectedElements()) { - std::string str = getSelectedString(); - QApplication::clipboard()->setText(QString::fromStdString(str)); + std::wstring str = getSelectedString(); + QApplication::clipboard()->setText(QString::fromStdWString(str)); return; } } @@ -477,7 +477,7 @@ void QtSmartSearchBox::mouseMoveEvent(QMouseEvent* event) { QLineEdit::mouseMoveEvent(event); - if (!m_mousePressed || !m_elements.size()) + if (!m_mousePressed || m_elements.empty()) { return; } @@ -557,14 +557,14 @@ void QtSmartSearchBox::onTextEdited(const QString& text) bool matchesChanged = false; SearchMatch match; - std::deque matches = getMatchesForInput(text.toStdString()); + std::deque matches = getMatchesForInput(text.toStdWString()); - while (matches.size()) + while (!matches.empty()) { match = matches.front(); matches.pop_front(); - if (matches.size() || match.isValid()) + if (!matches.empty() || match.isValid()) { addMatch(match); match = SearchMatch(); @@ -572,9 +572,9 @@ void QtSmartSearchBox::onTextEdited(const QString& text) } } - if (match.name.size() && lastMatchIsNoFilter()) + if (!match.name.empty() && lastMatchIsNoFilter()) { - if (m_matches.size()) + if (!m_matches.empty()) { matchesChanged = true; } @@ -583,7 +583,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text) if (matchesChanged) { - setEditText(QString::fromStdString(match.getFullName())); + setEditText(QString::fromStdWString(match.getFullName())); updateElements(); } else @@ -591,7 +591,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text) layoutElements(); } - if (match.name.size()) + if (!match.name.empty()) { requestAutoCompletions(); } @@ -626,7 +626,7 @@ void QtSmartSearchBox::onAutocompletionActivated(const SearchMatch& match) { addMatchAndUpdate(match); - if (match.name.size()) + if (!match.name.empty()) { search(); } @@ -668,7 +668,7 @@ void QtSmartSearchBox::onElementSelected(QtSearchElement* element) } } - if (text().size()) + if (!text().isEmpty()) { if (m_cursorIndex <= idx) { @@ -713,7 +713,7 @@ void QtSmartSearchBox::moveCursorTo(int target) void QtSmartSearchBox::addMatch(const SearchMatch& match) { - if (!match.name.size()) + if (match.name.empty()) { return; } @@ -740,7 +740,7 @@ void QtSmartSearchBox::addMatch(const SearchMatch& match) void QtSmartSearchBox::addMatchAndUpdate(const SearchMatch& match) { - if (match.name.size()) + if (!match.name.empty()) { m_oldText.clear(); clearLineEdit(); @@ -764,9 +764,9 @@ void QtSmartSearchBox::setEditText(const QString& text) bool QtSmartSearchBox::editTextToElement() { - if (text().size()) + if (!text().isEmpty()) { - addMatch(SearchMatch(text().toStdString())); + addMatch(SearchMatch(text().toStdWString())); clearLineEdit(); updateElements(); @@ -790,7 +790,7 @@ SearchMatch QtSmartSearchBox::editElement(QtSearchElement* element) SearchMatch match = m_matches[m_cursorIndex]; m_matches.erase(m_matches.begin() + m_cursorIndex); - setEditText(QString::fromStdString(match.getFullName())); + setEditText(QString::fromStdWString(match.getFullName())); updateElements(); return match; @@ -810,14 +810,14 @@ void QtSmartSearchBox::updateElements() for (const SearchMatch& match : m_matches) { - std::string name = match.getFullName(); - name = utility::replace(name, "&", "&&"); + std::wstring name = match.getFullName(); + name = utility::replace(name, L"&", L"&&"); if (match.isFilterCommand()) { - name += ':'; + name += L':'; } - QtSearchElement* element = new QtSearchElement(QString::fromStdString(name), this); + QtSearchElement* element = new QtSearchElement(QString::fromStdWString(name), this); m_elements.push_back(element); std::string color; @@ -834,12 +834,12 @@ void QtSmartSearchBox::updateElements() } else { - std::string typeName = match.getSearchTypeName(); + const std::wstring typeName = match.getSearchTypeName(); - color = scheme->getSearchTypeColor(typeName, "fill"); - hoverColor = scheme->getSearchTypeColor(typeName, "fill", "hover"); - textColor = scheme->getSearchTypeColor(typeName, "text"); - textHoverColor = scheme->getSearchTypeColor(typeName, "text", "hover");; + color = scheme->getSearchTypeColor(utility::encodeToUtf8(typeName), "fill"); + hoverColor = scheme->getSearchTypeColor(utility::encodeToUtf8(typeName), "fill", "hover"); + textColor = scheme->getSearchTypeColor(utility::encodeToUtf8(typeName), "text"); + textHoverColor = scheme->getSearchTypeColor(utility::encodeToUtf8(typeName), "text", "hover");; } std::stringstream css; @@ -947,9 +947,9 @@ bool QtSmartSearchBox::hasSelectedElements() const return false; } -std::string QtSmartSearchBox::getSelectedString() const +std::wstring QtSmartSearchBox::getSelectedString() const { - std::string str; + std::wstring str; for (size_t i = 0; i < m_elements.size(); i++) { if (m_elements[i]->isChecked()) @@ -1019,7 +1019,7 @@ void QtSmartSearchBox::deleteSelectedElements() void QtSmartSearchBox::updatePlaceholder() { - if (!text().size() && !m_elements.size()) + if (text().isEmpty() && m_elements.empty()) { setPlaceholderText("Search"); } @@ -1037,9 +1037,9 @@ void QtSmartSearchBox::clearLineEdit() void QtSmartSearchBox::requestAutoCompletions() { - if (text().size() && !text().startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER)) + if (!text().isEmpty() && !text().startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER)) { - MessageSearchAutocomplete(text().toStdString(), getMatchAcceptedNodeTypes()).dispatch(); + MessageSearchAutocomplete(text().toStdWString(), getMatchAcceptedNodeTypes()).dispatch(); } else { @@ -1052,10 +1052,10 @@ void QtSmartSearchBox::hideAutoCompletions() m_completer->popup()->hide(); } -std::deque QtSmartSearchBox::getMatchesForInput(const std::string& text) const +std::deque QtSmartSearchBox::getMatchesForInput(const std::wstring& text) const { std::deque matches; - if (text.size()) + if (!text.empty()) { matches.push_back(SearchMatch(text)); } @@ -1088,5 +1088,5 @@ NodeTypeSet QtSmartSearchBox::getMatchAcceptedNodeTypes() const bool QtSmartSearchBox::lastMatchIsNoFilter() const { - return !m_matches.size() || !m_matches.back().isFilterCommand(); + return m_matches.empty() || !m_matches.back().isFilterCommand(); } diff --git a/src/lib_gui/qt/element/QtSmartSearchBox.h b/src/lib_gui/qt/element/QtSmartSearchBox.h index 92134316..4ccca5ee 100644 --- a/src/lib_gui/qt/element/QtSmartSearchBox.h +++ b/src/lib_gui/qt/element/QtSmartSearchBox.h @@ -87,7 +87,7 @@ private: void layoutElements(); bool hasSelectedElements() const; - std::string getSelectedString() const; + std::wstring getSelectedString() const; void selectAllElementsWith(bool selected); void selectElementsTo(size_t idx, bool selected); @@ -99,7 +99,7 @@ private: void requestAutoCompletions(); void hideAutoCompletions(); - std::deque getMatchesForInput(const std::string& text) const; + std::deque getMatchesForInput(const std::wstring& text) const; NodeTypeSet getMatchAcceptedNodeTypes() const; bool lastMatchIsNoFilter() const; diff --git a/src/lib_gui/qt/view/QtSearchView.cpp b/src/lib_gui/qt/view/QtSearchView.cpp index 59abcc2a..e3da4004 100644 --- a/src/lib_gui/qt/view/QtSearchView.cpp +++ b/src/lib_gui/qt/view/QtSearchView.cpp @@ -35,9 +35,9 @@ void QtSearchView::refreshView() }); } -std::string QtSearchView::getQuery() const +std::wstring QtSearchView::getQuery() const { - return m_widget->query().toStdString(); + return m_widget->query().toStdWString(); } void QtSearchView::setMatches(const std::vector& matches) diff --git a/src/lib_gui/qt/view/QtSearchView.h b/src/lib_gui/qt/view/QtSearchView.h index 88c3eab8..aabb6188 100644 --- a/src/lib_gui/qt/view/QtSearchView.h +++ b/src/lib_gui/qt/view/QtSearchView.h @@ -19,19 +19,13 @@ public: virtual void refreshView(); // SearchView implementation - virtual std::string getQuery() const; + virtual std::wstring getQuery() const; virtual void setMatches(const std::vector& matches); virtual void setFocus(); virtual void findFulltext(); virtual void setAutocompletionList(const std::vector& autocompletionList); private: - void doRefreshView(); - void doSetMatches(const std::vector& matches); - void doSetFocus(); - void doFindFulltext(); - void doSetAutocompletionList(const std::vector& autocompletionList); - void setStyleSheet(); QtThreadedLambdaFunctor m_onQtThread; diff --git a/src/lib_gui/qt/window/QtMainWindow.cpp b/src/lib_gui/qt/window/QtMainWindow.cpp index eb8d3b95..9b76aed0 100644 --- a/src/lib_gui/qt/window/QtMainWindow.cpp +++ b/src/lib_gui/qt/window/QtMainWindow.cpp @@ -889,10 +889,10 @@ void QtMainWindow::setupHistoryMenu() for (size_t i = 0; i < m_history.size(); i++) { SearchMatch& match = m_history[i]; - std::string name = utility::elide(match.nodeType.isFile() ? match.text : match.name, utility::ELIDE_RIGHT, 50); + const std::wstring name = utility::elide(match.nodeType.isFile() ? match.text : match.name, utility::ELIDE_RIGHT, 50); QAction* action = new QAction(); - action->setText(name.c_str()); + action->setText(QString::fromStdWString(name)); action->setData(QVariant(int(i))); connect(action, &QAction::triggered, this, &QtMainWindow::openHistoryAction); diff --git a/src/test/SearchIndexTestSuite.h b/src/test/SearchIndexTestSuite.h index a2b453c8..b74bb086 100644 --- a/src/test/SearchIndexTestSuite.h +++ b/src/test/SearchIndexTestSuite.h @@ -10,9 +10,9 @@ public: void test_search_index_finds_id_of_element_added() { SearchIndex index; - index.addNode(1, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfoo\tsvoid\tp() const").getQualifiedName())); + index.addNode(1, NameHierarchy::deserialize(L"::\tmfoo\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", NodeTypeSet::all(), 0); + std::vector results = index.search(L"oo", NodeTypeSet::all(), 0); TS_ASSERT_EQUALS(1, results.size()); TS_ASSERT_EQUALS(1, results[0].elementIds.size()); @@ -22,9 +22,9 @@ public: void test_search_index_finds_correct_indices_for_query() { SearchIndex index; - index.addNode(1, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfoo\tsvoid\tp() const").getQualifiedName())); + index.addNode(1, NameHierarchy::deserialize(L"::\tmfoo\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", NodeTypeSet::all(), 0); + std::vector results = index.search(L"oo", NodeTypeSet::all(), 0); TS_ASSERT_EQUALS(1, results.size()); TS_ASSERT_EQUALS(2, results[0].indices.size()); @@ -35,10 +35,10 @@ public: void test_search_index_finds_ids_for_ambiguous_query() { SearchIndex index; - index.addNode(1, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfor\tsvoid\tp() const").getQualifiedName())); - index.addNode(2, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfos\tsvoid\tp() const").getQualifiedName())); + index.addNode(1, NameHierarchy::deserialize(L"::\tmfor\tsvoid\tp() const").getQualifiedName()); + index.addNode(2, NameHierarchy::deserialize(L"::\tmfos\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("fo", NodeTypeSet::all(), 0); + std::vector results = index.search(L"fo", NodeTypeSet::all(), 0); TS_ASSERT_EQUALS(2, results.size()); TS_ASSERT_EQUALS(1, results[0].elementIds.size()); @@ -50,10 +50,10 @@ public: void test_search_index_does_not_find_anything_after_clear() { SearchIndex index; - index.addNode(1, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfoo\tsvoid\tp() const").getQualifiedName())); + index.addNode(1, NameHierarchy::deserialize(L"::\tmfoo\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); index.clear(); - std::vector results = index.search("oo", NodeTypeSet::all(), 0); + std::vector results = index.search(L"oo", NodeTypeSet::all(), 0); TS_ASSERT_EQUALS(0, results.size()); } @@ -61,10 +61,10 @@ public: void test_search_index_does_not_find_all_results_when_max_amount_is_limited() { SearchIndex index; - index.addNode(1, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfoo1\tsvoid\tp() const").getQualifiedName())); - index.addNode(2, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfoo2\tsvoid\tp() const").getQualifiedName())); + index.addNode(1, NameHierarchy::deserialize(L"::\tmfoo1\tsvoid\tp() const").getQualifiedName()); + index.addNode(2, NameHierarchy::deserialize(L"::\tmfoo2\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", NodeTypeSet::all(), 1); + std::vector results = index.search(L"oo", NodeTypeSet::all(), 1); TS_ASSERT_EQUALS(1, results.size()); } @@ -72,10 +72,10 @@ public: void test_search_index_query_is_case_insensitive() { SearchIndex index; - index.addNode(1, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmfoo1\tsvoid\tp() const").getQualifiedName())); - index.addNode(2, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmFOO2\tsvoid\tp() const").getQualifiedName())); + index.addNode(1, NameHierarchy::deserialize(L"::\tmfoo1\tsvoid\tp() const").getQualifiedName()); + index.addNode(2, NameHierarchy::deserialize(L"::\tmFOO2\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", NodeTypeSet::all(), 0); + std::vector results = index.search(L"oo", NodeTypeSet::all(), 0); TS_ASSERT_EQUALS(2, results.size()); } @@ -84,13 +84,13 @@ public: { SearchIndex index; - index.addNode(1, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmoaabbcc\tsvoid\tp() const").getQualifiedName())); - index.addNode(2, utility::encodeToUtf8(NameHierarchy::deserialize(L"::\tmocbcabc\tsvoid\tp() const").getQualifiedName())); + index.addNode(1, NameHierarchy::deserialize(L"::\tmoaabbcc\tsvoid\tp() const").getQualifiedName()); + index.addNode(2, NameHierarchy::deserialize(L"::\tmocbcabc\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("abc", NodeTypeSet::all(), 0); + std::vector results = index.search(L"abc", NodeTypeSet::all(), 0); TS_ASSERT_EQUALS(2, results.size()); - TS_ASSERT_EQUALS("ocbcabc", results[0].text); - TS_ASSERT_EQUALS("oaabbcc", results[1].text); + TS_ASSERT_EQUALS(L"ocbcabc", results[0].text); + TS_ASSERT_EQUALS(L"oaabbcc", results[1].text); } };