mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Merge remote-tracking branch 'upstream/develop' into 6735-embedded-file-extractor-retries
This commit is contained in:
commit
30f89ee797
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Autopsy
|
||||
*
|
||||
* Copyright 2020 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* Abstract class to define methods expected of a list of artifacts in the
|
||||
* discovery details section.
|
||||
*/
|
||||
abstract class AbstractArtifactListPanel extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Add a listener to the table of artifacts to perform actions when an
|
||||
* artifact is selected.
|
||||
*
|
||||
* @param listener The listener to add to the table of artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract void addMouseListener(java.awt.event.MouseAdapter mouseListener);
|
||||
|
||||
/**
|
||||
* Display the specified JPopupMenu at the specified point.
|
||||
*
|
||||
* @param popupMenu The JPopupMenu to display.
|
||||
* @param point The point the menu should be displayed at.
|
||||
*/
|
||||
abstract void showPopupMenu(JPopupMenu popupMenu, Point point);
|
||||
|
||||
/**
|
||||
* The artifact which is currently selected, null if no artifact is
|
||||
* selected.
|
||||
*
|
||||
* @return The currently selected BlackboardArtifact or null if none is
|
||||
* selected.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract BlackboardArtifact getSelectedArtifact();
|
||||
|
||||
/**
|
||||
* Select the row at the specified point.
|
||||
*
|
||||
* @param point The point which if a row exists it should be selected.
|
||||
*
|
||||
* @return True if a row was selected, false if no row was selected.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract boolean selectAtPoint(Point point);
|
||||
|
||||
/**
|
||||
* Add the specified list of artifacts to the list of artifacts which should
|
||||
* be displayed.
|
||||
*
|
||||
* @param artifactList The list of artifacts to display.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract void addArtifacts(List<BlackboardArtifact> artifactList);
|
||||
|
||||
/**
|
||||
* Remove a listener from the table of artifacts.
|
||||
*
|
||||
* @param listener The listener to remove from the table of artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract void removeSelectionListener(ListSelectionListener listener);
|
||||
|
||||
/**
|
||||
* Add a listener to the table of artifacts to perform actions when an
|
||||
* artifact is selected.
|
||||
*
|
||||
* @param listener The listener to add to the table of artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract void addSelectionListener(ListSelectionListener listener);
|
||||
|
||||
/**
|
||||
* Select the first available artifact in the list if it is not empty to
|
||||
* populate the panel to the right.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract void selectFirst();
|
||||
|
||||
/**
|
||||
* Remove all artifacts from the list of artifacts displayed.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract void clearList();
|
||||
|
||||
/**
|
||||
* Whether the list of artifacts is empty.
|
||||
*
|
||||
* @return true if the list of artifacts is empty, false if there are
|
||||
* artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
abstract boolean isEmpty();
|
||||
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Autopsy
|
||||
*
|
||||
* Copyright 2020 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.DataModelActionsFactory;
|
||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.actionhelpers.ExtractActionHelper;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* MouseAdapter to display a context menu on the specified
|
||||
* AbstractArtifactListPanel when the user right clicks.
|
||||
*/
|
||||
class ArtifactMenuMouseAdapter extends java.awt.event.MouseAdapter {
|
||||
|
||||
private final AbstractArtifactListPanel listPanel;
|
||||
private static final Logger logger = Logger.getLogger(ArtifactMenuMouseAdapter.class.getName());
|
||||
|
||||
/**
|
||||
* Create a new ArtifactMenMouseAdapter.
|
||||
*
|
||||
* @param listPanel The panel which the menu should be in regards to.
|
||||
*/
|
||||
ArtifactMenuMouseAdapter(AbstractArtifactListPanel listPanel) {
|
||||
this.listPanel = listPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||
if (!evt.isPopupTrigger() && SwingUtilities.isRightMouseButton(evt) && listPanel != null && !listPanel.isEmpty()) {
|
||||
if (listPanel.selectAtPoint(evt.getPoint())) {
|
||||
showPopupMenu(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If an artifact is selected display a JPopupMenu which has available
|
||||
* actions.
|
||||
*
|
||||
* @param event The mouseEvent being responded to.
|
||||
*/
|
||||
private void showPopupMenu(java.awt.event.MouseEvent event) {
|
||||
BlackboardArtifact artifact = listPanel.getSelectedArtifact();
|
||||
if (artifact == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
JMenuItem[] items = getMenuItems(artifact);
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
for (JMenuItem menu : items) {
|
||||
if (menu != null) {
|
||||
popupMenu.add(menu);
|
||||
} else {
|
||||
popupMenu.add(new JSeparator());
|
||||
}
|
||||
}
|
||||
listPanel.showPopupMenu(popupMenu, event.getPoint());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to get source content of artifact with ID: " + artifact.getArtifactID(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of JMenuItems for the artifact. The list list may contain
|
||||
* nulls which should be removed or replaced with JSeparators.
|
||||
*
|
||||
* @param artifact The artifact to get menu items for.
|
||||
*
|
||||
* @return List of menu items.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private JMenuItem[] getMenuItems(BlackboardArtifact artifact) throws TskCoreException {
|
||||
List<JMenuItem> menuItems = new ArrayList<>();
|
||||
BlackboardAttribute pathIdAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID));
|
||||
long contentId;
|
||||
if (pathIdAttr != null) {
|
||||
contentId = pathIdAttr.getValueLong();
|
||||
} else {
|
||||
contentId = artifact.getObjectID();
|
||||
}
|
||||
Content content = artifact.getSleuthkitCase().getContentById(contentId);
|
||||
menuItems.addAll(getTimelineMenuItems(artifact));
|
||||
menuItems.addAll(getDataModelActionFactoryMenuItems(artifact, content));
|
||||
menuItems.add(DeleteFileContentTagAction.getInstance().getMenuForFiles(Arrays.asList((AbstractFile) content)));
|
||||
menuItems.add(DeleteFileBlackboardArtifactTagAction.getInstance().getMenuForArtifacts(Arrays.asList(artifact)));
|
||||
return menuItems.toArray(new JMenuItem[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Timeline Menu Items for this artifact.
|
||||
*
|
||||
* @param artifact The artifact to get menu items for.
|
||||
*
|
||||
* @return List of timeline menu items.
|
||||
*/
|
||||
private List<JMenuItem> getTimelineMenuItems(BlackboardArtifact artifact) {
|
||||
List<JMenuItem> menuItems = new ArrayList<>();
|
||||
//if this artifact has a time stamp add the action to view it in the timeline
|
||||
try {
|
||||
if (ViewArtifactInTimelineAction.hasSupportedTimeStamp(artifact)) {
|
||||
menuItems.add(new JMenuItem(new ViewArtifactInTimelineAction(artifact)));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error getting arttribute(s) from blackboard artifact %d.", artifact.getArtifactID()), ex); //NON-NLS
|
||||
}
|
||||
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the DateModelActionsFactory to get some of the basic actions for the
|
||||
* artifact. The advantage to using the DataModelActionsFactory is that the
|
||||
* menu items can be put in a consistent order with other parts of the UI.
|
||||
*
|
||||
* @param artifact The artifact to get menu items for.
|
||||
* @param content The file the artifact is in regards to.
|
||||
*
|
||||
* @return List of JMenuItems for the DataModelActionFactory actions.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ArtifactMenuMouseAdapter_ExternalViewer_label=Open in external viewer"
|
||||
})
|
||||
private List<JMenuItem> getDataModelActionFactoryMenuItems(BlackboardArtifact artifact, Content content) {
|
||||
List<JMenuItem> menuItems = new ArrayList<>();
|
||||
List<Action> actions = DataModelActionsFactory.getActions(content, true);
|
||||
for (Action action : actions) {
|
||||
if (action == null) {
|
||||
menuItems.add(null);
|
||||
} else if (action instanceof ExportCSVAction) {
|
||||
// Do nothing we don't need this menu item.
|
||||
} else if (action instanceof AddContentTagAction) {
|
||||
menuItems.add(((AddContentTagAction) action).getMenuForContent(Arrays.asList((AbstractFile) content)));
|
||||
} else if (action instanceof AddBlackboardArtifactTagAction) {
|
||||
menuItems.add(((AddBlackboardArtifactTagAction) action).getMenuForContent(Arrays.asList(artifact)));
|
||||
} else if (action instanceof ExternalViewerShortcutAction) {
|
||||
// Replace with an ExternalViewerAction
|
||||
ExternalViewerAction newAction = new ExternalViewerAction(Bundle.ArtifactMenuMouseAdapter_ExternalViewer_label(), new FileNode((AbstractFile) content));
|
||||
menuItems.add(new JMenuItem(newAction));
|
||||
} else if (action instanceof ExtractAction) {
|
||||
menuItems.add(new JMenuItem(new ExtractFileAction((AbstractFile) content)));
|
||||
} else {
|
||||
menuItems.add(new JMenuItem(action));
|
||||
}
|
||||
}
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* An action class for extracting the related file.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ArtifactMenuMouseAdapter_label=Extract Files"
|
||||
})
|
||||
private final class ExtractFileAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
final private AbstractFile file;
|
||||
|
||||
/**
|
||||
* Construct a new ExtractFileAction.
|
||||
*
|
||||
* @param file The AbstractFile to be extracted.
|
||||
*/
|
||||
private ExtractFileAction(AbstractFile file) {
|
||||
super(Bundle.ArtifactMenuMouseAdapter_label());
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ExtractActionHelper helper = new ExtractActionHelper();
|
||||
helper.extract(e, Arrays.asList(file));
|
||||
}
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="jTable1">
|
||||
<Component class="javax.swing.JTable" name="artifactsTable">
|
||||
<Properties>
|
||||
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
|
@ -18,10 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
@ -38,11 +39,11 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Panel to display list of artifacts for selected domain.
|
||||
*
|
||||
*/
|
||||
class ArtifactsListPanel extends JPanel {
|
||||
final class ArtifactsListPanel extends AbstractArtifactListPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final DomainArtifactTableModel tableModel;
|
||||
private static final Logger logger = Logger.getLogger(ArtifactsListPanel.class.getName());
|
||||
private final DomainArtifactTableModel tableModel;
|
||||
|
||||
/**
|
||||
* Creates new form ArtifactsListPanel.
|
||||
@ -53,68 +54,62 @@ class ArtifactsListPanel extends JPanel {
|
||||
ArtifactsListPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) {
|
||||
tableModel = new DomainArtifactTableModel(artifactType);
|
||||
initComponents();
|
||||
jTable1.getRowSorter().toggleSortOrder(0);
|
||||
jTable1.getRowSorter().toggleSortOrder(0);
|
||||
artifactsTable.getRowSorter().toggleSortOrder(0);
|
||||
artifactsTable.getRowSorter().toggleSortOrder(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener to the table of artifacts to perform actions when an
|
||||
* artifact is selected.
|
||||
*
|
||||
* @param listener The listener to add to the table of artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
void addMouseListener(java.awt.event.MouseAdapter mouseListener) {
|
||||
artifactsTable.addMouseListener(mouseListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
void showPopupMenu(JPopupMenu popupMenu, Point point) {
|
||||
popupMenu.show(artifactsTable, point.x, point.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
void addSelectionListener(ListSelectionListener listener) {
|
||||
jTable1.getSelectionModel().addListSelectionListener(listener);
|
||||
artifactsTable.getSelectionModel().addListSelectionListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener from the table of artifacts.
|
||||
*
|
||||
* @param listener The listener to remove from the table of artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
void removeListSelectionListener(ListSelectionListener listener) {
|
||||
jTable1.getSelectionModel().removeListSelectionListener(listener);
|
||||
@Override
|
||||
void removeSelectionListener(ListSelectionListener listener) {
|
||||
artifactsTable.getSelectionModel().removeListSelectionListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* The artifact which is currently selected, null if no artifact is
|
||||
* selected.
|
||||
*
|
||||
* @return The currently selected BlackboardArtifact or null if none is
|
||||
* selected.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
boolean selectAtPoint(Point point) {
|
||||
boolean pointSelected = false;
|
||||
int row = artifactsTable.rowAtPoint(point);
|
||||
if (row < artifactsTable.getRowCount() && row >= 0) {
|
||||
artifactsTable.clearSelection();
|
||||
artifactsTable.addRowSelectionInterval(row, row);
|
||||
pointSelected = true;
|
||||
}
|
||||
return pointSelected;
|
||||
}
|
||||
|
||||
@Override
|
||||
BlackboardArtifact getSelectedArtifact() {
|
||||
int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex();
|
||||
if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex() || jTable1.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) {
|
||||
int selectedIndex = artifactsTable.getSelectionModel().getLeadSelectionIndex();
|
||||
if (selectedIndex < artifactsTable.getSelectionModel().getMinSelectionIndex() || artifactsTable.getSelectionModel().getMaxSelectionIndex() < 0 || selectedIndex > artifactsTable.getSelectionModel().getMaxSelectionIndex()) {
|
||||
return null;
|
||||
}
|
||||
return tableModel.getArtifactByRow(jTable1.convertRowIndexToModel(selectedIndex));
|
||||
return tableModel.getArtifactByRow(artifactsTable.convertRowIndexToModel(selectedIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the list of artifacts is empty.
|
||||
*
|
||||
* @return true if the list of artifacts is empty, false if there are
|
||||
* artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
boolean isEmpty() {
|
||||
return tableModel.getRowCount() <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the first available artifact in the list if it is not empty to
|
||||
* populate the panel to the right.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
void selectFirst() {
|
||||
if (!isEmpty()) {
|
||||
jTable1.setRowSelectionInterval(0, 0);
|
||||
artifactsTable.setRowSelectionInterval(0, 0);
|
||||
} else {
|
||||
jTable1.clearSelection();
|
||||
artifactsTable.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,10 +120,11 @@ class ArtifactsListPanel extends JPanel {
|
||||
* @param artifactList The list of artifacts to display.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
void addArtifacts(List<BlackboardArtifact> artifactList) {
|
||||
tableModel.setContents(artifactList);
|
||||
jTable1.validate();
|
||||
jTable1.repaint();
|
||||
artifactsTable.validate();
|
||||
artifactsTable.repaint();
|
||||
tableModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
@ -136,7 +132,8 @@ class ArtifactsListPanel extends JPanel {
|
||||
* Remove all artifacts from the list of artifacts displayed.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
void clearArtifacts() {
|
||||
@Override
|
||||
void clearList() {
|
||||
tableModel.setContents(new ArrayList<>());
|
||||
tableModel.fireTableDataChanged();
|
||||
}
|
||||
@ -150,19 +147,18 @@ class ArtifactsListPanel extends JPanel {
|
||||
private void initComponents() {
|
||||
|
||||
javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
|
||||
jTable1 = new javax.swing.JTable();
|
||||
artifactsTable = new javax.swing.JTable();
|
||||
|
||||
setOpaque(false);
|
||||
setPreferredSize(new java.awt.Dimension(300, 0));
|
||||
|
||||
jScrollPane1.setBorder(null);
|
||||
jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 0));
|
||||
jScrollPane1.setPreferredSize(new java.awt.Dimension(0, 0));
|
||||
|
||||
jTable1.setAutoCreateRowSorter(true);
|
||||
jTable1.setModel(tableModel);
|
||||
jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
jScrollPane1.setViewportView(jTable1);
|
||||
artifactsTable.setAutoCreateRowSorter(true);
|
||||
artifactsTable.setModel(tableModel);
|
||||
artifactsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
jScrollPane1.setViewportView(artifactsTable);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
@ -172,7 +168,7 @@ class ArtifactsListPanel extends JPanel {
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 607, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -204,7 +200,7 @@ class ArtifactsListPanel extends JPanel {
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
void setContents(List<BlackboardArtifact> artifacts) {
|
||||
jTable1.clearSelection();
|
||||
artifactsTable.clearSelection();
|
||||
artifactList.clear();
|
||||
artifactList.addAll(artifacts);
|
||||
}
|
||||
@ -347,6 +343,6 @@ class ArtifactsListPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTable jTable1;
|
||||
private javax.swing.JTable artifactsTable;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
ArtifactMenuMouseAdapter_ExternalViewer_label=Open in external viewer
|
||||
ArtifactMenuMouseAdapter_label=Extract Files
|
||||
ArtifactsListPanel.dateColumn.name=Date/Time
|
||||
ArtifactsListPanel.fileNameColumn.name=Name
|
||||
ArtifactsListPanel.mimeTypeColumn.name=MIME Type
|
||||
|
@ -27,6 +27,7 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
||||
@ -100,6 +101,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
||||
}
|
||||
});
|
||||
rightSplitPane.setTopComponent(resultsPanel);
|
||||
rightSplitPane.setBottomComponent(new JPanel());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,6 +63,7 @@ final class DomainArtifactsTabPanel extends JPanel {
|
||||
initComponents();
|
||||
this.artifactType = type;
|
||||
listPanel = new ArtifactsListPanel(artifactType);
|
||||
listPanel.addMouseListener(new ArtifactMenuMouseAdapter(listPanel));
|
||||
jSplitPane1.setLeftComponent(listPanel);
|
||||
setRightComponent();
|
||||
listPanel.addSelectionListener(listener);
|
||||
@ -113,7 +114,7 @@ final class DomainArtifactsTabPanel extends JPanel {
|
||||
void setStatus(ArtifactRetrievalStatus status) {
|
||||
this.status = status;
|
||||
if (status == ArtifactRetrievalStatus.UNPOPULATED) {
|
||||
listPanel.clearArtifacts();
|
||||
listPanel.clearList();
|
||||
if (rightPanel != null){
|
||||
rightPanel.setArtifact(null);
|
||||
}
|
||||
@ -131,7 +132,7 @@ final class DomainArtifactsTabPanel extends JPanel {
|
||||
void handleArtifactSearchResultEvent(DiscoveryEventUtils.ArtifactSearchResultEvent artifactresultEvent) {
|
||||
if (artifactType == artifactresultEvent.getArtifactType()) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
listPanel.removeListSelectionListener(listener);
|
||||
listPanel.removeSelectionListener(listener);
|
||||
listPanel.addArtifacts(artifactresultEvent.getListOfArtifacts());
|
||||
status = ArtifactRetrievalStatus.POPULATED;
|
||||
setEnabled(!listPanel.isEmpty());
|
||||
|
@ -18,10 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@ -36,7 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
/**
|
||||
* Panel to display list of artifacts types and descriptions.
|
||||
*/
|
||||
class MiniTimelineArtifactListPanel extends JPanel {
|
||||
class MiniTimelineArtifactListPanel extends AbstractArtifactListPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final TypeDescriptionTableModel tableModel;
|
||||
@ -53,91 +54,76 @@ class MiniTimelineArtifactListPanel extends JPanel {
|
||||
MiniTimelineArtifactListPanel() {
|
||||
tableModel = new TypeDescriptionTableModel();
|
||||
initComponents();
|
||||
jTable1.getRowSorter().toggleSortOrder(0);
|
||||
jTable1.getRowSorter().toggleSortOrder(0);
|
||||
artifactsTable.getRowSorter().toggleSortOrder(0);
|
||||
artifactsTable.getRowSorter().toggleSortOrder(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener to the table of artifacts to perform actions when a
|
||||
* artifact is selected.
|
||||
*
|
||||
* @param listener The listener to add to the table of artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
void addMouseListener(java.awt.event.MouseAdapter mouseListener) {
|
||||
artifactsTable.addMouseListener(mouseListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
void showPopupMenu(JPopupMenu popupMenu, Point point) {
|
||||
popupMenu.show(artifactsTable, point.x, point.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
void addSelectionListener(ListSelectionListener listener) {
|
||||
jTable1.getSelectionModel().addListSelectionListener(listener);
|
||||
artifactsTable.getSelectionModel().addListSelectionListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener from the table of artifacts.
|
||||
*
|
||||
* @param listener The listener to remove from the table of artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
void removeListSelectionListener(ListSelectionListener listener) {
|
||||
jTable1.getSelectionModel().removeListSelectionListener(listener);
|
||||
@Override
|
||||
void removeSelectionListener(ListSelectionListener listener) {
|
||||
artifactsTable.getSelectionModel().removeListSelectionListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the list of artifacts is empty.
|
||||
*
|
||||
* @return True if the list of artifacts is empty, false if there are
|
||||
* artifacts.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
boolean isEmpty() {
|
||||
return tableModel.getRowCount() <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the first available artifact in the list if it is not empty to
|
||||
* populate the list to the right.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
void selectFirst() {
|
||||
if (!isEmpty()) {
|
||||
jTable1.setRowSelectionInterval(0, 0);
|
||||
artifactsTable.setRowSelectionInterval(0, 0);
|
||||
} else {
|
||||
jTable1.clearSelection();
|
||||
artifactsTable.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The artifact which is currently selected, null if no artifact is
|
||||
* selected.
|
||||
*
|
||||
* @return The currently selected BlackboardArtifact or null if none is
|
||||
* selected.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
boolean selectAtPoint(Point point) {
|
||||
boolean pointSelected = false;
|
||||
int row = artifactsTable.rowAtPoint(point);
|
||||
artifactsTable.clearSelection();
|
||||
if (row < artifactsTable.getRowCount() && row >= 0) {
|
||||
artifactsTable.addRowSelectionInterval(row, row);
|
||||
pointSelected = true;
|
||||
}
|
||||
return pointSelected;
|
||||
}
|
||||
|
||||
@Override
|
||||
BlackboardArtifact getSelectedArtifact() {
|
||||
int selectedIndex = jTable1.getSelectionModel().getLeadSelectionIndex();
|
||||
if (selectedIndex < jTable1.getSelectionModel().getMinSelectionIndex()
|
||||
|| jTable1.getSelectionModel().getMaxSelectionIndex() < 0
|
||||
|| selectedIndex > jTable1.getSelectionModel().getMaxSelectionIndex()) {
|
||||
int selectedIndex = artifactsTable.getSelectionModel().getLeadSelectionIndex();
|
||||
if (selectedIndex < artifactsTable.getSelectionModel().getMinSelectionIndex()
|
||||
|| artifactsTable.getSelectionModel().getMaxSelectionIndex() < 0
|
||||
|| selectedIndex > artifactsTable.getSelectionModel().getMaxSelectionIndex()) {
|
||||
return null;
|
||||
}
|
||||
return tableModel.getArtifactByRow(jTable1.convertRowIndexToModel(selectedIndex));
|
||||
return tableModel.getArtifactByRow(artifactsTable.convertRowIndexToModel(selectedIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified list of artifacts to the list of artifacts which should
|
||||
* be displayed.
|
||||
*
|
||||
* @param artifacttList The list of artifacts to display.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
void addArtifacts(List<BlackboardArtifact> artifacttList) {
|
||||
tableModel.setContents(artifacttList);
|
||||
jTable1.validate();
|
||||
jTable1.repaint();
|
||||
@Override
|
||||
void addArtifacts(List<BlackboardArtifact> artifactList) {
|
||||
tableModel.setContents(artifactList);
|
||||
artifactsTable.validate();
|
||||
artifactsTable.repaint();
|
||||
tableModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all artifacts from the list of artifacts displayed.
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
@Override
|
||||
void clearList() {
|
||||
tableModel.setContents(new ArrayList<>());
|
||||
tableModel.fireTableDataChanged();
|
||||
@ -149,7 +135,7 @@ class MiniTimelineArtifactListPanel extends JPanel {
|
||||
private void initComponents() {
|
||||
//This class is a refactored copy of ArtifactsListPanel so lacks the form however the init method still constructs the proper UI elements.
|
||||
javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
|
||||
jTable1 = new javax.swing.JTable();
|
||||
artifactsTable = new javax.swing.JTable();
|
||||
|
||||
setOpaque(false);
|
||||
setPreferredSize(new java.awt.Dimension(300, 0));
|
||||
@ -157,10 +143,10 @@ class MiniTimelineArtifactListPanel extends JPanel {
|
||||
jScrollPane1.setBorder(null);
|
||||
jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 0));
|
||||
|
||||
jTable1.setAutoCreateRowSorter(true);
|
||||
jTable1.setModel(tableModel);
|
||||
jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
jScrollPane1.setViewportView(jTable1);
|
||||
artifactsTable.setAutoCreateRowSorter(true);
|
||||
artifactsTable.setModel(tableModel);
|
||||
artifactsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
jScrollPane1.setViewportView(artifactsTable);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
@ -191,7 +177,7 @@ class MiniTimelineArtifactListPanel extends JPanel {
|
||||
*/
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
void setContents(List<BlackboardArtifact> artifactList) {
|
||||
jTable1.clearSelection();
|
||||
artifactsTable.clearSelection();
|
||||
this.artifactList.clear();
|
||||
this.artifactList.addAll(artifactList);
|
||||
}
|
||||
@ -266,6 +252,6 @@ class MiniTimelineArtifactListPanel extends JPanel {
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTable jTable1;
|
||||
private javax.swing.JTable artifactsTable;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ class MiniTimelinePanel extends javax.swing.JPanel {
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
MiniTimelinePanel() {
|
||||
initComponents();
|
||||
artifactListPanel.addMouseListener(new ArtifactMenuMouseAdapter(artifactListPanel));
|
||||
artifactListener = new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent event) {
|
||||
@ -73,7 +74,7 @@ class MiniTimelinePanel extends javax.swing.JPanel {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent event) {
|
||||
if (!event.getValueIsAdjusting()) {
|
||||
artifactListPanel.removeListSelectionListener(artifactListener);
|
||||
artifactListPanel.removeSelectionListener(artifactListener);
|
||||
artifactListPanel.clearList();
|
||||
artifactListPanel.addArtifacts(dateListPanel.getArtifactsForSelectedDate());
|
||||
artifactListPanel.addSelectionListener(artifactListener);
|
||||
@ -127,7 +128,7 @@ class MiniTimelinePanel extends javax.swing.JPanel {
|
||||
void handleMiniTimelineResultEvent(DiscoveryEventUtils.MiniTimelineResultEvent miniTimelineResultEvent) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
dateListPanel.removeListSelectionListener(dateListener);
|
||||
artifactListPanel.removeListSelectionListener(artifactListener);
|
||||
artifactListPanel.removeSelectionListener(artifactListener);
|
||||
dateListPanel.addArtifacts(miniTimelineResultEvent.getResultList());
|
||||
status = DomainArtifactsTabPanel.ArtifactRetrievalStatus.POPULATED;
|
||||
setEnabled(!dateListPanel.isEmpty());
|
||||
|
Loading…
x
Reference in New Issue
Block a user