quick-hide/filter WIP 3

This commit is contained in:
jmillman 2015-09-23 16:02:57 -04:00
parent 56358568f0
commit b290534f07
13 changed files with 88 additions and 64 deletions

View File

@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.coreutils;
import java.util.Objects;
import javafx.beans.property.Property;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;

View File

@ -1076,6 +1076,7 @@ public class EventDB {
+ "\n GROUP BY interval, " + typeColumn + " , " + descriptionColumn // NON-NLS
+ "\n ORDER BY min(time)"; // NON-NLS
System.out.println(query);
// perform query and map results to AggregateEvent objects
List<EventCluster> events = new ArrayList<>();

View File

@ -89,6 +89,4 @@ public abstract class CompoundFilter<SubFilterType extends Filter> extends Abstr
}
return true;
}
}

View File

@ -48,7 +48,7 @@ public class DescriptionFilter extends AbstractFilter {
@Override
public String getDisplayName() {
return getFilterMode().getDisplayName() + " Description";
return getFilterMode().getDisplayName() + " " + getDescription();
}
@Override
@ -86,10 +86,6 @@ public class DescriptionFilter extends AbstractFilter {
}
}
public boolean test(String t) {
return (filterMode == FilterMode.INCLUDE) == getDescription().equals(t);
}
@Override
public int hashCode() {
int hash = 7;

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

View File

@ -304,7 +304,7 @@ public abstract class AbstractVisualization<X, Y, N, C extends XYChart<X, Y> & T
//x-positions (pixels) of the current branch and leaf labels
double leafLabelX = 0;
if (dateTime.branch.equals("")) {
if (dateTime.branch.isEmpty()) {
//if there is only one part to the date (ie only year), just add a label for each tick
for (Axis.TickMark<X> t : tickMarks) {
assignLeafLabel(new TwoPartDateTime(getTickMarkLabel(t.getValue())).leaf,

View File

@ -85,7 +85,7 @@ public abstract class AbstractDetailViewNode< T extends EventBundle, S extends A
static final Image HASH_PIN = new Image("/org/sleuthkit/autopsy/images/hashset_hits.png");
static final Image PLUS = new Image("/org/sleuthkit/autopsy/timeline/images/plus-button.png"); // NON-NLS
static final Image MINUS = new Image("/org/sleuthkit/autopsy/timeline/images/minus-button.png"); // NON-NLS
static final Image HIDE = new Image("/org/sleuthkit/autopsy/timeline/images/funnel.png"); // NON-NLS
static final Image TAG = new Image("/org/sleuthkit/autopsy/images/green-tag-icon-16.png"); // NON-NLS
static final CornerRadii CORNER_RADII = new CornerRadii(3);
/**
@ -166,9 +166,9 @@ public abstract class AbstractDetailViewNode< T extends EventBundle, S extends A
private final Region spacer = new Region();
private final CollapseClusterAction collapseClusterAction;
private final CollapseBundleAction collapseClusterAction;
private final ExpandClusterAction expandClusterAction;
private final HideClusterAction hideClusterAction;
private final EventDetailChart.HideBundleAction hideClusterAction;
public AbstractDetailViewNode(EventDetailChart chart, T bundle, S parentEventNode) {
this.eventBundle = bundle;
@ -186,7 +186,7 @@ public abstract class AbstractDetailViewNode< T extends EventBundle, S extends A
show(tagIV, false);
}
hideClusterAction = new HideClusterAction();
hideClusterAction = chart.new HideBundleAction(getEventBundle());
hideButton = ActionUtils.createButton(hideClusterAction, ActionUtils.ActionTextBehavior.HIDE);
configureLODButton(hideButton);
@ -194,7 +194,7 @@ public abstract class AbstractDetailViewNode< T extends EventBundle, S extends A
plusButton = ActionUtils.createButton(expandClusterAction, ActionUtils.ActionTextBehavior.HIDE);
configureLODButton(plusButton);
collapseClusterAction = new CollapseClusterAction();
collapseClusterAction = new CollapseBundleAction();
minusButton = ActionUtils.createButton(collapseClusterAction, ActionUtils.ActionTextBehavior.HIDE);
configureLODButton(minusButton);
@ -545,9 +545,9 @@ public abstract class AbstractDetailViewNode< T extends EventBundle, S extends A
}
}
private class CollapseClusterAction extends Action {
private class CollapseBundleAction extends Action {
CollapseClusterAction() {
CollapseBundleAction() {
super("Collapse");
setGraphic(new ImageView(MINUS));
@ -561,20 +561,4 @@ public abstract class AbstractDetailViewNode< T extends EventBundle, S extends A
}
}
private class HideClusterAction extends Action {
HideClusterAction() {
super("Hide");
setGraphic(new ImageView(HIDE));
setEventHandler((ActionEvent t) -> {
DescriptionFilter descriptionFilter = new DescriptionFilter(getDescLOD(), getDescription(), DescriptionFilter.FilterMode.EXCLUDE);
chart.getBundleFilters().add(descriptionFilter);
RootFilter rootFilter = eventsModel.getFilter();
rootFilter.getSubFilters().add(descriptionFilter);
chart.getController().pushFilters(rootFilter.copyOf());
chart.setRequiresLayout(true);
chart.requestChartLayout();
});
}
}
}

View File

@ -68,10 +68,10 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
import org.sleuthkit.autopsy.timeline.filters.DescriptionFilter;
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualization;
import org.sleuthkit.autopsy.timeline.ui.countsview.CountsViewPane;
import org.sleuthkit.autopsy.timeline.ui.detailview.tree.NavTreeNode;
@ -243,8 +243,8 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
});
}
public ObservableList<DescriptionFilter> getBundleFilters() {
return chart.getBundleFilters();
public ObservableList<String> getQuickHideMasks() {
return chart.getQuickHideMasks();
}
@Override
@ -301,11 +301,12 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
if (isCancelled()) {
return null;
}
Platform.runLater(() -> {
if (isCancelled() == false) {
Platform.runLater(() -> {
setCursor(Cursor.WAIT);
}
});
}
updateProgress(-1, 1);
updateMessage(NbBundle.getMessage(this.getClass(), "DetailViewPane.loggedTask.preparing"));
@ -315,6 +316,7 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
final long upperBound = rangeInfo.getUpperBound();
updateMessage(NbBundle.getMessage(this.getClass(), "DetailViewPane.loggedTask.queryDb"));
getQuickHideMasks().clear();
aggregatedEvents.setAll(filteredEvents.getAggregatedEvents());
Platform.runLater(() -> {
@ -336,13 +338,12 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
updateProgress(i++, size);
updateMessage(NbBundle.getMessage(this.getClass(), "DetailViewPane.loggedTask.updateUI"));
final XYChart.Data<DateTime, EventCluster> xyData = new BarChart.Data<>(new DateTime(e.getSpan().getStartMillis()), e);
Platform.runLater(() -> {
if (isCancelled() == false) {
Platform.runLater(() -> {
getSeries(e.getEventType()).getData().add(xyData);
}
});
}
}
Platform.runLater(() -> {
setCursor(Cursor.NONE);
@ -485,4 +486,11 @@ public class DetailViewPane extends AbstractVisualization<DateTime, EventCluster
}
public EventDetailChart.UnhideBundleAction newUnhideBundleAction(String description) {
return chart.new UnhideBundleAction(description);
}
public EventDetailChart.HideBundleAction newHideBundleAction(EventBundle bundle) {
return chart.new HideBundleAction(bundle);
}
}

View File

@ -98,6 +98,9 @@ import org.sleuthkit.autopsy.timeline.ui.TimeLineChart;
*/
public final class EventDetailChart extends XYChart<DateTime, EventCluster> implements TimeLineChart<DateTime> {
static final Image HIDE = new Image("/org/sleuthkit/autopsy/timeline/images/eye--minus.png"); // NON-NLS
static final Image SHOW = new Image("/org/sleuthkit/autopsy/timeline/images/eye--plus.png"); // NON-NLS
private static final int PROJECTED_LINE_Y_OFFSET = 5;
private static final int PROJECTED_LINE_STROKE_WIDTH = 5;
@ -203,7 +206,7 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
*/
private final SimpleDoubleProperty truncateWidth = new SimpleDoubleProperty(200.0);
private final SimpleBooleanProperty alternateLayout = new SimpleBooleanProperty(true);
private ObservableList<DescriptionFilter> bundleFilters = FXCollections.observableArrayList();
private ObservableList<String> quickHideMasks = FXCollections.observableArrayList();
EventDetailChart(DateAxis dateAxis, final Axis<EventCluster> verticalAxis, ObservableList<DetailViewNode<?>> selectedNodes) {
super(dateAxis, verticalAxis);
@ -499,8 +502,8 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
shownPartition = bundleStream
.map(nodeMap::get)
.sorted(Comparator.comparing(AbstractDetailViewNode<?, ?>::getStartMillis))
.collect(Collectors.partitioningBy(node -> getBundleFilters().stream()
.allMatch(filter -> filter.test(node.getDescription()))));
.collect(Collectors.partitioningBy(node -> getQuickHideMasks().stream()
.anyMatch(mask -> mask.equals(node.getDescription()))));
layoutNodesHelper(shownPartition.get(false), shownPartition.get(true), minY);
minY = maxY.get();
@ -508,9 +511,9 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
} else {
shownPartition = nodeMap.values().stream()
.sorted(Comparator.comparing(AbstractDetailViewNode<?, ?>::getStartMillis))
.collect(Collectors.partitioningBy(node -> getBundleFilters().stream()
.allMatch(filter -> filter.test(node.getDescription()))));
layoutNodesHelper(shownPartition.get(false), shownPartition.get(true), 0);
.collect(Collectors.partitioningBy(node -> getQuickHideMasks().stream()
.anyMatch(mask -> mask.equals(node.getDescription()))));
layoutNodesHelper(shownPartition.get(true), shownPartition.get(false), 0);
}
setCursor(null);
requiresLayout = false;
@ -756,8 +759,8 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
return alternateLayout;
}
ObservableList<DescriptionFilter> getBundleFilters() {
return bundleFilters;
ObservableList<String> getQuickHideMasks() {
return quickHideMasks;
}
private class DetailIntervalSelector extends IntervalSelector<DateTime> {
@ -798,4 +801,36 @@ public final class EventDetailChart extends XYChart<DateTime, EventCluster> impl
void applySelectionEffect(DetailViewNode<?> c1, Boolean selected) {
c1.applySelectionEffect(selected);
}
public class HideBundleAction extends Action {
/**
*
* @param description the value of description
*/
public HideBundleAction(final EventBundle bundle) {
super("Hide");
setGraphic(new ImageView(HIDE));
setEventHandler((ActionEvent t) -> {
getQuickHideMasks().add(bundle.getDescription());
filteredEvents.getFilter().getSubFilters().add(new DescriptionFilter(bundle.getDescriptionLOD(), bundle.getDescription(), DescriptionFilter.FilterMode.EXCLUDE));
setRequiresLayout(true);
requestChartLayout();
});
}
}
public class UnhideBundleAction extends Action {
public UnhideBundleAction(String description) {
super("Unhide");
setGraphic(new ImageView(SHOW));
setEventHandler((ActionEvent t) -> {
getQuickHideMasks().removeAll(description);
setRequiresLayout(true);
requestChartLayout();
});
}
}
}

View File

@ -18,6 +18,7 @@
*/
package org.sleuthkit.autopsy.timeline.ui.detailview.tree;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.Comparator;
import javafx.application.Platform;
@ -36,13 +37,13 @@ import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import org.controlsfx.control.action.ActionUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.TimeLineView;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.filters.DescriptionFilter;
import org.sleuthkit.autopsy.timeline.ui.detailview.DetailViewNode;
import org.sleuthkit.autopsy.timeline.ui.detailview.DetailViewPane;
@ -144,30 +145,35 @@ public class NavPanel extends BorderPane implements TimeLineView {
ImageView imageView = new ImageView(item.getType().getFXImage());
setGraphic(new StackPane(rect, imageView));
detailViewPane.getBundleFilters().addListener((Observable observable) -> {
asdasd(item, rect, imageView);
detailViewPane.getQuickHideMasks().addListener((Observable observable) -> {
configureHiddenState(item, rect, imageView);
});
asdasd(item, rect, imageView);
configureHiddenState(item, rect, imageView);
} else {
setText(null);
setTooltip(null);
setGraphic(null);
}
setContextMenu(null);
}
private void asdasd(NavTreeNode item, Rectangle rect, ImageView imageView) {
if (detailViewPane.getBundleFilters().stream().allMatch((DescriptionFilter t) -> t.test(item.getDescription())) == false) {
}
private void configureHiddenState(NavTreeNode item, Rectangle rect, ImageView imageView) {
if (detailViewPane.getQuickHideMasks().stream().anyMatch(mask -> mask.equals(item.getDescription()))) {
setTextFill(Color.gray(0, .6));
imageView.setOpacity(.6);
rect.setStroke(item.getType().getColor().deriveColor(0, .6, 1, .6));
rect.setFill(item.getType().getColor().deriveColor(0, .6, .6, 0.1));
setContextMenu(ActionUtils.createContextMenu(ImmutableList.of(detailViewPane.newUnhideBundleAction(item.getDescription()))));
} else {
setTextFill(Color.BLACK);
imageView.setOpacity(1);
rect.setStroke(item.getType().getColor());
rect.setFill(item.getType().getColor().deriveColor(0, 1, 1, 0.1));
// setContextMenu(ActionUtils.createContextMenu(ImmutableList.of(detailViewPane.newHideBundleAction(item.getDescription()))));
}
}
}
}

View File

@ -22,7 +22,6 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.control.TreeItem;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
@ -69,8 +68,7 @@ class RootItem extends NavTreeItem {
Platform.runLater(() -> {
synchronized (getChildren()) {
getChildren().add(newTreeItem);
FXCollections.sort(getChildren(), TreeComparator.Type);
getChildren().sort(TreeComparator.Type);
}
});
} else {

View File

@ -89,7 +89,7 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
assert applyButton != null : "fx:id=\"applyButton\" was not injected: check your FXML file 'FilterSetPanel.fxml'."; // NON-NLS
applyButton.setOnAction(e -> {
controller.pushFilters((RootFilter) filterTreeTable.getRoot().getValue().copyOf());
controller.pushFilters((RootFilter) filterTreeTable.getRoot().getValue());
});
applyButton.setText(Bundle.FilterSetPanel_applyButton_text());
defaultButton.setText(Bundle.FilterSetPanel_defaultButton_text());
@ -173,7 +173,6 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
@Override
public void setModel(FilteredEventsModel filteredEvents) {
this.filteredEvents = filteredEvents;
filteredEvents.registerForEvents(this);
refresh();
this.filteredEvents.filterProperty().addListener((Observable o) -> {
refresh();
@ -182,7 +181,7 @@ final public class FilterSetPanel extends BorderPane implements TimeLineView {
private void refresh() {
Platform.runLater(() -> {
filterTreeTable.setRoot(new FilterTreeItem(filteredEvents.getFilter().copyOf(), expansionMap));
filterTreeTable.setRoot(new FilterTreeItem(filteredEvents.getFilter(), expansionMap));
});
}
}