disable Timeline and image gallery if there are more than 6M files in the DB

This commit is contained in:
millmanorama 2017-12-11 10:30:14 +01:00
parent 91c48b7e72
commit b68e794a0e
6 changed files with 201 additions and 80 deletions

View File

@ -0,0 +1,84 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017 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.guiutils;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.image.Image;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
/**
* Utilities for dealing with JavaFX gui components.
*
*/
public class JavaFXUtils {
private static final Logger logger = Logger.getLogger(JavaFXUtils.class.getName());
/**
* Image to use as title bar icon in dialogs
*/
private static final Image AUTOPSY_ICON;
static {
Image tempImg = null;
try {
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
}
AUTOPSY_ICON = tempImg;
}
private JavaFXUtils() {
}
/**
* 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)
public static void setDialogIcons(Dialog<?> dialog) {
((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().setAll(AUTOPSY_ICON);
}
@NbBundle.Messages(value = {"# {0} - Tool name",
"JavaFXUtils.showTooManyFiles.contentText="
+ "There are too many files in the DB to ensure reasonable performance."
+ " {0} will be disabled. ",
"JavaFXUtils.showTooManyFiles.headerText="})
public static void showTooManyFiles(String toolName) {
Alert dialog = new Alert(Alert.AlertType.INFORMATION, Bundle.JavaFXUtils_showTooManyFiles_contentText(toolName), ButtonType.OK);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.setTitle(toolName);
setDialogIcons(dialog);
dialog.setHeaderText(Bundle.JavaFXUtils_showTooManyFiles_headerText());
dialog.showAndWait();
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2014-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.timeline;
import java.awt.Component; import java.awt.Component;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import org.openide.awt.ActionID; import org.openide.awt.ActionID;
@ -36,8 +37,10 @@ import org.sleuthkit.autopsy.core.Installer;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.guiutils.JavaFXUtils;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* An Action that opens the Timeline window. Has methods to open the window in * An Action that opens the Timeline window. Has methods to open the window in
@ -51,9 +54,8 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
public final class OpenTimelineAction extends CallableSystemAction implements Presenter.Toolbar { public final class OpenTimelineAction extends CallableSystemAction implements Presenter.Toolbar {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(OpenTimelineAction.class.getName()); private static final Logger logger = Logger.getLogger(OpenTimelineAction.class.getName());
private static final int FILE_LIMIT = 6_000_000;
private static final boolean FX_INITED = Installer.isJavaFxInited();
private static TimeLineController timeLineController = null; private static TimeLineController timeLineController = null;
@ -78,15 +80,26 @@ public final class OpenTimelineAction extends CallableSystemAction implements Pr
/** /**
* We used to also check if Case.getCurrentCase().hasData() was true. We * We used to also check if Case.getCurrentCase().hasData() was true. We
* disabled that check because if it is executed while a data source is * disabled that check because if it is executed while a data source is
* being added, it blocks the edt * being added, it blocks the edt. We still do that in ImageGallery.
*/ */
return Case.isCaseOpen() && FX_INITED; return Case.isCaseOpen() && Installer.isJavaFxInited();
} }
@Override @Override
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
public void performAction() { public void performAction() {
showTimeline(); if (tooManyFiles()) {
Platform.runLater(() ->
JavaFXUtils.showTooManyFiles(Bundle.Timeline_dialogs_title()));
synchronized (OpenTimelineAction.this) {
if (timeLineController != null) {
timeLineController.shutDownTimeLine();
}
}
setEnabled(false);
} else {
showTimeline();
}
} }
@NbBundle.Messages({ @NbBundle.Messages({
@ -97,7 +110,7 @@ public final class OpenTimelineAction extends CallableSystemAction implements Pr
Case currentCase = Case.getCurrentCase(); Case currentCase = Case.getCurrentCase();
if (currentCase.hasData() == false) { if (currentCase.hasData() == false) {
MessageNotifyUtil.Message.info(Bundle.OpenTimeLineAction_msgdlg_text()); MessageNotifyUtil.Message.info(Bundle.OpenTimeLineAction_msgdlg_text());
LOGGER.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS logger.log(Level.INFO, "Could not create timeline, there are no data sources.");// NON-NLS
return; return;
} }
try { try {
@ -112,7 +125,7 @@ public final class OpenTimelineAction extends CallableSystemAction implements Pr
} catch (IOException iOException) { } catch (IOException iOException) {
MessageNotifyUtil.Message.error(Bundle.OpenTimelineAction_settingsErrorMessage()); MessageNotifyUtil.Message.error(Bundle.OpenTimelineAction_settingsErrorMessage());
LOGGER.log(Level.SEVERE, "Failed to initialize per case timeline settings.", iOException); logger.log(Level.SEVERE, "Failed to initialize per case timeline settings.", iOException);
} }
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
//there is no case... Do nothing. //there is no case... Do nothing.
@ -169,12 +182,12 @@ public final class OpenTimelineAction extends CallableSystemAction implements Pr
/** /**
* Set this action to be enabled/disabled * Set this action to be enabled/disabled
* *
* @param value whether to enable this action or not * @param enable whether to enable this action or not
*/ */
@Override @Override
public void setEnabled(boolean value) { public void setEnabled(boolean enable) {
super.setEnabled(value); super.setEnabled(enable);
toolbarButton.setEnabled(value); toolbarButton.setEnabled(enable);
} }
/** /**
@ -189,4 +202,16 @@ public final class OpenTimelineAction extends CallableSystemAction implements Pr
toolbarButton.setText(this.getName()); toolbarButton.setText(this.getName());
return toolbarButton; return toolbarButton;
} }
private boolean tooManyFiles() {
try {
return FILE_LIMIT < Case.getCurrentCase().getSleuthkitCase().countFilesWhere("1 = 1");
} catch (IllegalStateException ex) {
logger.log(Level.SEVERE, "Can not open timeline with no case open.", ex);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error counting files in the DB.", ex);
}
//if there is any doubt (no case, tskcore error, etc) just disable .
return false;
}
} }

View File

@ -18,10 +18,7 @@
*/ */
package org.sleuthkit.autopsy.timeline; package org.sleuthkit.autopsy.timeline;
import java.io.IOException;
import java.net.URL;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
@ -30,14 +27,13 @@ import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog; import javafx.scene.control.Dialog;
import javafx.scene.control.DialogPane; import javafx.scene.control.DialogPane;
import javafx.scene.control.ListView; import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.controlsfx.dialog.ProgressDialog; import org.controlsfx.dialog.ProgressDialog;
import org.controlsfx.tools.Borders; import org.controlsfx.tools.Borders;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.guiutils.JavaFXUtils;
/** /**
* Manager for the various prompts and dialogs Timeline shows the user related * Manager for the various prompts and dialogs Timeline shows the user related
@ -45,8 +41,6 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
*/ */
public final class PromptDialogManager { public final class PromptDialogManager {
private static final Logger LOGGER = Logger.getLogger(PromptDialogManager.class.getName());
@NbBundle.Messages("PrompDialogManager.buttonType.showTimeline=Continue") @NbBundle.Messages("PrompDialogManager.buttonType.showTimeline=Continue")
private static final ButtonType CONTINUE = new ButtonType(Bundle.PrompDialogManager_buttonType_showTimeline(), ButtonBar.ButtonData.OK_DONE); private static final ButtonType CONTINUE = new ButtonType(Bundle.PrompDialogManager_buttonType_showTimeline(), ButtonBar.ButtonData.OK_DONE);
@ -56,21 +50,6 @@ public final class PromptDialogManager {
@NbBundle.Messages("PrompDialogManager.buttonType.update=Update DB") @NbBundle.Messages("PrompDialogManager.buttonType.update=Update DB")
private static final ButtonType UPDATE = new ButtonType(Bundle.PrompDialogManager_buttonType_update(), ButtonBar.ButtonData.OK_DONE); private static final ButtonType UPDATE = new ButtonType(Bundle.PrompDialogManager_buttonType_update(), ButtonBar.ButtonData.OK_DONE);
/**
* Image to use as title bar icon in dialogs
*/
private static final Image AUTOPSY_ICON;
static {
Image tempImg = null;
try {
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
}
AUTOPSY_ICON = tempImg;
}
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private Dialog<?> currentDialog; private Dialog<?> currentDialog;
@ -143,8 +122,9 @@ public final class PromptDialogManager {
* @param dialog The dialog to set the title bar icon for. * @param dialog The dialog to set the title bar icon for.
*/ */
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
@Deprecated
public static void setDialogIcons(Dialog<?> dialog) { public static void setDialogIcons(Dialog<?> dialog) {
((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().setAll(AUTOPSY_ICON); JavaFXUtils.setDialogIcons(dialog);
} }
/** /**
@ -168,6 +148,8 @@ public final class PromptDialogManager {
return currentDialog.showAndWait().map(CONTINUE::equals).orElse(false); return currentDialog.showAndWait().map(CONTINUE::equals).orElse(false);
} }
/** /**
* Prompt the user to confirm rebuilding the database for the given list of * Prompt the user to confirm rebuilding the database for the given list of
* reasons. * reasons.
@ -177,7 +159,8 @@ public final class PromptDialogManager {
* @return True if the user a confirms rebuilding the database. * @return True if the user a confirms rebuilding the database.
*/ */
@NbBundle.Messages({ @NbBundle.Messages({
"PromptDialogManager.rebuildPrompt.headerText=The Timeline DB 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 DB is incomplete and/or out of date."
+ " Some events may be missing or inaccurate and some features may be unavailable.",
"PromptDialogManager.rebuildPrompt.details=Details"}) "PromptDialogManager.rebuildPrompt.details=Details"})
@ThreadConfined(type = ThreadConfined.ThreadType.JFX) @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
boolean confirmRebuild(List<String> rebuildReasons) { boolean confirmRebuild(List<String> rebuildReasons) {

View File

@ -58,6 +58,7 @@ import org.controlsfx.validation.Validator;
import org.joda.time.Interval; import org.joda.time.Interval;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.guiutils.JavaFXUtils;
import org.sleuthkit.autopsy.timeline.datamodel.SingleEvent; import org.sleuthkit.autopsy.timeline.datamodel.SingleEvent;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType; import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
import org.sleuthkit.autopsy.timeline.events.ViewInTimelineRequestedEvent; import org.sleuthkit.autopsy.timeline.events.ViewInTimelineRequestedEvent;
@ -151,7 +152,7 @@ final class ShowInTimelineDialog extends Dialog<ViewInTimelineRequestedEvent> {
Validator.createPredicateValidator(NumberUtils::isDigits, Bundle.ShowInTimelineDialog_amountValidator_message())); Validator.createPredicateValidator(NumberUtils::isDigits, Bundle.ShowInTimelineDialog_amountValidator_message()));
//configure dialog properties //configure dialog properties
PromptDialogManager.setDialogIcons(this); JavaFXUtils.setDialogIcons(this);
initModality(Modality.APPLICATION_MODAL); initModality(Modality.APPLICATION_MODAL);
//add scenegraph loaded from fxml to this dialog. //add scenegraph loaded from fxml to this dialog.

View File

@ -48,7 +48,7 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.timeline.PromptDialogManager; import org.sleuthkit.autopsy.guiutils.JavaFXUtils;
import org.sleuthkit.autopsy.timeline.TimeLineController; import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.snapshot.SnapShotReportWriter; import org.sleuthkit.autopsy.timeline.snapshot.SnapShotReportWriter;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -105,7 +105,7 @@ public class SaveSnapshotAsReport extends Action {
//prompt user to pick report name //prompt user to pick report name
TextInputDialog textInputDialog = new TextInputDialog(); TextInputDialog textInputDialog = new TextInputDialog();
PromptDialogManager.setDialogIcons(textInputDialog); JavaFXUtils.setDialogIcons(textInputDialog);
textInputDialog.setTitle(Bundle.SaveSnapShotAsReport_action_dialogs_title()); textInputDialog.setTitle(Bundle.SaveSnapShotAsReport_action_dialogs_title());
textInputDialog.getEditor().setPromptText(Bundle.SaveSnapShotAsReport_reportName_prompt(defaultReportName)); textInputDialog.getEditor().setPromptText(Bundle.SaveSnapShotAsReport_reportName_prompt(defaultReportName));
textInputDialog.setHeaderText(Bundle.SaveSnapShotAsReport_reportName_header()); textInputDialog.setHeaderText(Bundle.SaveSnapShotAsReport_reportName_header());

View File

@ -1,26 +1,28 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-17 Basis Technology Corp. * Copyright 2015-17 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.imagegallery.actions; package org.sleuthkit.autopsy.imagegallery.actions;
import java.awt.Component; import java.awt.Component;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import javafx.application.Platform;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@ -29,6 +31,7 @@ import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences; import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration; import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter; import org.openide.util.actions.Presenter;
@ -37,49 +40,53 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.Installer; import org.sleuthkit.autopsy.core.Installer;
import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.guiutils.JavaFXUtils;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule; import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent;
import org.sleuthkit.datamodel.TskCoreException;
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.imagegallery.OpenAction") @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.imagegallery.OpenAction")
@ActionReferences(value = { @ActionReferences(value = {
@ActionReference(path = "Menu/Tools", position = 101), @ActionReference(path = "Menu/Tools", position = 101),
@ActionReference(path = "Toolbars/Case", position = 101) @ActionReference(path = "Toolbars/Case", position = 101)})
})
@ActionRegistration(displayName = "#CTL_OpenAction", lazy = false) @ActionRegistration(displayName = "#CTL_OpenAction", lazy = false)
@Messages({"CTL_OpenAction=View Images/Videos", @Messages({"CTL_OpenAction=View Images/Videos",
"OpenAction.stale.confDlg.msg=The image / video database may be out of date. " + "OpenAction.stale.confDlg.msg=The image / video database may be out of date. "
"Do you want to update and listen for further ingest results?\n" + + "Do you want to update and listen for further ingest results?\n"
"Choosing 'yes' will update the database and enable listening to future ingests.", + "Choosing 'yes' will update the database and enable listening to future ingests.",
"OpenAction.stale.confDlg.title=Image Gallery"}) "OpenAction.stale.confDlg.title=Image Gallery"})
public final class OpenAction extends CallableSystemAction implements Presenter.Toolbar { public final class OpenAction extends CallableSystemAction implements Presenter.Toolbar {
private static final Logger LOGGER = Logger.getLogger(OpenAction.class.getName()); private static final Logger logger = Logger.getLogger(OpenAction.class.getName());
private static final String VIEW_IMAGES_VIDEOS = Bundle.CTL_OpenAction(); private static final String VIEW_IMAGES_VIDEOS = Bundle.CTL_OpenAction();
private final JButton toolbarButton = new JButton(); private final JButton toolbarButton = new JButton();
private final PropertyChangeListener pcl; private final PropertyChangeListener pcl;
private static final long FILE_LIMIT = 6_000_000;
public OpenAction() { public OpenAction() {
super(); super();
toolbarButton.addActionListener(actionEvent -> performAction()); toolbarButton.addActionListener(actionEvent -> performAction());
pcl = (PropertyChangeEvent evt) -> { pcl = (PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) { if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
setEnabled(RuntimeProperties.runningWithGUI() && evt.getNewValue() != null); setEnabled(RuntimeProperties.runningWithGUI() && evt.getNewValue() != null);
} }
}; };
Case.addPropertyChangeListener(pcl); Case.addPropertyChangeListener(pcl);
this.setEnabled(false); this.setEnabled(false);
} }
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return Case.isCaseOpen() && Installer.isJavaFxInited() && Case.getCurrentCase().hasData(); return Case.isCaseOpen() && Installer.isJavaFxInited() && Case.getCurrentCase().hasData();
} }
/** Returns the toolbar component of this action /**
* Returns the toolbar component of this action
* *
* @return component the toolbar button */ * @return component the toolbar button
*/
@Override @Override
public Component getToolbarPresenter() { public Component getToolbarPresenter() {
ImageIcon icon = new ImageIcon(getClass().getResource("btn_icon_image_gallery_26.png")); //NON-NLS ImageIcon icon = new ImageIcon(getClass().getResource("btn_icon_image_gallery_26.png")); //NON-NLS
@ -87,7 +94,7 @@ public final class OpenAction extends CallableSystemAction implements Presenter.
toolbarButton.setText(this.getName()); toolbarButton.setText(this.getName());
return toolbarButton; return toolbarButton;
} }
/** /**
* Set this action to be enabled/disabled * Set this action to be enabled/disabled
* *
@ -98,26 +105,35 @@ public final class OpenAction extends CallableSystemAction implements Presenter.
super.setEnabled(value); super.setEnabled(value);
toolbarButton.setEnabled(value); toolbarButton.setEnabled(value);
} }
@Override @Override
@SuppressWarnings("fallthrough") @SuppressWarnings("fallthrough")
@NbBundle.Messages({
"OpenAction.dialogTitle=Image Gallery"
})
public void performAction() { public void performAction() {
//check case //check case
if (!Case.isCaseOpen()) { if (!Case.isCaseOpen()) {
return; return;
} }
final Case currentCase = Case.getCurrentCase(); final Case currentCase = Case.getCurrentCase();
if (tooManyFiles()) {
Platform.runLater(() ->
JavaFXUtils.showTooManyFiles(Bundle.OpenAction_dialogTitle()));
setEnabled(false);
return;
}
if (ImageGalleryModule.isDrawableDBStale(currentCase)) { if (ImageGalleryModule.isDrawableDBStale(currentCase)) {
//drawable db is stale, ask what to do //drawable db is stale, ask what to do
int answer = JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), Bundle.OpenAction_stale_confDlg_msg(), int answer = JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), Bundle.OpenAction_stale_confDlg_msg(),
Bundle.OpenAction_stale_confDlg_title(), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); Bundle.OpenAction_stale_confDlg_title(), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
switch (answer) { switch (answer) {
case JOptionPane.YES_OPTION: case JOptionPane.YES_OPTION:
ImageGalleryController.getDefault().setListeningEnabled(true); ImageGalleryController.getDefault().setListeningEnabled(true);
//fall through //fall through
case JOptionPane.NO_OPTION: case JOptionPane.NO_OPTION:
ImageGalleryTopComponent.openTopComponent(); ImageGalleryTopComponent.openTopComponent();
break; break;
@ -129,17 +145,29 @@ public final class OpenAction extends CallableSystemAction implements Presenter.
ImageGalleryTopComponent.openTopComponent(); ImageGalleryTopComponent.openTopComponent();
} }
} }
private boolean tooManyFiles() {
try {
return FILE_LIMIT < Case.getCurrentCase().getSleuthkitCase().countFilesWhere("1 = 1");
} catch (IllegalStateException ex) {
logger.log(Level.SEVERE, "Can not open image gallery with no case open.", ex);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error counting files in the DB.", ex);
}
//if there is any doubt (no case, tskcore error, etc) just disable .
return false;
}
@Override @Override
public String getName() { public String getName() {
return VIEW_IMAGES_VIDEOS; return VIEW_IMAGES_VIDEOS;
} }
@Override @Override
public HelpCtx getHelpCtx() { public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
} }
@Override @Override
public boolean asynchronous() { public boolean asynchronous() {
return false; // run on edt return false; // run on edt