19 package org.sleuthkit.autopsy.datasourcesummary.ui;
22 import java.awt.EventQueue;
23 import java.beans.PropertyVetoException;
24 import javax.swing.ListSelectionModel;
25 import org.netbeans.swing.outline.DefaultOutlineModel;
26 import org.netbeans.swing.outline.Outline;
27 import org.openide.explorer.ExplorerManager;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
32 import java.util.Observer;
33 import java.util.logging.Level;
35 import javax.swing.event.ListSelectionListener;
36 import org.openide.nodes.Node;
40 import static javax.swing.SwingConstants.RIGHT;
41 import javax.swing.SwingUtilities;
42 import javax.swing.table.TableColumn;
53 final class DataSourceBrowser
extends javax.swing.JPanel implements ExplorerManager.Provider {
55 private static final long serialVersionUID = 1L;
56 private static final Logger logger = Logger.getLogger(DataSourceBrowser.class.getName());
57 private static final int COUNT_COLUMN_WIDTH = 20;
58 private static final int INGEST_STATUS_WIDTH = 50;
59 private static final int USAGE_COLUMN_WIDTH = 110;
60 private static final int DATA_SOURCE_COLUMN_WIDTH = 280;
61 private final Outline outline;
62 private final org.openide.explorer.view.OutlineView outlineView;
63 private final ExplorerManager explorerManager;
64 private final List<DataSourceSummary> dataSourceSummaryList;
65 private final RightAlignedTableCellRenderer rightAlignedRenderer =
new RightAlignedTableCellRenderer();
70 DataSourceBrowser(Map<Long, String> usageMap, Map<Long, Long> fileCountsMap) {
72 rightAlignedRenderer.setHorizontalAlignment(RIGHT);
73 explorerManager =
new ExplorerManager();
74 outlineView =
new org.openide.explorer.view.OutlineView();
75 this.setVisible(
true);
76 outlineView.setPropertyColumns(
77 Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(),
78 Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(),
79 Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(),
80 Bundle.DataSourceSummaryNode_column_results_header(), Bundle.DataSourceSummaryNode_column_results_header(),
81 Bundle.DataSourceSummaryNode_column_tags_header(), Bundle.DataSourceSummaryNode_column_tags_header());
82 outline = outlineView.getOutline();
84 outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
86 dataSourceSummaryList = getDataSourceSummaryList(usageMap, fileCountsMap);
87 outline.setRootVisible(
false);
88 add(outlineView, java.awt.BorderLayout.CENTER);
89 explorerManager.setRootContext(
new DataSourceSummaryNode(dataSourceSummaryList));
90 ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.DataSourceSummaryNode_column_dataSourceName_header());
91 for (TableColumn column : Collections.list(outline.getColumnModel().getColumns())) {
92 if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_files_header())
93 || column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_results_header())
94 || column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_tags_header())) {
95 column.setCellRenderer(rightAlignedRenderer);
96 column.setPreferredWidth(COUNT_COLUMN_WIDTH);
97 }
else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_type_header())) {
98 column.setPreferredWidth(USAGE_COLUMN_WIDTH);
99 }
else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_status_header())) {
100 column.setPreferredWidth(INGEST_STATUS_WIDTH);
102 column.setPreferredWidth(DATA_SOURCE_COLUMN_WIDTH);
105 this.setVisible(
true);
116 void selectDataSource(Long dataSourceId) {
117 EventQueue.invokeLater(() -> {
118 if (dataSourceId != null) {
119 for (Node node : explorerManager.getRootContext().getChildren().getNodes()) {
120 if (node instanceof DataSourceSummaryEntryNode && ((DataSourceSummaryEntryNode) node).getDataSource().getId() == dataSourceId) {
122 explorerManager.setExploredContextAndSelection(node,
new Node[]{node});
124 }
catch (PropertyVetoException ex) {
125 logger.log(Level.WARNING,
"Failed to select the datasource in the explorer view", ex);
131 if (explorerManager.getRootContext().getChildren().getNodes().length > 0) {
132 outline.getSelectionModel().setSelectionInterval(0, 0);
143 void addObserver(Observer observer) {
144 ((DataSourceSummaryNode) explorerManager.getRootContext()).addObserver(observer);
154 private List<DataSourceSummary> getDataSourceSummaryList(Map<Long, String> usageMap, Map<Long, Long> fileCountsMap) {
155 List<DataSourceSummary> summaryList =
new ArrayList<>();
157 final Map<Long, Long> artifactCountsMap = CaseDataSourcesSummary.getCountsOfArtifacts();
158 final Map<Long, Long> tagCountsMap = CaseDataSourcesSummary.getCountsOfTags();
160 SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
161 for (DataSource dataSource : skCase.getDataSources()) {
162 summaryList.add(
new DataSourceSummary(dataSource, usageMap.get(dataSource.getId()),
163 fileCountsMap.get(dataSource.getId()), artifactCountsMap.get(dataSource.getId()), tagCountsMap.get(dataSource.getId())));
165 }
catch (TskCoreException | NoCurrentCaseException ex) {
166 logger.log(Level.WARNING,
"Unable to datasources or their counts, providing empty results", ex);
176 void addListSelectionListener(ListSelectionListener listener) {
177 outline.getSelectionModel().addListSelectionListener(listener);
185 DataSource getSelectedDataSource() {
186 Node selectedNode[] = explorerManager.getSelectedNodes();
187 if (selectedNode.length == 1 && selectedNode[0] instanceof DataSourceSummaryEntryNode) {
188 return ((DataSourceSummaryEntryNode) selectedNode[0]).getDataSource();
200 void refresh(
long dataSourceId, IngestJobInfo.IngestJobStatusType newStatus) {
203 for (DataSourceSummary summary : dataSourceSummaryList) {
204 if (summary.getDataSource().getId() == dataSourceId) {
205 summary.setIngestStatus(newStatus);
209 Node[] selectedNodes = explorerManager.getSelectedNodes();
210 SwingUtilities.invokeLater(() -> {
211 explorerManager.setRootContext(
new DataSourceSummaryNode(dataSourceSummaryList));
212 List<Node> nodesToSelect =
new ArrayList<>();
213 for (Node node : explorerManager.getRootContext().getChildren().getNodes()) {
214 if (node instanceof DataSourceSummaryEntryNode) {
216 for (Node selectedNode : selectedNodes) {
217 if (((DataSourceSummaryEntryNode) node).getDataSource().equals(((DataSourceSummaryEntryNode) selectedNode).getDataSource())) {
218 nodesToSelect.add(node);
225 explorerManager.setSelectedNodes(nodesToSelect.toArray(
new Node[nodesToSelect.size()]));
226 }
catch (PropertyVetoException ex) {
227 logger.log(Level.WARNING,
"Error selecting previously selected nodes", ex);
239 @SuppressWarnings(
"unchecked")
241 private
void initComponents() {
243 setLayout(
new java.awt.BorderLayout());
247 public ExplorerManager getExplorerManager() {
248 return explorerManager;