3408 clean up comments and names for multi user case explorer changes

This commit is contained in:
William Schaefer 2018-01-10 12:30:07 -05:00
parent 80b77a0739
commit 9d4f6bb146
5 changed files with 81 additions and 100 deletions

View File

@ -24,7 +24,7 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents> <SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1"> <Container class="javax.swing.JScrollPane" name="caseTableScrollPane">
<Properties> <Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/> <Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">

View File

@ -39,44 +39,29 @@ import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerManager;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.EmptyNode; import org.sleuthkit.autopsy.datamodel.EmptyNode;
/** /**
* A Swing JPanel with a JTabbedPane child component. The tabbed pane contains * A Swing JPanel with a scroll pane child component. The scroll pane contain
* result viewers. * the table of cases.
* *
* The "main" DataResultPanel for the desktop application has a table viewer * Used to display a list of multi user cases and allow the user to open one of
* (DataResultViewerTable) and a thumbnail viewer (DataResultViewerThumbnail), * them.
* plus zero to many additional DataResultViewers, since the DataResultViewer
* interface is an extension point.
* *
* The "main" DataResultPanel resides in the "main" results view
* (DataResultTopComponent) that is normally docked into the upper right hand
* side of the main window of the desktop application.
*
* The result viewers in the "main panel" are used to view the child nodes of a
* node selected in the tree view (DirectoryTreeTopComponent) that is normally
* docked into the left hand side of the main window of the desktop application.
*
* Nodes selected in the child results viewers of a DataResultPanel are
* displayed in a content view (implementation of the DataContent interface)
* supplied the panel. The default content view is (DataContentTopComponent) is
* normally docked into the lower right hand side of the main window, underneath
* the results view. A custom content view may be specified instead.
*/ */
class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider { class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Outline outline; private final Outline outline;
private ExplorerManager em; private ExplorerManager em;
private final org.openide.explorer.view.OutlineView outlineView; private final org.openide.explorer.view.OutlineView outlineView;
private int originalPathColumnIndex = 0; private int originalPathColumnIndex = 0;
private static final Logger LOGGER = Logger.getLogger(CaseBrowser.class.getName()); private static final Logger LOGGER = Logger.getLogger(CaseBrowser.class.getName());
private LoadCaseListWorker tableWorker; private LoadCaseMapWorker tableWorker;
@Override @Override
public ExplorerManager getExplorerManager() { public ExplorerManager getExplorerManager() {
@ -84,7 +69,7 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
} }
/** /**
* Creates new form CaseBrowser * Creates a new CaseBrowser
*/ */
CaseBrowser() { CaseBrowser() {
outlineView = new org.openide.explorer.view.OutlineView(); outlineView = new org.openide.explorer.view.OutlineView();
@ -99,6 +84,9 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
} }
/**
* Configures the the table of cases and its columns.
*/
private void customize() { private void customize() {
TableColumnModel columnModel = outline.getColumnModel(); TableColumnModel columnModel = outline.getColumnModel();
int dateColumnIndex = 0; int dateColumnIndex = 0;
@ -116,25 +104,20 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name());
outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
outline.setColumnSorted(dateColumnIndex, false, 1); //it would be nice if the column index wasn't hardcoded outline.setColumnSorted(dateColumnIndex, false, 1); //it would be nice if the column index wasn't hardcoded
}
/**
* Initializes this panel. Intended to be called by a parent top component
* when the top component is opened.
*/
void open() {
if (null == em) { if (null == em) {
em = new ExplorerManager(); em = new ExplorerManager();
} }
jScrollPane1.setViewportView(outlineView); caseTableScrollPane.setViewportView(outlineView);
setColumnWidths(); setColumnWidths();
this.setVisible(true); this.setVisible(true);
outline.setRowSelectionAllowed(false);
} }
void setRowSelectionAllowed(boolean allowed) { /**
outline.setRowSelectionAllowed(allowed); * Add a listener to changes in case selections in the table
} *
* @param listener the ListSelectionListener to add
*/
void addListSelectionListener(ListSelectionListener listener) { void addListSelectionListener(ListSelectionListener listener) {
outline.getSelectionModel().addListSelectionListener(listener); outline.getSelectionModel().addListSelectionListener(listener);
} }
@ -145,12 +128,17 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
try { try {
return ((Node.Property) outline.getModel().getValueAt(outline.convertRowIndexToModel(selectedRows[0]), originalPathColumnIndex)).getValue().toString(); return ((Node.Property) outline.getModel().getValueAt(outline.convertRowIndexToModel(selectedRows[0]), originalPathColumnIndex)).getValue().toString();
} catch (IllegalAccessException | InvocationTargetException ex) { } catch (IllegalAccessException | InvocationTargetException ex) {
System.out.println("THROW"); //WJS-TODO THROW SOMETHING
} }
} }
return null; return null;
} }
/**
* Check if a row could be and is selected.
*
* @return true if a row is selected, false if no row is selected
*/
boolean isRowSelected() { boolean isRowSelected() {
return outline.getRowSelectionAllowed() && outline.getSelectedRows().length > 0; return outline.getRowSelectionAllowed() && outline.getSelectedRows().length > 0;
} }
@ -162,8 +150,8 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
final int rows = Math.min(100, outline.getRowCount()); final int rows = Math.min(100, outline.getRowCount());
for (int column = 0; column < outline.getColumnModel().getColumnCount(); column++) { for (int column = 0; column < outline.getColumnModel().getColumnCount(); column++) {
int columnWidthLimit = 800; int columnWidthLimit = 2000;
int columnWidth = 0; int columnWidth = 200;
// find the maximum width needed to fit the values for the first 100 rows, at most // find the maximum width needed to fit the values for the first 100 rows, at most
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {
@ -179,18 +167,19 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
} }
} }
@NbBundle.Messages({"CaseBrowser.caseListLoading.message=Please Wait..."})
/** /**
* Gets the list of cases known to the review mode cases manager and * Gets the list of cases known to the review mode cases manager and
* refreshes the cases table. * refreshes the cases table.
*/ */
void refresh() { void refresh() {
if (tableWorker == null || tableWorker.isDone()) { if (tableWorker == null || tableWorker.isDone()) {
setRowSelectionAllowed(false); outline.setRowSelectionAllowed(false);
//create a new TableWorker to and execute it in a background thread if one is not currently working //create a new TableWorker to and execute it in a background thread if one is not currently working
//set the table to display text informing the user that the list is being retreived and disable case selection //set the table to display text informing the user that the list is being retreived and disable case selection
EmptyNode emptyNode = new EmptyNode(Bundle.MultiUserCasesPanel_caseListLoading_message()); EmptyNode emptyNode = new EmptyNode(Bundle.CaseBrowser_caseListLoading_message());
em.setRootContext(emptyNode); em.setRootContext(emptyNode);
tableWorker = new LoadCaseListWorker(); tableWorker = new LoadCaseMapWorker();
tableWorker.execute(); tableWorker.execute();
} }
@ -205,22 +194,27 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane(); caseTableScrollPane = new javax.swing.JScrollPane();
setMinimumSize(new java.awt.Dimension(0, 5)); setMinimumSize(new java.awt.Dimension(0, 5));
setPreferredSize(new java.awt.Dimension(5, 5)); setPreferredSize(new java.awt.Dimension(5, 5));
setLayout(new java.awt.BorderLayout()); setLayout(new java.awt.BorderLayout());
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); caseTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 5)); caseTableScrollPane.setMinimumSize(new java.awt.Dimension(0, 5));
jScrollPane1.setOpaque(false); caseTableScrollPane.setOpaque(false);
jScrollPane1.setPreferredSize(new java.awt.Dimension(5, 5)); caseTableScrollPane.setPreferredSize(new java.awt.Dimension(5, 5));
add(jScrollPane1, java.awt.BorderLayout.CENTER); add(caseTableScrollPane, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane caseTableScrollPane;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
private class LoadCaseListWorker extends SwingWorker<Void, Void> {
/**
* Swingworker to fetch the updated map of cases and their status in a
* background thread
*/
private class LoadCaseMapWorker extends SwingWorker<Void, Void> {
private static final String ALERT_FILE_NAME = "autoingest.alert"; private static final String ALERT_FILE_NAME = "autoingest.alert";
private Map<CaseMetadata, Boolean> cases; private Map<CaseMetadata, Boolean> cases;
@ -314,11 +308,11 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider
@Override @Override
protected void done() { protected void done() {
EventQueue.invokeLater(() -> { EventQueue.invokeLater(() -> {
CaseNode caseListNode = new CaseNode(cases); MultiUserNode caseListNode = new MultiUserNode(cases);
em.setRootContext(caseListNode); em.setRootContext(caseListNode);
setRowSelectionAllowed(true); setColumnWidths();
outline.setRowSelectionAllowed(true);
}); });
} }
} }

View File

@ -30,19 +30,18 @@ import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter; import javax.swing.table.TableRowSorter;
import org.openide.util.Lookup; import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/** /**
* A panel that allows a user to open cases created by auto ingest. * A panel that allows a user to open cases created by auto ingest.
*/ */
@NbBundle.Messages({"MultiUserCasesPanel.caseListLoading.message=Please Wait..."})
final class MultiUserCasesPanel extends JPanel{ final class MultiUserCasesPanel extends JPanel{
private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName());
private static final long serialVersionUID = 1L;
private final JDialog parentDialog; private final JDialog parentDialog;
private final CaseBrowser caseListPanel; private final CaseBrowser caseBrowserPanel;
/** /**
* Constructs a panel that allows a user to open cases created by automated * Constructs a panel that allows a user to open cases created by automated
@ -52,16 +51,14 @@ final class MultiUserCasesPanel extends JPanel{
this.parentDialog = parentDialog; this.parentDialog = parentDialog;
initComponents(); initComponents();
caseListPanel = new CaseBrowser(); caseBrowserPanel = new CaseBrowser();
caseListPanel.open(); caseExplorerScrollPane.add(caseBrowserPanel);
caseListPanel.setRowSelectionAllowed(false); caseExplorerScrollPane.setViewportView(caseBrowserPanel);
caseExplorerScrollPane.add(caseListPanel);
caseExplorerScrollPane.setViewportView(caseListPanel);
/* /*
* Listen for row selection changes and set button state for the current * Listen for row selection changes and set button state for the current
* selection. * selection.
*/ */
caseListPanel.addListSelectionListener((ListSelectionEvent e) -> { caseBrowserPanel.addListSelectionListener((ListSelectionEvent e) -> {
setButtons(); setButtons();
}); });
@ -72,7 +69,7 @@ final class MultiUserCasesPanel extends JPanel{
* refreshes the cases table. * refreshes the cases table.
*/ */
void refresh() { void refresh() {
caseListPanel.refresh(); caseBrowserPanel.refresh();
} }
/** /**
@ -80,7 +77,7 @@ final class MultiUserCasesPanel extends JPanel{
* in the cases table. * in the cases table.
*/ */
void setButtons() { void setButtons() {
bnOpen.setEnabled(caseListPanel.isRowSelected()); bnOpen.setEnabled(caseBrowserPanel.isRowSelected());
} }
/** /**
@ -229,7 +226,7 @@ final class MultiUserCasesPanel extends JPanel{
* @param evt -- The event that caused this to be called * @param evt -- The event that caused this to be called
*/ */
private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed
openCase(caseListPanel.getCasePath()); openCase(caseBrowserPanel.getCasePath());
}//GEN-LAST:event_bnOpenActionPerformed }//GEN-LAST:event_bnOpenActionPerformed
private void bnOpenSingleUserCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenSingleUserCaseActionPerformed private void bnOpenSingleUserCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenSingleUserCaseActionPerformed

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2017-2018 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");
@ -40,37 +40,31 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.autopsy.datamodel.NodeProperty;
/** /**
* Provides a root node for the results views with a single child node that * A root node containing child nodes of the multi user cases
* displays a message as the sole item in its property sheet, useful for
* displaying explanatory text in the result views when there is a node with no
* children in the tree view.
*/ */
public final class CaseNode extends AbstractNode { public final class MultiUserNode extends AbstractNode {
@Messages({"CaseNode.column.name=Name", @Messages({"CaseNode.column.name=Name",
"CaseNode.column.createdTime=Created Time", "CaseNode.column.createdTime=Created Time",
"CaseNode.column.status=Status", "CaseNode.column.status=Status",
"CaseNode.column.metadataFilePath=Path"}) "CaseNode.column.metadataFilePath=Path"})
private static final Logger LOGGER = Logger.getLogger(CaseNode.class.getName()); private static final Logger LOGGER = Logger.getLogger(MultiUserNode.class.getName());
/** /**
* Provides a root node for the results views with a single child node that * Provides a root node with children which each represent a case.
* displays a message as the sole item in its property sheet, useful for
* displaying explanatory text in the result views when there is a node with
* no children in the tree view.
* *
* @param displayedMessage The text for the property sheet of the child * @param caseMap the map of cases and a boolean indicating if they have an
* node. * alert
*/ */
CaseNode(Map<CaseMetadata, Boolean> caseList) { MultiUserNode(Map<CaseMetadata, Boolean> caseMap) {
super(Children.create(new CaseNodeChildren(caseList), true)); super(Children.create(new MultiUserNodeChildren(caseMap), true));
} }
static class CaseNodeChildren extends ChildFactory<Entry<CaseMetadata, Boolean>> { static class MultiUserNodeChildren extends ChildFactory<Entry<CaseMetadata, Boolean>> {
private final Map<CaseMetadata, Boolean> caseMap; private final Map<CaseMetadata, Boolean> caseMap;
CaseNodeChildren(Map<CaseMetadata, Boolean> caseMap) { MultiUserNodeChildren(Map<CaseMetadata, Boolean> caseMap) {
this.caseMap = caseMap; this.caseMap = caseMap;
} }
@ -84,31 +78,30 @@ public final class CaseNode extends AbstractNode {
@Override @Override
protected Node createNodeForKey(Entry<CaseMetadata, Boolean> key) { protected Node createNodeForKey(Entry<CaseMetadata, Boolean> key) {
return new CaseNameNode(key); return new MultiUserCaseNode(key);
} }
} }
/** /**
* The single child node of an EmptyNode, responsible for displaying a * A node which represents a single multi user case.
* message as the sole item in its property sheet.
*/ */
public static final class CaseNameNode extends DisplayableItemNode { public static final class MultiUserCaseNode extends DisplayableItemNode {
private final String caseName; private final String caseName;
private final String caseCreatedDate; private final String caseCreatedDate;
private final String caseMetadataFilePath; private final String caseMetadataFilePath;
private final boolean caseHasAlert; private final boolean caseHasAlert;
CaseNameNode(Entry<CaseMetadata, Boolean> userCase) { MultiUserCaseNode(Entry<CaseMetadata, Boolean> multiUserCase) {
super(Children.LEAF); super(Children.LEAF);
caseName = userCase.getKey().getCaseDisplayName(); caseName = multiUserCase.getKey().getCaseDisplayName();
caseCreatedDate = userCase.getKey().getCreatedDate(); caseCreatedDate = multiUserCase.getKey().getCreatedDate();
caseHasAlert = userCase.getValue(); caseHasAlert = multiUserCase.getValue();
super.setName(caseName); super.setName(caseName);
setName(caseName); setName(caseName);
setDisplayName(caseName); setDisplayName(caseName);
caseMetadataFilePath = userCase.getKey().getFilePath().toString(); caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString();
} }
@Override @Override
@ -152,14 +145,14 @@ public final class CaseNode extends AbstractNode {
@Override @Override
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
// actions.addAll(Arrays.asList(super.getActions(context))); actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); //open case context menu option
actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath));
return actions.toArray(new Action[actions.size()]); return actions.toArray(new Action[actions.size()]);
} }
} }
/** /**
* An action that opens the case node which it was generated off of * An action that opens the specified case and hides the multi user case
* panel.
*/ */
private static final class OpenMultiUserCaseAction extends AbstractAction { private static final class OpenMultiUserCaseAction extends AbstractAction {
@ -188,10 +181,7 @@ public final class CaseNode extends AbstractNode {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
//GUI changes done back on the EDT //GUI changes done back on the EDT
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}); MultiUserCasesDialog.getInstance().setVisible(true);
} finally {
SwingUtilities.invokeLater(() -> {
//GUI changes done back on the EDT
}); });
} }
} }

View File

@ -18,7 +18,7 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.casemodule.CaseNode; import org.sleuthkit.autopsy.casemodule.MultiUserNode;
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode;
import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode;
import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode;
@ -159,7 +159,7 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(EmptyNode.MessageNode emptyNode); T visit(EmptyNode.MessageNode emptyNode);
T visit(CaseNode.CaseNameNode caseNode); T visit(MultiUserNode.MultiUserCaseNode caseNode);
T visit(InterestingHits.InterestingItemTypeNode aThis); T visit(InterestingHits.InterestingItemTypeNode aThis);
@ -245,7 +245,7 @@ public interface DisplayableItemNodeVisitor<T> {
return defaultVisit(ftByMimeTypeEmptyNode); return defaultVisit(ftByMimeTypeEmptyNode);
} }
@Override @Override
public T visit(CaseNode.CaseNameNode caseNameNode) { public T visit(MultiUserNode.MultiUserCaseNode caseNameNode) {
return defaultVisit(caseNameNode); return defaultVisit(caseNameNode);
} }
@Override @Override