mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 02:07:42 +00:00
Merge pull request #5155 from wschaeferB/5423-DiscoveryThumbnailViewer
5423 discovery thumbnail viewer
This commit is contained in:
commit
11296bbbd3
@ -117,6 +117,10 @@ FileSorter.SortingMethod.filetype.displayName=By file type
|
|||||||
FileSorter.SortingMethod.frequency.displayName=By central repo frequency
|
FileSorter.SortingMethod.frequency.displayName=By central repo frequency
|
||||||
FileSorter.SortingMethod.keywordlist.displayName=By keyword list names
|
FileSorter.SortingMethod.keywordlist.displayName=By keyword list names
|
||||||
FileSorter.SortingMethod.parent.displayName=By parent path
|
FileSorter.SortingMethod.parent.displayName=By parent path
|
||||||
|
# {0} - numberOfInstances
|
||||||
|
ImageThumbnailPanel.countLabel.text=Number of Instances: {0}
|
||||||
|
# {0} - fileSize
|
||||||
|
ImageThumbnailPanel.sizeLabel.text=Size: {0} bytes
|
||||||
ResultsDialog.dialogTitle.text=File search results
|
ResultsDialog.dialogTitle.text=File search results
|
||||||
ResultsDialog.exitButton.text=Exit
|
ResultsDialog.exitButton.text=Exit
|
||||||
ResultsDialog.searchButton.text=Run another search
|
ResultsDialog.searchButton.text=Run another search
|
||||||
|
@ -116,7 +116,7 @@ class FileSearch {
|
|||||||
|
|
||||||
// Sort and group the results
|
// Sort and group the results
|
||||||
searchResults.sortGroupsAndFiles();
|
searchResults.sortGroupsAndFiles();
|
||||||
LinkedHashMap<String, List<ResultFile>> resultHashMap = searchResults.toLinkedHashMap();
|
Map<String, List<ResultFile>> resultHashMap = searchResults.toLinkedHashMap();
|
||||||
for (String groupName : resultHashMap.keySet()) {
|
for (String groupName : resultHashMap.keySet()) {
|
||||||
groupCache.put(groupName, resultHashMap.get(groupName));
|
groupCache.put(groupName, resultHashMap.get(groupName));
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ class FileSearch {
|
|||||||
// Collect everything in the search results
|
// Collect everything in the search results
|
||||||
SearchResults searchResults = new SearchResults(groupSortingType, groupAttributeType, fileSortingMethod);
|
SearchResults searchResults = new SearchResults(groupSortingType, groupAttributeType, fileSortingMethod);
|
||||||
searchResults.add(resultFiles);
|
searchResults.add(resultFiles);
|
||||||
LinkedHashMap<String, List<ResultFile>> resultHashMap = searchResults.toLinkedHashMap();
|
Map<String, List<ResultFile>> resultHashMap = searchResults.toLinkedHashMap();
|
||||||
for (String groupName : resultHashMap.keySet()) {
|
for (String groupName : resultHashMap.keySet()) {
|
||||||
groupCache.put(groupName, resultHashMap.get(groupName));
|
groupCache.put(groupName, resultHashMap.get(groupName));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||||
|
<Component id="thumbnailPanel" max="32767" attributes="0"/>
|
||||||
|
<Component id="countLabel" alignment="0" pref="201" max="32767" attributes="0"/>
|
||||||
|
<Component id="fileSizeLabel" alignment="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="thumbnailPanel" min="-2" pref="178" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="fileSizeLabel" min="-2" pref="16" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="countLabel" min="-2" pref="12" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="thumbnailPanel">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JLabel" name="thumbnailLabel">
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.JLabel" name="fileSizeLabel">
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="countLabel">
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.filequery;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JList;
|
||||||
|
import javax.swing.ListCellRenderer;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which displays a thumbnail and information for an image file.
|
||||||
|
*/
|
||||||
|
public class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellRenderer<ImageThumbnailWrapper> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Color SELECTION_COLOR = new Color(0, 120, 215);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form ImageThumbnailPanel
|
||||||
|
*/
|
||||||
|
public ImageThumbnailPanel() {
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JPanel thumbnailPanel = new javax.swing.JPanel();
|
||||||
|
thumbnailLabel = new javax.swing.JLabel();
|
||||||
|
fileSizeLabel = new javax.swing.JLabel();
|
||||||
|
countLabel = new javax.swing.JLabel();
|
||||||
|
|
||||||
|
thumbnailPanel.setLayout(new java.awt.GridBagLayout());
|
||||||
|
thumbnailPanel.add(thumbnailLabel, new java.awt.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()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||||
|
.addComponent(thumbnailPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(countLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 201, Short.MAX_VALUE)
|
||||||
|
.addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(thumbnailPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(countLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JLabel countLabel;
|
||||||
|
private javax.swing.JLabel fileSizeLabel;
|
||||||
|
private javax.swing.JLabel thumbnailLabel;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
@NbBundle.Messages({"# {0} - fileSize",
|
||||||
|
"ImageThumbnailPanel.sizeLabel.text=Size: {0} bytes",
|
||||||
|
"# {0} - numberOfInstances",
|
||||||
|
"ImageThumbnailPanel.countLabel.text=Number of Instances: {0}"})
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(JList<? extends ImageThumbnailWrapper> list, ImageThumbnailWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
|
fileSizeLabel.setText(Bundle.ImageThumbnailPanel_sizeLabel_text(value.getResultFile().getFirstInstance().getSize()));
|
||||||
|
countLabel.setText(Bundle.ImageThumbnailPanel_countLabel_text(value.getResultFile().getAllInstances().size()));
|
||||||
|
thumbnailLabel.setIcon(new ImageIcon(value.getThumbnail()));
|
||||||
|
setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-117,0,0,1,-22"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="thumbnailListScrollPane">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||||
|
</AuxValues>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||||
|
<BorderConstraints direction="Center"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JList" name="thumbnailList">
|
||||||
|
<Properties>
|
||||||
|
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="thumbnailListModel" type="code"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="selectionMode" type="int" value="0"/>
|
||||||
|
<Property name="cellRenderer" type="javax.swing.ListCellRenderer" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="new ImageThumbnailPanel()" type="code"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="layoutOrientation" type="int" value="2"/>
|
||||||
|
<Property name="visibleRowCount" type="int" value="0"/>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ImageThumbnailWrapper>"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.filequery;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.DefaultListModel;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JPanel to display image thumbnails.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ImageThumbnailViewer extends javax.swing.JPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final DefaultListModel<ImageThumbnailWrapper> thumbnailListModel = new DefaultListModel<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form ImageThumbnailViewer
|
||||||
|
*/
|
||||||
|
public ImageThumbnailViewer() {
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JScrollPane thumbnailListScrollPane = new javax.swing.JScrollPane();
|
||||||
|
thumbnailList = new javax.swing.JList<>();
|
||||||
|
|
||||||
|
setLayout(new java.awt.BorderLayout());
|
||||||
|
|
||||||
|
thumbnailList.setModel(thumbnailListModel);
|
||||||
|
thumbnailList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
thumbnailList.setCellRenderer(new ImageThumbnailPanel());
|
||||||
|
thumbnailList.setLayoutOrientation(javax.swing.JList.HORIZONTAL_WRAP);
|
||||||
|
thumbnailList.setVisibleRowCount(0);
|
||||||
|
thumbnailListScrollPane.setViewportView(thumbnailList);
|
||||||
|
|
||||||
|
add(thumbnailListScrollPane, java.awt.BorderLayout.CENTER);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JList<ImageThumbnailWrapper> thumbnailList;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a selection listener to the list of thumbnails being displayed.
|
||||||
|
*
|
||||||
|
* @param listener The ListSelectionListener to add to the selection model.
|
||||||
|
*/
|
||||||
|
void addListSelectionListener(ListSelectionListener listener) {
|
||||||
|
thumbnailList.getSelectionModel().addListSelectionListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of AbstractFiles which are represented by the selected image
|
||||||
|
* thumbnail.
|
||||||
|
*
|
||||||
|
* @return The list of AbstractFiles which are represented by the selected image
|
||||||
|
* thumbnail.
|
||||||
|
*/
|
||||||
|
List<AbstractFile> getInstancesForSelected() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (thumbnailList.getSelectedIndex() == -1) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
} else {
|
||||||
|
return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getAllInstances();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the list of thumbnails being displayed.
|
||||||
|
*/
|
||||||
|
void clearViewer() {
|
||||||
|
synchronized (this) {
|
||||||
|
thumbnailListModel.removeAllElements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the thumbnail for an image to the panel.
|
||||||
|
*
|
||||||
|
* @param thumbnailWrapper The object which contains the thumbnail which
|
||||||
|
* will be displayed.
|
||||||
|
*/
|
||||||
|
void addImage(ImageThumbnailWrapper thumbnailWrapper) {
|
||||||
|
synchronized (this) {
|
||||||
|
thumbnailListModel.addElement(thumbnailWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.filequery;
|
||||||
|
|
||||||
|
import java.awt.Image;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to wrap all the information necessary for an image thumbnail to be
|
||||||
|
* displayed.
|
||||||
|
*/
|
||||||
|
public class ImageThumbnailWrapper {
|
||||||
|
|
||||||
|
private Image thumbnail;
|
||||||
|
private final ResultFile resultFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new ImageThumbnailsWrapper.
|
||||||
|
*
|
||||||
|
* @param file The ResultFile which represents the image file which the
|
||||||
|
* thumbnails were created for.
|
||||||
|
*/
|
||||||
|
ImageThumbnailWrapper(ResultFile file) {
|
||||||
|
this.thumbnail = ImageUtils.getDefaultThumbnail();
|
||||||
|
this.resultFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the image thumbnail which exists.
|
||||||
|
*
|
||||||
|
* @param thumbnail The thumbnail which exists for this file.
|
||||||
|
*/
|
||||||
|
void setImageThumbnail(Image thumbnail) {
|
||||||
|
this.thumbnail = thumbnail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ResultFile which represents the image file which the thumbnail
|
||||||
|
* was created for.
|
||||||
|
*
|
||||||
|
* @return The ResultFile which represents the image file which the
|
||||||
|
* thumbnail was created for.
|
||||||
|
*/
|
||||||
|
ResultFile getResultFile() {
|
||||||
|
return resultFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the thumbnail for the image.
|
||||||
|
*
|
||||||
|
* @return The Image which is the thumbnail for the image.
|
||||||
|
*/
|
||||||
|
Image getThumbnail() {
|
||||||
|
return thumbnail;
|
||||||
|
}
|
||||||
|
}
|
@ -238,10 +238,18 @@
|
|||||||
<Dimension value="[777, 125]"/>
|
<Dimension value="[777, 125]"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JPanel" name="instancesPanel">
|
<Container class="javax.swing.JPanel" name="instancesPanel">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||||
<JSplitPaneConstraints position="right"/>
|
<JSplitPaneConstraints position="right"/>
|
||||||
@ -269,6 +277,8 @@
|
|||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Container class="javax.swing.JScrollPane" name="instancesScrollPane">
|
<Container class="javax.swing.JScrollPane" name="instancesScrollPane">
|
||||||
<AuxValues>
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
|
|
||||||
@ -286,6 +296,7 @@
|
|||||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="instancesListModel" type="code"/>
|
<Connection code="instancesListModel" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property name="selectionMode" type="int" value="0"/>
|
||||||
<Property name="cellRenderer" type="javax.swing.ListCellRenderer" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
<Property name="cellRenderer" type="javax.swing.ListCellRenderer" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
<Connection code="new InstancesCellRenderer()" type="code"/>
|
<Connection code="new InstancesCellRenderer()" type="code"/>
|
||||||
</Property>
|
</Property>
|
||||||
|
@ -33,13 +33,12 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
import org.openide.nodes.AbstractNode;
|
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail;
|
|
||||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -51,9 +50,9 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
public class ResultsPanel extends javax.swing.JPanel {
|
public class ResultsPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private final DataResultViewerThumbnail thumbnailViewer;
|
|
||||||
private final DataResultViewerTable tableViewer;
|
private final DataResultViewerTable tableViewer;
|
||||||
private final VideoThumbnailViewer videoThumbnailViewer;
|
private final VideoThumbnailViewer videoThumbnailViewer;
|
||||||
|
private final ImageThumbnailViewer imageThumbnailViewer;
|
||||||
private List<FileSearchFiltering.FileFilter> searchFilters;
|
private List<FileSearchFiltering.FileFilter> searchFilters;
|
||||||
private FileSearch.AttributeType groupingAttribute;
|
private FileSearch.AttributeType groupingAttribute;
|
||||||
private FileGroup.GroupSortingAlgorithm groupSort;
|
private FileGroup.GroupSortingAlgorithm groupSort;
|
||||||
@ -74,22 +73,35 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
public ResultsPanel(ExplorerManager explorerManager, EamDb centralRepo) {
|
public ResultsPanel(ExplorerManager explorerManager, EamDb centralRepo) {
|
||||||
initComponents();
|
initComponents();
|
||||||
this.centralRepo = centralRepo;
|
this.centralRepo = centralRepo;
|
||||||
thumbnailViewer = new DataResultViewerThumbnail(explorerManager);
|
|
||||||
tableViewer = new DataResultViewerTable(explorerManager);
|
tableViewer = new DataResultViewerTable(explorerManager);
|
||||||
|
imageThumbnailViewer = new ImageThumbnailViewer();
|
||||||
videoThumbnailViewer = new VideoThumbnailViewer();
|
videoThumbnailViewer = new VideoThumbnailViewer();
|
||||||
// Disable manual editing of page size spinner
|
|
||||||
videoThumbnailViewer.addListSelectionListener((e) -> {
|
videoThumbnailViewer.addListSelectionListener((e) -> {
|
||||||
if (!e.getValueIsAdjusting()) {
|
if (!e.getValueIsAdjusting()) {
|
||||||
populateInstancesList();
|
populateInstancesList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
imageThumbnailViewer.addListSelectionListener((e) -> {
|
||||||
|
if (!e.getValueIsAdjusting()) {
|
||||||
|
populateInstancesList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Disable manual editing of page size spinner
|
||||||
((JSpinner.DefaultEditor) pageSizeSpinner.getEditor()).getTextField().setEditable(false);
|
((JSpinner.DefaultEditor) pageSizeSpinner.getEditor()).getTextField().setEditable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a list selection listener to the instances list.
|
||||||
|
*
|
||||||
|
* @param listener The ListSelectionListener to add to the instances list.
|
||||||
|
*/
|
||||||
void addListSelectionListener(ListSelectionListener listener) {
|
void addListSelectionListener(ListSelectionListener listener) {
|
||||||
instancesList.addListSelectionListener(listener);
|
instancesList.addListSelectionListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the instances list.
|
||||||
|
*/
|
||||||
synchronized void populateInstancesList() {
|
synchronized void populateInstancesList() {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
instancesListModel.removeAllElements();
|
instancesListModel.removeAllElements();
|
||||||
@ -102,6 +114,12 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the AbstractFile for the item currently selected in the instances
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
* @return The AbstractFile which is currently selected.
|
||||||
|
*/
|
||||||
synchronized AbstractFile getSelectedFile() {
|
synchronized AbstractFile getSelectedFile() {
|
||||||
if (instancesList.getSelectedIndex() == -1) {
|
if (instancesList.getSelectedIndex() == -1) {
|
||||||
return null;
|
return null;
|
||||||
@ -110,9 +128,18 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of all instances for the the currently selected item in the
|
||||||
|
* results viewer area.
|
||||||
|
*
|
||||||
|
* @return The list of AbstractFiles which are represented by the item
|
||||||
|
* selected in the results viewer area.
|
||||||
|
*/
|
||||||
private List<AbstractFile> getInstancesForSelected() {
|
private List<AbstractFile> getInstancesForSelected() {
|
||||||
if (resultType == FileSearchData.FileType.VIDEO) {
|
if (resultType == FileSearchData.FileType.VIDEO) {
|
||||||
return videoThumbnailViewer.getInstancesForSelected();
|
return videoThumbnailViewer.getInstancesForSelected();
|
||||||
|
} else if (resultType == FileSearchData.FileType.IMAGE) {
|
||||||
|
return imageThumbnailViewer.getInstancesForSelected();
|
||||||
}
|
}
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
@ -128,23 +155,13 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
populateInstancesList();
|
populateInstancesList();
|
||||||
currentPage = pageRetrievedEvent.getPageNumber();
|
currentPage = pageRetrievedEvent.getPageNumber();
|
||||||
updateControls();
|
updateControls();
|
||||||
thumbnailViewer.resetComponent();
|
resetResultViewer();
|
||||||
tableViewer.resetComponent();
|
|
||||||
resultsViewerPanel.remove(thumbnailViewer);
|
|
||||||
resultsViewerPanel.remove(tableViewer);
|
|
||||||
resultsViewerPanel.remove(videoThumbnailViewer);
|
|
||||||
if (pageRetrievedEvent.getType() == FileSearchData.FileType.IMAGE) {
|
if (pageRetrievedEvent.getType() == FileSearchData.FileType.IMAGE) {
|
||||||
resultsViewerPanel.add(thumbnailViewer);
|
populateImageViewer(pageRetrievedEvent.getSearchResults());
|
||||||
if (pageRetrievedEvent.getSearchResults().size() > 0) {
|
resultsViewerPanel.add(imageThumbnailViewer);
|
||||||
List<AbstractFile> filesList = pageRetrievedEvent.getSearchResults().stream().map(file -> file.getFirstInstance()).collect(Collectors.toList());
|
|
||||||
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new DiscoveryThumbnailChildren(filesList))), true));
|
|
||||||
} else {
|
|
||||||
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
|
|
||||||
}
|
|
||||||
} else if (pageRetrievedEvent.getType() == FileSearchData.FileType.VIDEO) {
|
} else if (pageRetrievedEvent.getType() == FileSearchData.FileType.VIDEO) {
|
||||||
populateVideoViewer(pageRetrievedEvent.getSearchResults());
|
populateVideoViewer(pageRetrievedEvent.getSearchResults());
|
||||||
resultsViewerPanel.add(videoThumbnailViewer);
|
resultsViewerPanel.add(videoThumbnailViewer);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resultsViewerPanel.add(tableViewer);
|
resultsViewerPanel.add(tableViewer);
|
||||||
if (pageRetrievedEvent.getSearchResults().size() > 0) {
|
if (pageRetrievedEvent.getSearchResults().size() > 0) {
|
||||||
@ -154,10 +171,22 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
tableViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
|
tableViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
resultsViewerPanel.revalidate();
|
||||||
|
resultsViewerPanel.repaint();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void populateVideoViewer(List<ResultFile> files) {
|
/**
|
||||||
|
* Reset the result viewer and any associate workers to a default empty
|
||||||
|
* state.
|
||||||
|
*/
|
||||||
|
private synchronized void resetResultViewer() {
|
||||||
|
resultsViewerPanel.remove(imageThumbnailViewer);
|
||||||
|
tableViewer.resetComponent();
|
||||||
|
resultsViewerPanel.remove(tableViewer);
|
||||||
|
resultsViewerPanel.remove(videoThumbnailViewer);
|
||||||
|
|
||||||
//cancel any unfished thumb workers
|
//cancel any unfished thumb workers
|
||||||
for (SwingWorker<Void, Void> thumbWorker : thumbnailWorkers) {
|
for (SwingWorker<Void, Void> thumbWorker : thumbnailWorkers) {
|
||||||
if (!thumbWorker.isDone()) {
|
if (!thumbWorker.isDone()) {
|
||||||
@ -167,6 +196,16 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
//clear old thumbnails
|
//clear old thumbnails
|
||||||
thumbnailWorkers.clear();
|
thumbnailWorkers.clear();
|
||||||
videoThumbnailViewer.clearViewer();
|
videoThumbnailViewer.clearViewer();
|
||||||
|
imageThumbnailViewer.clearViewer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the video thumbnail viewer, cancelling any thumbnails which are
|
||||||
|
* currently being created first.
|
||||||
|
*
|
||||||
|
* @param files The list of ResultFiles to populate the video viewer with.
|
||||||
|
*/
|
||||||
|
synchronized void populateVideoViewer(List<ResultFile> files) {
|
||||||
for (ResultFile file : files) {
|
for (ResultFile file : files) {
|
||||||
VideoThumbnailWorker thumbWorker = new VideoThumbnailWorker(file);
|
VideoThumbnailWorker thumbWorker = new VideoThumbnailWorker(file);
|
||||||
thumbWorker.execute();
|
thumbWorker.execute();
|
||||||
@ -175,6 +214,21 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the image thumbnail viewer, cancelling any thumbnails which are
|
||||||
|
* currently being created first.
|
||||||
|
*
|
||||||
|
* @param files The list of ResultFiles to populate the image viewer with.
|
||||||
|
*/
|
||||||
|
synchronized void populateImageViewer(List<ResultFile> files) {
|
||||||
|
for (ResultFile file : files) {
|
||||||
|
ImageThumbnailWorker thumbWorker = new ImageThumbnailWorker(file);
|
||||||
|
thumbWorker.execute();
|
||||||
|
//keep track of thumb worker for possible cancelation
|
||||||
|
thumbnailWorkers.add(thumbWorker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribe and respond to GroupSelectedEvents.
|
* Subscribe and respond to GroupSelectedEvents.
|
||||||
*
|
*
|
||||||
@ -201,8 +255,7 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
currentPage = 0;
|
currentPage = 0;
|
||||||
updateControls();
|
updateControls();
|
||||||
videoThumbnailViewer.clearViewer();
|
videoThumbnailViewer.clearViewer();
|
||||||
thumbnailViewer.resetComponent();
|
imageThumbnailViewer.clearViewer();
|
||||||
thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
|
|
||||||
tableViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
|
tableViewer.setNode(new TableFilterNode(new DataResultFilterNode(Node.EMPTY), true));
|
||||||
resultsViewerPanel.revalidate();
|
resultsViewerPanel.revalidate();
|
||||||
resultsViewerPanel.repaint();
|
resultsViewerPanel.repaint();
|
||||||
@ -262,9 +315,9 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
javax.swing.JLabel gotoPageLabel = new javax.swing.JLabel();
|
javax.swing.JLabel gotoPageLabel = new javax.swing.JLabel();
|
||||||
gotoPageField = new javax.swing.JTextField();
|
gotoPageField = new javax.swing.JTextField();
|
||||||
javax.swing.JLabel pageSizeLabel = new javax.swing.JLabel();
|
javax.swing.JLabel pageSizeLabel = new javax.swing.JLabel();
|
||||||
resultsSplitPane = new javax.swing.JSplitPane();
|
javax.swing.JSplitPane resultsSplitPane = new javax.swing.JSplitPane();
|
||||||
instancesPanel = new javax.swing.JPanel();
|
javax.swing.JPanel instancesPanel = new javax.swing.JPanel();
|
||||||
instancesScrollPane = new javax.swing.JScrollPane();
|
javax.swing.JScrollPane instancesScrollPane = new javax.swing.JScrollPane();
|
||||||
instancesList = new javax.swing.JList<>();
|
instancesList = new javax.swing.JList<>();
|
||||||
resultsViewerPanel = new javax.swing.JPanel();
|
resultsViewerPanel = new javax.swing.JPanel();
|
||||||
|
|
||||||
@ -374,6 +427,7 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
instancesList.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ResultsPanel.class, "ResultsPanel.instancesList.border.title"))); // NOI18N
|
instancesList.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(ResultsPanel.class, "ResultsPanel.instancesList.border.title"))); // NOI18N
|
||||||
instancesList.setModel(instancesListModel);
|
instancesList.setModel(instancesListModel);
|
||||||
|
instancesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
instancesList.setCellRenderer(new InstancesCellRenderer());
|
instancesList.setCellRenderer(new InstancesCellRenderer());
|
||||||
instancesScrollPane.setViewportView(instancesList);
|
instancesScrollPane.setViewportView(instancesList);
|
||||||
|
|
||||||
@ -489,33 +543,82 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
private javax.swing.JLabel currentPageLabel;
|
private javax.swing.JLabel currentPageLabel;
|
||||||
private javax.swing.JTextField gotoPageField;
|
private javax.swing.JTextField gotoPageField;
|
||||||
private javax.swing.JList<AbstractFile> instancesList;
|
private javax.swing.JList<AbstractFile> instancesList;
|
||||||
private javax.swing.JPanel instancesPanel;
|
|
||||||
private javax.swing.JScrollPane instancesScrollPane;
|
|
||||||
private javax.swing.JButton nextPageButton;
|
private javax.swing.JButton nextPageButton;
|
||||||
private javax.swing.JSpinner pageSizeSpinner;
|
private javax.swing.JSpinner pageSizeSpinner;
|
||||||
private javax.swing.JPanel pagingPanel;
|
private javax.swing.JPanel pagingPanel;
|
||||||
private javax.swing.JButton previousPageButton;
|
private javax.swing.JButton previousPageButton;
|
||||||
private javax.swing.JSplitPane resultsSplitPane;
|
|
||||||
private javax.swing.JPanel resultsViewerPanel;
|
private javax.swing.JPanel resultsViewerPanel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing worker to handle the retrieval of video thumbnails and population
|
||||||
|
* of the Video Thumbnail Viewer.
|
||||||
|
*/
|
||||||
private class VideoThumbnailWorker extends SwingWorker<Void, Void> {
|
private class VideoThumbnailWorker extends SwingWorker<Void, Void> {
|
||||||
|
|
||||||
private final VideoThumbnailsWrapper thumbnailWrapper;
|
private final VideoThumbnailsWrapper thumbnailWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new VideoThumbnailWorker.
|
||||||
|
*
|
||||||
|
* @param file The ResultFile which represents the video file thumbnails
|
||||||
|
* are being retrieved for.
|
||||||
|
*/
|
||||||
VideoThumbnailWorker(ResultFile file) {
|
VideoThumbnailWorker(ResultFile file) {
|
||||||
thumbnailWrapper = new VideoThumbnailsWrapper(new ArrayList<Image>(), new int[4], file);
|
thumbnailWrapper = new VideoThumbnailsWrapper(file);
|
||||||
videoThumbnailViewer.addRow(thumbnailWrapper);
|
videoThumbnailViewer.addVideo(thumbnailWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Exception {
|
protected Void doInBackground() throws Exception {
|
||||||
FileSearch.getVideoThumbnails(thumbnailWrapper);
|
FileSearch.getVideoThumbnails(thumbnailWrapper);
|
||||||
videoThumbnailViewer.repaint();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
videoThumbnailViewer.repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing worker to handle the retrieval of image thumbnails and population
|
||||||
|
* of the Image Thumbnail Viewer.
|
||||||
|
*/
|
||||||
|
private class ImageThumbnailWorker extends SwingWorker<Void, Void> {
|
||||||
|
|
||||||
|
private final ImageThumbnailWrapper thumbnailWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new ImageThumbnailWorker.
|
||||||
|
*
|
||||||
|
* @param file The ResultFile which represents the image file thumbnails
|
||||||
|
* are being retrieved for.
|
||||||
|
*/
|
||||||
|
ImageThumbnailWorker(ResultFile file) {
|
||||||
|
thumbnailWrapper = new ImageThumbnailWrapper(file);
|
||||||
|
imageThumbnailViewer.addImage(thumbnailWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Exception {
|
||||||
|
Image thumbnail = ImageUtils.getThumbnail(thumbnailWrapper.getResultFile().getFirstInstance(), ImageUtils.ICON_SIZE_LARGE);
|
||||||
|
if (thumbnail != null) {
|
||||||
|
thumbnailWrapper.setImageThumbnail(thumbnail);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
imageThumbnailViewer.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cell renderer for the instances list.
|
||||||
|
*/
|
||||||
private class InstancesCellRenderer extends DefaultListCellRenderer {
|
private class InstancesCellRenderer extends DefaultListCellRenderer {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -150,8 +150,8 @@ class SearchResults {
|
|||||||
*
|
*
|
||||||
* @return the grouped and sorted results
|
* @return the grouped and sorted results
|
||||||
*/
|
*/
|
||||||
LinkedHashMap<String, List<ResultFile>> toLinkedHashMap() throws FileSearchException {
|
Map<String, List<ResultFile>> toLinkedHashMap() throws FileSearchException {
|
||||||
LinkedHashMap<String, List<ResultFile>> map = new LinkedHashMap<>();
|
Map<String, List<ResultFile>> map = new LinkedHashMap<>();
|
||||||
|
|
||||||
// Sort the groups and files
|
// Sort the groups and files
|
||||||
sortGroupsAndFiles();
|
sortGroupsAndFiles();
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
<Component id="fileSizeLabel" pref="19" max="32767" attributes="0"/>
|
<Component id="fileSizeLabel" pref="19" max="32767" attributes="0"/>
|
||||||
<Component id="countLabel" max="32767" attributes="0"/>
|
<Component id="countLabel" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="32767" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
@ -35,7 +35,7 @@ import org.openide.util.NbBundle.Messages;
|
|||||||
final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRenderer<VideoThumbnailsWrapper> {
|
final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRenderer<VideoThumbnailsWrapper> {
|
||||||
|
|
||||||
private static final int GAP_SIZE = 4;
|
private static final int GAP_SIZE = 4;
|
||||||
private static final Color SELECTION_COLOR = new Color(100, 200, 255);
|
private static final Color SELECTION_COLOR = new Color(0,120,215);
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +124,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
|
|||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||||
.addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 19, Short.MAX_VALUE)
|
.addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 19, Short.MAX_VALUE)
|
||||||
.addComponent(countLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addComponent(countLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
@ -50,21 +50,12 @@ public class VideoThumbnailViewer extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the AbstractFile associated with the selected thumbnails.
|
* Get the list of AbstractFiles which are represented by the selected Video
|
||||||
|
* thumbnails.
|
||||||
*
|
*
|
||||||
* @return The AbstractFile associated with the selected thumbnails, or null
|
* @return The list of AbstractFiles which are represented by the selected Video
|
||||||
* if no thumbnails are selected.
|
* thumbnails.
|
||||||
*/
|
*/
|
||||||
AbstractFile getSelectedFile() {
|
|
||||||
synchronized (this) {
|
|
||||||
if (thumbnailList.getSelectedIndex() == -1) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return thumbnailListModel.getElementAt(thumbnailList.getSelectedIndex()).getResultFile().getFirstInstance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AbstractFile> getInstancesForSelected() {
|
List<AbstractFile> getInstancesForSelected() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (thumbnailList.getSelectedIndex() == -1) {
|
if (thumbnailList.getSelectedIndex() == -1) {
|
||||||
@ -90,7 +81,7 @@ public class VideoThumbnailViewer extends javax.swing.JPanel {
|
|||||||
* @param thumbnailWrapper The object which contains the thumbnails which
|
* @param thumbnailWrapper The object which contains the thumbnails which
|
||||||
* will be displayed.
|
* will be displayed.
|
||||||
*/
|
*/
|
||||||
void addRow(VideoThumbnailsWrapper thumbnailWrapper) {
|
void addVideo(VideoThumbnailsWrapper thumbnailWrapper) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
thumbnailListModel.addElement(thumbnailWrapper);
|
thumbnailListModel.addElement(thumbnailWrapper);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.filequery;
|
package org.sleuthkit.autopsy.filequery;
|
||||||
|
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -28,23 +29,19 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
final class VideoThumbnailsWrapper {
|
final class VideoThumbnailsWrapper {
|
||||||
|
|
||||||
private List<Image> thumbnails;
|
private final List<Image> thumbnails;
|
||||||
private final ResultFile resultFile;
|
private final ResultFile resultFile;
|
||||||
private int[] timeStamps;
|
private int[] timeStamps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new VideoThumbnailsWrapper.
|
* Construct a new VideoThumbnailsWrapper.
|
||||||
*
|
*
|
||||||
* @param thumbnails The list of Images which are the thumbnails for the
|
* @param file The ResultFile which represents the video file which the
|
||||||
* video.
|
* thumbnails were created for.
|
||||||
* @param timeStamps An array containing the time in milliseconds into the
|
|
||||||
* video that each thumbnail created for.
|
|
||||||
* @param file The ResultFile which represents the video file which
|
|
||||||
* the thumbnails were created for.
|
|
||||||
*/
|
*/
|
||||||
VideoThumbnailsWrapper(List<Image> thumbnails, int[] timeStamps, ResultFile file) {
|
VideoThumbnailsWrapper(ResultFile file) {
|
||||||
this.thumbnails = thumbnails;
|
this.thumbnails = new ArrayList<>();
|
||||||
this.timeStamps = timeStamps;
|
this.timeStamps = new int[4];
|
||||||
this.resultFile = file;
|
this.resultFile = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,9 +76,17 @@ final class VideoThumbnailsWrapper {
|
|||||||
return Collections.unmodifiableList(thumbnails);
|
return Collections.unmodifiableList(thumbnails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the thumbnails and their associated time stamps.
|
||||||
|
*
|
||||||
|
* @param videoThumbnails The list of Images which are the thumbnails for
|
||||||
|
* the video.
|
||||||
|
* @param framePositions An array containing the time in milliseconds into
|
||||||
|
* the video that each thumbnail created for.
|
||||||
|
*/
|
||||||
void setThumbnails(List<Image> videoThumbnails, int[] framePositions) {
|
void setThumbnails(List<Image> videoThumbnails, int[] framePositions) {
|
||||||
this.thumbnails = videoThumbnails;
|
this.thumbnails.addAll(videoThumbnails);
|
||||||
this.timeStamps = framePositions;
|
this.timeStamps = framePositions.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user