connect historymanager to filtered events through property: back is broken

This commit is contained in:
jmillman 2014-08-26 17:36:49 -04:00
parent 054bb6cf34
commit 3b1586fd2d
8 changed files with 122 additions and 136 deletions

View File

@ -36,11 +36,11 @@ public class HistoryManager<T> {
private final ReadOnlyObjectWrapper<T> currentState = new ReadOnlyObjectWrapper<>(); private final ReadOnlyObjectWrapper<T> currentState = new ReadOnlyObjectWrapper<>();
public ReadOnlyObjectWrapper<T> getCurrentState() { public ReadOnlyObjectWrapper<T> currentState() {
return currentState; return currentState;
} }
public T currentState() { public T getCurrentState() {
return currentState.get(); return currentState.get();
} }
@ -78,7 +78,7 @@ public class HistoryManager<T> {
return peek; return peek;
} }
synchronized private void advance(T newState) { synchronized public void advance(T newState) {
if (currentState.equals(newState) == false) { if (currentState.equals(newState) == false) {
historyStack.push(currentState.get()); historyStack.push(currentState.get());

View File

@ -46,12 +46,12 @@ import org.openide.windows.WindowManager;
*/ */
public class ProgressWindow extends JFrame { public class ProgressWindow extends JFrame {
private final SwingWorker<?,?> worker; private final SwingWorker<?, ?> worker;
/** /**
* Creates new form TimelineProgressDialog * Creates new form TimelineProgressDialog
*/ */
public ProgressWindow(Component parent, boolean modal, SwingWorker<?,?> worker) { public ProgressWindow(Component parent, boolean modal, SwingWorker<?, ?> worker) {
super(); super();
initComponents(); initComponents();
@ -60,18 +60,13 @@ public class ProgressWindow extends JFrame {
setAlwaysOnTop(modal); setAlwaysOnTop(modal);
//set icon the same as main app //set icon the same as main app
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override setIconImage(WindowManager.getDefault().getMainWindow().getIconImage());
public void run() {
setIconImage(WindowManager.getDefault().getMainWindow().getIconImage());
}
}); });
//progressBar.setIndeterminate(true); //progressBar.setIndeterminate(true);
setName("Timeline");
setName("Advanced Timeline"); setTitle("Generating Timeline data");
setTitle("Generating Advanced Timeline data");
// Close the dialog when Esc is pressed // Close the dialog when Esc is pressed
String cancelName = "cancel"; String cancelName = "cancel";
InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
@ -89,66 +84,42 @@ public class ProgressWindow extends JFrame {
} }
public void updateProgress(final int progress) { public void updateProgress(final int progress) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override progressBar.setValue(progress);
public void run() {
progressBar.setValue(progress);
}
}); });
} }
public void updateProgress(final int progress, final String message) { public void updateProgress(final int progress, final String message) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override progressBar.setValue(progress);
public void run() { progressBar.setString(message);
progressBar.setValue(progress);
progressBar.setString(message);
}
}); });
} }
public void updateProgress(final String message) { public void updateProgress(final String message) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override progressBar.setString(message);
public void run() {
progressBar.setString(message);
}
}); });
} }
public void setProgressTotal(final int total) { public void setProgressTotal(final int total) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override progressBar.setIndeterminate(false);
public void run() { progressBar.setMaximum(total);
progressBar.setIndeterminate(false); progressBar.setStringPainted(true);
progressBar.setMaximum(total);
progressBar.setStringPainted(true);
}
}); });
} }
public void updateHeaderMessage(final String headerMessage) { public void updateHeaderMessage(final String headerMessage) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override progressHeader.setText(headerMessage);
public void run() {
progressHeader.setText(headerMessage);
}
}); });
} }
public void setIndeterminate() { public void setIndeterminate() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override progressBar.setIndeterminate(true);
public void run() { progressBar.setStringPainted(true);
progressBar.setIndeterminate(true);
progressBar.setStringPainted(true);
}
}); });
} }
@ -206,17 +177,14 @@ public class ProgressWindow extends JFrame {
}//GEN-LAST:event_closeDialog }//GEN-LAST:event_closeDialog
public void cancel() { public void cancel() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override if (isVisible()) {
public void run() { int showConfirmDialog = JOptionPane.showConfirmDialog(ProgressWindow.this, "Do you want to cancel time line creation?", "Cancel timeline creation?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (isVisible()) { if (showConfirmDialog == JOptionPane.YES_OPTION) {
int showConfirmDialog = JOptionPane.showConfirmDialog(ProgressWindow.this, "Do you want to cancel time line creation?", "Cancel timeline creation?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (showConfirmDialog == JOptionPane.YES_OPTION) {
close();
}
} else {
close(); close();
} }
} else {
close();
} }
}); });
} }

View File

@ -172,17 +172,16 @@ public class TimeLineController {
/** list based stack to hold history, 'top' is at index 0; */ /** list based stack to hold history, 'top' is at index 0; */
@GuardedBy("this") @GuardedBy("this")
private final ObservableStack<ZoomParams> historyStack = new ObservableStack<>(); private final HistoryManager<ZoomParams> historyManager = new HistoryManager<>();
@GuardedBy("this")
private final ObservableStack<ZoomParams> forwardStack = new ObservableStack<>();
synchronized public ObservableStack<ZoomParams> getHistoryStack() { synchronized public ObservableStack<ZoomParams> getHistoryStack() {
return historyStack; return historyManager.getHistoryStack();
} }
synchronized public ObservableStack<ZoomParams> getForwardStack() { synchronized public ObservableStack<ZoomParams> getForwardStack() {
return forwardStack; return historyManager.getForwardStack();
} }
//all members should be access with the intrinsict lock of this object held //all members should be access with the intrinsict lock of this object held
@ -221,17 +220,17 @@ public class TimeLineController {
public TimeLineController() { public TimeLineController() {
//initalize repository and filteredEvents on creation //initalize repository and filteredEvents on creation
eventsRepository = new EventsRepository(); eventsRepository = new EventsRepository(historyManager.currentState());
filteredEvents = eventsRepository.getEventsModel(); filteredEvents = eventsRepository.getEventsModel();
InitialZoomState = new ZoomParams(filteredEvents.getSpanningInterval(), InitialZoomState = new ZoomParams(filteredEvents.getSpanningInterval(),
EventTypeZoomLevel.BASE_TYPE, EventTypeZoomLevel.BASE_TYPE,
Filter.getDefaultFilter(), Filter.getDefaultFilter(),
DescriptionLOD.SHORT); DescriptionLOD.SHORT);
filteredEvents.requestZoomState(InitialZoomState, true); historyManager.currentState().set(InitialZoomState);
//persistent listener instances //persistent listener instances
caseListener = new AutopsyCaseListener(); caseListener = new AutopsyCaseListener();
} }
/** @return a shared events model */ /** @return a shared events model */
@ -354,7 +353,7 @@ public class TimeLineController {
LOGGER.log(Level.SEVERE, "Unexpected error when generating timeline, ", ex); LOGGER.log(Level.SEVERE, "Unexpected error when generating timeline, ", ex);
} }
} }
@SuppressWarnings("deprecation")
private long getCaseLastArtifactID(final SleuthkitCase sleuthkitCase) { private long getCaseLastArtifactID(final SleuthkitCase sleuthkitCase) {
long caseLastArtfId = -1; long caseLastArtfId = -1;
try (ResultSet runQuery = sleuthkitCase.runQuery("select Max(artifact_id) as max_id from blackboard_artifacts")) { try (ResultSet runQuery = sleuthkitCase.runQuery("select Max(artifact_id) as max_id from blackboard_artifacts")) {
@ -502,51 +501,52 @@ public class TimeLineController {
} }
synchronized public ZoomParams goForward() { synchronized public ZoomParams goForward() {
return historyManager.advance();
final ZoomParams currentZoom = filteredEvents.getRequestedZoomParamters().get(); //
// final ZoomParams currentZoom = filteredEvents.getRequestedZoomParamters().get();
final ZoomParams fpeek = forwardStack.peek(); //
// final ZoomParams fpeek = forwardStack.peek();
if (fpeek != null && currentZoom.equals(fpeek) == false) { //
historyStack.push(currentZoom); // if (fpeek != null && currentZoom.equals(fpeek) == false) {
filteredEvents.requestZoomState(fpeek, false); // historyStack.push(currentZoom);
forwardStack.pop(); // filteredEvents.requestZoomState(fpeek, false);
} // forwardStack.pop();
return fpeek; // }
// return fpeek;
} }
synchronized public ZoomParams goBack() { synchronized public ZoomParams goBack() {
final ZoomParams currentZoom = filteredEvents.getRequestedZoomParamters().get();
final ZoomParams peek = historyStack.peek();
if (peek != null && peek.equals(currentZoom) == false) { return historyManager.retreat();
forwardStack.push(currentZoom); // final ZoomParams currentZoom = filteredEvents.getRequestedZoomParamters().get();
filteredEvents.requestZoomState(historyStack.pop(), false); // final ZoomParams peek = historyStack.peek();
} else if (peek != null && peek.equals(currentZoom)) { //
historyStack.pop(); // if (peek != null && peek.equals(currentZoom) == false) {
return goBack(); // forwardStack.push(currentZoom);
} // filteredEvents.requestZoomState(historyStack.pop(), false);
return peek; // } else if (peek != null && peek.equals(currentZoom)) {
// historyStack.pop();
// return goBack();
// }
// return peek;
} }
synchronized private void pushZoom(ZoomParams newState) {
synchronized private void pushZoom(ZoomParams zCrumb) { historyManager.advance(newState);
final ZoomParams currentZoom = filteredEvents.getRequestedZoomParamters().get(); // final ZoomParams currentZoom = filteredEvents.getRequestedZoomParamters().get();
//
if ( currentZoom.equals(zCrumb) == false) { // if (currentZoom.equals(zCrumb) == false) {
historyStack.push(currentZoom); // historyStack.push(currentZoom);
filteredEvents.requestZoomState(zCrumb, false); // filteredEvents.requestZoomState(zCrumb, false);
if (zCrumb.equals(forwardStack.peek())) { // if (zCrumb.equals(forwardStack.peek())) {
forwardStack.pop(); // forwardStack.pop();
} else { // } else {
forwardStack.clear(); // forwardStack.clear();
} // }
} // }
} }
public void selectTimeAndType(Interval interval, EventType type) { public void selectTimeAndType(Interval interval, EventType type) {
final Interval timeRange = filteredEvents.getSpanningInterval().overlap(interval); final Interval timeRange = filteredEvents.getSpanningInterval().overlap(interval);

View File

@ -56,7 +56,7 @@ import org.sleuthkit.autopsy.timeline.ui.filtering.FilterSetPanel;
import org.sleuthkit.autopsy.timeline.zooming.ZoomSettingsPane; import org.sleuthkit.autopsy.timeline.zooming.ZoomSettingsPane;
/** /**
* TopComponent for the advanced timeline module. * TopComponent for the timeline feature.
*/ */
@ConvertAsProperties( @ConvertAsProperties(
dtd = "-//org.sleuthkit.autopsy.timeline//TimeLine//EN", dtd = "-//org.sleuthkit.autopsy.timeline//TimeLine//EN",

View File

@ -19,10 +19,11 @@
package org.sleuthkit.autopsy.timeline.events; package org.sleuthkit.autopsy.timeline.events;
import java.util.Collection; import java.util.Collection;
import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javafx.beans.Observable;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
@ -88,13 +89,29 @@ public class FilteredEventsModel {
@GuardedBy("this") @GuardedBy("this")
private final EventsRepository repo; private final EventsRepository repo;
public FilteredEventsModel(EventsRepository repo) { public FilteredEventsModel(EventsRepository repo, ObjectProperty<ZoomParams> currentStateProperty) {
this.repo = repo; this.repo = repo;
requestedZoomParamters.set(new ZoomParams(new Interval(repo.getMinTime(), repo.getMaxTime(), DateTimeZone.UTC), requestedZoomParamters.bind(currentStateProperty);
EventTypeZoomLevel.BASE_TYPE, // currentStateProperty.set(new ZoomParams(new Interval(repo.getMinTime(), repo.getMaxTime(), DateTimeZone.UTC), EventTypeZoomLevel.BASE_TYPE,
Filter.getDefaultFilter(), // Filter.getDefaultFilter(),
DescriptionLOD.SHORT, // DescriptionLOD.SHORT,
EnumSet.noneOf(ZoomParams.Field.class))); // EnumSet.noneOf(ZoomParams.Field.class)));
requestedZoomParamters.addListener((Observable observable) -> {
final ZoomParams zoomParams = requestedZoomParamters.get();
if (zoomParams.getTypeZoomLevel().equals(requestedTypeZoom.get()) == false
|| zoomParams.getDescrLOD().equals(requestedLOD.get()) == false
|| zoomParams.getFilter().equals(requestedFilter.get()) == false
|| zoomParams.getTimeRange().equals(requestedTimeRange.get()) == false) {
// requestedZoomParamters.set(zoomParams);
requestedTypeZoom.set(zoomParams.getTypeZoomLevel());
requestedFilter.set(zoomParams.getFilter().copyOf());
requestedTimeRange.set(zoomParams.getTimeRange());
requestedLOD.set(zoomParams.getDescrLOD());
}
});
this.requestedTimeRange.set(getSpanningInterval()); this.requestedTimeRange.set(getSpanningInterval());
} }
@ -233,18 +250,18 @@ public class FilteredEventsModel {
return requestedTypeZoom.get(); return requestedTypeZoom.get();
} }
synchronized public void requestZoomState(ZoomParams zCrumb, boolean force) { // synchronized public void requestZoomState(ZoomParams zCrumb, boolean force) {
if (force // if (force
|| zCrumb.getTypeZoomLevel().equals(requestedTypeZoom.get()) == false // || zCrumb.getTypeZoomLevel().equals(requestedTypeZoom.get()) == false
|| zCrumb.getDescrLOD().equals(requestedLOD.get()) == false // || zCrumb.getDescrLOD().equals(requestedLOD.get()) == false
|| zCrumb.getFilter().equals(requestedFilter.get()) == false // || zCrumb.getFilter().equals(requestedFilter.get()) == false
|| zCrumb.getTimeRange().equals(requestedTimeRange.get()) == false) { // || zCrumb.getTimeRange().equals(requestedTimeRange.get()) == false) {
//
requestedZoomParamters.set(zCrumb); // requestedZoomParamters.set(zCrumb);
requestedTypeZoom.set(zCrumb.getTypeZoomLevel()); // requestedTypeZoom.set(zCrumb.getTypeZoomLevel());
requestedFilter.set(zCrumb.getFilter().copyOf()); // requestedFilter.set(zCrumb.getFilter().copyOf());
requestedTimeRange.set(zCrumb.getTimeRange()); // requestedTimeRange.set(zCrumb.getTimeRange());
requestedLOD.set(zCrumb.getDescrLOD()); // requestedLOD.set(zCrumb.getDescrLOD());
} // }
} // }
} }

View File

@ -50,6 +50,7 @@ import org.joda.time.DateTimeZone;
import org.joda.time.Interval; import org.joda.time.Interval;
import org.joda.time.Period; import org.joda.time.Period;
import org.openide.util.Exceptions; import org.openide.util.Exceptions;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.timeline.TimeLineController; import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.events.AggregateEvent; import org.sleuthkit.autopsy.timeline.events.AggregateEvent;
import org.sleuthkit.autopsy.timeline.events.TimeLineEvent; import org.sleuthkit.autopsy.timeline.events.TimeLineEvent;
@ -67,12 +68,11 @@ import org.sleuthkit.autopsy.timeline.zooming.DescriptionLOD;
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel; import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
import org.sleuthkit.autopsy.timeline.zooming.TimeUnits; import org.sleuthkit.autopsy.timeline.zooming.TimeUnits;
import org.sleuthkit.autopsy.timeline.zooming.ZoomParams; import org.sleuthkit.autopsy.timeline.zooming.ZoomParams;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sqlite.SQLiteJDBCLoader; import org.sqlite.SQLiteJDBCLoader;
/** /**
* This class provides access to the Advanced Timeline SQLite database. This * This class provides access to the Timeline SQLite database. This
* class borrows a lot of ideas and techniques from {@link SleuthkitCase}, * class borrows a lot of ideas and techniques from {@link SleuthkitCase},
* Creating an abstract base class for sqlite databases, or using a higherlevel * Creating an abstract base class for sqlite databases, or using a higherlevel
* persistence api may make sense in the future. * persistence api may make sense in the future.

View File

@ -32,11 +32,14 @@ import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.beans.property.ObjectProperty;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.joda.time.Interval; import org.joda.time.Interval;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.timeline.ProgressWindow; import org.sleuthkit.autopsy.timeline.ProgressWindow;
import org.sleuthkit.autopsy.timeline.events.AggregateEvent; import org.sleuthkit.autopsy.timeline.events.AggregateEvent;
import org.sleuthkit.autopsy.timeline.events.FilteredEventsModel; import org.sleuthkit.autopsy.timeline.events.FilteredEventsModel;
@ -47,8 +50,6 @@ import org.sleuthkit.autopsy.timeline.events.type.FileSystemTypes;
import org.sleuthkit.autopsy.timeline.events.type.RootEventType; import org.sleuthkit.autopsy.timeline.events.type.RootEventType;
import org.sleuthkit.autopsy.timeline.filters.Filter; import org.sleuthkit.autopsy.timeline.filters.Filter;
import org.sleuthkit.autopsy.timeline.zooming.ZoomParams; import org.sleuthkit.autopsy.timeline.zooming.ZoomParams;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
@ -103,7 +104,7 @@ public class EventsRepository {
return modelInstance; return modelInstance;
} }
public EventsRepository() { public EventsRepository(ObjectProperty<ZoomParams> currentStateProperty) {
//TODO: we should check that case is open, or get passed a case object/directory -jm //TODO: we should check that case is open, or get passed a case object/directory -jm
this.eventDB = EventDB.getEventDB(Case.getCurrentCase().getCaseDirectory()); this.eventDB = EventDB.getEventDB(Case.getCurrentCase().getCaseDirectory());
@ -118,7 +119,7 @@ public class EventsRepository {
}).build(CacheLoader.from(eventDB::getAggregatedEvents)); }).build(CacheLoader.from(eventDB::getAggregatedEvents));
maxCache = CacheBuilder.newBuilder().build(CacheLoader.from(eventDB::getMaxTime)); maxCache = CacheBuilder.newBuilder().build(CacheLoader.from(eventDB::getMaxTime));
minCache = CacheBuilder.newBuilder().build(CacheLoader.from(eventDB::getMinTime)); minCache = CacheBuilder.newBuilder().build(CacheLoader.from(eventDB::getMinTime));
this.modelInstance = new FilteredEventsModel(this); this.modelInstance = new FilteredEventsModel(this, currentStateProperty);
} }