diff --git a/Core/src/org/sleuthkit/autopsy/discovery/AbstractDiscoveryFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/AbstractDiscoveryFilterPanel.java index a7f9bcbd28..08967a2d86 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/AbstractDiscoveryFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/AbstractDiscoveryFilterPanel.java @@ -24,7 +24,9 @@ import javax.swing.JLabel; import javax.swing.JList; import javax.swing.event.ListSelectionListener; - +/** + * Abstract class extending JPanel for filter controls. + */ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; @@ -40,20 +42,44 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { */ abstract void configurePanel(boolean selected, int[] indicesSelected); + /** + * Get the checkbox which enables and disables this filter. + * + * @return The JCheckBox which enables and disables this filter. + */ abstract JCheckBox getCheckbox(); + /** + * Get the list of values associated with this filter if one exists. If one + * does not exist this should return null. + * + * @return The JList which contains the values available for selection for + * this filter. + */ abstract JList getList(); + /** + * Get any additional text that should be displayed under the checkbox. If + * no text should be displayed this should return null. + * + * @return The JLabel to display under the JCheckBox. + */ abstract JLabel getAdditionalLabel(); + /** + * Check if this filter is configured to valid settings. + * + * @return True if the filter is configured with valid search settings, + * false otherwise. + */ abstract String checkForError(); /** * Add listeners to the checkbox/list set if listeners have not already been * added. * - * @param listener - * @param listListener + * @param actionlistener The listener for the checkbox selection events. + * @param listListener The listener for the list selection events. */ void addListeners(ActionListener actionListener, ListSelectionListener listListener) { if (getCheckbox() != null) { @@ -64,8 +90,17 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { } } + /** + * Get the FileFilter which is represented by this Panel. + * + * @return The FileFilter for the selected settings, null if the settings + * are not in use. + */ abstract FileSearchFiltering.FileFilter getFilter(); + /** + * Remove listeners from the checkbox and the list if they exist. + */ void removeListeners() { if (getCheckbox() != null) { for (ActionListener listener : getCheckbox().getActionListeners()) { @@ -79,6 +114,12 @@ abstract class AbstractDiscoveryFilterPanel extends javax.swing.JPanel { } } + /** + * Return whether or not this filter has a panel. + * + * @return True if there is a panel to display associated with this filter, + * return false if the filter only has a checkbox. + */ boolean hasPanel() { return true; } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java index b8f6ba9e5a..884a940ddd 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/AbstractFiltersPanel.java @@ -31,7 +31,10 @@ import javax.swing.JSplitPane; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; - +/** + * Abstract class extending JPanel for displaying all the filters associated + * with a type. + */ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, ListSelectionListener { private boolean isInitialized = false; @@ -49,13 +52,32 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li private int firstColumnY = 0; private int secondColumnY = 0; + /** + * Setup necessary for implementations of this abstract class. + */ AbstractFiltersPanel() { firstColumnPanel.setLayout(new GridBagLayout()); secondColumnPanel.setLayout(new GridBagLayout()); } + /** + * Get the type of results this filters panel is for. + * + * @return The type of results this panel filters. + */ abstract FileSearchData.FileType getFileType(); + /** + * Add a DiscoveryFilterPanel to the specified column with the specified + * settings. + * + * @param filterPanel The DiscoveryFilterPanel to add to this panel. + * @param isSelected True if the checkbox should be selected, false + * otherwise. + * @param indicesSelected The array of indices that are selected in the + * list, null if none are selected. + * @param column The column to add the DiscoveryFilterPanel to. + */ final synchronized void addFilter(AbstractDiscoveryFilterPanel filterPanel, boolean isSelected, int[] indicesSelected, int column) { if (!isInitialized) { constraints.gridy = 0; @@ -98,6 +120,11 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li } } + /** + * Add the panels representing the two columns to the specified JSplitPane. + * + * @param splitPane The JSplitPane which the columns are added to. + */ final void addPanelsToScrollPane(JSplitPane splitPane) { splitPane.setLeftComponent(firstColumnPanel); splitPane.setRightComponent(secondColumnPanel); @@ -105,6 +132,9 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li repaint(); } + /** + * Clear the filters from the panel + */ final synchronized void clearFilters() { for (AbstractDiscoveryFilterPanel filterPanel : filters) { filterPanel.removeListeners(); @@ -118,7 +148,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li constraints.gridy += constraints.gridheight; addToColumn(additionalComponentToAdd, constraints, columnIndex); constraints.gridy -= constraints.gridheight; - } + } } private void addToColumn(Component component, Object constraints, int columnNumber) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DataSourceFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/DataSourceFilterPanel.java index 59ccc90055..fed38d0083 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DataSourceFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/DataSourceFilterPanel.java @@ -136,6 +136,7 @@ final class DataSourceFilterPanel extends AbstractDiscoveryFilterPanel { try { DefaultListModel dsListModel = (DefaultListModel) dataSourceList.getModel(); dsListModel.removeAllElements(); + System.out.println("CASE: " + Case.getCurrentCase().getName()); for (DataSource ds : Case.getCurrentCase().getSleuthkitCase().getDataSources()) { dsListModel.add(count, new DataSourceItem(ds)); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java index e270e83486..31aff3d8ae 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/DiscoveryDialog.java @@ -22,9 +22,12 @@ import static java.awt.BorderLayout.CENTER; import java.awt.Color; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; import org.apache.commons.lang.StringUtils; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.coreutils.Logger; @@ -34,6 +37,8 @@ import org.sleuthkit.autopsy.discovery.FileSorter.SortingMethod; final class DiscoveryDialog extends javax.swing.JDialog { + private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE, + Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED); private static final long serialVersionUID = 1L; private final static Logger logger = Logger.getLogger(DiscoveryDialog.class.getName()); private ImageFilterPanel imageFilterPanel = new ImageFilterPanel(); @@ -83,12 +88,14 @@ final class DiscoveryDialog extends javax.swing.JDialog { groupSortingComboBox.addItem(groupSortAlgorithm); } updateSearchSettings(); + Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, this.new CasePropertyChangeListener()); } /** * Update the search settings to a default state. */ void updateSearchSettings() { + System.out.println("UPDATE CALLED"); imageFilterPanel = new ImageFilterPanel(); videoFilterPanel = new VideoFilterPanel(); documentFilterPanel = new DocumentFilterPanel(); @@ -487,4 +494,30 @@ final class DiscoveryDialog extends javax.swing.JDialog { private javax.swing.JButton searchButton; private javax.swing.JButton videosButton; // End of variables declaration//GEN-END:variables + + private class CasePropertyChangeListener implements PropertyChangeListener { + + @Override + @SuppressWarnings("fallthrough") + public void propertyChange(PropertyChangeEvent evt) { + System.out.println("EVENT RECEIVED"); + switch (Case.Events.valueOf(evt.getPropertyName())) { + case CURRENT_CASE: { + if (evt.getNewValue() == null) { + //do not refresh when a case is closed only when it is opened. + break; + } + //else fallthrough + } + case DATA_SOURCE_ADDED: + //fallthrough + case DATA_SOURCE_DELETED: + updateSearchSettings(); + break; + default: + //do nothing if the event is not one of the above events. + break; + } + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java index a2689db979..c25d211036 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/GroupListPanel.java @@ -50,15 +50,12 @@ final class GroupListPanel extends javax.swing.JPanel { */ GroupListPanel() { initComponents(); - SwingUtilities.invokeLater(() -> { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - }); } /** - * Subscribe to and reset the panel in response to SearchStartedEvents + * Subscribe to and reset the panel in response to SearchStartedEvents. * - * @param searchStartedEvent the SearchStartedEvent which was received + * @param searchStartedEvent The SearchStartedEvent which was received. */ @Subscribe void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) { @@ -70,9 +67,9 @@ final class GroupListPanel extends javax.swing.JPanel { "GroupsListPanel.noResults.title.text=No results found"}) /** * Subscribe to and update list of groups in response to - * SearchCompleteEvents + * SearchCompleteEvents. * - * @param searchCompleteEvent the SearchCompleteEvent which was received + * @param searchCompleteEvent The SearchCompleteEvent which was received. */ @Subscribe void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) { @@ -95,6 +92,18 @@ final class GroupListPanel extends javax.swing.JPanel { }); } + /** + * Subscribe to SearchCancelledEvent and reset the panel in response to it. + * + * @param searchCancelledEvent The SearchCancelledEvent which was received. + */ + @Subscribe + void handleSearchCancelledEvent(DiscoveryEventUtils.SearchCancelledEvent searchCancelledEvent) { + SwingUtilities.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + }); + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -138,6 +147,9 @@ final class GroupListPanel extends javax.swing.JPanel { * Reset the group list to be empty. */ void resetGroupList() { + SwingUtilities.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); groupKeyList.setListData(new GroupKey[0]); } @@ -160,6 +172,7 @@ final class GroupListPanel extends javax.swing.JPanel { } } else { DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.NoResultsEvent()); + } } }//GEN-LAST:event_groupSelected diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java index 393ece054b..ca31818390 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ImageFilterPanel.java @@ -34,7 +34,7 @@ final class ImageFilterPanel extends AbstractFiltersPanel { SizeFilterPanel sizeFilterPanel = new SizeFilterPanel(FILE_TYPE); int[] sizeIndicesSelected = {1, 2, 3, 4, 5}; addFilter(sizeFilterPanel, true, sizeIndicesSelected, 0); - addFilter(new ObjectDetectedFilterPanel(), false, null, 0); + addFilter(new DataSourceFilterPanel(), false, null, 0); int[] pastOccurrencesIndices; if (!CentralRepository.isEnabled()) { pastOccurrencesIndices = new int[]{0}; @@ -45,10 +45,10 @@ final class ImageFilterPanel extends AbstractFiltersPanel { addFilter(new UserCreatedFilterPanel(), false, null, 1); addFilter(new HashSetFilterPanel(), false, null, 1); addFilter(new InterestingItemsFilterPanel(), false, null, 1); - addFilter(new DataSourceFilterPanel(), false, null, 1); + addFilter(new ObjectDetectedFilterPanel(), false, null, 1); addFilter(new ParentFolderFilterPanel(), false, null, 1); addPanelsToScrollPane(imageFiltersSplitPane); - + } /** diff --git a/Core/src/org/sleuthkit/autopsy/discovery/OpenDiscoveryAction.java b/Core/src/org/sleuthkit/autopsy/discovery/OpenDiscoveryAction.java index 545fca578f..64088c815e 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/OpenDiscoveryAction.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/OpenDiscoveryAction.java @@ -132,7 +132,6 @@ public final class OpenDiscoveryAction extends CallableSystemAction implements P @Override public void setEnabled(boolean value) { super.setEnabled(value); - DiscoveryDialog.getDiscoveryDialogInstance().updateSearchSettings(); toolbarButton.setEnabled(value); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java index 908461c478..4b580dfc70 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ResultsPanel.java @@ -108,9 +108,6 @@ final class ResultsPanel extends javax.swing.JPanel { DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.ClearInstanceSelectionEvent()); } } - }); - SwingUtilities.invokeLater(() -> { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); }); } @@ -137,6 +134,18 @@ final class ResultsPanel extends javax.swing.JPanel { return new ArrayList<>(); } + /** + * Subscribe to and reset the panel in response to SearchStartedEvents + * + * @param searchStartedEvent the SearchStartedEvent which was received + */ + @Subscribe + void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) { + SwingUtilities.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + } + /** * Subscribe and respond to PageRetrievedEvents. * @@ -145,6 +154,7 @@ final class ResultsPanel extends javax.swing.JPanel { @Subscribe void handlePageRetrievedEvent(DiscoveryEventUtils.PageRetrievedEvent pageRetrievedEvent) { SwingUtilities.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); //send populateMesage DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateInstancesListEvent(getInstancesForSelected())); @@ -257,7 +267,6 @@ final class ResultsPanel extends javax.swing.JPanel { resultType = groupSelectedEvent.getResultType(); groupSize = groupSelectedEvent.getGroupSize(); setPage(0); - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); }); } @@ -270,6 +279,7 @@ final class ResultsPanel extends javax.swing.JPanel { @Subscribe void handleNoResultsEvent(DiscoveryEventUtils.NoResultsEvent noResultsEvent) { SwingUtilities.invokeLater(() -> { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); groupSize = 0; currentPage = 0; updateControls(); @@ -281,6 +291,8 @@ final class ResultsPanel extends javax.swing.JPanel { }); } + @Subscribe + /** * Set the page number and retrieve its contents. * diff --git a/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimator.java b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimator.java index f01acc0d93..1276bf81e5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimator.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimator.java @@ -24,13 +24,11 @@ import javax.swing.Timer; /** * - * Class to animate Layouts and Fades for a given component. + * Class to animate Layouts for a given component. * * @author Greg Cope * https://www.algosome.com/articles/java-swing-panel-animation.html * - * - * */ final class SwingAnimator { @@ -41,77 +39,38 @@ final class SwingAnimator { private Timer timer = null; //duration in milliseconds betweeen each firing of the Timer - private static final int INITIAL_DURATION = 10; - private static int duration = INITIAL_DURATION; + private static final int INITIAL_TIMING = 10; + private static int timing = INITIAL_TIMING; /** * * Constructs a new SwingAnimator. * - * - * @param callback The object to callback to + * @param callback The SwingAnimatorCallback to call. * */ SwingAnimator(SwingAnimatorCallback callback) { - - this(callback, false); - + this(callback, INITIAL_TIMING); } /** * + * Constructs a new SwingAnimator. * - * - * @param callback The object to callback to - * - * @param start true to automatically start the animation, false - * otherwise - * - */ - SwingAnimator(SwingAnimatorCallback callback, boolean start) { - - this(callback, INITIAL_DURATION, start); - - } - - /** - * - * - * - * @param callback The object to callback to - * - * @param frameTiming Timing between each call to callback. - * - * @param start true to automatically start the animation, false - * otherwise - * - */ - SwingAnimator(SwingAnimatorCallback callback, int frameTiming, boolean start) { - this.callback = callback; - duration = frameTiming; - if (start) { - start(); - } - } - - /** - * - * - * - * @param callback The object to callback to - * + * @param callback The SwingAnimatorCallback to call. * @param frameTiming Timing between each call to callback. * */ SwingAnimator(SwingAnimatorCallback callback, int frameTiming) { - this(callback, frameTiming, false); + this.callback = callback; + timing = frameTiming; } /** * * Checks if this animator is running. * - * @return + * @return True if the animator is running, false otherwise. * */ boolean isRunning() { @@ -135,26 +94,19 @@ final class SwingAnimator { /** * * Starts the timer to fire. If the current timer is non-null and running, - * this method will first - * - * stop the timer before beginning a new one. * + * this method will first stop the timer before beginning a new one. */ void start() { - if (timer != null && timer.isRunning()) { stop(); } - timer = new Timer(duration, new CallbackListener()); + timer = new Timer(timing, new CallbackListener()); timer.start(); } /** * - * ActionListener implements to be passed to the internal timer instance - * - * @author Greg Cope - * - * + * ActionListener implements to be passed to the internal timer instance. * */ private class CallbackListener implements ActionListener { @@ -170,5 +122,5 @@ final class SwingAnimator { callback.callback(SwingAnimator.this); } } - + } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimatorCallback.java b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimatorCallback.java index f36f51a885..86f7d2f7fb 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimatorCallback.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/SwingAnimatorCallback.java @@ -20,7 +20,9 @@ package org.sleuthkit.autopsy.discovery; /** * - * Callback interface to be notified by a SwingAnimator of a new time frame. * + * Callback interface to be notified by a SwingAnimator of a new time frame. + * + * * @author Greg Cope * https://www.algosome.com/articles/java-swing-panel-animation.html * @@ -29,17 +31,18 @@ interface SwingAnimatorCallback { /** * - * Callback method for the SwingAnimator + * Callback method for the SwingAnimator. * - * @param caller + * @param caller The object which is calling the Callback. * */ void callback(Object caller); /** * - * Returns true if the SwingAnimator should terminate. * - * @return + * Returns true if the SwingAnimator has terminated. + * + * @return True if the animator has terminated, false otherwise. * */ boolean hasTerminated();