From 9f2509e7de282a0897a430aa04bd44417f71ea79 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Sun, 3 Sep 2017 15:38:25 +0200 Subject: [PATCH] ui: node type keywords to filter autocompletions or activate all nodes (issue #78) * Fix history stack activating wrong symbol when aggregation was clicked --- .../controller/ActivationController.cpp | 38 +++---- .../component/controller/CodeController.cpp | 2 +- .../component/controller/GraphController.cpp | 24 +++- .../component/controller/SearchController.cpp | 11 +- .../controller/UndoRedoController.cpp | 18 ++- src/lib/data/HierarchyCache.cpp | 22 ++++ src/lib/data/HierarchyCache.h | 2 + src/lib/data/access/StorageAccess.h | 3 +- src/lib/data/access/StorageAccessProxy.cpp | 14 ++- src/lib/data/access/StorageAccessProxy.h | 3 +- src/lib/data/graph/Node.cpp | 14 +++ src/lib/data/graph/Node.h | 5 +- src/lib/data/search/SearchMatch.cpp | 66 ++++++++--- src/lib/data/search/SearchMatch.h | 5 +- src/lib/data/storage/PersistentStorage.cpp | 105 +++++++++++++++--- src/lib/data/storage/PersistentStorage.h | 10 +- .../messaging/type/MessageActivateAll.h | 6 +- .../utility/messaging/type/MessageSearch.h | 4 +- .../type/MessageSearchAutocomplete.h | 10 +- .../qt/element/QtAutocompletionList.cpp | 4 +- src/lib_gui/qt/element/QtSmartSearchBox.cpp | 58 +++++++--- src/lib_gui/qt/element/QtSmartSearchBox.h | 3 +- 22 files changed, 333 insertions(+), 94 deletions(-) diff --git a/src/lib/component/controller/ActivationController.cpp b/src/lib/component/controller/ActivationController.cpp index 82799c3f..a9b58cb8 100644 --- a/src/lib/component/controller/ActivationController.cpp +++ b/src/lib/component/controller/ActivationController.cpp @@ -94,32 +94,28 @@ void ActivationController::handleMessage(MessageSearch* message) { const std::vector& matches = message->getMatches(); - for (const SearchMatch& match : matches) + if (matches.size() && matches.back().searchType == SearchMatch::SEARCH_COMMAND) { - if (match.searchType == SearchMatch::SEARCH_COMMAND) + switch (matches.back().getCommandType()) { - SearchMatch::CommandType type = SearchMatch::getCommandType(match.getFullName()); - - switch (type) + case SearchMatch::COMMAND_ALL: + case SearchMatch::COMMAND_NODE_FILTER: { - case SearchMatch::COMMAND_ALL: - { - MessageActivateAll().dispatchImmediately(); - return; - } + MessageActivateAll(message->filter).dispatchImmediately(); + return; + } - case SearchMatch::COMMAND_ERROR: - { - MessageShowErrors(m_storageAccess->getErrorCount()).dispatch(); - MessageFlushUpdates().dispatch(); - return; - } + case SearchMatch::COMMAND_ERROR: + { + MessageShowErrors(m_storageAccess->getErrorCount()).dispatch(); + MessageFlushUpdates().dispatch(); + return; + } - case SearchMatch::COMMAND_COLOR_SCHEME_TEST: - { - MessageColorSchemeTest().dispatchImmediately(); - return; - } + case SearchMatch::COMMAND_COLOR_SCHEME_TEST: + { + MessageColorSchemeTest().dispatchImmediately(); + return; } } } diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 980ccf69..107cb559 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -34,7 +34,7 @@ void CodeController::handleMessage(MessageActivateAll* message) clear(); Project* currentProject = Application::getInstance()->getCurrentProject().get(); - if (!currentProject) + if (!currentProject || message->filter) { return; } diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 540078eb..6ab124ec 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -38,15 +38,27 @@ void GraphController::handleMessage(MessageActivateAll* message) m_dummyGraphNodes.clear(); - createDummyGraphForTokenIdsAndSetActiveAndVisibility(std::vector(), m_storageAccess->getGraphForAll()); + if (message->filter) + { + createDummyGraphForTokenIdsAndSetActiveAndVisibility( + std::vector(), m_storageAccess->getGraphForFilter(message->filter)); - bundleNodesByType(); + addCharacterIndex(); + layoutNesting(); + layoutList(); + } + else + { + createDummyGraphForTokenIdsAndSetActiveAndVisibility(std::vector(), m_storageAccess->getGraphForAll()); - layoutNesting(); - assignBundleIds(); - layoutGraph(); + bundleNodesByType(); - buildGraph(message, false, true, false); + layoutNesting(); + assignBundleIds(); + layoutGraph(); + } + + buildGraph(message, false, true, message->filter); } void GraphController::handleMessage(MessageActivateTokens* message) diff --git a/src/lib/component/controller/SearchController.cpp b/src/lib/component/controller/SearchController.cpp index 966da252..c34b0194 100644 --- a/src/lib/component/controller/SearchController.cpp +++ b/src/lib/component/controller/SearchController.cpp @@ -16,6 +16,15 @@ SearchController::~SearchController() void SearchController::handleMessage(MessageActivateAll* message) { + if (message->filter) + { + if (message->isReplayed()) + { + getView()->setMatches(SearchMatch::createCommandsForFilter(message->filter)); + } + return; + } + getView()->setMatches(std::vector(1, SearchMatch::createCommand(SearchMatch::COMMAND_ALL))); } @@ -78,7 +87,7 @@ void SearchController::handleMessage(MessageSearchAutocomplete* message) } LOG_INFO("autocomplete string: \"" + message->query + "\""); - view->setAutocompletionList(m_storageAccess->getAutocompletionMatches(message->query)); + view->setAutocompletionList(m_storageAccess->getAutocompletionMatches(message->query, message->filter)); } void SearchController::handleMessage(MessageSearchFullText* message) diff --git a/src/lib/component/controller/UndoRedoController.cpp b/src/lib/component/controller/UndoRedoController.cpp index e6d00f15..1ba979db 100644 --- a/src/lib/component/controller/UndoRedoController.cpp +++ b/src/lib/component/controller/UndoRedoController.cpp @@ -44,7 +44,8 @@ UndoRedoController::Command::Command(std::shared_ptr message, Order void UndoRedoController::handleMessage(MessageActivateAll* message) { - if (sameMessageTypeAsLast(message)) + if (sameMessageTypeAsLast(message) && + static_cast(lastMessage())->filter == message->filter) { return; } @@ -595,7 +596,12 @@ SearchMatch UndoRedoController::getSearchMatchForMessage(MessageBase* message) c { if (message->getType() == MessageActivateAll::getStaticType()) { - return SearchMatch::createCommand(SearchMatch::COMMAND_ALL); + SearchMatch match = SearchMatch::createCommand(SearchMatch::COMMAND_ALL); + if (dynamic_cast(message)->filter) + { + match.name = match.text = "filter"; // TODO: show filter names + } + return match; } else if (message->getType() == MessageActivateTokens::getStaticType()) { @@ -604,6 +610,14 @@ SearchMatch UndoRedoController::getSearchMatchForMessage(MessageBase* message) c { return msg->searchMatches.front(); } + else if (msg->isAggregation) + { + SearchMatch match; + match.name = match.text = "aggregation"; // TODO: show aggregation source and target + match.searchType = SearchMatch::SEARCH_TOKEN; + match.nodeType = Node::NODE_TYPE; + return match; + } } else if (message->getType() == MessageSearchFullText::getStaticType()) { diff --git a/src/lib/data/HierarchyCache.cpp b/src/lib/data/HierarchyCache.cpp index 02f62ca4..446d3c87 100644 --- a/src/lib/data/HierarchyCache.cpp +++ b/src/lib/data/HierarchyCache.cpp @@ -278,6 +278,28 @@ bool HierarchyCache::nodeHasChildren(Id nodeId) const return false; } +bool HierarchyCache::nodeIsVisible(Id nodeId) const +{ + HierarchyNode* node = getNode(nodeId); + if (node) + { + return node->isVisible(); + } + + return false; +} + +bool HierarchyCache::nodeIsImplicit(Id nodeId) const +{ + HierarchyNode* node = getNode(nodeId); + if (node) + { + return node->isImplicit(); + } + + return false; +} + std::vector>> HierarchyCache::getInheritanceEdgesForNodeId( Id nodeId, const std::set& nodeIds) const { diff --git a/src/lib/data/HierarchyCache.h b/src/lib/data/HierarchyCache.h index 6e611a21..d8b4f339 100644 --- a/src/lib/data/HierarchyCache.h +++ b/src/lib/data/HierarchyCache.h @@ -29,6 +29,8 @@ public: bool isChildOfVisibleNodeOrInvisible(Id nodeId) const; bool nodeHasChildren(Id nodeId) const; + bool nodeIsVisible(Id nodeId) const; + bool nodeIsImplicit(Id nodeId) const; std::vector>> getInheritanceEdgesForNodeId(Id nodeId, const std::set& nodeIds) const; diff --git a/src/lib/data/access/StorageAccess.h b/src/lib/data/access/StorageAccess.h index fae06f7d..88a9a312 100644 --- a/src/lib/data/access/StorageAccess.h +++ b/src/lib/data/access/StorageAccess.h @@ -47,10 +47,11 @@ public: virtual std::shared_ptr getFullTextSearchLocations( const std::string& searchTerm, bool caseSensitive) const = 0; - virtual std::vector getAutocompletionMatches(const std::string& query) const = 0; + virtual std::vector getAutocompletionMatches(const std::string& query, Node::NodeTypeMask filter) const = 0; virtual std::vector getSearchMatchesForTokenIds(const std::vector& tokenIds) const = 0; virtual std::shared_ptr getGraphForAll() const = 0; + virtual std::shared_ptr getGraphForFilter(Node::NodeTypeMask filter) const = 0; virtual std::shared_ptr getGraphForActiveTokenIds( const std::vector& tokenIds, const std::vector& expandedNodeIds, bool* isActiveNamespace = nullptr) const = 0; virtual std::shared_ptr getGraphForChildrenOfNodeId(Id nodeId) const = 0; diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index d1462963..4fc4f186 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -125,11 +125,11 @@ std::shared_ptr StorageAccessProxy::getFullTextSearchL return std::make_shared(); } -std::vector StorageAccessProxy::getAutocompletionMatches(const std::string& query) const +std::vector StorageAccessProxy::getAutocompletionMatches(const std::string& query, Node::NodeTypeMask filter) const { if (hasSubject()) { - return m_subject->getAutocompletionMatches(query); + return m_subject->getAutocompletionMatches(query, filter); } return std::vector(); @@ -155,6 +155,16 @@ std::shared_ptr StorageAccessProxy::getGraphForAll() const return std::make_shared(); } +std::shared_ptr StorageAccessProxy::getGraphForFilter(Node::NodeTypeMask filter) const +{ + if (hasSubject()) + { + return m_subject->getGraphForFilter(filter); + } + + return std::make_shared(); +} + std::shared_ptr StorageAccessProxy::getGraphForActiveTokenIds( const std::vector& tokenIds, const std::vector& expandedNodeIds, bool* isActiveNamespace) const { diff --git a/src/lib/data/access/StorageAccessProxy.h b/src/lib/data/access/StorageAccessProxy.h index 1e36fad4..2d8e35b3 100644 --- a/src/lib/data/access/StorageAccessProxy.h +++ b/src/lib/data/access/StorageAccessProxy.h @@ -33,10 +33,11 @@ public: virtual std::shared_ptr getFullTextSearchLocations( const std::string& searchTerm, bool caseSensitive) const; - virtual std::vector getAutocompletionMatches(const std::string& query) const; + virtual std::vector getAutocompletionMatches(const std::string& query, Node::NodeTypeMask filter) const; virtual std::vector getSearchMatchesForTokenIds(const std::vector& tokenIds) const; virtual std::shared_ptr getGraphForAll() const; + virtual std::shared_ptr getGraphForFilter(Node::NodeTypeMask filter) const; virtual std::shared_ptr getGraphForActiveTokenIds( const std::vector& tokenIds, const std::vector& expandedNodeIds, bool* isActiveNamespace = nullptr) const; virtual std::shared_ptr getGraphForChildrenOfNodeId(Id nodeId) const; diff --git a/src/lib/data/graph/Node.cpp b/src/lib/data/graph/Node.cpp index 0b8cbc8c..981f637d 100644 --- a/src/lib/data/graph/Node.cpp +++ b/src/lib/data/graph/Node.cpp @@ -73,6 +73,20 @@ std::string Node::getReadableTypeString(NodeType type) return ""; } +Node::NodeType Node::getTypeForReadableTypeString(const std::string str) +{ + for (Node::NodeTypeMask mask = 1; mask <= NODE_MAX_VALUE; mask *= 2) + { + Node::NodeType type = intToType(mask); + if (getReadableTypeString(type) == str) + { + return type; + } + } + + return NODE_NON_INDEXED; +} + int Node::typeToInt(NodeType type) { return type; diff --git a/src/lib/data/graph/Node.h b/src/lib/data/graph/Node.h index c678a8d5..5c65b0e8 100644 --- a/src/lib/data/graph/Node.h +++ b/src/lib/data/graph/Node.h @@ -46,11 +46,14 @@ public: NODE_FILE = 0x20000, NODE_MACRO = 0x40000, - NODE_UNION = 0x80000 + NODE_UNION = 0x80000, + + NODE_MAX_VALUE = NODE_UNION }; static std::string getUnderscoredTypeString(NodeType type); static std::string getReadableTypeString(NodeType type); + static Node::NodeType getTypeForReadableTypeString(const std::string str); static int typeToInt(NodeType type); static NodeType intToType(int value); diff --git a/src/lib/data/search/SearchMatch.cpp b/src/lib/data/search/SearchMatch.cpp index 7c0f2004..b311d677 100644 --- a/src/lib/data/search/SearchMatch.cpp +++ b/src/lib/data/search/SearchMatch.cpp @@ -56,6 +56,27 @@ SearchMatch SearchMatch::createCommand(CommandType type) return match; } +std::vector SearchMatch::createCommandsForFilter(Node::NodeTypeMask filter) +{ + std::vector matches; + + for (Node::NodeTypeMask type = 1; type <= filter; type *= 2) + { + if (type & filter) + { + SearchMatch match; + match.name = Node::getReadableTypeString(Node::intToType(type)); + match.text = match.name; + match.typeName = "filter"; + match.searchType = SEARCH_COMMAND; + match.nodeType = Node::intToType(type); + matches.push_back(match); + } + } + + return matches; +} + std::string SearchMatch::getCommandName(CommandType type) { switch (type) @@ -64,6 +85,8 @@ std::string SearchMatch::getCommandName(CommandType type) return "overview"; case COMMAND_ERROR: return "error"; + case COMMAND_NODE_FILTER: + return "node_filter"; case COMMAND_COLOR_SCHEME_TEST: return "color_scheme_test"; } @@ -71,26 +94,9 @@ std::string SearchMatch::getCommandName(CommandType type) return "none"; } -SearchMatch::CommandType SearchMatch::getCommandType(const std::string& name) -{ - if (name == "overview") - { - return COMMAND_ALL; - } - else if (name == "error") - { - return COMMAND_ERROR; - } - else if (name == "color_scheme_test") - { - return COMMAND_COLOR_SCHEME_TEST; - } - - return COMMAND_ALL; -} - SearchMatch::SearchMatch() : typeName("") + , nodeType(Node::NODE_NON_INDEXED) , searchType(SEARCH_NONE) , hasChildren(false) { @@ -100,6 +106,7 @@ SearchMatch::SearchMatch(const std::string& query) : name(query) , text(query) , typeName("") + , nodeType(Node::NODE_NON_INDEXED) , searchType(SEARCH_NONE) , hasChildren(false) { @@ -193,6 +200,11 @@ bool SearchMatch::isValid() const return searchType != SEARCH_NONE; } +bool SearchMatch::isFilterCommand() const +{ + return searchType == SEARCH_COMMAND && getCommandType() == COMMAND_NODE_FILTER; +} + void SearchMatch::print(std::ostream& ostream) const { ostream << name << std::endl << '\t'; @@ -229,3 +241,21 @@ std::string SearchMatch::getSearchTypeName() const { return getSearchTypeName(searchType); } + +SearchMatch::CommandType SearchMatch::getCommandType() const +{ + if (name == "overview") + { + return COMMAND_ALL; + } + else if (name == "error") + { + return COMMAND_ERROR; + } + else if (name == "color_scheme_test") + { + return COMMAND_COLOR_SCHEME_TEST; + } + + return COMMAND_NODE_FILTER; +} diff --git a/src/lib/data/search/SearchMatch.h b/src/lib/data/search/SearchMatch.h index 8f5be19b..eb7237fb 100644 --- a/src/lib/data/search/SearchMatch.h +++ b/src/lib/data/search/SearchMatch.h @@ -24,6 +24,7 @@ struct SearchMatch { COMMAND_ALL, COMMAND_ERROR, + COMMAND_NODE_FILTER, COMMAND_COLOR_SCHEME_TEST }; @@ -33,8 +34,8 @@ struct SearchMatch static std::string searchMatchesToString(const std::vector& matches); static SearchMatch createCommand(CommandType type); + static std::vector createCommandsForFilter(Node::NodeTypeMask filter); static std::string getCommandName(CommandType type); - static CommandType getCommandType(const std::string& name); static const char FULLTEXT_SEARCH_CHARACTER = '?'; @@ -47,12 +48,14 @@ struct SearchMatch size_t getTextSizeForSorting(const std::string* str) const; bool isValid() const; + bool isFilterCommand() const; void print(std::ostream& ostream) const; std::string getFullName() const; std::string getNodeTypeAsUnderscoredString() const; std::string getSearchTypeName() const; + CommandType getCommandType() const; std::string name; std::vector tokenIds; diff --git a/src/lib/data/storage/PersistentStorage.cpp b/src/lib/data/storage/PersistentStorage.cpp index 9a11e697..e405ee59 100644 --- a/src/lib/data/storage/PersistentStorage.cpp +++ b/src/lib/data/storage/PersistentStorage.cpp @@ -31,7 +31,30 @@ PersistentStorage::PersistentStorage(const FilePath& dbPath, const FilePath& boo { m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_ALL)); m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR)); + + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_NON_INDEXED)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_TYPE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_BUILTIN_TYPE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_NAMESPACE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_PACKAGE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_STRUCT)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_CLASS)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_INTERFACE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_GLOBAL_VARIABLE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_FIELD)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_FUNCTION)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_METHOD)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_ENUM)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_ENUM_CONSTANT)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_TYPEDEF)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_TEMPLATE_PARAMETER_TYPE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_TYPE_PARAMETER)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_FILE)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_MACRO)); + m_commandIndex.addNode(0, Node::getReadableTypeString(Node::NODE_UNION)); + // m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_COLOR_SCHEME_TEST)); + m_commandIndex.finishSetup(); } @@ -558,7 +581,7 @@ std::shared_ptr PersistentStorage::getFullTextSearchLo return collection; } -std::vector PersistentStorage::getAutocompletionMatches(const std::string& query) const +std::vector PersistentStorage::getAutocompletionMatches(const std::string& query, Node::NodeTypeMask filter) const { TRACE(); @@ -568,9 +591,18 @@ std::vector PersistentStorage::getAutocompletionMatches(const std:: // create SearchMatches std::vector matches; - utility::append(matches, getAutocompletionSymbolMatches(query, maxResultsCount)); - utility::append(matches, getAutocompletionFileMatches(query, maxResultsCount)); - utility::append(matches, getAutocompletionCommandMatches(query)); + + if (!filter || (filter & ~Node::NODE_FILE)) + { + utility::append(matches, getAutocompletionSymbolMatches(query, filter, maxResultsCount)); + } + + if (!filter || (filter & Node::NODE_FILE)) + { + utility::append(matches, getAutocompletionFileMatches(query, maxResultsCount)); + } + + utility::append(matches, getAutocompletionCommandMatches(query, filter)); std::set matchesSet; for (SearchMatch& match : matches) @@ -592,7 +624,7 @@ std::vector PersistentStorage::getAutocompletionMatches(const std:: } std::vector PersistentStorage::getAutocompletionSymbolMatches( - const std::string& query, size_t maxResultsCount) const + const std::string& query, Node::NodeTypeMask filter, size_t maxResultsCount) const { // search in indices std::vector results = m_symbolIndex.search(query, maxResultsCount, maxResultsCount); @@ -632,7 +664,7 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( { match.tokenIds.push_back(elementId); - if (!match.hasChildren) + if (!match.hasChildren && !filter) // TODO: apply filter to children { match.hasChildren = m_hierarchyCache.nodeHasChildren(elementId); } @@ -644,6 +676,11 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( } } + if (filter && !(filter & Node::intToType(firstNode->type))) + { + continue; + } + match.name = result.text; match.text = result.text; @@ -705,7 +742,8 @@ std::vector PersistentStorage::getAutocompletionFileMatches(const s return matches; } -std::vector PersistentStorage::getAutocompletionCommandMatches(const std::string& query) const +std::vector PersistentStorage::getAutocompletionCommandMatches( + const std::string& query, Node::NodeTypeMask filter) const { // search in indices std::vector results = m_commandIndex.search(query, 0); @@ -727,7 +765,16 @@ std::vector PersistentStorage::getAutocompletionCommandMatches(cons match.searchType = SearchMatch::SEARCH_COMMAND; match.typeName = "command"; - matches.push_back(match); + if (match.getCommandType() == SearchMatch::COMMAND_NODE_FILTER) + { + match.nodeType = Node::getTypeForReadableTypeString(match.name); + match.typeName = "filter"; + } + + if (!filter || (match.getCommandType() == SearchMatch::COMMAND_NODE_FILTER && !(filter & match.nodeType))) + { + matches.push_back(match); + } } return matches; @@ -809,6 +856,38 @@ std::shared_ptr PersistentStorage::getGraphForAll() const return graph; } +std::shared_ptr PersistentStorage::getGraphForFilter(Node::NodeTypeMask filter) const +{ + TRACE(); + + std::shared_ptr graph = std::make_shared(); + + std::vector tokenIds; + for (StorageNode& node: m_sqliteIndexStorage.getAll()) + { + if ((filter & Node::intToType(node.type))) + { + auto it = m_symbolDefinitionKinds.find(node.id); + if (it != m_symbolDefinitionKinds.end() && it->second == DEFINITION_EXPLICIT) + { + tokenIds.push_back(node.id); + } + } + } + + if (!filter || (filter & Node::NODE_FILE)) + { + for (const auto& p : m_fileNodePaths) + { + tokenIds.push_back(p.first); + } + } + + addNodesWithParentsAndEdgesToGraph(tokenIds, std::vector(), graph.get(), false); + + return graph; +} + std::shared_ptr PersistentStorage::getGraphForActiveTokenIds( const std::vector& tokenIds, const std::vector& expandedNodeIds, bool* isActiveNamespace) const { @@ -918,7 +997,7 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds( } else { - addNodesWithParentsAndEdgesToGraph(nodeIds, edgeIds, graph); + addNodesWithParentsAndEdgesToGraph(nodeIds, edgeIds, graph, true); } if (addAggregations) @@ -1035,7 +1114,7 @@ std::shared_ptr PersistentStorage::getGraphForTrail( std::shared_ptr graph = std::make_shared(); - addNodesWithParentsAndEdgesToGraph(utility::toVector(nodeIds), utility::toVector(edgeIds), graph.get()); + addNodesWithParentsAndEdgesToGraph(utility::toVector(nodeIds), utility::toVector(edgeIds), graph.get(), false); addComponentAccessToGraph(graph.get()); return graph; @@ -2128,7 +2207,7 @@ void PersistentStorage::addEdgesToGraph(const std::vector& newEdgeIds, Graph } void PersistentStorage::addNodesWithParentsAndEdgesToGraph( - const std::vector& nodeIds, const std::vector& edgeIds, Graph* graph + const std::vector& nodeIds, const std::vector& edgeIds, Graph* graph, bool addChildCount ) const { TRACE(); @@ -2153,7 +2232,7 @@ void PersistentStorage::addNodesWithParentsAndEdgesToGraph( allNodeIds.insert(parentNodeIds.begin(), parentNodeIds.end()); - addNodesToGraph(utility::toVector(allNodeIds), graph, true); + addNodesToGraph(utility::toVector(allNodeIds), graph, addChildCount); addEdgesToGraph(utility::toVector(allEdgeIds), graph); } @@ -2231,7 +2310,7 @@ void PersistentStorage::addAggregationEdgesToGraph( nodeIdsToAdd.push_back(aggregationTargetNodeId); } } - addNodesWithParentsAndEdgesToGraph(nodeIdsToAdd, std::vector(), graph); + addNodesWithParentsAndEdgesToGraph(nodeIdsToAdd, std::vector(), graph, true); // create aggregation edges between parents and active node Node* sourceNode = graph->getNodeById(nodeId); diff --git a/src/lib/data/storage/PersistentStorage.h b/src/lib/data/storage/PersistentStorage.h index 2d60c0de..7a7e42e1 100644 --- a/src/lib/data/storage/PersistentStorage.h +++ b/src/lib/data/storage/PersistentStorage.h @@ -87,13 +87,15 @@ public: virtual std::shared_ptr getFullTextSearchLocations( const std::string& searchTerm, bool caseSensitive) const; - virtual std::vector getAutocompletionMatches(const std::string& query) const; - std::vector getAutocompletionSymbolMatches(const std::string& query, size_t maxResultsCount) const; + virtual std::vector getAutocompletionMatches(const std::string& query, Node::NodeTypeMask filter) const; + std::vector getAutocompletionSymbolMatches( + const std::string& query, Node::NodeTypeMask filter, size_t maxResultsCount) const; std::vector getAutocompletionFileMatches(const std::string& query, size_t maxResultsCount) const; - std::vector getAutocompletionCommandMatches(const std::string& query) const; + std::vector getAutocompletionCommandMatches(const std::string& query, Node::NodeTypeMask filter) const; virtual std::vector getSearchMatchesForTokenIds(const std::vector& elementIds) const; virtual std::shared_ptr getGraphForAll() const; + virtual std::shared_ptr getGraphForFilter(Node::NodeTypeMask filter) const; virtual std::shared_ptr getGraphForActiveTokenIds( const std::vector& tokenIds, const std::vector& expandedNodeIds, bool* isActiveNamespace = nullptr) const; virtual std::shared_ptr getGraphForChildrenOfNodeId(Id nodeId) const; @@ -163,7 +165,7 @@ private: void addNodesToGraph(const std::vector& nodeIds, Graph* graph, bool addChildCount) const; void addEdgesToGraph(const std::vector& edgeIds, Graph* graph) const; void addNodesWithParentsAndEdgesToGraph( - const std::vector& nodeIds, const std::vector& edgeIds, Graph* graph) const; + const std::vector& nodeIds, const std::vector& edgeIds, Graph* graphh, bool addChildCount) const; void addAggregationEdgesToGraph(const Id nodeId, const std::vector& edgesToAggregate, Graph* graph) const; void addComponentAccessToGraph(Graph* graph) const; diff --git a/src/lib/utility/messaging/type/MessageActivateAll.h b/src/lib/utility/messaging/type/MessageActivateAll.h index d16075ae..70f5a5ac 100644 --- a/src/lib/utility/messaging/type/MessageActivateAll.h +++ b/src/lib/utility/messaging/type/MessageActivateAll.h @@ -1,13 +1,15 @@ #ifndef MESSAGE_ACTIVATE_ALL_H #define MESSAGE_ACTIVATE_ALL_H +#include "data/graph/Node.h" #include "utility/messaging/Message.h" class MessageActivateAll : public Message { public: - MessageActivateAll() + MessageActivateAll(Node::NodeTypeMask filter = 0) + : filter(filter) { setIsParallel(true); } @@ -16,6 +18,8 @@ public: { return "MessageActivateAll"; } + + Node::NodeTypeMask filter; }; #endif // MESSAGE_ACTIVATE_ALL_H diff --git a/src/lib/utility/messaging/type/MessageSearch.h b/src/lib/utility/messaging/type/MessageSearch.h index b2245599..341a79df 100644 --- a/src/lib/utility/messaging/type/MessageSearch.h +++ b/src/lib/utility/messaging/type/MessageSearch.h @@ -9,8 +9,9 @@ class MessageSearch : public Message { public: - MessageSearch(const std::vector& matches) + MessageSearch(const std::vector& matches, Node::NodeTypeMask filter = 0) : isFromSearch(true) + , filter(filter) , m_matches(matches) { } @@ -71,6 +72,7 @@ public: } bool isFromSearch; + Node::NodeTypeMask filter; private: const std::vector m_matches; diff --git a/src/lib/utility/messaging/type/MessageSearchAutocomplete.h b/src/lib/utility/messaging/type/MessageSearchAutocomplete.h index fe5527a2..cb6b21dc 100644 --- a/src/lib/utility/messaging/type/MessageSearchAutocomplete.h +++ b/src/lib/utility/messaging/type/MessageSearchAutocomplete.h @@ -1,13 +1,16 @@ #ifndef MESSAGE_SEARCH_AUTOCOMPLETE_H #define MESSAGE_SEARCH_AUTOCOMPLETE_H +#include "data/graph/Node.h" #include "utility/messaging/Message.h" -class MessageSearchAutocomplete: public Message +class MessageSearchAutocomplete + : public Message { public: - MessageSearchAutocomplete(const std::string& query) + MessageSearchAutocomplete(const std::string& query, Node::NodeTypeMask filter) : query(query) + , filter(filter) { } @@ -18,10 +21,11 @@ public: virtual void print(std::ostream& os) const { - os << query; + os << query << " " << filter; } const std::string query; + const Node::NodeTypeMask filter; }; #endif // MESSAGE_SEARCH_AUTOCOMPLETE_H diff --git a/src/lib_gui/qt/element/QtAutocompletionList.cpp b/src/lib_gui/qt/element/QtAutocompletionList.cpp index 19f452f2..300bad04 100644 --- a/src/lib_gui/qt/element/QtAutocompletionList.cpp +++ b/src/lib_gui/qt/element/QtAutocompletionList.cpp @@ -144,12 +144,10 @@ void QtAutocompletionDelegate::paint(QPainter* painter, const QStyleOptionViewIt // define highlight colors ColorScheme* scheme = ColorScheme::getInstance().get(); -// QColor fillColor("#FFFFFF"); QColor fillColor(0xFF, 0xFF, 0xFF); -// QColor textColor("#000000"); QColor textColor(0, 0, 0); - if (type.size() && type != "command") + if (type.size() && type != "command" && type != "filter") { const GraphViewStyle::NodeColor& nodeColor = GraphViewStyle::getNodeColor(Node::getUnderscoredTypeString(nodeType), false); fillColor = QColor(nodeColor.fill.c_str()); diff --git a/src/lib_gui/qt/element/QtSmartSearchBox.cpp b/src/lib_gui/qt/element/QtSmartSearchBox.cpp index 5c118282..0eb22cbf 100644 --- a/src/lib_gui/qt/element/QtSmartSearchBox.cpp +++ b/src/lib_gui/qt/element/QtSmartSearchBox.cpp @@ -32,6 +32,11 @@ void QtSmartSearchBox::search() { editTextToElement(); + if (!m_matches.size()) + { + return; + } + // Do a fulltext search if no autocompletion match was selected for this match if (m_matches.size() == 1) { @@ -55,7 +60,7 @@ void QtSmartSearchBox::search() std::vector matches = utility::toVector(m_matches); - MessageSearch(matches).dispatch(); + MessageSearch(matches, getMatchFilter()).dispatch(); } void QtSmartSearchBox::fullTextSearch() @@ -83,7 +88,6 @@ void QtSmartSearchBox::fullTextSearch() QtSmartSearchBox::QtSmartSearchBox(QWidget* parent) : QLineEdit(parent) - , m_allowMultipleElements(false) , m_allowTextChange(false) , m_cursorIndex(0) , m_shiftKeyDown(false) @@ -176,20 +180,20 @@ bool QtSmartSearchBox::event(QEvent *event) { if (m_completer->popup()->isVisible()) { - if (m_highlightedMatch.hasChildren) + if (m_highlightedMatch.isFilterCommand()) + { + addMatchAndUpdate(m_highlightedMatch); + } + else if (m_highlightedMatch.hasChildren) { setEditText((m_highlightedMatch.getFullName() + nameDelimiterTypeToString(m_highlightedMatch.delimiter)).c_str()); + requestAutoCompletions(); } else { setEditText(m_highlightedMatch.getFullName().c_str()); + requestAutoCompletions(); } - - requestAutoCompletions(); - } - else if (m_allowMultipleElements) - { - requestAutoCompletions(); } return true; } @@ -525,7 +529,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text) } } - if (match.name.size() && !m_allowMultipleElements) + if (match.name.size() && lastMatchIsNoFilter()) { if (m_matches.size()) { @@ -544,7 +548,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text) layoutElements(); } - if (match.name.size() || m_elements.size()) + if (match.name.size()) { requestAutoCompletions(); } @@ -665,7 +669,7 @@ void QtSmartSearchBox::addMatch(const SearchMatch& match) } } - if (!m_allowMultipleElements) + if (lastMatchIsNoFilter()) { clearMatches(); } @@ -743,6 +747,10 @@ void QtSmartSearchBox::updateElements() { std::string name = match.getFullName(); name = utility::replace(name, "&", "&&"); + if (match.isFilterCommand()) + { + name += ':'; + } std::shared_ptr element = std::make_shared(QString::fromStdString(name), this); m_elements.push_back(element); @@ -964,7 +972,7 @@ void QtSmartSearchBox::requestAutoCompletions() { if (text().size() && !text().startsWith(SearchMatch::FULLTEXT_SEARCH_CHARACTER)) { - MessageSearchAutocomplete(text().toStdString()).dispatch(); + MessageSearchAutocomplete(text().toStdString(), getMatchFilter()).dispatch(); } else { @@ -986,3 +994,27 @@ std::deque QtSmartSearchBox::getMatchesForInput(const std::string& } return matches; } + +Node::NodeTypeMask QtSmartSearchBox::getMatchFilter() const +{ + Node::NodeTypeMask filter = 0; + + for (const SearchMatch& match : m_matches) + { + if (match.isFilterCommand()) + { + filter |= match.nodeType; + } + else + { + break; + } + } + + return filter; +} + +bool QtSmartSearchBox::lastMatchIsNoFilter() const +{ + return !m_matches.size() || !m_matches.back().isFilterCommand(); +} diff --git a/src/lib_gui/qt/element/QtSmartSearchBox.h b/src/lib_gui/qt/element/QtSmartSearchBox.h index 4cf1067d..981b5b20 100644 --- a/src/lib_gui/qt/element/QtSmartSearchBox.h +++ b/src/lib_gui/qt/element/QtSmartSearchBox.h @@ -99,7 +99,8 @@ private: std::deque getMatchesForInput(const std::string& text) const; - bool m_allowMultipleElements; + Node::NodeTypeMask getMatchFilter() const; + bool lastMatchIsNoFilter() const; bool m_allowTextChange; QString m_oldText;