diff --git a/Core/src/org/sleuthkit/autopsy/filequery/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/filequery/Bundle.properties-MERGED index 9d482a0f24..678e0f0b61 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/filequery/Bundle.properties-MERGED @@ -1,4 +1,5 @@ CTL_FileDiscoveryTestAction=Test file discovery +DiscoveryTopComponent.name=\ File Discovery # {0} - Data source name # {1} - Data source ID FileSearch.DataSourceGroupKey.datasourceAndID={0}(ID: {1}) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryEvents.java b/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryEvents.java index 73473b0234..d3dad4b24f 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryEvents.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryEvents.java @@ -209,10 +209,24 @@ final class DiscoveryEvents { * Construct a new NoResultsEvent. */ NoResultsEvent() { - //no arg conustructor + //no arg constructor } } + /** + * Event to signal that a search has been cancelled + */ + static final class SearchCancelledEvent { + + /** + * Construct a new SearchCancelledEvent. + */ + SearchCancelledEvent() { + //no arg constructor + } + + } + /** * Event to signal that a group has been selected. */ diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryDialog.form b/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryTopComponent.form similarity index 93% rename from Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryDialog.form rename to Core/src/org/sleuthkit/autopsy/filequery/DiscoveryTopComponent.form index cc70ee2002..92772c1173 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryDialog.form +++ b/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryTopComponent.form @@ -1,16 +1,11 @@ -
+ - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryDialog.java b/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryTopComponent.java similarity index 66% rename from Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryDialog.java rename to Core/src/org/sleuthkit/autopsy/filequery/DiscoveryTopComponent.java index f5b332f599..54a7cda52d 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/DiscoveryTopComponent.java @@ -18,26 +18,40 @@ */ package org.sleuthkit.autopsy.filequery; -import javax.swing.JFrame; +import java.awt.Cursor; +import java.util.logging.Level; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.openide.explorer.ExplorerManager; import org.openide.nodes.Node; +import org.openide.util.NbBundle; +import org.openide.windows.Mode; +import org.openide.windows.RetainLocation; +import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.corecomponents.DataContentPanel; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.SleuthkitCase; /** * Create a dialog for displaying the file discovery tool */ -class FileDiscoveryDialog extends javax.swing.JDialog { +@TopComponent.Description(preferredID = "DiscoveryTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER) +@TopComponent.Registration(mode = "discovery", openAtStartup = false) +@RetainLocation("discovery") +@NbBundle.Messages("DiscoveryTopComponent.name= File Discovery") +final class DiscoveryTopComponent extends TopComponent { private static final long serialVersionUID = 1L; + private static final String PREFERRED_ID = "DiscoveryTopComponent"; // NON-NLS + private final static Logger logger = Logger.getLogger(DiscoveryTopComponent.class.getName()); private final FileSearchPanel fileSearchPanel; private final GroupListPanel groupListPanel; private final DataContentPanel dataContentPanel; @@ -47,16 +61,24 @@ class FileDiscoveryDialog extends javax.swing.JDialog { /** * Creates new form FileDiscoveryDialog */ - FileDiscoveryDialog(java.awt.Frame parent, boolean modal, SleuthkitCase caseDb, EamDb centralRepoDb) { - super((JFrame) WindowManager.getDefault().getMainWindow(), Bundle.FileSearchPanel_dialogTitle_text(), modal); + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + DiscoveryTopComponent() { initComponents(); + // Load the central repository database. + EamDb centralRepoDb = null; + if (EamDb.isEnabled()) { + try { + centralRepoDb = EamDb.getInstance(); + } catch (EamDbException ex) { + logger.log(Level.SEVERE, "Error loading central repository database, no central repository options will be available for File Discovery", ex); + } + } + setName(Bundle.DiscoveryTopComponent_name()); explorerManager = new ExplorerManager(); - fileSearchPanel = new FileSearchPanel(caseDb, centralRepoDb); + fileSearchPanel = new FileSearchPanel(Case.getCurrentCase().getSleuthkitCase(), centralRepoDb); dataContentPanel = DataContentPanel.createInstance(); resultsPanel = new ResultsPanel(explorerManager, centralRepoDb); - DiscoveryEvents.getDiscoveryEventBus().register(resultsPanel); groupListPanel = new GroupListPanel(); - DiscoveryEvents.getDiscoveryEventBus().register(groupListPanel); leftSplitPane.setLeftComponent(fileSearchPanel); leftSplitPane.setRightComponent(groupListPanel); rightSplitPane.setTopComponent(resultsPanel); @@ -101,20 +123,49 @@ class FileDiscoveryDialog extends javax.swing.JDialog { } /** - * Show the dialog + * Open the instance of the DiscoveryTopComponent which exists. */ - void display() { - this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); - setVisible(true); + static void openTopComponent() { + final DiscoveryTopComponent tc = (DiscoveryTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (tc != null) { + WindowManager.getDefault().isTopComponentFloating(tc); + if (tc.isOpened() == false) { + Mode mode = WindowManager.getDefault().findMode("discovery"); // NON-NLS + if (mode != null) { + mode.dockInto(tc); + } + tc.open(); + } + tc.toFront(); + } + } + + /** + * Sets the cursor for the instance of the DiscoveryTopComponent which + * exists. + * + * @param cursor The Cursor which you want to have displayed. + */ + static void changeCursor(Cursor cursor) { + WindowManager.getDefault().findTopComponent(PREFERRED_ID).setCursor(cursor); } @Override - public void dispose() { + public void componentOpened() { + super.componentOpened(); + WindowManager.getDefault().setTopComponentFloating(this, true); + DiscoveryEvents.getDiscoveryEventBus().register(resultsPanel); + DiscoveryEvents.getDiscoveryEventBus().register(groupListPanel); + DiscoveryEvents.getDiscoveryEventBus().register(fileSearchPanel); + } + + @Override + protected void componentClosed() { fileSearchPanel.cancelSearch(); - FileSearch.clearCache(); + DiscoveryEvents.getDiscoveryEventBus().unregister(fileSearchPanel); DiscoveryEvents.getDiscoveryEventBus().unregister(groupListPanel); DiscoveryEvents.getDiscoveryEventBus().unregister(resultsPanel); - super.dispose(); + super.componentClosed(); } /** @@ -130,8 +181,8 @@ class FileDiscoveryDialog extends javax.swing.JDialog { leftSplitPane = new javax.swing.JSplitPane(); rightSplitPane = new javax.swing.JSplitPane(); - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setPreferredSize(new java.awt.Dimension(1100, 700)); + setLayout(new java.awt.BorderLayout()); mainSplitPane.setDividerLocation(550); mainSplitPane.setResizeWeight(0.2); @@ -147,9 +198,7 @@ class FileDiscoveryDialog extends javax.swing.JDialog { rightSplitPane.setResizeWeight(0.5); mainSplitPane.setRightComponent(rightSplitPane); - getContentPane().add(mainSplitPane, java.awt.BorderLayout.CENTER); - - pack(); + add(mainSplitPane, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryTestAction.java b/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryTestAction.java index 75baedb528..2962ec6fe5 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryTestAction.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileDiscoveryTestAction.java @@ -18,18 +18,13 @@ */ package org.sleuthkit.autopsy.filequery; -import java.util.logging.Level; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionRegistration; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; -import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.coreutils.Logger; /** * Class to test the file search API. Allows the user to run searches and see @@ -41,7 +36,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; @NbBundle.Messages({"CTL_FileDiscoveryTestAction=Test file discovery"}) public final class FileDiscoveryTestAction extends CallableSystemAction { - private final static Logger logger = Logger.getLogger(FileDiscoveryTestAction.class.getName()); private static final String DISPLAY_NAME = "Test file discovery"; private static final long serialVersionUID = 1L; @@ -53,22 +47,7 @@ public final class FileDiscoveryTestAction extends CallableSystemAction { @Override @SuppressWarnings("fallthrough") public void performAction() { - - // Load the central repository database. - EamDb crDb = null; - if (EamDb.isEnabled()) { - try { - crDb = EamDb.getInstance(); - } catch (EamDbException ex) { - logger.log(Level.SEVERE, "Error loading central repository database", ex); - return; - } - } - //modal set to true currently to prevent multiple dialogs being opened because messaging uses a shared eventbus - FileDiscoveryDialog dialog = new FileDiscoveryDialog(WindowManager.getDefault().getMainWindow(), true, Case.getCurrentCase().getSleuthkitCase(), crDb); - // Display the dialog - dialog.display(); - + DiscoveryTopComponent.openTopComponent(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.form b/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.form index e0835a9d76..5d319cb4f9 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.form +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.form @@ -828,6 +828,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.java index c9bbb29cbe..d8fce68807 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearchPanel.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.filequery; +import com.google.common.eventbus.Subscribe; +import java.awt.Cursor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -32,6 +34,7 @@ import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.JCheckBox; import javax.swing.JList; +import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.openide.util.NbBundle; @@ -215,6 +218,9 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener addListeners(keywordCheckbox, keywordList); } + /** + * Initialize the hash filter. + */ private void setUpHashFilter() { int count = 0; try { @@ -234,6 +240,9 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener addListeners(hashSetCheckbox, hashSetList); } + /** + * Initialize the interesting items filter. + */ private void setUpInterestingItemsFilter() { int count = 0; try { @@ -253,6 +262,9 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener addListeners(interestingItemsCheckbox, interestingItemsList); } + /** + * Initialize the tags filter. + */ private void setUpTagsFilter() { int count = 0; try { @@ -329,6 +341,18 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener addListeners(scoreCheckbox, scoreList); } + /** + * Get the names of the sets which exist in the case database for the + * specified artifact and attribute types. + * + * @param artifactType The artifact type to get the list of sets for. + * @param setNameAttribute The attribute type which contains the set names. + * + * @return A list of set names which exist in the case for the specified + * artifact and attribute types. + * + * @throws TskCoreException + */ private List getSetNames(BlackboardArtifact.ARTIFACT_TYPE artifactType, BlackboardAttribute.ATTRIBUTE_TYPE setNameAttribute) throws TskCoreException { List arts = caseDb.getBlackboardArtifacts(artifactType); List setNames = new ArrayList<>(); @@ -1116,6 +1140,7 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener errorLabel.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(FileSearchPanel.class, "FileSearchPanel.cancelButton.text")); // NOI18N + cancelButton.setEnabled(false); cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancelButtonActionPerformed(evt); @@ -1169,7 +1194,8 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener }// //GEN-END:initComponents private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed - searchButton.setEnabled(false); + enableSearch(false); + FileType searchType = fileTypeComboBox.getItemAt(fileTypeComboBox.getSelectedIndex()); DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.SearchStartedEvent(searchType)); // For testing, allow the user to run different searches in loop @@ -1183,10 +1209,92 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener // Get the file sorting method FileSorter.SortingMethod fileSort = getFileSortingMethod(); - searchWorker = new SearchWorker(centralRepoDb, searchButton, filters, groupingAttr, groupSortAlgorithm, fileSort); + searchWorker = new SearchWorker(centralRepoDb, filters, groupingAttr, groupSortAlgorithm, fileSort); searchWorker.execute(); }//GEN-LAST:event_searchButtonActionPerformed + /** + * Set the enabled status of the search controls. + * + * @param enabled Boolean which indicates if the search should be enabled. + * True if the search button and controls should be enabled, + * false otherwise. + */ + private void enableSearch(boolean enabled) { + if (enabled) { + DiscoveryTopComponent.changeCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } else { + DiscoveryTopComponent.changeCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } + searchButton.setEnabled(enabled); + cancelButton.setEnabled(!enabled); + fileTypeComboBox.setEnabled(enabled); + orderByCombobox.setEnabled(enabled); + groupByCombobox.setEnabled(enabled); + attributeRadioButton.setEnabled(enabled); + groupSizeRadioButton.setEnabled(enabled); + sizeCheckbox.setEnabled(enabled); + sizeScrollPane.setEnabled(enabled && sizeCheckbox.isSelected()); + sizeList.setEnabled(enabled && sizeCheckbox.isSelected()); + dataSourceCheckbox.setEnabled(enabled); + dataSourceList.setEnabled(enabled && dataSourceCheckbox.isSelected()); + dataSourceScrollPane.setEnabled(enabled && dataSourceCheckbox.isSelected()); + crFrequencyCheckbox.setEnabled(enabled); + crFrequencyScrollPane.setEnabled(enabled && crFrequencyCheckbox.isSelected()); + crFrequencyList.setEnabled(enabled && crFrequencyCheckbox.isSelected()); + keywordCheckbox.setEnabled(enabled); + keywordList.setEnabled(enabled && keywordCheckbox.isSelected()); + keywordScrollPane.setEnabled(enabled && keywordCheckbox.isSelected()); + hashSetCheckbox.setEnabled(enabled); + hashSetScrollPane.setEnabled(enabled && hashSetCheckbox.isSelected()); + hashSetList.setEnabled(enabled && hashSetCheckbox.isSelected()); + objectsCheckbox.setEnabled(enabled); + objectsScrollPane.setEnabled(enabled && objectsCheckbox.isSelected()); + objectsList.setEnabled(enabled && objectsCheckbox.isSelected()); + tagsCheckbox.setEnabled(enabled); + tagsScrollPane.setEnabled(enabled && tagsCheckbox.isSelected()); + tagsList.setEnabled(enabled && tagsCheckbox.isSelected()); + interestingItemsCheckbox.setEnabled(enabled); + interestingItemsScrollPane.setEnabled(enabled && interestingItemsCheckbox.isSelected()); + interestingItemsList.setEnabled(enabled && interestingItemsCheckbox.isSelected()); + scoreCheckbox.setEnabled(enabled); + scoreScrollPane.setEnabled(enabled && scoreCheckbox.isSelected()); + scoreList.setEnabled(enabled && scoreCheckbox.isSelected()); + exifCheckbox.setEnabled(enabled); + notableCheckbox.setEnabled(enabled); + parentCheckbox.setEnabled(enabled); + parentScrollPane.setEnabled(enabled && parentCheckbox.isSelected()); + parentList.setEnabled(enabled && parentCheckbox.isSelected()); + parentTextField.setEnabled(enabled && parentCheckbox.isSelected()); + addButton.setEnabled(enabled && parentCheckbox.isSelected()); + deleteButton.setEnabled(enabled && parentCheckbox.isSelected() && !parentListModel.isEmpty()); + fullRadioButton.setEnabled(enabled && parentCheckbox.isSelected()); + substringRadioButton.setEnabled(enabled && parentCheckbox.isSelected()); + } + + /** + * Update the user interface when a search has been cancelled. + * + * @param searchCancelledEvent The SearchCancelledEvent which was received. + */ + @Subscribe + void handleSearchCancelledEvent(DiscoveryEvents.SearchCancelledEvent searchCancelledEvent) { + SwingUtilities.invokeLater(() -> { + enableSearch(true); + }); + } + + /** + * Update the user interface when a search has been successfully completed. + * + * @param searchCompleteEvent The SearchCompleteEvent which was received. + */ + @Subscribe + void handleSearchCompleteEvent(DiscoveryEvents.SearchCompleteEvent searchCompleteEvent) { + SwingUtilities.invokeLater(() -> { + enableSearch(true); + }); + } private void parentCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_parentCheckboxActionPerformed parentList.setEnabled(parentCheckbox.isSelected()); @@ -1194,7 +1302,7 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener substringRadioButton.setEnabled(parentCheckbox.isSelected()); parentTextField.setEnabled(parentCheckbox.isSelected()); addButton.setEnabled(parentCheckbox.isSelected()); - deleteButton.setEnabled(parentCheckbox.isSelected()); + deleteButton.setEnabled(parentCheckbox.isSelected() && !parentListModel.isEmpty()); }//GEN-LAST:event_parentCheckboxActionPerformed private void keywordCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_keywordCheckboxActionPerformed @@ -1222,6 +1330,9 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener } }//GEN-LAST:event_addButtonActionPerformed + /** + * Cancel the current search. + */ void cancelSearch() { if (searchWorker != null) { searchWorker.cancel(true); @@ -1230,7 +1341,9 @@ final class FileSearchPanel extends javax.swing.JPanel implements ActionListener private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButtonActionPerformed int index = parentList.getSelectedIndex(); - parentListModel.remove(index); + if (index >= 0) { + parentListModel.remove(index); + } validateFields(); }//GEN-LAST:event_deleteButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/filequery/PageWorker.java b/Core/src/org/sleuthkit/autopsy/filequery/PageWorker.java index e65916008a..7c4ca5c9c7 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/PageWorker.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/PageWorker.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.filequery; import java.util.List; +import java.util.ArrayList; import java.util.logging.Level; import javax.swing.SwingWorker; import org.sleuthkit.autopsy.casemodule.Case; @@ -41,6 +42,7 @@ final class PageWorker extends SwingWorker { private final int pageSize; private final FileSearchData.FileType resultType; private final EamDb centralRepo; + private final List results = new ArrayList<>(); /** * Construct a new PageWorker. @@ -77,16 +79,24 @@ final class PageWorker extends SwingWorker { try { // Run the search - List results = FileSearch.getFilesInGroup(searchfilters, + results.addAll(FileSearch.getFilesInGroup(searchfilters, groupingAttribute, groupSort, fileSortMethod, groupKey, startingEntry, pageSize, - Case.getCurrentCase().getSleuthkitCase(), centralRepo); - int currentPage = startingEntry / pageSize; //integer division should round down to get page number correctly - DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.PageRetrievedEvent(resultType, currentPage, results)); + Case.getCurrentCase().getSleuthkitCase(), centralRepo)); } catch (FileSearchException ex) { logger.log(Level.SEVERE, "Error running file search test", ex); + cancel(true); } return null; } + + @Override + protected void done() { + if (!isCancelled()) { + int currentPage = startingEntry / pageSize; //integer division should round down to get page number correctly + DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.PageRetrievedEvent(resultType, currentPage, results)); + } + } + } diff --git a/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java index 41467235da..08aa564826 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java @@ -249,8 +249,14 @@ public class ResultsPanel extends javax.swing.JPanel { }); } + /** + * Handle and respond to NoResultsEvent, updating the panel to reflect that + * there were no results. + * + * @param noResultsEvent the NoResultsEvent received. + */ @Subscribe - void handleNoResultsEvent(DiscoveryEvents.NoResultsEvent noResultsEven) { + void handleNoResultsEvent(DiscoveryEvents.NoResultsEvent noResultsEvent) { SwingUtilities.invokeLater(() -> { groupSize = 0; currentPage = 0; diff --git a/Core/src/org/sleuthkit/autopsy/filequery/SearchWorker.java b/Core/src/org/sleuthkit/autopsy/filequery/SearchWorker.java index 913760c493..f465a5d628 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/SearchWorker.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/SearchWorker.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.filequery; import java.util.LinkedHashMap; -import javax.swing.JButton; import javax.swing.SwingWorker; import java.util.List; import java.util.logging.Level; @@ -34,27 +33,24 @@ import org.sleuthkit.autopsy.filequery.FileSearch.GroupKey; final class SearchWorker extends SwingWorker { private final static Logger logger = Logger.getLogger(SearchWorker.class.getName()); - private final JButton searchButtonToEnable; private final List filters; private final FileSearch.AttributeType groupingAttr; private final FileSorter.SortingMethod fileSort; private final FileGroup.GroupSortingAlgorithm groupSortAlgorithm; private final EamDb centralRepoDb; + private final LinkedHashMap results = new LinkedHashMap<>(); /** * Create a SwingWorker which performs a search * * @param centralRepo the central repository being used for the search - * @param searchButton the search button to renable when the search is - * complete * @param searchfilters the FileFilters to use for the search * @param groupingAttribute the AttributeType to group by * @param groupSort the Algorithm to sort groups by * @param fileSortMethod the SortingMethod to use for files */ - SearchWorker(EamDb centralRepo, JButton searchButton, List searchfilters, FileSearch.AttributeType groupingAttribute, FileGroup.GroupSortingAlgorithm groupSort, FileSorter.SortingMethod fileSortMethod) { + SearchWorker(EamDb centralRepo, List searchfilters, FileSearch.AttributeType groupingAttribute, FileGroup.GroupSortingAlgorithm groupSort, FileSorter.SortingMethod fileSortMethod) { centralRepoDb = centralRepo; - searchButtonToEnable = searchButton; filters = searchfilters; groupingAttr = groupingAttribute; groupSortAlgorithm = groupSort; @@ -63,26 +59,26 @@ final class SearchWorker extends SwingWorker { @Override protected Void doInBackground() throws Exception { - try { // Run the search - LinkedHashMap results = FileSearch.getGroupSizes(filters, + results.putAll(FileSearch.getGroupSizes(filters, groupingAttr, groupSortAlgorithm, fileSort, - Case.getCurrentCase().getSleuthkitCase(), centralRepoDb); - DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.SearchCompleteEvent(results, filters, groupingAttr, groupSortAlgorithm, fileSort)); + Case.getCurrentCase().getSleuthkitCase(), centralRepoDb)); } catch (FileSearchException ex) { logger.log(Level.SEVERE, "Error running file search test", ex); + cancel(true); } return null; } @Override protected void done() { - //If a search button was provided re-enable it - if (searchButtonToEnable != null) { - searchButtonToEnable.setEnabled(true); + if (isCancelled()) { + DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.SearchCancelledEvent()); + } else { + DiscoveryEvents.getDiscoveryEventBus().post(new DiscoveryEvents.SearchCompleteEvent(results, filters, groupingAttr, groupSortAlgorithm, fileSort)); } } }