mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 19:14:55 +00:00
5372 multiple thumbnails
This commit is contained in:
parent
497e37e371
commit
5c26ff2590
@ -114,6 +114,8 @@ 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} - file name
|
||||||
|
ResultFile.genVideoThumb.progress.text=extracting temporary file {0}
|
||||||
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
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.filequery;
|
package org.sleuthkit.autopsy.filequery;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
@ -31,7 +29,6 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
|||||||
import org.sleuthkit.autopsy.corecomponents.DataContentPanel;
|
import org.sleuthkit.autopsy.corecomponents.DataContentPanel;
|
||||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
|
||||||
|
@ -18,14 +18,26 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.filequery;
|
package org.sleuthkit.autopsy.filequery;
|
||||||
|
|
||||||
|
import com.google.common.io.Files;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
import org.sleuthkit.autopsy.filequery.FileSearchData.FileType;
|
import org.sleuthkit.autopsy.filequery.FileSearchData.FileType;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
|
import org.opencv.core.Mat;
|
||||||
|
import org.opencv.highgui.VideoCapture;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
|
||||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
|
import static org.sleuthkit.autopsy.coreutils.VideoUtils.getVideoFileInTempDir;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||||
import org.sleuthkit.datamodel.HashUtility;
|
import org.sleuthkit.datamodel.HashUtility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,6 +226,173 @@ class ResultFile {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"# {0} - file name",
|
||||||
|
"ResultFile.genVideoThumb.progress.text=extracting temporary file {0}"})
|
||||||
|
static ThumbnailsWrapper createVideoThumbnails(AbstractFile file) {
|
||||||
|
java.io.File tempFile;
|
||||||
|
try {
|
||||||
|
tempFile = getVideoFileInTempDir(file);
|
||||||
|
} catch (NoCurrentCaseException ex) {
|
||||||
|
// LOGGER.log(Level.WARNING, "Exception while getting open case.", ex); //NON-NLS
|
||||||
|
int[] framePositions = new int[]{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0};
|
||||||
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
return new ThumbnailsWrapper(videoThumbnails, framePositions, file);
|
||||||
|
}
|
||||||
|
if (tempFile.exists() == false || tempFile.length() < file.getSize()) {
|
||||||
|
ProgressHandle progress = ProgressHandle.createHandle(Bundle.ResultFile_genVideoThumb_progress_text(file.getName()));
|
||||||
|
progress.start(100);
|
||||||
|
try {
|
||||||
|
Files.createParentDirs(tempFile);
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
int[] framePositions = new int[]{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0};
|
||||||
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
return new ThumbnailsWrapper(videoThumbnails, framePositions, file);
|
||||||
|
}
|
||||||
|
ContentUtils.writeToFile(file, tempFile, progress, null, true);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
// LOGGER.log(Level.WARNING, "Error extracting temporary file for " + ImageUtils.getContentPathSafe(file), ex); //NON-NLS
|
||||||
|
} finally {
|
||||||
|
progress.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VideoCapture videoFile = new VideoCapture(); // will contain the video
|
||||||
|
BufferedImage bufferedImage = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!videoFile.open(tempFile.toString())) {
|
||||||
|
// LOGGER.log(Level.WARNING, "Error opening {0} for preview generation.", ImageUtils.getContentPathSafe(file)); //NON-NLS
|
||||||
|
int[] framePositions = new int[]{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0};
|
||||||
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
return new ThumbnailsWrapper(videoThumbnails, framePositions, file);
|
||||||
|
}
|
||||||
|
double fps = videoFile.get(5); // gets frame per second
|
||||||
|
double totalFrames = videoFile.get(7); // gets total frames
|
||||||
|
if (fps <= 0 || totalFrames <= 0) {
|
||||||
|
// LOGGER.log(Level.WARNING, "Error getting fps or total frames for {0}", ImageUtils.getContentPathSafe(file)); //NON-NLS
|
||||||
|
int[] framePositions = new int[]{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0};
|
||||||
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
return new ThumbnailsWrapper(videoThumbnails, framePositions, file);
|
||||||
|
}
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
int[] framePositions = new int[]{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0};
|
||||||
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
return new ThumbnailsWrapper(videoThumbnails, framePositions, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
double duration = 1000 * (totalFrames / fps); //total milliseconds
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Four attempts are made to grab a frame from a video. The first
|
||||||
|
* attempt at 50% will give us a nice frame in the middle that gets
|
||||||
|
* to the heart of the content. If that fails, the next positions
|
||||||
|
* tried will be 25% and 75%. After three failed attempts, 1% will
|
||||||
|
* be tried in a last-ditch effort, the idea being the video may be
|
||||||
|
* corrupt and that our best chance at retrieving a frame is early
|
||||||
|
* on in the video.
|
||||||
|
*
|
||||||
|
* If no frame can be retrieved, no thumbnail will be created.
|
||||||
|
*/
|
||||||
|
int[] framePositions = new int[]{
|
||||||
|
(int) (duration * .01),
|
||||||
|
(int) (duration * .25),
|
||||||
|
(int) (duration * .5),
|
||||||
|
(int) (duration * .75),};
|
||||||
|
|
||||||
|
Mat imageMatrix = new Mat();
|
||||||
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
for (int i = 0; i < framePositions.length; i++) {
|
||||||
|
if (!videoFile.set(0, framePositions[i])) {
|
||||||
|
// LOGGER.log(Level.WARNING, "Error seeking to " + framePositions[i] + "ms in {0}", ImageUtils.getContentPathSafe(file)); //NON-NLS
|
||||||
|
// If we can't set the time, continue to the next frame position and try again.
|
||||||
|
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Read the frame into the image/matrix.
|
||||||
|
if (!videoFile.read(imageMatrix)) {
|
||||||
|
// LOGGER.log(Level.WARNING, "Error reading frame at " + framePositions[i] + "ms from {0}", ImageUtils.getContentPathSafe(file)); //NON-NLS
|
||||||
|
// If the image is bad for some reason, continue to the next frame position and try again.
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If the image is empty, return since no buffered image can be created.
|
||||||
|
if (imageMatrix.empty()) {
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int matrixColumns = imageMatrix.cols();
|
||||||
|
int matrixRows = imageMatrix.rows();
|
||||||
|
|
||||||
|
// Convert the matrix that contains the frame to a buffered image.
|
||||||
|
if (bufferedImage == null) {
|
||||||
|
bufferedImage = new BufferedImage(matrixColumns, matrixRows, BufferedImage.TYPE_3BYTE_BGR);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = new byte[matrixRows * matrixColumns * (int) (imageMatrix.elemSize())];
|
||||||
|
imageMatrix.get(0, 0, data); //copy the image to data
|
||||||
|
|
||||||
|
//todo: this looks like we are swapping the first and third channels. so we can use BufferedImage.TYPE_3BYTE_BGR
|
||||||
|
if (imageMatrix.channels() == 3) {
|
||||||
|
for (int k = 0; k < data.length; k += 3) {
|
||||||
|
byte temp = data[k];
|
||||||
|
data[k] = data[k + 2];
|
||||||
|
data[k + 2] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferedImage.getRaster().setDataElements(0, 0, matrixColumns, matrixRows, data);
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
return new ThumbnailsWrapper(videoThumbnails, framePositions, file);
|
||||||
|
}
|
||||||
|
videoThumbnails.add(bufferedImage == null ? ImageUtils.getDefaultThumbnail() : ScalrWrapper.resizeFast(bufferedImage, ImageUtils.ICON_SIZE_MEDIUM));
|
||||||
|
}
|
||||||
|
return new ThumbnailsWrapper(videoThumbnails, framePositions, file);
|
||||||
|
} finally {
|
||||||
|
videoFile.release(); // close the file}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<Image> getThumbnails(FileSearchData.FileType resultType) {
|
List<Image> getThumbnails(FileSearchData.FileType resultType) {
|
||||||
if (thumbnails.isEmpty()) {
|
if (thumbnails.isEmpty()) {
|
||||||
createThumbnails(resultType);
|
createThumbnails(resultType);
|
||||||
|
@ -421,7 +421,7 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
private final ResultFile file;
|
private final ResultFile file;
|
||||||
private final FileSearchData.FileType type;
|
private final FileSearchData.FileType type;
|
||||||
private List<Image> thumbnails = new ArrayList<>();
|
private ThumbnailsWrapper thumbnailWrapper;
|
||||||
|
|
||||||
ThumbnailWorker(ResultFile file, FileSearchData.FileType resultType) {
|
ThumbnailWorker(ResultFile file, FileSearchData.FileType resultType) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
@ -430,13 +430,13 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Exception {
|
protected Void doInBackground() throws Exception {
|
||||||
thumbnails.addAll(file.getThumbnails(type));
|
thumbnailWrapper = ResultFile.createVideoThumbnails(file.getAbstractFile());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done() {
|
protected void done() {
|
||||||
videoThumbnailViewer.addRow(new ThumbnailsWrapper(thumbnails, file.getAbstractFile()));
|
videoThumbnailViewer.addRow(thumbnailWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,12 +24,12 @@
|
|||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="imagePanel" pref="800" max="32767" attributes="0"/>
|
<Component id="imagePanel" pref="800" max="32767" attributes="0"/>
|
||||||
<Component id="fileInfoLabel" max="32767" attributes="0"/>
|
<Component id="fileInfoLabel" alignment="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -37,7 +37,7 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="imagePanel" min="-2" pref="148" max="-2" attributes="0"/>
|
<Component id="imagePanel" min="-2" pref="170" max="-2" attributes="0"/>
|
||||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="fileInfoLabel" min="-2" pref="19" max="-2" attributes="0"/>
|
<Component id="fileInfoLabel" min="-2" pref="19" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="32767" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
@ -10,6 +10,7 @@ import java.awt.Component;
|
|||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
@ -32,19 +33,36 @@ public final class ThumbnailPanel extends javax.swing.JPanel implements ListCell
|
|||||||
this.setFocusable(true);
|
this.setFocusable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addThumbnails(List<Image> thumbnails) {
|
private void addThumbnails(ThumbnailsWrapper thumbnailWrapper) {
|
||||||
imagePanel.removeAll();
|
imagePanel.removeAll();
|
||||||
GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
||||||
gridBagConstraints.gridx = 0;
|
gridBagConstraints.gridx = 0;
|
||||||
gridBagConstraints.gridy = 0;
|
gridBagConstraints.gridy = 0;
|
||||||
gridBagConstraints.anchor = GridBagConstraints.LINE_START;
|
gridBagConstraints.anchor = GridBagConstraints.LINE_START;
|
||||||
imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)));
|
imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
|
||||||
gridBagConstraints.gridx++;
|
gridBagConstraints.gridx++;
|
||||||
for (Image image : thumbnails) {
|
int timeIndex = 0;
|
||||||
|
int[] timeStamps = thumbnailWrapper.getTimeStamps();
|
||||||
|
for (Image image : thumbnailWrapper.getThumbnails()) {
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
imagePanel.add(new JLabel(new ImageIcon(image)), gridBagConstraints);
|
imagePanel.add(new JLabel(new ImageIcon(image)), gridBagConstraints);
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
long millis = timeStamps[timeIndex];
|
||||||
|
long hours = TimeUnit.MILLISECONDS.toHours(millis);
|
||||||
|
millis -= TimeUnit.HOURS.toMillis(hours);
|
||||||
|
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
|
||||||
|
millis -= TimeUnit.MINUTES.toMillis(minutes);
|
||||||
|
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
|
||||||
|
imagePanel.add(new JLabel(String.format("%01d:%02d:%02d", hours, minutes, seconds)), gridBagConstraints);
|
||||||
gridBagConstraints.gridx++;
|
gridBagConstraints.gridx++;
|
||||||
imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)));
|
gridBagConstraints.gridy = 0;
|
||||||
|
imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
|
||||||
|
gridBagConstraints.gridy = 1;
|
||||||
|
imagePanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 0), new java.awt.Dimension(GAP_SIZE, 32767)), gridBagConstraints);
|
||||||
gridBagConstraints.gridx++;
|
gridBagConstraints.gridx++;
|
||||||
|
timeIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +99,7 @@ public final class ThumbnailPanel extends javax.swing.JPanel implements ListCell
|
|||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(imagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 148, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(imagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 170, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
.addComponent(fileInfoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(fileInfoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
@ -97,7 +115,7 @@ public final class ThumbnailPanel extends javax.swing.JPanel implements ListCell
|
|||||||
@Override
|
@Override
|
||||||
public Component getListCellRendererComponent(JList<? extends ThumbnailsWrapper> list, ThumbnailsWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
|
public Component getListCellRendererComponent(JList<? extends ThumbnailsWrapper> list, ThumbnailsWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
fileInfoLabel.setText(value.getFileInfo());
|
fileInfoLabel.setText(value.getFileInfo());
|
||||||
addThumbnails(value.getThumbnails());
|
addThumbnails(value);
|
||||||
setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
|
setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,11 @@ public class ThumbnailsWrapper {
|
|||||||
|
|
||||||
private final List<Image> thumbnails;
|
private final List<Image> thumbnails;
|
||||||
private final AbstractFile abstractFile;
|
private final AbstractFile abstractFile;
|
||||||
|
private final int[] timeStamps;
|
||||||
|
|
||||||
public ThumbnailsWrapper(List<Image> thumbnails, AbstractFile file) {
|
public ThumbnailsWrapper(List<Image> thumbnails, int[] timeStamps, AbstractFile file) {
|
||||||
this.thumbnails = thumbnails;
|
this.thumbnails = thumbnails;
|
||||||
|
this.timeStamps = timeStamps;
|
||||||
this.abstractFile = file;
|
this.abstractFile = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +30,10 @@ public class ThumbnailsWrapper {
|
|||||||
return abstractFile;
|
return abstractFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int[] getTimeStamps(){
|
||||||
|
return timeStamps.clone();
|
||||||
|
}
|
||||||
|
|
||||||
String getFileInfo() {
|
String getFileInfo() {
|
||||||
return abstractFile.getParentPath();
|
return abstractFile.getParentPath();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user