From b5edf4d48607d48024da05367b14e73dd65da82c Mon Sep 17 00:00:00 2001 From: jmillman Date: Thu, 19 May 2016 16:22:22 -0400 Subject: [PATCH] actions that depend on actionsGlobalContext work. --- .../autopsy/timeline/Bundle.properties | 2 +- .../autopsy/timeline/Bundle_ja.properties | 89 +++---- .../timeline/TimeLineTopComponent.form | 40 +-- .../timeline/TimeLineTopComponent.java | 231 ++++++++++++------ .../autopsy/timeline/ui/Bundle.properties | 1 - .../autopsy/timeline/ui/Bundle_ja.properties | 2 +- .../timeline/ui/TimeLineResultView.java | 107 -------- .../timeline/ui/listvew/ListTimeline.java | 4 +- 8 files changed, 232 insertions(+), 244 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineResultView.java diff --git a/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties b/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties index d23cfbb773..b417dc2072 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/Bundle.properties @@ -24,4 +24,4 @@ TimelinePanel.jButton7.text=3d TimelinePanel.jButton2.text=1m TimelinePanel.jButton3.text=3m TimelinePanel.jButton4.text=2w -ProgressWindow.progressHeader.text=\ \ No newline at end of file +ProgressWindow.progressHeader.text=\ diff --git a/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties index ba1ee4f94a..3bd24f9ef1 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties @@ -1,48 +1,49 @@ -CTL_MakeTimeline=\u300C\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u300D -CTL_TimeLineTopComponent=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A6\u30A3\u30F3\u30C9\u30A6 -CTL_TimeLineTopComponentAction=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C8\u30C3\u30D7\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8 -HINT_TimeLineTopComponent=\u3053\u308C\u306F\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A6\u30A3\u30F3\u30C9\u30A6\u3067\u3059 -OpenTimelineAction.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3 -Timeline.frameName.text={0} - Autopsy\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3 -Timeline.goToButton.text=\u4E0B\u8A18\u3078\u79FB\u52D5\uFF1A -Timeline.node.root=\u30EB\u30FC\u30C8 -Timeline.pushDescrLOD.confdlg.msg={0}\u30A4\u30D9\u30F3\u30C8\u306E\u8A73\u7D30\u304C\u8868\u793A\u53EF\u80FD\u3067\u3059\u3002\u3053\u306E\u51E6\u7406\u306F\u9577\u6642\u9593\u304B\u304B\u308B\u3082\u3057\u304F\u306FAutopsy\u3092\u30AF\u30E9\u30C3\u30B7\u30E5\u3059\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n\n\u5B9F\u884C\u3057\u307E\u3059\u304B\uFF1F -Timeline.resultPanel.loading=\u30ED\u30FC\u30C9\u4E2D\u30FB\u30FB\u30FB -Timeline.resultsPanel.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u7D50\u679C -Timeline.runJavaFxThread.progress.creating=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u4F5C\u6210\u4E2D\u30FB\u30FB\u30FB -Timeline.zoomOutButton.text=\u30BA\u30FC\u30E0\u30A2\u30A6\u30C8 -TimelineFrame.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3 -TimeLineTopComponent.eventsTab.name=\u30A4\u30D9\u30F3\u30C8 -TimeLineTopComponent.filterTab.name=\u30D5\u30A3\u30EB\u30BF\u30FC -OpenTimeLineAction.msgdlg.text=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -PrompDialogManager.buttonType.continueNoUpdate=\u66F4\u65B0\u305B\u305A\u6B21\u3078 -PrompDialogManager.buttonType.showTimeline=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u3092\u8868\u793A -PrompDialogManager.buttonType.update=\u66F4\u65B0 -PromptDialogManager.confirmDuringIngest.contentText=\u6B21\u3078\u9032\u307F\u307E\u3059\u304B\uFF1F -PromptDialogManager.confirmDuringIngest.headerText=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u5B8C\u4E86\u3059\u308B\u524D\u306B\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u3092\u8868\u793A\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059\u3002\n\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u304C\u5B8C\u6210\u3057\u3066\u3044\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -PromptDialogManager.progressDialog.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C7\u30FC\u30BF\u3092\u5165\u529B\u4E2D -PromptDialogManager.rebuildPrompt.details=\u8A73\u7D30\uFF1A -PromptDialogManager.rebuildPrompt.headerText=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u4E0D\u5B8C\u5168\u307E\u305F\u306F\u6700\u65B0\u3067\u306F\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002\n \u6B20\u843D\u3057\u3066\u3044\u308B\u307E\u305F\u306F\u4E0D\u6B63\u78BA\u306A\u30A4\u30D9\u30F3\u30C8\u304C\u4E00\u90E8\u3042\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002\u4E00\u90E8\u306E\u6A5F\u80FD\u304C\u5229\u7528\u3067\u304D\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -Timeline.confirmation.dialogs.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u66F4\u65B0\u3057\u307E\u3059\u304B\uFF1F -Timeline.pushDescrLOD.confdlg.title=\u8AAC\u660E\u306E\u8A18\u8FF0\u30EC\u30D9\u30EB\u3092\u5909\u66F4\u3057\u307E\u3059\u304B\uFF1F -TimeLineController.errorTitle=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A8\u30E9\u30FC -TimeLineController.outOfDate.errorMessage=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u304C\u6700\u65B0\u304B\u78BA\u8A8D\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002\u66F4\u65B0\u304C\u5FC5\u8981\u3060\u3068\u60F3\u5B9A\u3057\u307E\u3059\u3002 -TimeLineController.rebuildReasons.incompleteOldSchema=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A4\u30D9\u30F3\u30C8\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u4E0D\u5B8C\u5168\u306A\u60C5\u5831\u304C\u4EE5\u524D\u5165\u529B\u3055\u308C\u3066\u3044\u307E\u3057\u305F\uFF1A\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u66F4\u65B0\u3057\u306A\u3044\u3068\u3001\u4E00\u90E8\u306E\u6A5F\u80FD\u304C\u5229\u7528\u3067\u304D\u306A\u3044\u3001\u307E\u305F\u306F\u6A5F\u80FD\u3057\u306A\u3044\u304B\u3082\u3057\u308C\u306A\u3044\u3067\u3059\u3002 -TimeLineController.rebuildReasons.ingestWasRunning=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u5B9F\u884C\u4E2D\u306B\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A4\u30D9\u30F3\u30C8\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u60C5\u5831\u304C\u5165\u529B\u3055\u308C\u3066\u3044\u307E\u3057\u305F\uFF1A\u30A4\u30D9\u30F3\u30C8\u304C\u6B20\u3051\u3066\u3044\u308B\u3001\u4E0D\u5B8C\u5168\u3001\u307E\u305F\u306F\u4E0D\u6B63\u78BA\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 -TimeLineController.rebuildReasons.outOfDate=\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u304C\u6700\u65B0\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF1A\u898B\u308C\u306A\u3044\u30A4\u30D9\u30F3\u30C8\u304C\u3042\u308A\u307E\u3059\u3002 -TimeLineController.rebuildReasons.outOfDateError=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C7\u30FC\u30BF\u304C\u6700\u65B0\u304B\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -TimeLinecontroller.updateNowQuestion=\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4ECA\u66F4\u65B0\u3057\u307E\u3059\u304B\uFF1F +CTL_MakeTimeline=\u300c\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u300d +CTL_TimeLineTopComponent=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a6\u30a3\u30f3\u30c9\u30a6 +CTL_TimeLineTopComponentAction=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c8\u30c3\u30d7\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8 +HINT_TimeLineTopComponent=\u3053\u308c\u306f\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a6\u30a3\u30f3\u30c9\u30a6\u3067\u3059 +OpenTimelineAction.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +Timeline.frameName.text={0} - Autopsy\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +Timeline.goToButton.text=\u4e0b\u8a18\u3078\u79fb\u52d5\uff1a +Timeline.node.root=\u30eb\u30fc\u30c8 +Timeline.pushDescrLOD.confdlg.msg={0}\u30a4\u30d9\u30f3\u30c8\u306e\u8a73\u7d30\u304c\u8868\u793a\u53ef\u80fd\u3067\u3059\u3002\u3053\u306e\u51e6\u7406\u306f\u9577\u6642\u9593\u304b\u304b\u308b\u3082\u3057\u304f\u306fAutopsy\u3092\u30af\u30e9\u30c3\u30b7\u30e5\u3059\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\n\n\u5b9f\u884c\u3057\u307e\u3059\u304b\uff1f +Timeline.resultPanel.loading=\u30ed\u30fc\u30c9\u4e2d\u30fb\u30fb\u30fb +Timeline.resultsPanel.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u7d50\u679c +Timeline.runJavaFxThread.progress.creating=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u4f5c\u6210\u4e2d\u30fb\u30fb\u30fb +Timeline.zoomOutButton.text=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8 +TimelineFrame.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +TimeLineTopComponent.eventsTab.name=\u30a4\u30d9\u30f3\u30c8 +TimeLineTopComponent.filterTab.name=\u30d5\u30a3\u30eb\u30bf\u30fc +OpenTimeLineAction.msgdlg.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +PrompDialogManager.buttonType.continueNoUpdate=\u66f4\u65b0\u305b\u305a\u6b21\u3078 +PrompDialogManager.buttonType.showTimeline=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u8868\u793a +PrompDialogManager.buttonType.update=\u66f4\u65b0 +PromptDialogManager.confirmDuringIngest.contentText=\u6b21\u3078\u9032\u307f\u307e\u3059\u304b\uff1f +PromptDialogManager.confirmDuringIngest.headerText=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u8868\u793a\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002\n\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u304c\u5b8c\u6210\u3057\u3066\u3044\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +PromptDialogManager.progressDialog.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u3092\u5165\u529b\u4e2d +PromptDialogManager.rebuildPrompt.details=\u8a73\u7d30\uff1a +PromptDialogManager.rebuildPrompt.headerText=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u4e0d\u5b8c\u5168\u307e\u305f\u306f\u6700\u65b0\u3067\u306f\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\n \u6b20\u843d\u3057\u3066\u3044\u308b\u307e\u305f\u306f\u4e0d\u6b63\u78ba\u306a\u30a4\u30d9\u30f3\u30c8\u304c\u4e00\u90e8\u3042\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\u4e00\u90e8\u306e\u6a5f\u80fd\u304c\u5229\u7528\u3067\u304d\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +Timeline.confirmation.dialogs.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f +Timeline.pushDescrLOD.confdlg.title=\u8aac\u660e\u306e\u8a18\u8ff0\u30ec\u30d9\u30eb\u3092\u5909\u66f4\u3057\u307e\u3059\u304b\uff1f +TimeLineController.errorTitle=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a8\u30e9\u30fc +TimeLineController.outOfDate.errorMessage=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u304c\u6700\u65b0\u304b\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u66f4\u65b0\u304c\u5fc5\u8981\u3060\u3068\u60f3\u5b9a\u3057\u307e\u3059\u3002 +TimeLineController.rebuildReasons.incompleteOldSchema=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a4\u30d9\u30f3\u30c8\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u4e0d\u5b8c\u5168\u306a\u60c5\u5831\u304c\u4ee5\u524d\u5165\u529b\u3055\u308c\u3066\u3044\u307e\u3057\u305f\uff1a\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u306a\u3044\u3068\u3001\u4e00\u90e8\u306e\u6a5f\u80fd\u304c\u5229\u7528\u3067\u304d\u306a\u3044\u3001\u307e\u305f\u306f\u6a5f\u80fd\u3057\u306a\u3044\u304b\u3082\u3057\u308c\u306a\u3044\u3067\u3059\u3002 +TimeLineController.rebuildReasons.ingestWasRunning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b9f\u884c\u4e2d\u306b\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a4\u30d9\u30f3\u30c8\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u60c5\u5831\u304c\u5165\u529b\u3055\u308c\u3066\u3044\u307e\u3057\u305f\uff1a\u30a4\u30d9\u30f3\u30c8\u304c\u6b20\u3051\u3066\u3044\u308b\u3001\u4e0d\u5b8c\u5168\u3001\u307e\u305f\u306f\u4e0d\u6b63\u78ba\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002 +TimeLineController.rebuildReasons.outOfDate=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u304c\u6700\u65b0\u3067\u306f\u3042\u308a\u307e\u305b\u3093\uff1a\u898b\u308c\u306a\u3044\u30a4\u30d9\u30f3\u30c8\u304c\u3042\u308a\u307e\u3059\u3002 +TimeLineController.rebuildReasons.outOfDateError=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u304c\u6700\u65b0\u304b\u78ba\u8a8d\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +TimeLinecontroller.updateNowQuestion=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4eca\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f TimelinePanel.jButton13.text=\u5168\u3066 -Timeline.yearBarChart.x.years=\u5E74 -TimelinePanel.jButton1.text=6\u30F6\u6708 +Timeline.yearBarChart.x.years=\u5e74 +TimelinePanel.jButton1.text=6\u30f6\u6708 TimelinePanel.jButton10.text=1\u6642\u9593 TimelinePanel.jButton9.text=12\u6642\u9593 -TimelinePanel.jButton11.text=5\u5E74 -TimelinePanel.jButton12.text=10\u5E74 +TimelinePanel.jButton11.text=5\u5e74 +TimelinePanel.jButton12.text=10\u5e74 TimelinePanel.jButton6.text=1\u9031\u9593 -TimelinePanel.jButton5.text=1\u5E74 -TimelinePanel.jButton8.text=1\u65E5 -TimelinePanel.jButton7.text=3\u65E5 -TimelinePanel.jButton2.text=1\u30F6\u6708 -TimelinePanel.jButton3.text=3\u30F6\u6708 -TimelinePanel.jButton4.text=2\u9031\u9593 \ No newline at end of file +TimelinePanel.jButton5.text=1\u5e74 +TimelinePanel.jButton8.text=1\u65e5 +TimelinePanel.jButton7.text=3\u65e5 +TimelinePanel.jButton2.text=1\u30f6\u6708 +TimelinePanel.jButton3.text=3\u30f6\u6708 +TimelinePanel.jButton4.text=2\u9031\u9593 +TimeLineResultView.startDateToEndDate.text={0}\u304b\u3089{1} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form index 1f0f367115..a0ca021ff5 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form @@ -82,33 +82,45 @@ - - - - - - + - + + + + + + + + + + + + - - - - - - + - + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java index 2a37c6ef1b..1e616fb735 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-16 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,15 +19,15 @@ package org.sleuthkit.autopsy.timeline; import com.google.common.collect.Iterables; -import java.awt.BorderLayout; import java.beans.PropertyVetoException; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.beans.Observable; -import javafx.embed.swing.JFXPanel; import javafx.scene.Scene; import javafx.scene.control.SplitPane; import javafx.scene.control.Tab; @@ -40,6 +40,7 @@ import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javax.swing.SwingUtilities; import org.controlsfx.control.Notifications; +import org.joda.time.format.DateTimeFormatter; import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerUtils; import org.openide.nodes.AbstractNode; @@ -54,12 +55,13 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.corecomponents.DataContentPanel; import org.sleuthkit.autopsy.corecomponents.DataResultPanel; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.timeline.actions.Back; import org.sleuthkit.autopsy.timeline.actions.Forward; import org.sleuthkit.autopsy.timeline.explorernodes.EventNode; +import org.sleuthkit.autopsy.timeline.explorernodes.EventRootNode; import org.sleuthkit.autopsy.timeline.ui.HistoryToolBar; import org.sleuthkit.autopsy.timeline.ui.StatusBar; -import org.sleuthkit.autopsy.timeline.ui.TimeLineResultView; import org.sleuthkit.autopsy.timeline.ui.TimeZonePanel; import org.sleuthkit.autopsy.timeline.ui.VisualizationPanel; import org.sleuthkit.autopsy.timeline.ui.detailview.tree.EventsTree; @@ -80,55 +82,31 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer private static final Logger LOGGER = Logger.getLogger(TimeLineTopComponent.class.getName()); + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private final DataContentPanel contentViewerPanel; - private final TimeLineResultView tlResultView; + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + private DataResultPanel dataResultPanel; + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private final ExplorerManager em = new ExplorerManager(); + private final TimeLineController controller; + private Set selectedEventIDs = new HashSet<>(); + @NbBundle.Messages({ "TimelineTopComponent.selectedEventListener.errorMsg=There was a problem getting the content for the selected event."}) /** * Listener that drives the ContentViewer when in List ViewMode. */ - private final InvalidationListener selectedEventListener = new InvalidationListener() { + private final InvalidationListener selectedEventsListener = new InvalidationListener() { @Override public void invalidated(Observable observable) { - if (controller.getSelectedEventIDs().size() == 1) { - try { - EventNode eventNode = EventNode.createEventNode(Iterables.getOnlyElement(controller.getSelectedEventIDs()), controller.getEventsModel()); - SwingUtilities.invokeLater(() -> { - - Node[] eventNodes = new Node[]{eventNode}; - Children.Array children = new Children.Array(); - children.add(eventNodes); - - em.setRootContext(new AbstractNode(children)); - try { - em.setSelectedNodes(eventNodes); - System.out.println(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); - - } catch (PropertyVetoException ex) { - LOGGER.log(Level.SEVERE, "Explorer manager selection was vetoed.", ex); //NON-NLS - } - contentViewerPanel.setNode(eventNode); - }); - - } catch (IllegalStateException ex) { - //Since the case is closed, the user probably doesn't care about this, just log it as a precaution. - LOGGER.log(Level.SEVERE, "There was no case open to lookup the Sleuthkit object backing a SingleEvent.", ex); // NON-NLS - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a SingleEvent.", ex); // NON-NLS - Platform.runLater(() -> { - Notifications.create() - .owner(jFXVizPanel.getScene().getWindow()) - .text(Bundle.TimelineTopComponent_selectedEventListener_errorMsg()) - .showError(); - }); - } + if (controller.getViewMode() == ViewMode.LIST) { + updateContentViewer(); } else { - SwingUtilities.invokeLater(() -> contentViewerPanel.setNode(null)); + updateResultView(); } } }; @@ -142,11 +120,17 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer setIcon(WindowManager.getDefault().getMainWindow().getIconImage()); //use the same icon as main application contentViewerPanel = DataContentPanel.createInstance(); - this.contentViewerContainerPanel.add(contentViewerPanel, BorderLayout.CENTER); - tlResultView = new TimeLineResultView(controller, contentViewerPanel); - final DataResultPanel dataResultPanel = tlResultView.getDataResultPanel(); - this.resultContainerPanel.add(dataResultPanel, BorderLayout.CENTER); + dataResultPanel = DataResultPanel.createInstanceUninitialized("", "", Node.EMPTY, 0, contentViewerPanel); + + lowerSplitXPane.setLeftComponent(dataResultPanel); dataResultPanel.open(); + lowerSplitXPane.setRightComponent(contentViewerPanel); + + //set up listeners on relevant properties + TimeLineController.getTimeZone().addListener(timeZone -> dataResultPanel.setPath(getResultViewerSummaryString())); + + controller.getSelectedEventIDs().addListener(selectedEventsListener); + updateResultView(); customizeFXComponents(); //Listen to ViewMode and adjust GUI componenets as needed. @@ -156,28 +140,18 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer case DETAIL: /* * For counts and details mode, restore the result table at - * the bottom left, if neccesary. + * the bottom left. */ - SwingUtilities.invokeLater(() -> { - splitYPane.remove(contentViewerContainerPanel); - if ((lowerSplitXPane.getParent() == splitYPane) == false) { - splitYPane.add(lowerSplitXPane); - lowerSplitXPane.add(contentViewerContainerPanel); - } - }); - controller.getSelectedEventIDs().removeListener(selectedEventListener); + controller.getSelectedEventIDs().removeListener(selectedEventsListener); + SwingUtilities.invokeLater(this::showResultTable); break; case LIST: /* * For list mode, remove the result table, and let the * content viewer expand across the bottom. */ - SwingUtilities.invokeLater(() -> { - splitYPane.remove(lowerSplitXPane); - splitYPane.add(contentViewerContainerPanel); - dataResultPanel.setNode(null); - }); - controller.getSelectedEventIDs().addListener(selectedEventListener); + controller.getSelectedEventIDs().addListener(selectedEventsListener); + SwingUtilities.invokeLater(this::hideResultTable); break; default: throw new UnsupportedOperationException("Unknown ViewMode: " + controller.getViewMode()); @@ -256,12 +230,12 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer // //GEN-BEGIN:initComponents private void initComponents() { - jFXstatusPanel = new JFXPanel(); + jFXstatusPanel = new javafx.embed.swing.JFXPanel(); splitYPane = new javax.swing.JSplitPane(); - jFXVizPanel = new JFXPanel(); + jFXVizPanel = new javafx.embed.swing.JFXPanel(); lowerSplitXPane = new javax.swing.JSplitPane(); - resultContainerPanel = new javax.swing.JPanel(); - contentViewerContainerPanel = new javax.swing.JPanel(); + leftFillerPanel = new javax.swing.JPanel(); + rightfillerPanel = new javax.swing.JPanel(); jFXstatusPanel.setPreferredSize(new java.awt.Dimension(100, 16)); @@ -276,13 +250,31 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer lowerSplitXPane.setPreferredSize(new java.awt.Dimension(1200, 300)); lowerSplitXPane.setRequestFocusEnabled(false); - resultContainerPanel.setPreferredSize(new java.awt.Dimension(700, 300)); - resultContainerPanel.setLayout(new java.awt.BorderLayout()); - lowerSplitXPane.setLeftComponent(resultContainerPanel); + javax.swing.GroupLayout leftFillerPanelLayout = new javax.swing.GroupLayout(leftFillerPanel); + leftFillerPanel.setLayout(leftFillerPanelLayout); + leftFillerPanelLayout.setHorizontalGroup( + leftFillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 599, Short.MAX_VALUE) + ); + leftFillerPanelLayout.setVerticalGroup( + leftFillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 54, Short.MAX_VALUE) + ); - contentViewerContainerPanel.setPreferredSize(new java.awt.Dimension(500, 300)); - contentViewerContainerPanel.setLayout(new java.awt.BorderLayout()); - lowerSplitXPane.setRightComponent(contentViewerContainerPanel); + lowerSplitXPane.setLeftComponent(leftFillerPanel); + + javax.swing.GroupLayout rightfillerPanelLayout = new javax.swing.GroupLayout(rightfillerPanel); + rightfillerPanel.setLayout(rightfillerPanelLayout); + rightfillerPanelLayout.setHorizontalGroup( + rightfillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 364, Short.MAX_VALUE) + ); + rightfillerPanelLayout.setVerticalGroup( + rightfillerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 54, Short.MAX_VALUE) + ); + + lowerSplitXPane.setRightComponent(rightfillerPanel); splitYPane.setRightComponent(lowerSplitXPane); @@ -291,10 +283,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(splitYPane, javax.swing.GroupLayout.DEFAULT_SIZE, 972, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, 0) - .addComponent(jFXstatusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(0, 0, 0)) + .addComponent(jFXstatusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -306,11 +295,11 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JPanel contentViewerContainerPanel; private javafx.embed.swing.JFXPanel jFXVizPanel; private javafx.embed.swing.JFXPanel jFXstatusPanel; + private javax.swing.JPanel leftFillerPanel; private javax.swing.JSplitPane lowerSplitXPane; - private javax.swing.JPanel resultContainerPanel; + private javax.swing.JPanel rightfillerPanel; private javax.swing.JSplitPane splitYPane; // End of variables declaration//GEN-END:variables @@ -341,4 +330,98 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer public ExplorerManager getExplorerManager() { return em; } + + /** + * @return a String representation of all the Events displayed + */ + @NbBundle.Messages({ + "TimeLineResultView.startDateToEndDate.text={0} to {1}"}) + private String getResultViewerSummaryString() { + if (controller.getSelectedTimeRange().get() != null) { + final DateTimeFormatter zonedFormatter = TimeLineController.getZonedFormatter(); + String start = controller.getSelectedTimeRange().get().getStart() + .withZone(TimeLineController.getJodaTimeZone()) + .toString(zonedFormatter); + String end = controller.getSelectedTimeRange().get().getEnd() + .withZone(TimeLineController.getJodaTimeZone()) + .toString(zonedFormatter); + return Bundle.TimeLineResultView_startDateToEndDate_text(start, end); + } + return ""; + } + + /** + * refresh this view with the events selected in the controller + */ + private void updateResultView() { + Set newSelectedEventIDs = new HashSet<>(controller.getSelectedEventIDs()); + if (selectedEventIDs.equals(newSelectedEventIDs) == false) { + selectedEventIDs = newSelectedEventIDs; + final EventRootNode root = new EventRootNode( + NbBundle.getMessage(this.getClass(), "Timeline.node.root"), selectedEventIDs, + controller.getEventsModel()); + + //this must be in edt or exception is thrown + SwingUtilities.invokeLater(() -> { + dataResultPanel.setPath(getResultViewerSummaryString()); + dataResultPanel.setNode(root); + }); + } + } + + private void updateContentViewer() { + if (controller.getSelectedEventIDs().size() == 1) { + try { + EventNode eventNode = EventNode.createEventNode(Iterables.getOnlyElement(controller.getSelectedEventIDs()), controller.getEventsModel()); + SwingUtilities.invokeLater(() -> { + + Node[] eventNodes = new Node[]{eventNode}; + Children.Array children = new Children.Array(); + children.add(eventNodes); + + em.setRootContext(new AbstractNode(children)); + try { + em.setSelectedNodes(eventNodes); + System.out.println(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + + } catch (PropertyVetoException ex) { + LOGGER.log(Level.SEVERE, "Explorer manager selection was vetoed.", ex); //NON-NLS + } + contentViewerPanel.setNode(eventNode); + }); + + } catch (IllegalStateException ex) { + //Since the case is closed, the user probably doesn't care about this, just log it as a precaution. + LOGGER.log(Level.SEVERE, "There was no case open to lookup the Sleuthkit object backing a SingleEvent.", ex); // NON-NLS + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a SingleEvent.", ex); // NON-NLS + Platform.runLater(() -> { + Notifications.create() + .owner(jFXVizPanel.getScene().getWindow()) + .text(Bundle.TimelineTopComponent_selectedEventListener_errorMsg()) + .showError(); + }); + } + } else { + SwingUtilities.invokeLater(() -> contentViewerPanel.setNode(null)); + } + } + + private void showResultTable() { + splitYPane.remove(contentViewerPanel); + + controller.getSelectedEventIDs().addListener(selectedEventsListener); + if ((lowerSplitXPane.getParent() == splitYPane) == false) { + splitYPane.setBottomComponent(lowerSplitXPane); + lowerSplitXPane.setRightComponent(contentViewerPanel); + } + lowerSplitXPane.setOneTouchExpandable(true); + lowerSplitXPane.setContinuousLayout(true); + lowerSplitXPane.resetToPreferredSizes(); + } + + private void hideResultTable() { + controller.getSelectedEventIDs().removeListener(selectedEventsListener); + splitYPane.setBottomComponent(contentViewerPanel); + } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle.properties b/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle.properties index b08bf41e42..498dfbaace 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle.properties @@ -35,7 +35,6 @@ Timeline.ui.ZoomRanges.threeyears.text=Three Years Timeline.ui.ZoomRanges.fiveyears.text=Five Years Timeline.ui.ZoomRanges.tenyears.text=Ten Years Timeline.ui.ZoomRanges.all.text=All -TimeLineResultView.startDateToEndDate.text={0} to {1} VisualizationPanel.histogramTask.title=Rebuild Histogram VisualizationPanel.histogramTask.preparing=preparing VisualizationPanel.histogramTask.resetUI=resetting ui diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties index 2ba0472b32..3e0fab3823 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties @@ -1,7 +1,7 @@ Timeline.node.root=\u30eb\u30fc\u30c8 Timeline.ui.TimeLineChart.tooltip.text=\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3067\u4e0b\u8a18\u306e\u7bc4\u56f2\u3078\u30ba\u30fc\u30e0\uff1a\n{0}\u301c{1}\n\u53f3\u30af\u30ea\u30c3\u30af\u3067\u5143\u306b\u623b\u308a\u307e\u3059\u3002 Timeline.ui.ZoomRanges.all.text=\u5168\u3066 -TimeLineResultView.startDateToEndDate.text={0}\u304b\u3089{1} + VisualizationPanel.histogramTask.preparing=\u6e96\u5099\u4e2d VisualizationPanel.histogramTask.queryDb=DB\u3092\u30af\u30a8\u30ea\u4e2d VisualizationPanel.histogramTask.resetUI=ui\u3092\u518d\u8a2d\u5b9a\u4e2d diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineResultView.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineResultView.java deleted file mode 100644 index 9fb308229f..0000000000 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/TimeLineResultView.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2013 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.timeline.ui; - -import java.util.HashSet; -import java.util.Set; -import javafx.beans.Observable; -import javax.swing.SwingUtilities; -import org.joda.time.format.DateTimeFormatter; -import org.openide.nodes.Node; -import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; -import org.sleuthkit.autopsy.corecomponents.DataResultPanel; -import org.sleuthkit.autopsy.timeline.TimeLineController; -import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel; -import org.sleuthkit.autopsy.timeline.explorernodes.EventRootNode; - -/** - * Since it was too hard to derive from {@link DataResultPanel}, this class - * implements {@link TimeLineView}, listens to the events/state of a the - * assigned {@link FilteredEventsModel} and acts appropriately on its - * {@link DataResultPanel}. That is, this class acts as a sort of bridge/adapter - * between a FilteredEventsModel instance and a DataResultPanel instance. - */ -public class TimeLineResultView { - - /** - * the {@link DataResultPanel} that is the real view proxied by this class - */ - private final DataResultPanel dataResultPanel; - - private final TimeLineController controller; - - private final FilteredEventsModel filteredEvents; - - private Set selectedEventIDs = new HashSet<>(); - - public DataResultPanel getDataResultPanel() { - return dataResultPanel; - } - - public TimeLineResultView(TimeLineController controller, DataContent dataContent) { - - this.controller = controller; - this.filteredEvents = controller.getEventsModel(); - dataResultPanel = DataResultPanel.createInstanceUninitialized("", "", Node.EMPTY, 0, dataContent); - - //set up listeners on relevant properties - TimeLineController.getTimeZone().addListener(timeZone -> dataResultPanel.setPath(getSummaryString())); - - controller.getSelectedEventIDs().addListener((Observable selectedIDs) -> refresh()); - refresh(); - } - - /** - * @return a String representation of all the Events displayed - */ - private String getSummaryString() { - if (controller.getSelectedTimeRange().get() != null) { - final DateTimeFormatter zonedFormatter = TimeLineController.getZonedFormatter(); - return NbBundle.getMessage(this.getClass(), "TimeLineResultView.startDateToEndDate.text", - controller.getSelectedTimeRange().get().getStart() - .withZone(TimeLineController.getJodaTimeZone()) - .toString(zonedFormatter), - controller.getSelectedTimeRange().get().getEnd() - .withZone(TimeLineController.getJodaTimeZone()) - .toString(zonedFormatter)); - } - return ""; - } - - /** - * refresh this view with the events selected in the controller - */ - public final void refresh() { - - Set newSelectedEventIDs = new HashSet<>(controller.getSelectedEventIDs()); - if (selectedEventIDs.equals(newSelectedEventIDs) == false) { - selectedEventIDs = newSelectedEventIDs; - final EventRootNode root = new EventRootNode( - NbBundle.getMessage(this.getClass(), "Timeline.node.root"), selectedEventIDs, - filteredEvents); - - //this must be in edt or exception is thrown - SwingUtilities.invokeLater(() -> { - dataResultPanel.setPath(getSummaryString()); - dataResultPanel.setNode(root); - }); - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java index 1f96d9cd49..dd96f3c7a3 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/ListTimeline.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.logging.Level; import javafx.application.Platform; import javafx.beans.binding.Bindings; @@ -289,10 +290,9 @@ class ListTimeline extends BorderPane { if (element == null) { menuItems.add(new SeparatorMenuItem()); } else { - String actionName = element.getValue(Action.NAME).toString(); + String actionName = Objects.toString(element.getValue(Action.NAME)); if (Arrays.asList("&Properties", "Tools").contains(actionName) == false) { - if (element instanceof Presenter.Popup) { JMenuItem submenu = ((Presenter.Popup) element).getPopupPresenter(); menuItems.add(SwingMenuItemAdapter.create(submenu));