mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
Merge branch 'file-search' of https://github.com/sleuthkit/autopsy into 5661-FileDiscoveryCleanup1
This commit is contained in:
commit
685a3f1b81
@ -23,11 +23,14 @@ import com.google.common.cache.CacheBuilder;
|
|||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -37,10 +40,14 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.netbeans.api.progress.ProgressHandle;
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import org.opencv.highgui.VideoCapture;
|
import org.opencv.highgui.VideoCapture;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||||
@ -72,6 +79,8 @@ class FileSearch {
|
|||||||
|
|
||||||
private final static Logger logger = Logger.getLogger(FileSearch.class.getName());
|
private final static Logger logger = Logger.getLogger(FileSearch.class.getName());
|
||||||
private static final int MAXIMUM_CACHE_SIZE = 10;
|
private static final int MAXIMUM_CACHE_SIZE = 10;
|
||||||
|
private static final String THUMBNAIL_FORMAT = "png"; //NON-NLS
|
||||||
|
private static final String VIDEO_THUMBNAIL_DIR = "video-thumbnails"; //NON-NLS
|
||||||
private static final Cache<SearchKey, Map<GroupKey, List<ResultFile>>> searchCache = CacheBuilder.newBuilder()
|
private static final Cache<SearchKey, Map<GroupKey, List<ResultFile>>> searchCache = CacheBuilder.newBuilder()
|
||||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||||
.build();
|
.build();
|
||||||
@ -369,7 +378,15 @@ class FileSearch {
|
|||||||
"FileSearch.genVideoThumb.progress.text=extracting temporary file {0}"})
|
"FileSearch.genVideoThumb.progress.text=extracting temporary file {0}"})
|
||||||
static void getVideoThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
|
static void getVideoThumbnails(VideoThumbnailsWrapper thumbnailWrapper) {
|
||||||
AbstractFile file = thumbnailWrapper.getResultFile().getFirstInstance();
|
AbstractFile file = thumbnailWrapper.getResultFile().getFirstInstance();
|
||||||
//Currently this method always creates the thumbnails
|
String cacheDirectory;
|
||||||
|
try {
|
||||||
|
cacheDirectory = Case.getCurrentCaseThrows().getCacheDirectory();
|
||||||
|
} catch (NoCurrentCaseException ex) {
|
||||||
|
cacheDirectory = null;
|
||||||
|
logger.log(Level.WARNING, "Unable to get cache directory, video thumbnails will not be saved", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheDirectory == null || file.getMd5Hash() == null || !Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash()).toFile().exists()) {
|
||||||
java.io.File tempFile;
|
java.io.File tempFile;
|
||||||
try {
|
try {
|
||||||
tempFile = getVideoFileInTempDir(file);
|
tempFile = getVideoFileInTempDir(file);
|
||||||
@ -450,12 +467,30 @@ class FileSearch {
|
|||||||
|
|
||||||
Mat imageMatrix = new Mat();
|
Mat imageMatrix = new Mat();
|
||||||
List<Image> videoThumbnails = new ArrayList<>();
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
if (cacheDirectory == null || file.getMd5Hash() == null) {
|
||||||
|
cacheDirectory = null;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
FileUtils.forceMkdir(Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash()).toFile());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
cacheDirectory = null;
|
||||||
|
logger.log(Level.WARNING, "Unable to make video thumbnails directory, thumbnails will not be saved", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (int i = 0; i < framePositions.length; i++) {
|
for (int i = 0; i < framePositions.length; i++) {
|
||||||
if (!videoFile.set(0, framePositions[i])) {
|
if (!videoFile.set(0, framePositions[i])) {
|
||||||
logger.log(Level.WARNING, "Error seeking to " + framePositions[i] + "ms in {0}", file.getParentPath() + "/" + file.getName()); //NON-NLS
|
logger.log(Level.WARNING, "Error seeking to " + framePositions[i] + "ms in {0}", file.getParentPath() + "/" + file.getName()); //NON-NLS
|
||||||
// If we can't set the time, continue to the next frame position and try again.
|
// If we can't set the time, continue to the next frame position and try again.
|
||||||
|
|
||||||
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
if (cacheDirectory != null) {
|
||||||
|
try {
|
||||||
|
ImageIO.write((RenderedImage) ImageUtils.getDefaultThumbnail(), THUMBNAIL_FORMAT,
|
||||||
|
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to save default video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Read the frame into the image/matrix.
|
// Read the frame into the image/matrix.
|
||||||
@ -463,11 +498,28 @@ class FileSearch {
|
|||||||
logger.log(Level.WARNING, "Error reading frame at " + framePositions[i] + "ms from {0}", file.getParentPath() + "/" + file.getName()); //NON-NLS
|
logger.log(Level.WARNING, "Error reading frame at " + framePositions[i] + "ms from {0}", file.getParentPath() + "/" + file.getName()); //NON-NLS
|
||||||
// If the image is bad for some reason, continue to the next frame position and try again.
|
// If the image is bad for some reason, continue to the next frame position and try again.
|
||||||
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
if (cacheDirectory != null) {
|
||||||
|
try {
|
||||||
|
ImageIO.write((RenderedImage) ImageUtils.getDefaultThumbnail(), THUMBNAIL_FORMAT,
|
||||||
|
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to save default video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// If the image is empty, return since no buffered image can be created.
|
// If the image is empty, return since no buffered image can be created.
|
||||||
if (imageMatrix.empty()) {
|
if (imageMatrix.empty()) {
|
||||||
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
if (cacheDirectory != null) {
|
||||||
|
try {
|
||||||
|
ImageIO.write((RenderedImage) ImageUtils.getDefaultThumbnail(), THUMBNAIL_FORMAT,
|
||||||
|
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to save default video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,14 +545,61 @@ class FileSearch {
|
|||||||
bufferedImage.getRaster().setDataElements(0, 0, matrixColumns, matrixRows, data);
|
bufferedImage.getRaster().setDataElements(0, 0, matrixColumns, matrixRows, data);
|
||||||
if (Thread.interrupted()) {
|
if (Thread.interrupted()) {
|
||||||
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
|
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
|
||||||
|
try {
|
||||||
|
FileUtils.forceDelete(Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash()).toFile());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to delete directory for cancelled video thumbnail process", ex);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
videoThumbnails.add(ScalrWrapper.resizeFast(bufferedImage, ImageUtils.ICON_SIZE_LARGE));
|
BufferedImage thumbnail = ScalrWrapper.resizeFast(bufferedImage, ImageUtils.ICON_SIZE_LARGE);
|
||||||
|
videoThumbnails.add(thumbnail);
|
||||||
|
if (cacheDirectory != null) {
|
||||||
|
try {
|
||||||
|
ImageIO.write(thumbnail, THUMBNAIL_FORMAT,
|
||||||
|
Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, file.getMd5Hash(), i + "-" + framePositions[i] + "." + THUMBNAIL_FORMAT).toFile()); //NON-NLS)
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.WARNING, "Unable to save video thumbnail for " + file.getMd5Hash() + " at frame position " + framePositions[i], ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
|
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
|
||||||
} finally {
|
} finally {
|
||||||
videoFile.release(); // close the file}
|
videoFile.release(); // close the file}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
loadSavedThumbnails(cacheDirectory, thumbnailWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the thumbnails that exist in the cache directory for the specified
|
||||||
|
* video file.
|
||||||
|
*
|
||||||
|
* @param cacheDirectory The directory which exists for the video
|
||||||
|
* thumbnails.
|
||||||
|
* @param thumbnailWrapper The VideoThumbnailWrapper object which contains
|
||||||
|
* information about the file and the thumbnails
|
||||||
|
* associated with it.
|
||||||
|
*/
|
||||||
|
private static void loadSavedThumbnails(String cacheDirectory, VideoThumbnailsWrapper thumbnailWrapper) {
|
||||||
|
int[] framePositions = new int[4];
|
||||||
|
List<Image> videoThumbnails = new ArrayList<>();
|
||||||
|
int thumbnailNumber = 0;
|
||||||
|
String md5 = thumbnailWrapper.getResultFile().getFirstInstance().getMd5Hash();
|
||||||
|
for (String fileName : Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, md5).toFile().list()) {
|
||||||
|
try {
|
||||||
|
videoThumbnails.add(ImageIO.read(Paths.get(cacheDirectory, VIDEO_THUMBNAIL_DIR, md5, fileName).toFile()));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
videoThumbnails.add(ImageUtils.getDefaultThumbnail());
|
||||||
|
logger.log(Level.WARNING, "Unable to read saved video thumbnail " + fileName + " for " + md5, ex);
|
||||||
|
}
|
||||||
|
int framePos = Integer.valueOf(FilenameUtils.getBaseName(fileName).substring(2));
|
||||||
|
framePositions[thumbnailNumber] = framePos;
|
||||||
|
thumbnailNumber++;
|
||||||
|
|
||||||
|
}
|
||||||
|
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -630,14 +729,14 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return fileSize.toString();
|
return getFileSize().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(GroupKey otherGroupKey) {
|
public int compareTo(GroupKey otherGroupKey) {
|
||||||
if (otherGroupKey instanceof FileSizeGroupKey) {
|
if (otherGroupKey instanceof FileSizeGroupKey) {
|
||||||
FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherGroupKey;
|
FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherGroupKey;
|
||||||
return Integer.compare(fileSize.getRanking(), otherFileSizeGroupKey.fileSize.getRanking());
|
return Integer.compare(getFileSize().getRanking(), otherFileSizeGroupKey.getFileSize().getRanking());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -654,12 +753,19 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherKey;
|
FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherKey;
|
||||||
return fileSize.equals(otherFileSizeGroupKey.fileSize);
|
return getFileSize().equals(otherFileSizeGroupKey.getFileSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(fileSize.getRanking());
|
return Objects.hash(getFileSize().getRanking());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the fileSize
|
||||||
|
*/
|
||||||
|
FileSize getFileSize() {
|
||||||
|
return fileSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,16 +824,16 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return parentPath;
|
return getParentPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(GroupKey otherGroupKey) {
|
public int compareTo(GroupKey otherGroupKey) {
|
||||||
if (otherGroupKey instanceof ParentPathGroupKey) {
|
if (otherGroupKey instanceof ParentPathGroupKey) {
|
||||||
ParentPathGroupKey otherParentPathGroupKey = (ParentPathGroupKey) otherGroupKey;
|
ParentPathGroupKey otherParentPathGroupKey = (ParentPathGroupKey) otherGroupKey;
|
||||||
int comparisonResult = parentPath.compareTo(otherParentPathGroupKey.parentPath);
|
int comparisonResult = getParentPath().compareTo(otherParentPathGroupKey.getParentPath());
|
||||||
if (comparisonResult == 0) {
|
if (comparisonResult == 0) {
|
||||||
comparisonResult = parentID.compareTo(otherParentPathGroupKey.parentID);
|
comparisonResult = getParentID().compareTo(otherParentPathGroupKey.getParentID());
|
||||||
}
|
}
|
||||||
return comparisonResult;
|
return comparisonResult;
|
||||||
} else {
|
} else {
|
||||||
@ -746,16 +852,30 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ParentPathGroupKey otherParentPathGroupKey = (ParentPathGroupKey) otherKey;
|
ParentPathGroupKey otherParentPathGroupKey = (ParentPathGroupKey) otherKey;
|
||||||
return parentPath.equals(otherParentPathGroupKey.parentPath) && parentID.equals(otherParentPathGroupKey.parentID);
|
return getParentPath().equals(otherParentPathGroupKey.getParentPath()) && getParentID().equals(otherParentPathGroupKey.getParentID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hashCode = 11;
|
int hashCode = 11;
|
||||||
hashCode = 61 * hashCode + Objects.hash(parentPath);
|
hashCode = 61 * hashCode + Objects.hash(getParentPath());
|
||||||
hashCode = 61 * hashCode + Objects.hash(parentID);
|
hashCode = 61 * hashCode + Objects.hash(getParentID());
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the parentPath
|
||||||
|
*/
|
||||||
|
String getParentPath() {
|
||||||
|
return parentPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the parentID
|
||||||
|
*/
|
||||||
|
Long getParentID() {
|
||||||
|
return parentID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -805,7 +925,7 @@ class FileSearch {
|
|||||||
public int compareTo(GroupKey otherGroupKey) {
|
public int compareTo(GroupKey otherGroupKey) {
|
||||||
if (otherGroupKey instanceof DataSourceGroupKey) {
|
if (otherGroupKey instanceof DataSourceGroupKey) {
|
||||||
DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherGroupKey;
|
DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherGroupKey;
|
||||||
return Long.compare(dataSourceID, otherDataSourceGroupKey.dataSourceID);
|
return Long.compare(getDataSourceID(), otherDataSourceGroupKey.getDataSourceID());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -822,12 +942,19 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherKey;
|
DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherKey;
|
||||||
return dataSourceID == otherDataSourceGroupKey.dataSourceID;
|
return getDataSourceID() == otherDataSourceGroupKey.getDataSourceID();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(dataSourceID);
|
return Objects.hash(getDataSourceID());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the dataSourceID
|
||||||
|
*/
|
||||||
|
long getDataSourceID() {
|
||||||
|
return dataSourceID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,14 +992,14 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return fileType.toString();
|
return getFileType().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(GroupKey otherGroupKey) {
|
public int compareTo(GroupKey otherGroupKey) {
|
||||||
if (otherGroupKey instanceof FileTypeGroupKey) {
|
if (otherGroupKey instanceof FileTypeGroupKey) {
|
||||||
FileTypeGroupKey otherFileTypeGroupKey = (FileTypeGroupKey) otherGroupKey;
|
FileTypeGroupKey otherFileTypeGroupKey = (FileTypeGroupKey) otherGroupKey;
|
||||||
return Integer.compare(fileType.getRanking(), otherFileTypeGroupKey.fileType.getRanking());
|
return Integer.compare(getFileType().getRanking(), otherFileTypeGroupKey.getFileType().getRanking());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -889,12 +1016,19 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileTypeGroupKey otherFileTypeGroupKey = (FileTypeGroupKey) otherKey;
|
FileTypeGroupKey otherFileTypeGroupKey = (FileTypeGroupKey) otherKey;
|
||||||
return fileType.equals(otherFileTypeGroupKey.fileType);
|
return getFileType().equals(otherFileTypeGroupKey.getFileType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(fileType.getRanking());
|
return Objects.hash(getFileType().getRanking());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the fileType
|
||||||
|
*/
|
||||||
|
FileType getFileType() {
|
||||||
|
return fileType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,7 +1126,7 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return keywordListNamesString;
|
return getKeywordListNamesString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1001,17 +1135,17 @@ class FileSearch {
|
|||||||
KeywordListGroupKey otherKeywordListNamesGroupKey = (KeywordListGroupKey) otherGroupKey;
|
KeywordListGroupKey otherKeywordListNamesGroupKey = (KeywordListGroupKey) otherGroupKey;
|
||||||
|
|
||||||
// Put the empty list at the end
|
// Put the empty list at the end
|
||||||
if (keywordListNames.isEmpty()) {
|
if (getKeywordListNames().isEmpty()) {
|
||||||
if (otherKeywordListNamesGroupKey.keywordListNames.isEmpty()) {
|
if (otherKeywordListNamesGroupKey.getKeywordListNames().isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (otherKeywordListNamesGroupKey.keywordListNames.isEmpty()) {
|
} else if (otherKeywordListNamesGroupKey.getKeywordListNames().isEmpty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return keywordListNamesString.compareTo(otherKeywordListNamesGroupKey.keywordListNamesString);
|
return getKeywordListNamesString().compareTo(otherKeywordListNamesGroupKey.getKeywordListNamesString());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -1028,12 +1162,26 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeywordListGroupKey otherKeywordListGroupKey = (KeywordListGroupKey) otherKey;
|
KeywordListGroupKey otherKeywordListGroupKey = (KeywordListGroupKey) otherKey;
|
||||||
return keywordListNamesString.equals(otherKeywordListGroupKey.keywordListNamesString);
|
return getKeywordListNamesString().equals(otherKeywordListGroupKey.getKeywordListNamesString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(keywordListNamesString);
|
return Objects.hash(getKeywordListNamesString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the keywordListNames
|
||||||
|
*/
|
||||||
|
List<String> getKeywordListNames() {
|
||||||
|
return Collections.unmodifiableList(keywordListNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the keywordListNamesString
|
||||||
|
*/
|
||||||
|
String getKeywordListNamesString() {
|
||||||
|
return keywordListNamesString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1135,14 +1283,14 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return frequency.toString();
|
return getFrequency().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(GroupKey otherGroupKey) {
|
public int compareTo(GroupKey otherGroupKey) {
|
||||||
if (otherGroupKey instanceof FrequencyGroupKey) {
|
if (otherGroupKey instanceof FrequencyGroupKey) {
|
||||||
FrequencyGroupKey otherFrequencyGroupKey = (FrequencyGroupKey) otherGroupKey;
|
FrequencyGroupKey otherFrequencyGroupKey = (FrequencyGroupKey) otherGroupKey;
|
||||||
return Integer.compare(frequency.getRanking(), otherFrequencyGroupKey.frequency.getRanking());
|
return Integer.compare(getFrequency().getRanking(), otherFrequencyGroupKey.getFrequency().getRanking());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -1159,12 +1307,19 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FrequencyGroupKey otherFrequencyGroupKey = (FrequencyGroupKey) otherKey;
|
FrequencyGroupKey otherFrequencyGroupKey = (FrequencyGroupKey) otherKey;
|
||||||
return frequency.equals(otherFrequencyGroupKey.frequency);
|
return getFrequency().equals(otherFrequencyGroupKey.getFrequency());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(frequency.getRanking());
|
return Objects.hash(getFrequency().getRanking());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the frequency
|
||||||
|
*/
|
||||||
|
Frequency getFrequency() {
|
||||||
|
return frequency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1261,7 +1416,7 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return hashSetNamesString;
|
return getHashSetNamesString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1270,17 +1425,17 @@ class FileSearch {
|
|||||||
HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherGroupKey;
|
HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherGroupKey;
|
||||||
|
|
||||||
// Put the empty list at the end
|
// Put the empty list at the end
|
||||||
if (hashSetNames.isEmpty()) {
|
if (getHashSetNames().isEmpty()) {
|
||||||
if (otherHashHitsGroupKey.hashSetNames.isEmpty()) {
|
if (otherHashHitsGroupKey.getHashSetNames().isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (otherHashHitsGroupKey.hashSetNames.isEmpty()) {
|
} else if (otherHashHitsGroupKey.getHashSetNames().isEmpty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return hashSetNamesString.compareTo(otherHashHitsGroupKey.hashSetNamesString);
|
return getHashSetNamesString().compareTo(otherHashHitsGroupKey.getHashSetNamesString());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -1297,12 +1452,26 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherKey;
|
HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherKey;
|
||||||
return hashSetNamesString.equals(otherHashHitsGroupKey.hashSetNamesString);
|
return getHashSetNamesString().equals(otherHashHitsGroupKey.getHashSetNamesString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(hashSetNamesString);
|
return Objects.hash(getHashSetNamesString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the hashSetNames
|
||||||
|
*/
|
||||||
|
List<String> getHashSetNames() {
|
||||||
|
return Collections.unmodifiableList(hashSetNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the hashSetNamesString
|
||||||
|
*/
|
||||||
|
String getHashSetNamesString() {
|
||||||
|
return hashSetNamesString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1401,7 +1570,7 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return interestingItemSetNamesString;
|
return getInterestingItemSetNamesString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1410,17 +1579,17 @@ class FileSearch {
|
|||||||
InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherGroupKey;
|
InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherGroupKey;
|
||||||
|
|
||||||
// Put the empty list at the end
|
// Put the empty list at the end
|
||||||
if (this.interestingItemSetNames.isEmpty()) {
|
if (this.getInterestingItemSetNames().isEmpty()) {
|
||||||
if (otherInterestingItemGroupKey.interestingItemSetNames.isEmpty()) {
|
if (otherInterestingItemGroupKey.getInterestingItemSetNames().isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (otherInterestingItemGroupKey.interestingItemSetNames.isEmpty()) {
|
} else if (otherInterestingItemGroupKey.getInterestingItemSetNames().isEmpty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return interestingItemSetNamesString.compareTo(otherInterestingItemGroupKey.interestingItemSetNamesString);
|
return getInterestingItemSetNamesString().compareTo(otherInterestingItemGroupKey.getInterestingItemSetNamesString());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -1437,12 +1606,26 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherKey;
|
InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherKey;
|
||||||
return interestingItemSetNamesString.equals(otherInterestingItemGroupKey.interestingItemSetNamesString);
|
return getInterestingItemSetNamesString().equals(otherInterestingItemGroupKey.getInterestingItemSetNamesString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(interestingItemSetNamesString);
|
return Objects.hash(getInterestingItemSetNamesString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the interestingItemSetNames
|
||||||
|
*/
|
||||||
|
List<String> getInterestingItemSetNames() {
|
||||||
|
return Collections.unmodifiableList(interestingItemSetNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the interestingItemSetNamesString
|
||||||
|
*/
|
||||||
|
String getInterestingItemSetNamesString() {
|
||||||
|
return interestingItemSetNamesString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1540,7 +1723,7 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return objectDetectedNamesString;
|
return getObjectDetectedNamesString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1549,17 +1732,17 @@ class FileSearch {
|
|||||||
ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherGroupKey;
|
ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherGroupKey;
|
||||||
|
|
||||||
// Put the empty list at the end
|
// Put the empty list at the end
|
||||||
if (this.objectDetectedNames.isEmpty()) {
|
if (this.getObjectDetectedNames().isEmpty()) {
|
||||||
if (otherObjectDetectedGroupKey.objectDetectedNames.isEmpty()) {
|
if (otherObjectDetectedGroupKey.getObjectDetectedNames().isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (otherObjectDetectedGroupKey.objectDetectedNames.isEmpty()) {
|
} else if (otherObjectDetectedGroupKey.getObjectDetectedNames().isEmpty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return objectDetectedNamesString.compareTo(otherObjectDetectedGroupKey.objectDetectedNamesString);
|
return getObjectDetectedNamesString().compareTo(otherObjectDetectedGroupKey.getObjectDetectedNamesString());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -1576,12 +1759,26 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherKey;
|
ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherKey;
|
||||||
return objectDetectedNamesString.equals(otherObjectDetectedGroupKey.objectDetectedNamesString);
|
return getObjectDetectedNamesString().equals(otherObjectDetectedGroupKey.getObjectDetectedNamesString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(objectDetectedNamesString);
|
return Objects.hash(getObjectDetectedNamesString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the objectDetectedNames
|
||||||
|
*/
|
||||||
|
List<String> getObjectDetectedNames() {
|
||||||
|
return Collections.unmodifiableList(objectDetectedNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the objectDetectedNamesString
|
||||||
|
*/
|
||||||
|
String getObjectDetectedNamesString() {
|
||||||
|
return objectDetectedNamesString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1698,7 +1895,7 @@ class FileSearch {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getDisplayName() {
|
String getDisplayName() {
|
||||||
return tagNamesString;
|
return getTagNamesString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1707,17 +1904,17 @@ class FileSearch {
|
|||||||
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherGroupKey;
|
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherGroupKey;
|
||||||
|
|
||||||
// Put the empty list at the end
|
// Put the empty list at the end
|
||||||
if (tagNames.isEmpty()) {
|
if (getTagNames().isEmpty()) {
|
||||||
if (otherFileTagGroupKey.tagNames.isEmpty()) {
|
if (otherFileTagGroupKey.getTagNames().isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (otherFileTagGroupKey.tagNames.isEmpty()) {
|
} else if (otherFileTagGroupKey.getTagNames().isEmpty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tagNamesString.compareTo(otherFileTagGroupKey.tagNamesString);
|
return getTagNamesString().compareTo(otherFileTagGroupKey.getTagNamesString());
|
||||||
} else {
|
} else {
|
||||||
return compareClassNames(otherGroupKey);
|
return compareClassNames(otherGroupKey);
|
||||||
}
|
}
|
||||||
@ -1734,12 +1931,26 @@ class FileSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherKey;
|
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherKey;
|
||||||
return tagNamesString.equals(otherFileTagGroupKey.tagNamesString);
|
return getTagNamesString().equals(otherFileTagGroupKey.getTagNamesString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(tagNamesString);
|
return Objects.hash(getTagNamesString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the tagNames
|
||||||
|
*/
|
||||||
|
List<String> getTagNames() {
|
||||||
|
return Collections.unmodifiableList(tagNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the tagNamesString
|
||||||
|
*/
|
||||||
|
String getTagNamesString() {
|
||||||
|
return tagNamesString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1786,13 +1997,8 @@ class FileSearch {
|
|||||||
if (otherKey == this) {
|
if (otherKey == this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(otherKey instanceof NoGroupingGroupKey)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// As long as the other key is the same type, they are equal
|
// As long as the other key is the same type, they are equal
|
||||||
return true;
|
return otherKey instanceof NoGroupingGroupKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,6 +76,7 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
private PageWorker pageWorker;
|
private PageWorker pageWorker;
|
||||||
private final List<SwingWorker<Void, Void>> thumbnailWorkers = new ArrayList<>();
|
private final List<SwingWorker<Void, Void>> thumbnailWorkers = new ArrayList<>();
|
||||||
private final DefaultListModel<AbstractFile> instancesListModel = new DefaultListModel<>();
|
private final DefaultListModel<AbstractFile> instancesListModel = new DefaultListModel<>();
|
||||||
|
private ListSelectionListener listener = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form ResultsPanel.
|
* Creates new form ResultsPanel.
|
||||||
@ -89,11 +90,15 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
videoThumbnailViewer.addListSelectionListener((e) -> {
|
videoThumbnailViewer.addListSelectionListener((e) -> {
|
||||||
if (!e.getValueIsAdjusting()) {
|
if (!e.getValueIsAdjusting()) {
|
||||||
populateInstancesList();
|
populateInstancesList();
|
||||||
|
} else {
|
||||||
|
instancesList.clearSelection();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
imageThumbnailViewer.addListSelectionListener((e) -> {
|
imageThumbnailViewer.addListSelectionListener((e) -> {
|
||||||
if (!e.getValueIsAdjusting()) {
|
if (!e.getValueIsAdjusting()) {
|
||||||
populateInstancesList();
|
populateInstancesList();
|
||||||
|
} else {
|
||||||
|
instancesList.clearSelection();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//Add the context menu when right clicking
|
//Add the context menu when right clicking
|
||||||
@ -126,7 +131,9 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param listener The ListSelectionListener to add to the instances list.
|
* @param listener The ListSelectionListener to add to the instances list.
|
||||||
*/
|
*/
|
||||||
void addListSelectionListener(ListSelectionListener listener) {
|
void addListSelectionListener(ListSelectionListener newListener) {
|
||||||
|
instancesList.removeListSelectionListener(listener);
|
||||||
|
listener = newListener;
|
||||||
instancesList.addListSelectionListener(listener);
|
instancesList.addListSelectionListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,10 +142,12 @@ public class ResultsPanel extends javax.swing.JPanel {
|
|||||||
*/
|
*/
|
||||||
synchronized void populateInstancesList() {
|
synchronized void populateInstancesList() {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
instancesList.removeListSelectionListener(listener);
|
||||||
instancesListModel.removeAllElements();
|
instancesListModel.removeAllElements();
|
||||||
for (AbstractFile file : getInstancesForSelected()) {
|
for (AbstractFile file : getInstancesForSelected()) {
|
||||||
instancesListModel.addElement(file);
|
instancesListModel.addElement(file);
|
||||||
}
|
}
|
||||||
|
instancesList.addListSelectionListener(listener);
|
||||||
if (!instancesListModel.isEmpty()) {
|
if (!instancesListModel.isEmpty()) {
|
||||||
instancesList.setSelectedIndex(0);
|
instancesList.setSelectedIndex(0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user