Now working, using property getValue to color, adding listeners at node to update

This commit is contained in:
Sophie Mori 2016-10-25 14:12:14 -04:00
parent d961e4baa6
commit e35faceb08
9 changed files with 103 additions and 58 deletions

View File

@ -39,7 +39,7 @@ abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Seri
private transient T tag; private transient T tag;
/** /**
* The id of the tag that was added. This will bu used to re-load the * The id of the tag that was added. This will be used to re-load the
* transient tag from the database. * transient tag from the database.
*/ */
private final Long tagID; private final Long tagID;

View File

@ -60,18 +60,14 @@ import org.openide.nodes.Sheet;
import org.openide.util.Exceptions; import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbPreferences; import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* DataResult sortable table viewer * DataResult sortable table viewer
*/ */
// @@@ Restore implementation of DataResultViewerTable as a DataResultViewer // @@@ Restore implementation of DataResultViewerTable as a DataResultViewer
// service provider when DataResultViewers can be made compatible with node // service provider when DataResultViewers can be made compatible with node
// multiple selection actions. // multiple selection actions.
//@ServiceProvider(service = DataResultViewer.class) //@ServiceProvider(service = DataResultViewer.class)
public class DataResultViewerTable extends AbstractDataResultViewer { public class DataResultViewerTable extends AbstractDataResultViewer {
@ -166,7 +162,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
} }
oldColumnIndex = -1; oldColumnIndex = -1;
} }
}); });
} }
/** /**
@ -423,11 +419,12 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
for (int column = 0; column < ov.getOutline().getModel().getColumnCount(); column++) { for (int column = 0; column < ov.getOutline().getModel().getColumnCount(); column++) {
int firstColumnPadding = (column == 0) ? 32 : 0; int firstColumnPadding = (column == 0) ? 32 : 0;
int columnWidthLimit = (column == 0) ? 250 : 300; int columnWidthLimit = (column == 0) ? 350 : 300;
int valuesWidth = 0; int valuesWidth = 0;
// find the maximum width needed to fit the values for the first 30 rows, at most // find the maximum width needed to fit the values for the first 15 rows, at most
for (int row = 0; row < Math.min(30, ov.getOutline().getRowCount()); row++) { // *15 is an arbitrary number
for (int row = 0; row < Math.min(15, ov.getOutline().getRowCount()); row++) {
TableCellRenderer renderer = ov.getOutline().getCellRenderer(row, column); TableCellRenderer renderer = ov.getOutline().getCellRenderer(row, column);
Component comp = ov.getOutline().prepareRenderer(renderer, row, column); Component comp = ov.getOutline().prepareRenderer(renderer, row, column);
valuesWidth = Math.max(comp.getPreferredSize().width, valuesWidth); valuesWidth = Math.max(comp.getPreferredSize().width, valuesWidth);
@ -466,32 +463,26 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
Node node = currentRoot.getChildren().getNodeAt(table.convertRowIndexToModel(row)); Node node = currentRoot.getChildren().getNodeAt(table.convertRowIndexToModel(row));
boolean tagFound = false; boolean tagFound = false;
if (node != null) { if (node != null) {
//see if there is a blackboard artifact at the node and whether the artifact is tagged Node.PropertySet[] propSets = node.getPropertySets();
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
if (artifact != null) {
try {
tagFound = !Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact).isEmpty();
} catch (TskCoreException ex) {
Exceptions.printStackTrace(ex);
}
}
//if no tags have been found yet, see if the abstract file at the node is tagged if (propSets.length != 0) {
if (!tagFound) { Node.Property<?>[] props = propSets[0].getProperties();
AbstractFile abstractFile = node.getLookup().lookup(AbstractFile.class); for (Property<?> prop : props) {
if (abstractFile != null) { if (prop.getName().equals("Tags")) {
try { try {
tagFound = !Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(abstractFile).isEmpty(); tagFound = !prop.getValue().equals("");
} catch (TskCoreException ex) { } catch (IllegalAccessException | InvocationTargetException ex) {
Exceptions.printStackTrace(ex); Exceptions.printStackTrace(ex);
}
break;
} }
} }
} }
}
//if the node does have associated tags, set its background color //if the node does have associated tags, set its background color
if (tagFound) { if (tagFound) {
component.setBackground(TAGGED_COLOR); component.setBackground(TAGGED_COLOR);
}
} }
} }
return component; return component;
@ -500,7 +491,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
ov.getOutline().setDefaultRenderer(Object.class, new ColorTagCustomRenderer()); ov.getOutline().setDefaultRenderer(Object.class, new ColorTagCustomRenderer());
} }
} }
/** /**
* Store the current column order into a preference file. * Store the current column order into a preference file.
*/ */
@ -580,8 +571,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
+ prop.getName().replaceAll("[^a-zA-Z0-9_]", "") + ".column"; + prop.getName().replaceAll("[^a-zA-Z0-9_]", "") + ".column";
} }
// Populate a two-dimensional array with rows of property values for up // Populate a two-dimensional array with rows of property values for up
// to maxRows children of the node passed in. // to maxRows children of the node passed in.
private static Object[][] getRowValues(Node node, int maxRows) { private static Object[][] getRowValues(Node node, int maxRows) {
int numRows = Math.min(maxRows, node.getChildren().getNodesCount()); int numRows = Math.min(maxRows, node.getChildren().getNodesCount());
Object[][] rowValues = new Object[numRows][]; Object[][] rowValues = new Object[numRows][];
@ -591,10 +582,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
break; break;
} }
// BC: I got this once, I think it was because the table // BC: I got this once, I think it was because the table
// refreshed while we were in this method // refreshed while we were in this method
// could be better synchronized. Or it was from // could be better synchronized. Or it was from
// the lazy nodes updating... Didn't have time // the lazy nodes updating... Didn't have time
// to fully debug it. // to fully debug it.
if (rowCount > numRows) { if (rowCount > numRows) {
break; break;
} }

View File

@ -30,6 +30,8 @@ import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
@ -101,16 +103,30 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
// Skip // Skip
} }
} }
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
if (evt.getNewValue() == null) { if (evt.getNewValue() == null) {
// case was closed. Remove listeners so that we don't get called with a stale case handle // case was closed. Remove listeners so that we don't get called with a stale case handle
removeListeners(); removeListeners();
} }
} else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
ContentTagAddedEvent event = (ContentTagAddedEvent) evt;
if (event.getAddedTag().getContent().equals(content)) {
updateSheet();
}
} else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
ContentTagDeletedEvent event = (ContentTagDeletedEvent) evt;
if (event.getDeletedTagInfo().getContentID() == content.getId()) {
updateSheet();
}
} }
}; };
private void updateSheet() {
this.setSheet(createSheet());
}
// Note: this order matters for the search result, changed it if the order of property headers on the "KeywordSearchNode"changed // Note: this order matters for the search result, changed it if the order of property headers on the "KeywordSearchNode"changed
public static enum AbstractFilePropertyType { public static enum AbstractFilePropertyType {
@ -283,7 +299,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType()); map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType());
} }
static void addTagProperty(Sheet.Set ss, Content content) { protected void addTagProperty(Sheet.Set ss) {
final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc");
List<Tag> tags = new ArrayList<>(); List<Tag> tags = new ArrayList<>();
try { try {

View File

@ -85,7 +85,7 @@ public abstract class AbstractFsContentNode<T extends AbstractFile> extends Abst
} }
// add tags property to the sheet // add tags property to the sheet
AbstractAbstractFileNode.addTagProperty(ss, content); addTagProperty(ss);
return s; return s;
} }

View File

@ -18,6 +18,8 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -36,6 +38,10 @@ import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction; import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -72,6 +78,39 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
private static final Integer[] SHOW_FILE_METADATA = new Integer[]{ private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),}; BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())) {
BlackBoardArtifactTagAddedEvent event = (BlackBoardArtifactTagAddedEvent) evt;
if (event.getAddedTag().getArtifact().equals(artifact)) {
updateSheet();
}
} else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString())) {
BlackBoardArtifactTagDeletedEvent event = (BlackBoardArtifactTagDeletedEvent) evt;
if (event.getDeletedTagInfo().getArtifactID() == artifact.getArtifactID()) {
updateSheet();
}
} else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
ContentTagAddedEvent event = (ContentTagAddedEvent) evt;
if (event.getAddedTag().getContent().equals(associated)) {
updateSheet();
}
} else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
ContentTagDeletedEvent event = (ContentTagDeletedEvent) evt;
if (event.getDeletedTagInfo().getContentID()== associated.getId()) {
updateSheet();
}
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
if (evt.getNewValue() == null) {
// case was closed. Remove listeners so that we don't get called with a stale case handle
removeListeners();
}
}
}
};
/** /**
* Construct blackboard artifact node from an artifact and using provided * Construct blackboard artifact node from an artifact and using provided
* icon * icon
@ -88,6 +127,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
this.setName(Long.toString(artifact.getArtifactID())); this.setName(Long.toString(artifact.getArtifactID()));
this.setDisplayName(); this.setDisplayName();
this.setIconBaseWithExtension(iconPath); this.setIconBaseWithExtension(iconPath);
Case.addPropertyChangeListener(pcl);
} }
/** /**
@ -105,6 +145,11 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
this.setName(Long.toString(artifact.getArtifactID())); this.setName(Long.toString(artifact.getArtifactID()));
this.setDisplayName(); this.setDisplayName();
this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS
Case.addPropertyChangeListener(pcl);
}
private void removeListeners() {
Case.removePropertyChangeListener(pcl);
} }
@Override @Override
@ -311,6 +356,10 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
return s; return s;
} }
private void updateSheet() {
this.setSheet(createSheet());
}
private String getRootParentName() { private String getRootParentName() {
String parentName = associated.getName(); String parentName = associated.getName();
Content parent = associated; Content parent = associated;

View File

@ -444,9 +444,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
*/ */
} }
} else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())
|| eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
|| eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())
|| eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
try { try {
Case.getCurrentCase(); Case.getCurrentCase();
refresh(true); refresh(true);

View File

@ -203,9 +203,6 @@ public class KeywordHits implements AutopsyVisitableItem {
} }
populateMaps(artifactIds); populateMaps(artifactIds);
setChanged();
notifyObservers();
} }
} }
@ -309,12 +306,6 @@ public class KeywordHits implements AutopsyVisitableItem {
removeNotify(); removeNotify();
skCase = null; skCase = null;
} }
} else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())
|| eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString())
|| eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())
|| eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
refresh(true);
keywordResults.update();
} }
} }
}; };
@ -457,8 +448,8 @@ public class KeywordHits implements AutopsyVisitableItem {
public class TermNode extends DisplayableItemNode implements Observer { public class TermNode extends DisplayableItemNode implements Observer {
private String setName; private final String setName;
private String keyword; private final String keyword;
public TermNode(String setName, String keyword) { public TermNode(String setName, String keyword) {
super(Children.create(new HitsFactory(setName, keyword), true), Lookups.singleton(keyword)); super(Children.create(new HitsFactory(setName, keyword), true), Lookups.singleton(keyword));

View File

@ -87,7 +87,7 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
} }
// add tags property to the sheet // add tags property to the sheet
AbstractAbstractFileNode.addTagProperty(ss, content); addTagProperty(ss);
return s; return s;
} }

View File

@ -76,7 +76,7 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
} }
// add tags property to the sheet // add tags property to the sheet
AbstractAbstractFileNode.addTagProperty(ss, content); addTagProperty(ss);
return s; return s;
} }