Fixed UI bug

This commit is contained in:
Eugene Livis 2019-06-28 13:46:09 -04:00
parent d61f29bc9f
commit ccbb8aa64f

View File

@ -76,7 +76,7 @@ public class ViewContextAction extends AbstractAction {
* parent of the content, selecting the parent in the tree view, then
* selecting the content in the results view.
*
* @param displayName The display name for the action.
* @param displayName The display name for the action.
* @param artifactNode The artifact node for the artifact.
*/
public ViewContextAction(String displayName, BlackboardArtifactNode artifactNode) {
@ -98,21 +98,20 @@ public class ViewContextAction extends AbstractAction {
* parent of the content, selecting the parent in the tree view, then
* selecting the content in the results view.
*
* @param displayName The display name for the action.
* @param displayName The display name for the action.
* @param fileSystemContentNode The file system content node for the
* content.
* content.
*/
public ViewContextAction(String displayName, AbstractFsContentNode<? extends AbstractFile> fileSystemContentNode) {
super(displayName);
this.content = fileSystemContentNode.getLookup().lookup(Content.class);
}
/**
* An action that displays the context for abstract file by
* expanding the data sources branch of the tree view to the level of the
* parent of the content, selecting the parent in the tree view, then
* selecting the content in the results view.
* An action that displays the context for abstract file by expanding the
* data sources branch of the tree view to the level of the parent of the
* content, selecting the parent in the tree view, then selecting the
* content in the results view.
*
* @param displayName The display name for the action.
* @param abstractAbstractFileNode The AbstractAbstractFileNode node for the
@ -130,7 +129,7 @@ public class ViewContextAction extends AbstractAction {
* content in the results view.
*
* @param displayName The display name for the action.
* @param content The content.
* @param content The content.
*/
public ViewContextAction(String displayName, Content content) {
super(displayName);
@ -153,12 +152,29 @@ public class ViewContextAction extends AbstractAction {
})
public void actionPerformed(ActionEvent event) {
EventQueue.invokeLater(() -> {
/*
* Get the parent content for the content to be selected in the
* results view. If the parent content is null, then the specified
* content is a data source, and the parent tree view node is the
* "Data Sources" node. Otherwise, the tree view needs to be
* searched to find the parent treeview node.
*/
Content parentContent = null;
try {
parentContent = content.getParent();
} catch (TskCoreException ex) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory());
logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS
return;
}
/*
* Get the "Data Sources" node from the tree view.
*/
DirectoryTreeTopComponent treeViewTopComponent = DirectoryTreeTopComponent.findInstance();
ExplorerManager treeViewExplorerMgr = treeViewTopComponent.getExplorerManager();
Node parentTreeViewNode;
Node parentTreeViewNode = null;
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { // 'Group by Data Source' view
SleuthkitCase skCase;
@ -169,13 +185,44 @@ public class ViewContextAction extends AbstractAction {
long contentDSObjid = content.getDataSource().getId();
DataSource datasource = skCase.getDataSource(contentDSObjid);
dsname = datasource.getName();
Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
Node datasourceGroupingNode = rootChildren.findChild(dsname);
if (!Objects.isNull(datasourceGroupingNode)) {
Children dsChildren = datasourceGroupingNode.getChildren();
parentTreeViewNode = dsChildren.findChild(DataSourcesNode.NAME);
if (null != parentContent) {
// the tree view needs to be searched to find the parent treeview node.
/* NOTE: we can't do a lookup by data source name here, becase if there
are multiple data sources with the same name, then "getChildren().findChild(dsname)"
simply returns the first one that it finds. Instead we have to loop over all
data sources with that name, and make sure we find the correct one.
*/
for (int i = 0; i < rootChildren.getNodesCount(); i++) {
// in the root, look for a data source node with the name of interest
Node treeNode = rootChildren.getNodeAt(i);
if (!(treeNode.getName().equals(dsname))) {
continue;
}
// for this data source, get the "Data Sources" child node
Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourcesNode.NAME);
// check whether this is the data source we are looking for
parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode);
if (parentTreeViewNode != null) {
// found the data source node
break;
}
}
} else {
/* If the parent content is null, then the specified
* content is a data source, and the parent tree view node is the
* "Data Sources" node. */
Node datasourceGroupingNode = rootChildren.findChild(dsname);
if (!Objects.isNull(datasourceGroupingNode)) {
Children dsChildren = datasourceGroupingNode.getChildren();
parentTreeViewNode = dsChildren.findChild(DataSourcesNode.NAME);
}
}
if (parentTreeViewNode == null) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode());
logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS
return;
@ -188,65 +235,12 @@ public class ViewContextAction extends AbstractAction {
} else { // Classic view
// Start the search at the DataSourcesNode
parentTreeViewNode = treeViewExplorerMgr.getRootContext().getChildren().findChild(DataSourcesNode.NAME);
}
/*
* Get the parent content for the content to be selected in the
* results view. If the parent content is null, then the specified
* content is a data source, and the parent tree view node is the
* "Data Sources" node. Otherwise, the tree view needs to be
* searched to find the parent treeview node.
*/
Content parentContent = null;
try {
parentContent = content.getParent();
} catch (TskCoreException ex) {
MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory());
logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS
return;
}
if (null != parentContent) {
/*
* Get an ordered list of the ancestors of the specified
* content, starting with its data source.
*
*/
AncestorVisitor ancestorVisitor = new AncestorVisitor();
List<Content> contentBranch = parentContent.accept(ancestorVisitor);
Collections.reverse(contentBranch);
/**
* Convert the list of ancestors into a list of tree nodes.
*
* IMPORTANT: The "dummy" root node used to create this single
* layer of children needs to be wrapped in a
* DirectoryTreeFilterNode so that its child nodes will also be
* wrapped in DirectoryTreeFilterNodes, via
* DirectoryTreeFilterNodeChildren. Otherwise, the display names
* of the nodes in the branch will not have child node counts
* and will not match the display names of the corresponding
* nodes in the actual tree view.
*/
Node dummyRootNode = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(contentBranch)), true);
Children ancestorChildren = dummyRootNode.getChildren();
/*
* Search the tree for the parent node. Note that this algorithm
* simply discards "extra" ancestor nodes not shown in the tree,
* such as the root directory of the file system for file system
* content.
*/
Children treeNodeChildren = parentTreeViewNode.getChildren();
for (int i = 0; i < ancestorChildren.getNodesCount(); i++) {
Node ancestorNode = ancestorChildren.getNodeAt(i);
for (int j = 0; j < treeNodeChildren.getNodesCount(); j++) {
Node treeNode = treeNodeChildren.getNodeAt(j);
if (ancestorNode.getName().equals(treeNode.getName())) {
parentTreeViewNode = treeNode;
treeNodeChildren = treeNode.getChildren();
break;
}
if (null != parentContent) {
// the tree view needs to be searched to find the parent treeview node.
Node potentialParentTreeViewNode = findParentNodeInTree(parentContent, parentTreeViewNode);
if (potentialParentTreeViewNode != null) {
parentTreeViewNode = potentialParentTreeViewNode;
}
}
}
@ -292,6 +286,57 @@ public class ViewContextAction extends AbstractAction {
});
}
/**
* Searches tree for parent node by getting an ordered list of the ancestors
* of the specified content.
*
* @param parentContent parent content for the content to be searched for
* @param node Node tree to search
* @return Node object of the matching parent, NULL if not found
*/
private Node findParentNodeInTree(Content parentContent, Node node) {
/*
* Get an ordered list of the ancestors of the specified
* content, starting with its data source.
*
*/
AncestorVisitor ancestorVisitor = new AncestorVisitor();
List<Content> contentBranch = parentContent.accept(ancestorVisitor);
Collections.reverse(contentBranch);
/**
* Convert the list of ancestors into a list of tree nodes.
*
* IMPORTANT: The "dummy" root node used to create this single layer of
* children needs to be wrapped in a DirectoryTreeFilterNode so that its
* child nodes will also be wrapped in DirectoryTreeFilterNodes, via
* DirectoryTreeFilterNodeChildren. Otherwise, the display names of the
* nodes in the branch will not have child node counts and will not
* match the display names of the corresponding nodes in the actual tree
* view.
*/
Node dummyRootNode = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(contentBranch)), true);
Children ancestorChildren = dummyRootNode.getChildren();
/*
* Search the tree for the parent node. Note that this algorithm
* simply discards "extra" ancestor nodes not shown in the tree,
* such as the root directory of the file system for file system
* content.
*/
Children treeNodeChildren = node.getChildren();
for (int i = 0; i < ancestorChildren.getNodesCount(); i++) {
Node ancestorNode = ancestorChildren.getNodeAt(i);
for (int j = 0; j < treeNodeChildren.getNodesCount(); j++) {
Node treeNode = treeNodeChildren.getNodeAt(j);
if (ancestorNode.getName().equals(treeNode.getName())) {
return treeNode;
}
}
}
return null;
}
/**
* A ContentVisitor that returns a list of content objects by starting with
* a given content and following its chain of ancestors to the root content