From aecc22934503da0dc7a4101255779e557e2b88e5 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Tue, 5 Mar 2019 16:30:52 +0100 Subject: [PATCH] add right click menu option to add event with datetime prepopulated; other small cleanup and refactoring --- .../autopsy/timeline/TimeLineController.java | 13 ++++++++++--- .../timeline/TimeLineTopComponent.java | 2 +- .../timeline/actions/AddManualEvent.java | 19 ++++++++++++------- .../timeline/explorernodes/EventNode.java | 2 +- .../timeline/ui/AbstractTimeLineView.java | 4 ++-- .../autopsy/timeline/ui/IntervalSelector.java | 4 ++-- .../autopsy/timeline/ui/TimeLineChart.java | 1 + .../autopsy/timeline/ui/ViewFrame.java | 2 +- .../ui/detailview/DetailViewPane.java | 2 +- .../timeline/ui/detailview/DetailsChart.java | 5 +++++ 10 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index 56b8501c26..0d4e3fb8bb 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -23,6 +23,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeEvent; import java.time.ZoneId; import java.util.Collection; @@ -32,6 +33,7 @@ import java.util.Optional; import java.util.TimeZone; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import java.util.logging.Level; import javafx.application.Platform; import javafx.beans.Observable; @@ -116,7 +118,8 @@ public class TimeLineController { private static final ReadOnlyObjectWrapper timeZone = new ReadOnlyObjectWrapper<>(TimeZone.getDefault()); - private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); + private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor( + new ThreadFactoryBuilder().setNameFormat("Timeline Controller BG thread").build())); private final ReadOnlyListWrapper> tasks = new ReadOnlyListWrapper<>(FXCollections.observableArrayList()); private final ReadOnlyDoubleWrapper taskProgress = new ReadOnlyDoubleWrapper(-1); private final ReadOnlyStringWrapper taskMessage = new ReadOnlyStringWrapper(); @@ -134,13 +137,17 @@ public class TimeLineController { } public static DateTimeZone getJodaTimeZone() { - return DateTimeZone.forTimeZone(getTimeZone().get()); + return DateTimeZone.forTimeZone(timeZoneProperty().get()); } - public static ReadOnlyObjectProperty getTimeZone() { + public static ReadOnlyObjectProperty timeZoneProperty() { return timeZone.getReadOnlyProperty(); } + public static TimeZone getTimeZone() { + return timeZone.get(); + } + /** * Status is a string that will be displayed in the status bar as a kind of * user hint/information when it is not empty diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java index 26a8d4edfe..0ddf9dc46d 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java @@ -281,7 +281,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer Platform.runLater(this::initFXComponents); //set up listeners - TimeLineController.getTimeZone().addListener(timeZone -> dataResultPanel.setPath(getResultViewerSummaryString())); + TimeLineController.timeZoneProperty().addListener(timeZone -> dataResultPanel.setPath(getResultViewerSummaryString())); controller.getSelectedEventIDs().addListener(selectedEventsListener); //Listen to ViewMode and adjust GUI componenets as needed. diff --git a/Core/src/org/sleuthkit/autopsy/timeline/actions/AddManualEvent.java b/Core/src/org/sleuthkit/autopsy/timeline/actions/AddManualEvent.java index 276e9b0279..78acf63cd7 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/actions/AddManualEvent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/actions/AddManualEvent.java @@ -18,8 +18,10 @@ */ package org.sleuthkit.autopsy.timeline.actions; +import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -88,6 +90,10 @@ public class AddManualEvent extends Action { "CreateManualEvent.text=Add Event", "CreateManualEvent.longText=Manually add an event to the timeline."}) public AddManualEvent(TimeLineController controller) { + this(controller, System.currentTimeMillis()); + } + + public AddManualEvent(TimeLineController controller, long epochMillis) { super(Bundle.CreateManualEvent_text()); this.controller = controller; setGraphic(new ImageView(ADD_EVENT_IMAGE)); @@ -95,7 +101,7 @@ public class AddManualEvent extends Action { setEventHandler(actionEvent -> { //shoe the dialog and if it completed normally add the event. - new EventCreationDialog(controller).showAndWait().ifPresent(this::addEvent); + new EventCreationDialog(controller, epochMillis).showAndWait().ifPresent(this::addEvent); }); } @@ -147,8 +153,8 @@ public class AddManualEvent extends Action { */ private final EventCreationDialogPane eventCreationDialogPane; - EventCreationDialog(TimeLineController controller) { - this.eventCreationDialogPane = new EventCreationDialogPane(controller); + EventCreationDialog(TimeLineController controller, long epochMillis) { + this.eventCreationDialogPane = new EventCreationDialogPane(controller, epochMillis); setTitle("Add Event"); setDialogPane(eventCreationDialogPane); @@ -187,9 +193,10 @@ public class AddManualEvent extends Action { private final ValidationSupport validationSupport = new ValidationSupport(); private final TimeLineController controller; - EventCreationDialogPane(TimeLineController controller) { + EventCreationDialogPane(TimeLineController controller, long epochMillis) { this.controller = controller; FXMLConstructor.construct(this, "EventCreationDialog.fxml"); + timePicker.setLocalDateTime( LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMillis) , TimeLineController.getTimeZoneID())); } @FXML @@ -198,11 +205,9 @@ public class AddManualEvent extends Action { assert descriptionTextField != null : "fx:id=\"descriptionTextField\" was not injected: check your FXML file 'EventCreationDialog.fxml'."; timeZoneChooser.getItems().setAll(timeZoneList); - timeZoneChooser.getSelectionModel().select(TimeZoneUtils.createTimeZoneString(TimeZone.getDefault())); + timeZoneChooser.getSelectionModel().select(TimeZoneUtils.createTimeZoneString(TimeLineController.getTimeZone())); TextFields.bindAutoCompletion(timeZoneChooser.getEditor(), timeZoneList); - timePicker.setLocalDateTime(LocalDateTime.now()); - try { dataSourceChooser.getItems().setAll(controller.getAutopsyCase().getSleuthkitCase().getDataSources()); dataSourceChooser.getSelectionModel().select(0); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java b/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java index 8b8e6511cb..dde8ae88b9 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/EventNode.java @@ -184,7 +184,7 @@ public class EventNode extends DisplayableItemNode { super(name, String.class, displayName, shortDescription); setValue("suppressCustomEditor", Boolean.TRUE); // remove the "..." (editing) button NON-NLS this.value = value; - TimeLineController.getTimeZone().addListener(timeZone -> { + TimeLineController.timeZoneProperty().addListener(timeZone -> { try { setValue(getDateTimeString()); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java index e38db703c2..d9a51f2023 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java @@ -87,7 +87,7 @@ public abstract class AbstractTimeLineView extends BorderPane { this.filteredEvents = controller.getEventsModel(); this.filteredEvents.registerForEvents(this); this.filteredEvents.zoomStateProperty().addListener(updateListener); - TimeLineController.getTimeZone().addListener(updateListener); + TimeLineController.timeZoneProperty().addListener(updateListener); } /** @@ -225,7 +225,7 @@ public abstract class AbstractTimeLineView extends BorderPane { } //remvoe and gc updateListener this.filteredEvents.zoomStateProperty().removeListener(updateListener); - TimeLineController.getTimeZone().removeListener(updateListener); + TimeLineController.timeZoneProperty().removeListener(updateListener); updateListener = null; filteredEvents.unRegisterForEvents(this); controller.unRegisterForEvents(this); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/IntervalSelector.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/IntervalSelector.java index 58c4db3c85..43e5154138 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/IntervalSelector.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/IntervalSelector.java @@ -293,8 +293,8 @@ public abstract class IntervalSelector extends BorderPane { return getValueForDisplay(getBoundsInParent().getMinX()); } - private X getValueForDisplay(final double display) { - return chart.getXAxis().getValueForDisplay(chart.getXAxis().parentToLocal(display, 0).getX()); + private X getValueForDisplay(final double displayX) { + return chart.getXAxis().getValueForDisplay(chart.getXAxis().parentToLocal(displayX, 0).getX()); } /** diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineChart.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineChart.java index ed73a29f45..06c5cda0ac 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineChart.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineChart.java @@ -68,6 +68,7 @@ public interface TimeLineChart extends ContextMenuProvider, IntervalSelectorP @Override public TimeLineController getController(); + /** * Drag handler class used by TimeLineCharts to create IntervalSelectors * diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/ViewFrame.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/ViewFrame.java index 8945cac632..ea0da29822 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/ViewFrame.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/ViewFrame.java @@ -424,7 +424,7 @@ final public class ViewFrame extends BorderPane { filteredEvents.registerForEvents(this); //listen for changes in the time range / zoom params - TimeLineController.getTimeZone().addListener(timeZoneProp -> refreshTimeUI()); + TimeLineController.timeZoneProperty().addListener(timeZoneProp -> refreshTimeUI()); filteredEvents.timeRangeProperty().addListener(timeRangeProp -> refreshTimeUI()); filteredEvents.zoomStateProperty().addListener(zoomListener); refreshTimeUI(); //populate the view diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java index 3208d22600..8a47bfd96e 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/DetailViewPane.java @@ -395,7 +395,7 @@ final public class DetailViewPane extends AbstractTimelineChart { contextMenu.hide(); } + long selectedTimeMillis = getXAxis().getValueForDisplay(getXAxis().parentToLocal(mouseEvent.getX(), 0).getX()).getMillis(); + //make and assign a new context menu based on the given mouseEvent setContextMenu(ActionUtils.createContextMenu(Arrays.asList( new PlaceMarkerAction(this, mouseEvent), + new AddManualEvent(controller, selectedTimeMillis), ActionUtils.ACTION_SEPARATOR, TimeLineChart.newZoomHistoyActionGroup(getController()) )));