diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
index 54dd21e3c9..cae89e41ce 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
@@ -190,7 +190,6 @@ ImageFilePanel.sectorSizeLabel.text=Sector size:
LocalDiskPanel.sectorSizeLabel.text=Sector Size:
LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
LocalFilesPanel.errorLabel.text=Error Label
-LocalFilesPanel.selectedPaths.toolTipText=
LocalFilesPanel.clearButton.toolTipText=Clears currently selected local file paths
LocalFilesPanel.clearButton.text=Clear
LocalFilesPanel.selectButton.actionCommand=Add
@@ -263,8 +262,11 @@ AddImageWizardSelectHostVisual.specifyNewHostTextField.text=
AddImageWizardSelectHostVisual.specifyNewHostRadio.text=Specify new host name
AddImageWizardSelectHostVisual.generateNewRadio.text=Generate new host name based on data source name
AddImageWizardSelectHostVisual.validationMessage.text=\
+LocalFilesPanel.deleteButon.text=Delete
LocalFilesPanel.createTimeCheckBox.text=Creation Time - Often changed when a file is copied
LocalFilesPanel.modifiedTimeCheckBox.text=\ Modified Time - Often not changed when a file is copied
LocalFilesPanel.jLabel2.text=NOTE: Time stamps may have changed when the files were copied to the current location.
LocalFilesPanel.timestampToIncludeLabel.text=Timestamps To Include:
LocalFilesPanel.accessTimeCheckBox.text=Access Time - Can be changed when the file is opened
+LocalFilesPanel.timeStampToIncludeLabel.text=Timestamps To Include:
+LocalFilesPanel.timeStampNoteLabel.text=NOTE: Time stamps may have changed when the files were copied to the current location.
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED
index e5dc718df7..b671940118 100755
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED
@@ -417,7 +417,6 @@ ImageFilePanel.sectorSizeLabel.text=Sector size:
LocalDiskPanel.sectorSizeLabel.text=Sector Size:
LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
LocalFilesPanel.errorLabel.text=Error Label
-LocalFilesPanel.selectedPaths.toolTipText=
LocalFilesPanel.clearButton.toolTipText=Clears currently selected local file paths
LocalFilesPanel.clearButton.text=Clear
LocalFilesPanel.selectButton.actionCommand=Add
@@ -490,8 +489,11 @@ AddImageWizardSelectHostVisual.specifyNewHostTextField.text=
AddImageWizardSelectHostVisual.specifyNewHostRadio.text=Specify new host name
AddImageWizardSelectHostVisual.generateNewRadio.text=Generate new host name based on data source name
AddImageWizardSelectHostVisual.validationMessage.text=\
+LocalFilesPanel.deleteButon.text=Delete
LocalFilesPanel.createTimeCheckBox.text=Creation Time - Often changed when a file is copied
LocalFilesPanel.modifiedTimeCheckBox.text=\ Modified Time - Often not changed when a file is copied
LocalFilesPanel.jLabel2.text=NOTE: Time stamps may have changed when the files were copied to the current location.
LocalFilesPanel.timestampToIncludeLabel.text=Timestamps To Include:
LocalFilesPanel.accessTimeCheckBox.text=Access Time - Can be changed when the file is opened
+LocalFilesPanel.timeStampToIncludeLabel.text=Timestamps To Include:
+LocalFilesPanel.timeStampNoteLabel.text=NOTE: Time stamps may have changed when the files were copied to the current location.
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form
index 69014dd195..358f4e7fd5 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.form
@@ -27,185 +27,139 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -215,6 +169,11 @@
+
+
+
+
+
@@ -222,53 +181,114 @@
+
+
+
+
+
-
+
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -278,6 +298,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java
index 58dba0ccef..0bdb52b4fd 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java
@@ -19,31 +19,33 @@
package org.sleuthkit.autopsy.casemodule;
import java.io.File;
-import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
import javax.swing.JFileChooser;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import java.util.logging.Level;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.swing.AbstractListModel;
import javax.swing.JOptionPane;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PathValidator;
/**
- * A panel which allows the user to select local files and/or directories.
+ * A panel which allows the user to select local files and/or directories.
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final class LocalFilesPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
- private final Set currentFiles = new TreeSet<>(); //keep currents in a set to disallow duplicates per add
private boolean enableNext = false;
private static final Logger logger = Logger.getLogger(LocalFilesPanel.class.getName());
private String displayName = "";
+ private final LocalFilesModel listModel = new LocalFilesModel();
/**
* Creates new form LocalFilesPanel
@@ -56,7 +58,8 @@ final class LocalFilesPanel extends javax.swing.JPanel {
private void customInit() {
localFileChooser.setMultiSelectionEnabled(true);
errorLabel.setVisible(false);
- selectedPaths.setText("");
+ this.fileList.setModel(listModel);
+ listModel.clear();
this.displayNameLabel.setText(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.displayNameLabel.text"));
}
@@ -68,27 +71,33 @@ final class LocalFilesPanel extends javax.swing.JPanel {
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
+ java.awt.GridBagConstraints gridBagConstraints;
localFileChooser = new javax.swing.JFileChooser();
- jPanel1 = new javax.swing.JPanel();
selectButton = new javax.swing.JButton();
+ deleteButon = new javax.swing.JButton();
clearButton = new javax.swing.JButton();
- selectedPathsScrollPane = new javax.swing.JScrollPane();
- selectedPaths = new javax.swing.JTextArea();
+ javax.swing.JScrollPane fileListScrollpane = new javax.swing.JScrollPane();
+ fileList = new javax.swing.JList<>();
+ javax.swing.JPanel displayNamePanel = new javax.swing.JPanel();
changeNameButton = new javax.swing.JButton();
displayNameLabel = new javax.swing.JLabel();
- timestampToIncludeLabel = new javax.swing.JLabel();
+ javax.swing.JPanel padding = new javax.swing.JPanel();
+ javax.swing.JLabel timeStampToIncludeLabel = new javax.swing.JLabel();
+ modifiedTimeCheckBox = new javax.swing.JCheckBox();
createTimeCheckBox = new javax.swing.JCheckBox();
accessTimeCheckBox = new javax.swing.JCheckBox();
- modifiedTimeCheckBox = new javax.swing.JCheckBox();
- jLabel2 = new javax.swing.JLabel();
+ javax.swing.JLabel timeStampNoteLabel = new javax.swing.JLabel();
errorLabel = new javax.swing.JLabel();
+ javax.swing.JPanel paddingBottom = new javax.swing.JPanel();
localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N
localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N
localFileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.dialogTitle")); // NOI18N
localFileChooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_AND_DIRECTORIES);
+ setLayout(new java.awt.GridBagLayout());
+
org.openide.awt.Mnemonics.setLocalizedText(selectButton, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectButton.text")); // NOI18N
selectButton.setToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectButton.toolTipText")); // NOI18N
selectButton.setActionCommand(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectButton.actionCommand")); // NOI18N
@@ -100,6 +109,29 @@ final class LocalFilesPanel extends javax.swing.JPanel {
selectButtonActionPerformed(evt);
}
});
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
+ add(selectButton, gridBagConstraints);
+
+ org.openide.awt.Mnemonics.setLocalizedText(deleteButon, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.deleteButon.text")); // NOI18N
+ deleteButon.setMaximumSize(new java.awt.Dimension(70, 23));
+ deleteButon.setMinimumSize(new java.awt.Dimension(70, 23));
+ deleteButon.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ deleteButonActionPerformed(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
+ add(deleteButon, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(clearButton, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.clearButton.text")); // NOI18N
clearButton.setToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.clearButton.toolTipText")); // NOI18N
@@ -111,14 +143,30 @@ final class LocalFilesPanel extends javax.swing.JPanel {
clearButtonActionPerformed(evt);
}
});
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 2;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
+ add(clearButton, gridBagConstraints);
- selectedPathsScrollPane.setPreferredSize(new java.awt.Dimension(379, 96));
+ fileListScrollpane.setMaximumSize(new java.awt.Dimension(32767, 100));
+ fileListScrollpane.setMinimumSize(new java.awt.Dimension(100, 100));
+ fileListScrollpane.setPreferredSize(new java.awt.Dimension(258, 100));
- selectedPaths.setEditable(false);
- selectedPaths.setColumns(20);
- selectedPaths.setRows(5);
- selectedPaths.setToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectedPaths.toolTipText")); // NOI18N
- selectedPathsScrollPane.setViewportView(selectedPaths);
+ fileListScrollpane.setViewportView(fileList);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridheight = 3;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0);
+ add(fileListScrollpane, gridBagConstraints);
+
+ displayNamePanel.setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(changeNameButton, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.changeNameButton.text")); // NOI18N
changeNameButton.addActionListener(new java.awt.event.ActionListener() {
@@ -126,121 +174,127 @@ final class LocalFilesPanel extends javax.swing.JPanel {
changeNameButtonActionPerformed(evt);
}
});
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
+ displayNamePanel.add(changeNameButton, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(displayNameLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.displayNameLabel.text")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ displayNamePanel.add(displayNameLabel, gridBagConstraints);
- org.openide.awt.Mnemonics.setLocalizedText(timestampToIncludeLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.timestampToIncludeLabel.text")); // NOI18N
+ padding.setMinimumSize(new java.awt.Dimension(0, 0));
+ padding.setPreferredSize(new java.awt.Dimension(0, 0));
- org.openide.awt.Mnemonics.setLocalizedText(createTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.createTimeCheckBox.text")); // NOI18N
- createTimeCheckBox.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- createTimeCheckBoxActionPerformed(evt);
- }
- });
+ javax.swing.GroupLayout paddingLayout = new javax.swing.GroupLayout(padding);
+ padding.setLayout(paddingLayout);
+ paddingLayout.setHorizontalGroup(
+ paddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 0, Short.MAX_VALUE)
+ );
+ paddingLayout.setVerticalGroup(
+ paddingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 0, Short.MAX_VALUE)
+ );
- org.openide.awt.Mnemonics.setLocalizedText(accessTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.accessTimeCheckBox.text")); // NOI18N
- accessTimeCheckBox.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- accessTimeCheckBoxActionPerformed(evt);
- }
- });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 2;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.weightx = 1.0;
+ displayNamePanel.add(padding, gridBagConstraints);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 3;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
+ add(displayNamePanel, gridBagConstraints);
+
+ org.openide.awt.Mnemonics.setLocalizedText(timeStampToIncludeLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.timeStampToIncludeLabel.text")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 4;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
+ add(timeStampToIncludeLabel, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(modifiedTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.modifiedTimeCheckBox.text")); // NOI18N
- modifiedTimeCheckBox.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- modifiedTimeCheckBoxActionPerformed(evt);
- }
- });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 5;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 15, 5, 5);
+ add(modifiedTimeCheckBox, gridBagConstraints);
- org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.jLabel2.text")); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(createTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.createTimeCheckBox.text")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 6;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 15, 5, 5);
+ add(createTimeCheckBox, gridBagConstraints);
- javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
- jPanel1.setLayout(jPanel1Layout);
- jPanel1Layout.setHorizontalGroup(
- jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addContainerGap()
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
- .addComponent(selectedPathsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
- .addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- .addGap(2, 2, 2))
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addComponent(timestampToIncludeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addContainerGap())
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addComponent(displayNameLabel)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(changeNameButton)
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addGap(23, 23, 23)
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(modifiedTimeCheckBox)
- .addComponent(accessTimeCheckBox)
- .addComponent(createTimeCheckBox)))
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addContainerGap()
- .addComponent(jLabel2)))
- .addGap(0, 0, Short.MAX_VALUE))
- );
+ org.openide.awt.Mnemonics.setLocalizedText(accessTimeCheckBox, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.accessTimeCheckBox.text")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 7;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 15, 5, 5);
+ add(accessTimeCheckBox, gridBagConstraints);
- jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {clearButton, selectButton});
-
- jPanel1Layout.setVerticalGroup(
- jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addGap(0, 0, 0)
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(36, 36, 36)
- .addComponent(clearButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addComponent(selectedPathsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(changeNameButton)
- .addComponent(displayNameLabel))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(timestampToIncludeLabel)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(modifiedTimeCheckBox)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(createTimeCheckBox)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(accessTimeCheckBox)
- .addGap(18, 18, 18)
- .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addContainerGap(17, Short.MAX_VALUE))
- );
+ org.openide.awt.Mnemonics.setLocalizedText(timeStampNoteLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.timeStampNoteLabel.text")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 8;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(10, 5, 5, 5);
+ add(timeStampNoteLabel, gridBagConstraints);
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 9;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
+ add(errorLabel, gridBagConstraints);
- javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
- this.setLayout(layout);
- layout.setHorizontalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addContainerGap())
- .addGroup(layout.createSequentialGroup()
- .addContainerGap()
- .addComponent(errorLabel)
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ paddingBottom.setMinimumSize(new java.awt.Dimension(0, 0));
+
+ javax.swing.GroupLayout paddingBottomLayout = new javax.swing.GroupLayout(paddingBottom);
+ paddingBottom.setLayout(paddingBottomLayout);
+ paddingBottomLayout.setHorizontalGroup(
+ paddingBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 0, Short.MAX_VALUE)
);
- layout.setVerticalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
- .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(errorLabel))
+ paddingBottomLayout.setVerticalGroup(
+ paddingBottomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 0, Short.MAX_VALUE)
);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 10;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
+ gridBagConstraints.weighty = 1.0;
+ add(paddingBottom, gridBagConstraints);
}// //GEN-END:initComponents
private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed
@@ -248,20 +302,10 @@ final class LocalFilesPanel extends javax.swing.JPanel {
if (returnVal == JFileChooser.APPROVE_OPTION) {
File[] files = localFileChooser.getSelectedFiles();
- StringBuilder allPaths = new StringBuilder();
- for (File f : files) {
- currentFiles.add(f);
- }
- for (File f : currentFiles) {
- //loop over set of all files to ensure list is accurate
- //update label
- allPaths.append(f.getAbsolutePath()).append("\n");
- }
- this.selectedPaths.setText(allPaths.toString());
- this.selectedPaths.setToolTipText(allPaths.toString());
+ this.listModel.add(files);
}
- enableNext = !currentFiles.isEmpty();
+ enableNext = !this.listModel.getFiles().isEmpty();
try {
firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
@@ -285,24 +329,32 @@ final class LocalFilesPanel extends javax.swing.JPanel {
}
}//GEN-LAST:event_changeNameButtonActionPerformed
- private void createTimeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createTimeCheckBoxActionPerformed
-
- }//GEN-LAST:event_createTimeCheckBoxActionPerformed
+ private void deleteButonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButonActionPerformed
+ int minIdx = this.fileList.getMinSelectionIndex();
+ int maxIdx = this.fileList.getMaxSelectionIndex();
- private void accessTimeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accessTimeCheckBoxActionPerformed
+ if (minIdx >= 0 && maxIdx >= minIdx) {
+ this.listModel.remove(minIdx, maxIdx);
+ }
+ this.fileList.clearSelection();
- }//GEN-LAST:event_accessTimeCheckBoxActionPerformed
+ enableNext = !this.listModel.getFiles().isEmpty();
- private void modifiedTimeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_modifiedTimeCheckBoxActionPerformed
-
- }//GEN-LAST:event_modifiedTimeCheckBoxActionPerformed
+ try {
+ firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "LocalFilesPanel listener threw exception", e); //NON-NLS
+ MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "LocalFilesPanel.moduleErr"),
+ NbBundle.getMessage(this.getClass(), "LocalFilesPanel.moduleErr.msg"),
+ MessageNotifyUtil.MessageType.ERROR);
+ }
+ }//GEN-LAST:event_deleteButonActionPerformed
/**
* Clear the fields and undo any selection of files.
*/
void reset() {
- currentFiles.clear();
- selectedPaths.setText("");
+ this.listModel.clear();
enableNext = false;
errorLabel.setVisible(false);
displayName = "";
@@ -316,20 +368,17 @@ final class LocalFilesPanel extends javax.swing.JPanel {
MessageNotifyUtil.MessageType.ERROR);
}
}
+
/**
* Get the path(s) which have been selected on this panel
*
- * @return a List of Strings representing the path(s) for the selected files or directories
+ * @return a List of Strings representing the path(s) for the selected files
+ * or directories
*/
List getContentPaths() {
- List pathsList = new ArrayList<>();
- if (currentFiles == null) {
- return pathsList;
- }
- for (File f : currentFiles) {
- pathsList.add(f.getAbsolutePath());
- }
- return pathsList;
+ return this.listModel.getFiles().stream()
+ .map(File::getAbsolutePath)
+ .collect(Collectors.toList());
}
/**
@@ -409,20 +458,104 @@ final class LocalFilesPanel extends javax.swing.JPanel {
return this.displayName;
}
+ /**
+ * A record of a file for the specific purposes of displaying in a JList
+ * (with toString).
+ */
+ private static class FileRecord {
+
+ private final File file;
+
+ FileRecord(File file) {
+ this.file = file;
+ }
+
+ @Override
+ public String toString() {
+ return file == null ? "" : file.getAbsolutePath();
+ }
+
+ /**
+ * @return The underlying file.
+ */
+ File getFile() {
+ return file;
+ }
+ }
+
+ /**
+ * JListModel for displaying files.
+ */
+ private static class LocalFilesModel extends AbstractListModel {
+
+ private List items = Collections.emptyList();
+
+ @Override
+ public int getSize() {
+ return items.size();
+ }
+
+ @Override
+ public FileRecord getElementAt(int index) {
+ File f = items.get(index);
+ return new FileRecord(f);
+ }
+
+ /**
+ * Adds a series of files to the list model.
+ *
+ * @param files The files.
+ */
+ void add(File... files) {
+ items = Stream.concat(items.stream(), Stream.of(files))
+ .sorted(Comparator.comparing(f -> f.getAbsolutePath().toLowerCase()))
+ .distinct()
+ .collect(Collectors.toList());
+
+ this.fireContentsChanged(this, 0, items.size() - 1);
+ }
+
+ /**
+ * Removes files in the list starting at minIdx going to maxIdx.
+ *
+ * @param minIdx The minimum index of items to be removed.
+ * @param maxIdx The maximum index to be removed.
+ */
+ void remove(int minIdx, int maxIdx) {
+ for (int i = maxIdx; i >= minIdx; i--) {
+ items.remove(i);
+ }
+ this.fireContentsChanged(this, 0, items.size() - 1);
+ }
+
+ /**
+ * @return The files to be added to the local files data source.
+ */
+ List getFiles() {
+ return items;
+ }
+
+ /**
+ * Clears currently tracked local files.
+ */
+ void clear() {
+ items.clear();
+ this.fireContentsChanged(this, 0, 0);
+ }
+
+ }
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox accessTimeCheckBox;
private javax.swing.JButton changeNameButton;
private javax.swing.JButton clearButton;
private javax.swing.JCheckBox createTimeCheckBox;
+ private javax.swing.JButton deleteButon;
private javax.swing.JLabel displayNameLabel;
private javax.swing.JLabel errorLabel;
- private javax.swing.JLabel jLabel2;
- private javax.swing.JPanel jPanel1;
+ private javax.swing.JList fileList;
private javax.swing.JFileChooser localFileChooser;
private javax.swing.JCheckBox modifiedTimeCheckBox;
private javax.swing.JButton selectButton;
- private javax.swing.JTextArea selectedPaths;
- private javax.swing.JScrollPane selectedPathsScrollPane;
- private javax.swing.JLabel timestampToIncludeLabel;
// End of variables declaration//GEN-END:variables
}
diff --git a/docs/doxygen-user/images/keyword-search-bar.PNG b/docs/doxygen-user/images/keyword-search-bar.PNG
index e0d18b0639..677471f5e1 100644
Binary files a/docs/doxygen-user/images/keyword-search-bar.PNG and b/docs/doxygen-user/images/keyword-search-bar.PNG differ
diff --git a/docs/doxygen-user/images/keyword-search-hits.PNG b/docs/doxygen-user/images/keyword-search-hits.PNG
index 6a5617c4ac..525feea875 100644
Binary files a/docs/doxygen-user/images/keyword-search-hits.PNG and b/docs/doxygen-user/images/keyword-search-hits.PNG differ
diff --git a/docs/doxygen-user/images/keyword-search-ocr-indexed-text.png b/docs/doxygen-user/images/keyword-search-ocr-indexed-text.png
index 4b146c00b4..a40b814ee4 100644
Binary files a/docs/doxygen-user/images/keyword-search-ocr-indexed-text.png and b/docs/doxygen-user/images/keyword-search-ocr-indexed-text.png differ
diff --git a/docs/doxygen-user/images/keyword_results.PNG b/docs/doxygen-user/images/keyword_results.PNG
index e6f270ca3f..34fac12cd1 100644
Binary files a/docs/doxygen-user/images/keyword_results.PNG and b/docs/doxygen-user/images/keyword_results.PNG differ
diff --git a/docs/doxygen-user/keyword_search.dox b/docs/doxygen-user/keyword_search.dox
index 8e3ca972ca..ab7ea306cd 100644
--- a/docs/doxygen-user/keyword_search.dox
+++ b/docs/doxygen-user/keyword_search.dox
@@ -90,7 +90,7 @@ The following shows a sample image containing text:
\image html keyword-search-ocr-image.png
-The "Indexed Text" tab shows the results when running the keyword search module with the OCR option enabled. If we were to use Keyword Search to look for the word "forensics", this file would be a match.
+The "Extracted Text" tab shows the results when running the keyword search module with the OCR option enabled. If we were to use Keyword Search to look for the word "forensics", this file would be a match.
\image html keyword-search-ocr-indexed-text.png
@@ -119,7 +119,7 @@ The language files will now be supported when OCR is enabled in the Keyword Sear
The Keyword Search module will save the search results regardless whether the search is performed by the ingest process, or manually by the user. The saved results are available in the Directory Tree in the left hand side panel.
-The keyword results will appear in the tree under "Keyword Hits". Each keyword search term will display the number of matches, and can be expanded to show the matches. From here, clicking on one of the matches will show a list of files on the right side of the screen. Select a file and go to the Indexed Text tab to see exactly where the matches occurred in the file.
+The keyword results will appear in the tree under "Keyword Hits". Each keyword search term will display the number of matches, and can be expanded to show the matches. From here, clicking on one of the matches will show a list of files on the right side of the screen. Select a file and go to the "Extracted Text" tab to see exactly where the matches occurred in the file.
\image html keyword_results.PNG