cleanup in PromptDialogManager, CancellationProgressTask, and TimeLineController

This commit is contained in:
jmillman
2016-04-21 15:43:14 -04:00
parent 18c49ce382
commit 0bb69a45ac
3 changed files with 85 additions and 20 deletions
@@ -1,7 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
* Autopsy Forensic Browser
*
* Copyright 2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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;
@@ -12,8 +25,8 @@ import javafx.concurrent.Task;
* An extension of Task that allows a client to request cancellation, with out
* the Task entering the cancelled state immediately. This allows the task to
* continue to report progress of eg its cleanup operations. Implementations
* should use the {@link #isCancelRequested() } method to check for cancelation
* and call cancel() before returning form the call() method.
* should use the isCancelRequested() method to check for cancellation and call
* cancel() before returning from the call() method.
*/
public abstract class CancellationProgressTask<X> extends Task<X> {
@@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
/**
* Manager for the various prompts and dialogs Timeline shows the user related
* to rebuilding the database.
* to rebuilding the database. Methods must only be called on the JFX thread.
*/
public class PromptDialogManager {
@@ -57,21 +57,31 @@ public class PromptDialogManager {
@NbBundle.Messages("PrompDialogManager.buttonType.update=Update")
private static final ButtonType UPDATE = new ButtonType(Bundle.PrompDialogManager_buttonType_update(), ButtonBar.ButtonData.OK_DONE);
private static final Image LOGO;
/**
* Image to use as title bar icon in dialogs
*/
private static final Image AUTOPSY_ICON;
static {
Image x = null;
Image tempImg = null;
try {
x = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); //NON-NLS
tempImg = new Image(new URL("nbresloc:/org/netbeans/core/startup/frame.gif").openStream()); //NON-NLS
} catch (IOException ex) {
LOGGER.log(Level.WARNING, "Failed to load branded icon for progress dialog.", ex); //NON-NLS
}
LOGO = x;
AUTOPSY_ICON = tempImg;
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private Dialog<?> currentDialog;
private final TimeLineController controller;
/**
* Constructor
*
* @param controller the TimeLineController this manager belongs to.
*/
PromptDialogManager(TimeLineController controller) {
this.controller = controller;
}
@@ -91,9 +101,14 @@ public class PromptDialogManager {
return false;
}
/**
* Show a progress dialog for the given db population task
*
* @param task the task to show progress for.
*/
@NbBundle.Messages({"PromptDialogManager.progressDialog.title=Populating Timeline Data"})
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
void showProgressDialog(CancellationProgressTask<?> task) {
void showDBPopulationProgressDialog(CancellationProgressTask<?> task) {
currentDialog = new ProgressDialog(task);
currentDialog.initModality(Modality.NONE);
currentDialog.setTitle(Bundle.PromptDialogManager_progressDialog_title());
@@ -123,18 +138,24 @@ public class PromptDialogManager {
currentDialog.show();
}
/**
* Set the title bar icon for the given dialog to be the autopsy logo icon.
*
* @param dialog the dialog to set the title bar icon for.
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
static private void setDialogIcons(Dialog<?> dialog) {
((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().setAll(LOGO);
((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().setAll(AUTOPSY_ICON);
}
/**
* prompt the user that ingest is running and the db may not end up
* Prompt the user that ingest is running and the db may not end up
* complete.
*
* @return true if they want to continue anyways
*/
@NbBundle.Messages({"PromptDialogManager.confirmDuringIngest.headerText=You are trying to show a timeline before ingest has been completed.\nThe timeline may be incomplete.",
@NbBundle.Messages({
"PromptDialogManager.confirmDuringIngest.headerText=You are trying to show a timeline before ingest has been completed.\nThe timeline may be incomplete.",
"PromptDialogManager.confirmDuringIngest.contentText=Do you want to continue?"})
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
boolean confirmDuringIngest() {
@@ -144,11 +165,25 @@ public class PromptDialogManager {
setDialogIcons(currentDialog);
currentDialog.setHeaderText(Bundle.PromptDialogManager_confirmDuringIngest_headerText());
//show dialog and map all results except "show timeline" to false.
return currentDialog.showAndWait().map(SHOW_TIMELINE::equals).orElse(false);
}
/**
* Prompt the user to confirm rebuilding the database for the given list of
* reasons, adding that "ingest has finished" for the datasource with the
* given name, if not blank, as a reason and as extra header text.
*
* @param finishedDataSourceName the name of the datasource that has
* finished be analyzed.
* @param rebuildReasons a List of reasons why the database is out
* of date.
*
* @return true if the user a confirms rebuilding the database.
*/
@NbBundle.Messages({
"PromptDialogManager.rebuildPrompt.headerText=The Timeline database is incomplete and/or out of date. Some events may be missing or inaccurate and some features may be unavailable.",
"PromptDialogManager.rebuildPrompt.headerText=The Timeline database is incomplete and/or out of date."
+ " Some events may be missing or inaccurate and some features may be unavailable.",
"# {0} - data source name",
"PromptDialogManager.rebuildPrompt.ingestDone=Ingest has finished for {0}.",
"PromptDialogManager.rebuildPrompt.details=Details"})
@@ -159,6 +194,7 @@ public class PromptDialogManager {
currentDialog.setTitle(Bundle.Timeline_confirmation_dialogs_title());
setDialogIcons(currentDialog);
//configure header text depending on presence of finishedDataSourceName
String headerText = Bundle.PromptDialogManager_rebuildPrompt_headerText();
if (StringUtils.isNotBlank(finishedDataSourceName)) {
String datasourceMessage = Bundle.PromptDialogManager_rebuildPrompt_ingestDone(finishedDataSourceName);
@@ -167,20 +203,34 @@ public class PromptDialogManager {
}
currentDialog.setHeaderText(headerText);
DialogPane dialogPane = currentDialog.getDialogPane();
//set up listview of reasons to rebuild
ListView<String> listView = new ListView<>(FXCollections.observableArrayList(rebuildReasons));
listView.setCellFactory(lstView -> new WrappingListCell());
listView.setMaxHeight(75);
Node wrappedListView = Borders.wrap(listView).lineBorder().title(Bundle.PromptDialogManager_rebuildPrompt_details()).buildAll();
//wrap listview in title border.
Node wrappedListView = Borders.wrap(listView)
.lineBorder()
.title(Bundle.PromptDialogManager_rebuildPrompt_details())
.buildAll();
DialogPane dialogPane = currentDialog.getDialogPane();
dialogPane.setExpandableContent(wrappedListView);
dialogPane.setMaxWidth(500);
//show dialog and map all results except "update" to false.
return currentDialog.showAndWait().map(UPDATE::equals).orElse(false);
}
/**
* Prompt the user to confirm rebuilding the database for the given list of
* reasons.
*
* @param rebuildReasons a List of reasons why the database is out of date.
*
* @return true if the user a confirms rebuilding the database.
*/
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
boolean confirmRebuild(ArrayList<String> rebuildReasons) {
return confirmRebuild(null, rebuildReasons);
}
@@ -349,7 +349,7 @@ public class TimeLineController {
break;
}
});
promptDialogManager.showProgressDialog(rebuildRepository);
promptDialogManager.showDBPopulationProgressDialog(rebuildRepository);
}
/**
@@ -370,6 +370,9 @@ public class TimeLineController {
rebuildRepoHelper(eventsRepository::rebuildTags, false);
}
/**
* Show the entire range of the timeline.
*/
public void showFullRange() {
synchronized (filteredEvents) {
pushTimeRange(filteredEvents.getSpanningInterval());
@@ -781,7 +784,6 @@ public class TimeLineController {
} catch (IOException ex) {
MessageNotifyUtil.Notify.error("Timeline", "Failed to mark the timeline db as populated while ingest was" + (ingestRunning ? "" : "not ") + "running. Some results may be out of date or missing.");
LOGGER.log(Level.SEVERE, "Error marking the ingest state while the timeline db was populated.", ex);
}
}