logic: Refactored undo redo stack

* Store MessageActivateTokens instead of original view messages
* Renamed FeatureController to ActivationController
* Remove all non-activation messages from undo redo stack after reindexing project
* Added MessageShowReference to undo redo stack
* Added MessageScrollGraph for restoring graph view scroll position
* Fixed MessageGraphNodeMove not saved for bundles
* Refactored tokenIds and nodeNames in SearchMatch and MessageActivateTokens
* Refactored SearchController
* Fixed file expansion on undoing/redoing after switching code view mode
* Fixed redundant graph animation due to present qualifier nodes
* Fixed no restoring of graph node expansion when showing overview in between
This commit is contained in:
Eberhard Graether
2017-03-16 23:24:33 +01:00
parent aa49fffca6
commit 630009a2ba
44 changed files with 516 additions and 400 deletions
+55 -67
View File
@@ -491,6 +491,30 @@ Node::NodeType PersistentStorage::getNodeTypeForNodeWithId(Id nodeId) const
return Node::intToType(m_sqliteStorage.getFirstById<StorageNode>(nodeId).type);
}
std::vector<NameHierarchy> PersistentStorage::getNameHierarchiesForNodeIds(const std::vector<Id> nodeIds) const
{
std::vector<NameHierarchy> nameHierarchies;
for (const StorageNode& storageNode : m_sqliteStorage.getAllByIds<StorageNode>(nodeIds))
{
nameHierarchies.push_back(NameHierarchy::deserialize(storageNode.serializedName));
}
return nameHierarchies;
}
std::vector<Id> PersistentStorage::getNodeIdsForNameHierarchies(const std::vector<NameHierarchy> nameHierarchies) const
{
std::vector<Id> nodeIds;
for (const NameHierarchy& name : nameHierarchies)
{
Id nodeId = getIdForNodeWithNameHierarchy(name);
if (nodeId)
{
nodeIds.push_back(nodeId);
}
}
return nodeIds;
}
std::shared_ptr<TokenLocationCollection> PersistentStorage::getFullTextSearchLocations(
const std::string& searchTerm, bool caseSensitive
) const
@@ -660,32 +684,31 @@ std::vector<SearchMatch> PersistentStorage::getAutocompletionSymbolMatches(const
for (const SearchResult& result : results)
{
SearchMatch match;
const StorageNode* firstNode = nullptr;
for (const Id& elementId : result.elementIds)
{
if (elementId != 0)
{
const StorageNode& node = storageNodeMap[elementId];
match.nameHierarchies.push_back(NameHierarchy::deserialize(node.serializedName));
match.tokenIds.push_back(elementId);
if (!match.hasChildren)
{
match.hasChildren = m_hierarchyCache.nodeHasChildren(node.id);
match.hasChildren = m_hierarchyCache.nodeHasChildren(elementId);
}
if (!firstNode)
{
firstNode = &node;
firstNode = &storageNodeMap[elementId];
}
}
}
match.name = result.text;
match.text = result.text;
const size_t idx = m_hierarchyCache.getIndexOfLastVisibleParentNode(firstNode->id);
const NameHierarchy& name = match.nameHierarchies[0];
const NameHierarchy& name = NameHierarchy::deserialize(firstNode->serializedName);
match.text = name.getRange(idx, name.size()).getQualifiedName();
match.subtext = name.getRange(0, idx).getQualifiedName();
@@ -717,9 +740,8 @@ std::vector<SearchMatch> PersistentStorage::getAutocompletionFileMatches(const s
{
SearchMatch match;
match.nameHierarchies.push_back(NameHierarchy(result.text));
match.name = result.text;
match.tokenIds = utility::toVector(result.elementIds);
FilePath path(match.name);
match.text = path.fileName();
@@ -770,31 +792,36 @@ std::vector<SearchMatch> PersistentStorage::getSearchMatchesForTokenIds(const st
// In that case there should be only one search match.
std::vector<SearchMatch> matches;
// fetch StorageNodes for node ids
std::map<Id, StorageNode> storageNodeMap;
for (StorageNode& node : m_sqliteStorage.getAllByIds<StorageNode>(elementIds))
{
storageNodeMap.emplace(node.id, node);
}
for (Id elementId : elementIds)
{
SearchMatch match;
NameHierarchy nameHierarchy = NameHierarchy::deserialize(m_sqliteStorage.getFirstById<StorageNode>(elementId).serializedName);
match.name = nameHierarchy.getQualifiedName();
match.text = nameHierarchy.getRawName();
match.nameHierarchies.push_back(nameHierarchy.getQualifiedName());
match.searchType = SearchMatch::SEARCH_TOKEN;
if (m_sqliteStorage.isFile(elementId))
{
match.text = FilePath(match.text).fileName();
match.nodeType = Node::NODE_FILE;
}
else if (m_sqliteStorage.isNode(elementId))
{
StorageNode node = m_sqliteStorage.getFirstById<StorageNode>(elementId);
match.nodeType = Node::intToType(node.type);
}
else
if (storageNodeMap.find(elementId) == storageNodeMap.end())
{
continue;
}
StorageNode node = storageNodeMap[elementId];
SearchMatch match;
NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName);
match.name = nameHierarchy.getQualifiedName();
match.text = nameHierarchy.getRawName();
match.tokenIds.push_back(elementId);
match.nodeType = Node::intToType(node.type);
match.searchType = SearchMatch::SEARCH_TOKEN;
if (match.nodeType == Node::NODE_FILE)
{
match.text = FilePath(match.text).fileName();
}
matches.push_back(match);
}
@@ -1070,45 +1097,6 @@ bool PersistentStorage::checkNodeExistsByName(const std::string& serializedName)
return m_sqliteStorage.checkNodeExistsByName(serializedName);
}
std::vector<Id> PersistentStorage::getTokenIdsForMatches(const std::vector<SearchMatch>& matches) const
{
FilePath rootPath = getDbFilePath().parentDirectory();
std::set<Id> idSet;
for (const SearchMatch& match : matches)
{
if (match.nodeType == Node::NODE_FILE)
{
FilePath path(match.subtext);
if (!path.isAbsolute())
{
path = rootPath.concat(path).canonical();
}
idSet.insert(m_sqliteStorage.getFileByPath(path.str()).id);
}
else
{
for (size_t i = 0; i < match.nameHierarchies.size(); i++)
{
idSet.insert(
m_sqliteStorage.getNodeBySerializedName(NameHierarchy::serialize(match.nameHierarchies[i])).id
);
}
}
}
std::vector<Id> ids;
for (std::set<Id>::const_iterator it = idSet.begin(); it != idSet.end(); it++)
{
if (*it != 0)
{
ids.push_back(*it);
}
}
return ids;
}
Id PersistentStorage::getTokenIdForFileNode(const FilePath& filePath) const
{
return m_sqliteStorage.getFileByPath(filePath.str()).id;