mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-13 00:16:16 +00:00
cleanup FileTypeUtils and ImageGalleryController, and DrawableFile, etc...
This commit is contained in:
parent
e3aa664520
commit
626f97ff06
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Copyright 2015-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -38,7 +38,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Enum style singleton to provide utilities related to questions about a files
|
||||
* type, and wheather it should be supported in Image Gallery.
|
||||
* type, and whether it should be supported in Image Gallery.
|
||||
*
|
||||
* TODO: refactor this to remove code that duplicates
|
||||
* org.sleuthkit.autopsy.coreutils.ImageUtils
|
||||
@ -74,6 +74,7 @@ public enum FileTypeUtils {
|
||||
* videoExtensions sets.
|
||||
*/
|
||||
private static final Set<String> supportedExtensions;
|
||||
|
||||
/**
|
||||
* Lazily instantiated FileTypeDetector to use when the mimetype of a file
|
||||
* is needed
|
||||
@ -119,6 +120,14 @@ public enum FileTypeUtils {
|
||||
videoMimeTypes.addAll(Arrays.asList("application/x-shockwave-flash"));
|
||||
|
||||
supportedMimeTypes.addAll(videoMimeTypes);
|
||||
|
||||
/*
|
||||
* TODO: windows .cur cursor files get misidentified as
|
||||
* application/x-123, so we claim to support application/x-123 so we
|
||||
* don't miss them: ie this is a hack to cover another bug. when this is
|
||||
* fixed, we should remove application/x-123 from the list of supported
|
||||
* mime types.
|
||||
*/
|
||||
supportedMimeTypes.addAll(Arrays.asList("application/x-123"));
|
||||
|
||||
//add list of mimetypes ImageIO claims to support
|
||||
@ -126,21 +135,13 @@ public enum FileTypeUtils {
|
||||
.map(String::toLowerCase)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
supportedMimeTypes.removeIf("application/octet-stream"::equals); //this is rearely usefull
|
||||
supportedMimeTypes.removeIf("application/octet-stream"::equals); //this is rarely usefull
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Set<String> getAllSupportedMimeTypes() {
|
||||
return Collections.unmodifiableSet(supportedMimeTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static Set<String> getAllSupportedExtensions() {
|
||||
return Collections.unmodifiableSet(supportedExtensions);
|
||||
}
|
||||
@ -167,12 +168,9 @@ public enum FileTypeUtils {
|
||||
*/
|
||||
public static boolean isDrawable(AbstractFile file) throws TskCoreException {
|
||||
return hasDrawableMimeType(file).orElseGet(() -> {
|
||||
final boolean contains = FileTypeUtils.supportedExtensions.contains(file.getNameExtension());
|
||||
final boolean jpegFileHeader = ImageUtils.isJpegFileHeader(file);
|
||||
final boolean pngFileHeader = ImageUtils.isPngFileHeader(file);
|
||||
return contains
|
||||
|| jpegFileHeader
|
||||
|| pngFileHeader;
|
||||
return FileTypeUtils.supportedExtensions.contains(file.getNameExtension().toLowerCase())
|
||||
|| ImageUtils.isJpegFileHeader(file)
|
||||
|| ImageUtils.isPngFileHeader(file);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||
import org.sleuthkit.autopsy.coreutils.History;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.imagegallery.actions.UndoRedoManager;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
|
||||
@ -695,9 +696,8 @@ public final class ImageGalleryController implements Executor {
|
||||
* Task that runs when image gallery listening is (re) enabled.
|
||||
*
|
||||
* Grabs all files with supported image/video mime types or extensions, and
|
||||
* adds them to the Drawable DB. Uses the presence of TSK_FILE_TYPE_SIG
|
||||
* attributes as a approximation to 'analyzed'.
|
||||
*
|
||||
* adds them to the Drawable DB. Uses the presence of a mimetype as an
|
||||
* approximation to 'analyzed'.
|
||||
*/
|
||||
static private class CopyAnalyzedFiles extends InnerTask {
|
||||
|
||||
@ -747,7 +747,7 @@ public final class ImageGalleryController implements Executor {
|
||||
int units = 0;
|
||||
for (final AbstractFile f : files) {
|
||||
if (isCancelled()) {
|
||||
LOGGER.log(Level.WARNING, "task cancelled: not all contents may be transfered to database");
|
||||
LOGGER.log(Level.WARNING, "Task cancelled: not all contents may be transfered to drawable database.");
|
||||
progressHandle.finish();
|
||||
break;
|
||||
}
|
||||
@ -794,6 +794,7 @@ public final class ImageGalleryController implements Executor {
|
||||
} catch (TskCoreException ex) {
|
||||
progressHandle.progress("Stopping copy to drawable db task.");
|
||||
Logger.getLogger(CopyAnalyzedFiles.class.getName()).log(Level.WARNING, "Stopping copy to drawable db task. Failed to transfer all database contents: " + ex.getMessage());
|
||||
MessageNotifyUtil.Notify.warn("There was an error populating Image Gallery database.", ex.getMessage());
|
||||
progressHandle.finish();
|
||||
updateMessage("");
|
||||
updateProgress(-1.0);
|
||||
@ -810,7 +811,7 @@ public final class ImageGalleryController implements Executor {
|
||||
|
||||
/**
|
||||
* task that does pre-ingest copy over of files from a new datasource (uses
|
||||
* fs_obj_id to identify files from new datasource) *
|
||||
* fs_obj_id to identify files from new datasources)
|
||||
*
|
||||
* TODO: create methods to simplify progress value/text updates to both
|
||||
* netbeans and ImageGallery progress/status
|
||||
|
@ -33,7 +33,7 @@ public class CategorizeGroupAction extends Action {
|
||||
|
||||
public CategorizeGroupAction(Category cat, ImageGalleryController controller) {
|
||||
super(cat.getDisplayName(), (javafx.event.ActionEvent actionEvent) -> {
|
||||
Set<Long> fileIdSet = ImmutableSet.copyOf(controller.viewState().get().getGroup().fileIds());
|
||||
Set<Long> fileIdSet = ImmutableSet.copyOf(controller.viewState().get().getGroup().getFileIDs());
|
||||
new CategorizeAction(controller).addTagsToFiles(controller.getTagsManager().getTagName(cat), "", fileIdSet);
|
||||
});
|
||||
setGraphic(new ImageView(DrawableAttribute.CATEGORY.getIcon()));
|
||||
|
@ -33,7 +33,7 @@ public class TagGroupAction extends Action {
|
||||
|
||||
public TagGroupAction(final TagName tagName, ImageGalleryController controller) {
|
||||
super(tagName.getDisplayName(), (javafx.event.ActionEvent actionEvent) -> {
|
||||
Set<Long> fileIdSet = ImmutableSet.copyOf(controller.viewState().get().getGroup().fileIds());
|
||||
Set<Long> fileIdSet = ImmutableSet.copyOf(controller.viewState().get().getGroup().getFileIDs());
|
||||
new AddDrawableTagAction(controller).addTagsToFiles(tagName, "", fileIdSet);
|
||||
});
|
||||
setGraphic(new ImageView(DrawableAttribute.TAGS.getIcon()));
|
||||
|
@ -40,13 +40,22 @@ import org.sleuthkit.datamodel.TagName;
|
||||
public class DrawableAttribute<T extends Comparable<T>> {
|
||||
|
||||
public final static DrawableAttribute<String> MD5_HASH =
|
||||
new DrawableAttribute<>(AttributeName.MD5_HASH, "MD5 Hash", false, "icon-hashtag.png", f -> Collections.singleton(f.getMd5Hash()));
|
||||
new DrawableAttribute<>(AttributeName.MD5_HASH, "MD5 Hash",
|
||||
false,
|
||||
"icon-hashtag.png",
|
||||
f -> Collections.singleton(f.getMd5Hash()));
|
||||
|
||||
public final static DrawableAttribute<String> NAME =
|
||||
new DrawableAttribute<>(AttributeName.NAME, "Name", true, "folder-rename.png", f -> Collections.singleton(f.getName()));
|
||||
new DrawableAttribute<>(AttributeName.NAME, "Name",
|
||||
true,
|
||||
"folder-rename.png",
|
||||
f -> Collections.singleton(f.getName()));
|
||||
|
||||
public final static DrawableAttribute<Boolean> ANALYZED =
|
||||
new DrawableAttribute<>(AttributeName.ANALYZED, "Analyzed", true, "", f -> Collections.singleton(f.isAnalyzed()));
|
||||
new DrawableAttribute<>(AttributeName.ANALYZED, "Analyzed",
|
||||
true,
|
||||
"",
|
||||
f -> Collections.singleton(f.isAnalyzed()));
|
||||
|
||||
/**
|
||||
* since categories are really just tags in autopsy, they are not dealt with
|
||||
@ -57,40 +66,76 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
* advantage. move categories into DrawableDB?
|
||||
*/
|
||||
public final static DrawableAttribute<Category> CATEGORY =
|
||||
new DrawableAttribute<>(AttributeName.CATEGORY, "Category", false, "category-icon.png", f -> Collections.singleton(f.getCategory()));
|
||||
new DrawableAttribute<>(AttributeName.CATEGORY, "Category",
|
||||
false,
|
||||
"category-icon.png",
|
||||
f -> Collections.singleton(f.getCategory()));
|
||||
|
||||
public final static DrawableAttribute<TagName> TAGS =
|
||||
new DrawableAttribute<>(AttributeName.TAGS, "Tags", false, "tag_red.png", DrawableFile::getTagNames);
|
||||
new DrawableAttribute<>(AttributeName.TAGS, "Tags",
|
||||
false,
|
||||
"tag_red.png",
|
||||
DrawableFile::getTagNames);
|
||||
|
||||
public final static DrawableAttribute<String> PATH =
|
||||
new DrawableAttribute<>(AttributeName.PATH, "Path", true, "folder_picture.png", f -> Collections.singleton(f.getDrawablePath()));
|
||||
new DrawableAttribute<>(AttributeName.PATH, "Path",
|
||||
true,
|
||||
"folder_picture.png",
|
||||
f -> Collections.singleton(f.getDrawablePath()));
|
||||
|
||||
public final static DrawableAttribute<String> CREATED_TIME =
|
||||
new DrawableAttribute<>(AttributeName.CREATED_TIME, "Created Time", true, "clock--plus.png", f -> Collections.singleton(ContentUtils.getStringTime(f.getCrtime(), f)));
|
||||
new DrawableAttribute<>(AttributeName.CREATED_TIME, "Created Time",
|
||||
true,
|
||||
"clock--plus.png",
|
||||
f -> Collections.singleton(ContentUtils.getStringTime(f.getCrtime(), f)));
|
||||
|
||||
public final static DrawableAttribute<String> MODIFIED_TIME =
|
||||
new DrawableAttribute<>(AttributeName.MODIFIED_TIME, "Modified Time", true, "clock--pencil.png", f -> Collections.singleton(ContentUtils.getStringTime(f.getMtime(), f)));
|
||||
new DrawableAttribute<>(AttributeName.MODIFIED_TIME, "Modified Time",
|
||||
true,
|
||||
"clock--pencil.png",
|
||||
f -> Collections.singleton(ContentUtils.getStringTime(f.getMtime(), f)));
|
||||
|
||||
public final static DrawableAttribute<String> MAKE =
|
||||
new DrawableAttribute<>(AttributeName.MAKE, "Camera Make", true, "camera.png", f -> Collections.singleton(f.getMake()));
|
||||
new DrawableAttribute<>(AttributeName.MAKE, "Camera Make",
|
||||
true,
|
||||
"camera.png",
|
||||
f -> Collections.singleton(f.getMake()));
|
||||
|
||||
public final static DrawableAttribute<String> MODEL =
|
||||
new DrawableAttribute<>(AttributeName.MODEL, "Camera Model", true, "camera.png", f -> Collections.singleton(f.getModel()));
|
||||
new DrawableAttribute<>(AttributeName.MODEL, "Camera Model",
|
||||
true,
|
||||
"camera.png",
|
||||
f -> Collections.singleton(f.getModel()));
|
||||
|
||||
public final static DrawableAttribute<String> HASHSET =
|
||||
new DrawableAttribute<>(AttributeName.HASHSET, "Hashset", true, "hashset_hits.png", DrawableFile::getHashSetNamesUnchecked);
|
||||
new DrawableAttribute<>(AttributeName.HASHSET, "Hashset",
|
||||
true,
|
||||
"hashset_hits.png",
|
||||
DrawableFile::getHashSetNamesUnchecked);
|
||||
|
||||
public final static DrawableAttribute<Long> OBJ_ID =
|
||||
new DrawableAttribute<>(AttributeName.OBJ_ID, "Internal Object ID", true, "", f -> Collections.singleton(f.getId()));
|
||||
new DrawableAttribute<>(AttributeName.OBJ_ID, "Internal Object ID",
|
||||
true,
|
||||
"",
|
||||
f -> Collections.singleton(f.getId()));
|
||||
|
||||
public final static DrawableAttribute<Double> WIDTH =
|
||||
new DrawableAttribute<>(AttributeName.WIDTH, "Width", false, "arrow-resize.png", f -> Collections.singleton(f.getWidth()));
|
||||
new DrawableAttribute<>(AttributeName.WIDTH, "Width",
|
||||
false,
|
||||
"arrow-resize.png",
|
||||
f -> Collections.singleton(f.getWidth()));
|
||||
|
||||
public final static DrawableAttribute<Double> HEIGHT =
|
||||
new DrawableAttribute<>(AttributeName.HEIGHT, "Height", false, "arrow-resize-090.png", f -> Collections.singleton(f.getHeight()));
|
||||
new DrawableAttribute<>(AttributeName.HEIGHT, "Height",
|
||||
false,
|
||||
"arrow-resize-090.png",
|
||||
f -> Collections.singleton(f.getHeight()));
|
||||
|
||||
public final static DrawableAttribute<String> MIME_TYPE =
|
||||
new DrawableAttribute<>(AttributeName.MIME_TYPE, "MIME type", false, " ", f -> Collections.singleton(f.getMIMEType()));
|
||||
new DrawableAttribute<>(AttributeName.MIME_TYPE, "MIME type",
|
||||
false,
|
||||
"mime_types.png",
|
||||
f -> Collections.singleton(f.getMIMEType()));
|
||||
|
||||
final private static List< DrawableAttribute<?>> groupables =
|
||||
Arrays.asList(PATH, HASHSET, CATEGORY, TAGS, MAKE, MODEL, MIME_TYPE);
|
||||
@ -105,9 +150,10 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
this.attrName = name;
|
||||
this.displayName = new ReadOnlyStringWrapper(displayName);
|
||||
this.isDBColumn = isDBColumn;
|
||||
this.imageName = imageName;
|
||||
this.extractor = extractor;
|
||||
this.imageName = imageName;
|
||||
}
|
||||
private final String imageName;
|
||||
|
||||
private Image icon;
|
||||
|
||||
@ -117,17 +163,26 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
|
||||
private final StringProperty displayName;
|
||||
|
||||
private final String imageName;
|
||||
|
||||
public Image getIcon() {
|
||||
if (icon == null) {
|
||||
if (StringUtils.isBlank(imageName) == false) {
|
||||
/*
|
||||
* There is some issue with loading this in the constructor which gets
|
||||
* called at class load time, so instead we load them lazily the first
|
||||
* time they are needed
|
||||
*/
|
||||
if (null == icon && StringUtils.isNotBlank(imageName)) {
|
||||
this.icon = new Image("org/sleuthkit/autopsy/imagegallery/images/" + imageName, true);
|
||||
}
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: override this to load per value icons form some attributes like
|
||||
* mime-type and category
|
||||
*/
|
||||
public Image getIconForValue(T val) {
|
||||
return getIcon();
|
||||
}
|
||||
|
||||
public static List<DrawableAttribute<?>> getGroupableAttrs() {
|
||||
return Collections.unmodifiableList(groupables);
|
||||
}
|
||||
@ -144,6 +199,10 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
return displayName.get();
|
||||
}
|
||||
|
||||
public Collection<T> getValue(DrawableFile<?> f) {
|
||||
return extractor.apply(f);
|
||||
}
|
||||
|
||||
public static enum AttributeName {
|
||||
|
||||
NAME,
|
||||
@ -162,8 +221,4 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
MD5_HASH,
|
||||
MIME_TYPE;
|
||||
}
|
||||
|
||||
public Collection<T> getValue(DrawableFile<?> f) {
|
||||
return extractor.apply(f);
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import javax.swing.SortOrder;
|
||||
@ -127,7 +126,7 @@ public final class DrawableDB {
|
||||
*/
|
||||
private final Map<DrawableAttribute<?>, PreparedStatement> groupStatementMap = new HashMap<>();
|
||||
|
||||
private GroupManager groupManager;
|
||||
private final GroupManager groupManager;
|
||||
|
||||
private final Path dbPath;
|
||||
|
||||
@ -1200,6 +1199,7 @@ public final class DrawableDB {
|
||||
LOGGER.log(Level.SEVERE, "Failed to get content tags by tag name.", ex1);
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,7 +40,6 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.imagegallery.FileTypeUtils;
|
||||
import org.sleuthkit.autopsy.imagegallery.ThumbnailCache;
|
||||
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
@ -79,8 +78,7 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
return create(Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(id), analyzed);
|
||||
}
|
||||
|
||||
SoftReference<Image> imageRef;
|
||||
// SoftReference<Image> thumbref;
|
||||
private SoftReference<Image> imageRef;
|
||||
|
||||
private String drawablePath;
|
||||
|
||||
@ -327,14 +325,6 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
|
||||
abstract Double getHeight();
|
||||
|
||||
public String getMIMEType() {
|
||||
try {
|
||||
return new FileTypeDetector().getFileType(file);
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException | TskCoreException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDrawablePath() {
|
||||
if (drawablePath != null) {
|
||||
return drawablePath;
|
||||
|
@ -23,13 +23,14 @@ import com.google.common.eventbus.Subscribe;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.DoubleBinding;
|
||||
import javafx.beans.binding.IntegerBinding;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.ReadOnlyLongProperty;
|
||||
import javafx.beans.property.ReadOnlyLongWrapper;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||
@ -49,25 +50,37 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
private final GroupKey<?> groupKey;
|
||||
private final ObservableList<Long> fileIDs = FXCollections.observableArrayList();
|
||||
private final ObservableList<Long> unmodifiableFileIDS = FXCollections.unmodifiableObservableList(fileIDs);
|
||||
|
||||
//cache the number of files in this groups with hashset hits
|
||||
private final ReadOnlyLongWrapper hashSetHitsCount = new ReadOnlyLongWrapper(-1);
|
||||
|
||||
public ReadOnlyLongProperty hashSetHitsCountProperty() {
|
||||
return hashSetHitsCount.getReadOnlyProperty();
|
||||
}
|
||||
private final ReadOnlyBooleanWrapper seen = new ReadOnlyBooleanWrapper(false);
|
||||
//cache the number ofuncategorized files in this group
|
||||
private final ReadOnlyLongWrapper uncatCount = new ReadOnlyLongWrapper(-1);
|
||||
//cache the hash hit density for this group
|
||||
private final DoubleBinding hashDensity = hashSetHitsCount.multiply(100d).divide(Bindings.size(fileIDs));
|
||||
//cache if this group has been seen
|
||||
private final ReadOnlyBooleanWrapper seen = new ReadOnlyBooleanWrapper(false);
|
||||
|
||||
DrawableGroup(GroupKey<?> groupKey, Set<Long> filesInGroup, boolean seen) {
|
||||
this.groupKey = groupKey;
|
||||
this.fileIDs.setAll(filesInGroup);
|
||||
fileIDs.addListener((ListChangeListener.Change<? extends Long> listchange) -> {
|
||||
boolean seenChanged = false;
|
||||
while (false == seenChanged && listchange.next()) {
|
||||
seenChanged |= listchange.wasAdded();
|
||||
}
|
||||
invalidateProperties(seenChanged);
|
||||
});
|
||||
this.seen.set(seen);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ReturnOfCollectionOrArrayField")
|
||||
synchronized public ObservableList<Long> fileIds() {
|
||||
public synchronized ObservableList<Long> getFileIDs() {
|
||||
return unmodifiableFileIDS;
|
||||
}
|
||||
|
||||
final public GroupKey<?> groupKey;
|
||||
|
||||
public GroupKey<?> getGroupKey() {
|
||||
return groupKey;
|
||||
}
|
||||
@ -84,18 +97,7 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
return groupKey.getValueDisplayName();
|
||||
}
|
||||
|
||||
DrawableGroup(GroupKey<?> groupKey, Set<Long> filesInGroup, boolean seen) {
|
||||
this.groupKey = groupKey;
|
||||
this.fileIDs.setAll(filesInGroup);
|
||||
fileIDs.addListener((Observable observable) -> {
|
||||
hashSetHitsCount.set(-1);
|
||||
DrawableGroup.this.seen.set(false);
|
||||
});
|
||||
this.seen.set(seen);
|
||||
getUncategorizedCount();
|
||||
}
|
||||
|
||||
synchronized public int getSize() {
|
||||
public synchronized int getSize() {
|
||||
return fileIDs.size();
|
||||
}
|
||||
|
||||
@ -104,17 +106,19 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
}
|
||||
|
||||
public double getHashHitDensity() {
|
||||
return hashSetHitsCountProperty().divide((double) getSize()).get();
|
||||
getHashSetHitsCount(); //initialize hashSetHitsCount
|
||||
return hashDensity.get();
|
||||
}
|
||||
|
||||
synchronized private void invalidateUncatCount() {
|
||||
uncatCount.set(-1);
|
||||
public DoubleBinding hashHitDensityProperty() {
|
||||
getHashSetHitsCount(); //initialize hashSetHitsCount
|
||||
return hashDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of files in this group that have hash set hits
|
||||
*/
|
||||
synchronized public long getHashSetHitsCount() {
|
||||
public synchronized long getHashSetHitsCount() {
|
||||
if (hashSetHitsCount.get() < 0) {
|
||||
try {
|
||||
hashSetHitsCount.set(fileIDs.stream()
|
||||
@ -127,9 +131,15 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
}
|
||||
|
||||
return hashSetHitsCount.get();
|
||||
|
||||
}
|
||||
|
||||
final synchronized public long getUncategorizedCount() {
|
||||
public ReadOnlyLongProperty hashSetHitsCountProperty() {
|
||||
getHashSetHitsCount(); //initialize hashSetHitsCount
|
||||
return hashSetHitsCount.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public final synchronized long getUncategorizedCount() {
|
||||
if (uncatCount.get() < 0) {
|
||||
try {
|
||||
uncatCount.set(ImageGalleryController.getDefault().getDatabase().getCategoryCount(Category.ZERO, fileIDs));
|
||||
@ -143,7 +153,51 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
}
|
||||
|
||||
public ReadOnlyLongProperty uncatCountProperty() {
|
||||
getUncategorizedCount(); //initialize uncatCount
|
||||
return uncatCount.getReadOnlyProperty();
|
||||
|
||||
}
|
||||
|
||||
void setSeen(boolean isSeen) {
|
||||
this.seen.set(isSeen);
|
||||
}
|
||||
|
||||
public boolean isSeen() {
|
||||
return seen.get();
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanWrapper seenProperty() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public synchronized void handleCatChange(CategoryManager.CategoryChangeEvent event) {
|
||||
if (Iterables.any(event.getFileIDs(), fileIDs::contains)) {
|
||||
uncatCount.set(-1);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void addFile(Long f) {
|
||||
if (fileIDs.contains(f) == false) {
|
||||
fileIDs.add(f);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void setFiles(Set<? extends Long> newFileIds) {
|
||||
fileIDs.removeIf(fileID -> newFileIds.contains(fileID) == false);
|
||||
newFileIds.stream().forEach(this::addFile);
|
||||
}
|
||||
|
||||
synchronized void removeFile(Long f) {
|
||||
fileIDs.removeAll(f);
|
||||
}
|
||||
|
||||
private void invalidateProperties(boolean seenChanged) {
|
||||
if (seenChanged) {
|
||||
seen.set(false);
|
||||
}
|
||||
uncatCount.set(-1);
|
||||
hashSetHitsCount.set(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -170,50 +224,10 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
|
||||
((DrawableGroup) obj).groupKey);
|
||||
}
|
||||
|
||||
synchronized void addFile(Long f) {
|
||||
invalidateUncatCount();
|
||||
if (fileIDs.contains(f) == false) {
|
||||
fileIDs.add(f);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void setFiles(Set<? extends Long> newFileIds) {
|
||||
fileIDs.removeIf((Long t) -> newFileIds.contains(t) == false);
|
||||
|
||||
for (Long f : newFileIds) {
|
||||
if (fileIDs.contains(f) == false) {
|
||||
fileIDs.add(f);
|
||||
seen.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void removeFile(Long f) {
|
||||
fileIDs.removeAll(f);
|
||||
invalidateUncatCount();
|
||||
}
|
||||
|
||||
// By default, sort by group key name
|
||||
@Override
|
||||
public int compareTo(DrawableGroup other) {
|
||||
return this.groupKey.getValueDisplayName().compareTo(other.groupKey.getValueDisplayName());
|
||||
}
|
||||
|
||||
void setSeen(boolean isSeen) {
|
||||
this.seen.set(isSeen);
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanWrapper seenProperty() {
|
||||
return seen;
|
||||
}
|
||||
|
||||
public boolean isSeen() {
|
||||
return seen.get();
|
||||
}
|
||||
@Subscribe
|
||||
synchronized public void handleCatChange(CategoryManager.CategoryChangeEvent event) {
|
||||
if (Iterables.any(event.getFileIDs(), fileIDs::contains)) {
|
||||
invalidateUncatCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.imagegallery.datamodel.grouping;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javafx.scene.image.Image;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
@ -88,4 +89,7 @@ public class GroupKey<T extends Comparable<T>> implements Comparable<GroupKey<T>
|
||||
return val.compareTo(o.val);
|
||||
}
|
||||
|
||||
public Image getIcon() {
|
||||
return attr.getIconForValue(val);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Copyright 2013-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -35,7 +35,6 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@ -295,7 +294,7 @@ public class GroupManager {
|
||||
|
||||
// If we're grouping by category, we don't want to remove empty groups.
|
||||
if (groupKey.getAttribute() != DrawableAttribute.CATEGORY) {
|
||||
if (group.fileIds().isEmpty()) {
|
||||
if (group.getFileIDs().isEmpty()) {
|
||||
Platform.runLater(() -> {
|
||||
if (analyzedGroups.contains(group)) {
|
||||
analyzedGroups.remove(group);
|
||||
@ -357,12 +356,7 @@ public class GroupManager {
|
||||
Pattern.compile(",").splitAsStream(objIds)
|
||||
.map(Long::valueOf)
|
||||
.filter(db::isInDB)
|
||||
.findAny().ifPresent(new Consumer<Long>() {
|
||||
|
||||
public void accept(Long obj_id) {
|
||||
types.add(mimeType);
|
||||
}
|
||||
});
|
||||
.findAny().ifPresent(obj_id -> types.add(mimeType));
|
||||
}
|
||||
} catch (SQLException | TskCoreException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
@ -702,8 +696,8 @@ public class GroupManager {
|
||||
? "SELECT obj_id FROM tsk_files WHERE mime_type IS NULL"
|
||||
: "SELECT obj_id FROM tsk_files WHERE mime_type = '" + mimeType + "'";
|
||||
|
||||
try (SleuthkitCase.CaseDbQuery executeQuery = controller.getSleuthKitCase().executeQuery(query);) {
|
||||
ResultSet resultSet = executeQuery.getResultSet();
|
||||
try (SleuthkitCase.CaseDbQuery executeQuery = controller.getSleuthKitCase().executeQuery(query);
|
||||
ResultSet resultSet = executeQuery.getResultSet();) {
|
||||
while (resultSet.next()) {
|
||||
final long fileID = resultSet.getLong("obj_id");
|
||||
if (db.isInDB(fileID)) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-14 Basis Technology Corp.
|
||||
* Copyright 2013-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -59,7 +59,7 @@ public enum GroupSortBy implements ComparatorProvider {
|
||||
GROUP_BY_VALUE("Group Name", true, "folder-rename.png") {
|
||||
@Override
|
||||
public Comparator<DrawableGroup> getGrpComparator(final SortOrder sortOrder) {
|
||||
return applySortOrder(sortOrder, Comparator.comparing(t -> t.groupKey.getValueDisplayName()));
|
||||
return applySortOrder(sortOrder, Comparator.comparing(t -> t.getGroupByValueDislpayName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -71,10 +71,6 @@ public enum GroupSortBy implements ComparatorProvider {
|
||||
* don't sort the groups just use what ever order they come in (ingest
|
||||
* order)
|
||||
*/
|
||||
/**
|
||||
* don't sort the groups just use what ever order they come in (ingest
|
||||
* order)
|
||||
*/
|
||||
NONE("None", false, "prohibition.png") {
|
||||
@Override
|
||||
public Comparator<DrawableGroup> getGrpComparator(SortOrder sortOrder) {
|
||||
|
@ -254,7 +254,7 @@ public class GroupPane extends BorderPane {
|
||||
|
||||
private final InvalidationListener filesSyncListener = (observable) -> {
|
||||
final String header = getHeaderString();
|
||||
final List<Long> fileIds = getGroup().fileIds();
|
||||
final List<Long> fileIds = getGroup().getFileIDs();
|
||||
Platform.runLater(() -> {
|
||||
slideShowToggle.setDisable(fileIds.isEmpty());
|
||||
gridView.getItems().setAll(fileIds);
|
||||
@ -289,8 +289,8 @@ public class GroupPane extends BorderPane {
|
||||
}
|
||||
|
||||
//assign last selected file or if none first file in group
|
||||
if (slideShowFileID == null || getGroup().fileIds().contains(slideShowFileID) == false) {
|
||||
slideShowPane.setFile(getGroup().fileIds().get(0));
|
||||
if (slideShowFileID == null || getGroup().getFileIDs().contains(slideShowFileID) == false) {
|
||||
slideShowPane.setFile(getGroup().getFileIDs().get(0));
|
||||
} else {
|
||||
slideShowPane.setFile(slideShowFileID);
|
||||
}
|
||||
@ -324,7 +324,7 @@ public class GroupPane extends BorderPane {
|
||||
}
|
||||
|
||||
private void selectAllFiles() {
|
||||
selectionModel.clearAndSelectAll(getGroup().fileIds());
|
||||
selectionModel.clearAndSelectAll(getGroup().getFileIDs());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -676,7 +676,7 @@ public class GroupPane extends BorderPane {
|
||||
|
||||
if (isNull(viewState) || isNull(viewState.getGroup())) {
|
||||
if (nonNull(getGroup())) {
|
||||
getGroup().fileIds().removeListener(filesSyncListener);
|
||||
getGroup().getFileIDs().removeListener(filesSyncListener);
|
||||
}
|
||||
this.grouping.set(null);
|
||||
|
||||
@ -695,16 +695,16 @@ public class GroupPane extends BorderPane {
|
||||
} else {
|
||||
if (getGroup() != viewState.getGroup()) {
|
||||
if (nonNull(getGroup())) {
|
||||
getGroup().fileIds().removeListener(filesSyncListener);
|
||||
getGroup().getFileIDs().removeListener(filesSyncListener);
|
||||
}
|
||||
this.grouping.set(viewState.getGroup());
|
||||
|
||||
getGroup().fileIds().addListener(filesSyncListener);
|
||||
getGroup().getFileIDs().addListener(filesSyncListener);
|
||||
|
||||
final String header = getHeaderString();
|
||||
|
||||
Platform.runLater(() -> {
|
||||
gridView.getItems().setAll(getGroup().fileIds());
|
||||
gridView.getItems().setAll(getGroup().getFileIDs());
|
||||
slideShowToggle.setDisable(gridView.getItems().isEmpty());
|
||||
groupLabel.setText(header);
|
||||
resetScrollBar();
|
||||
@ -737,10 +737,10 @@ public class GroupPane extends BorderPane {
|
||||
|
||||
if (shiftDown) {
|
||||
//TODO: do more hear to implement slicker multiselect
|
||||
int endIndex = grouping.get().fileIds().indexOf(newFileID);
|
||||
int startIndex = IntStream.of(grouping.get().fileIds().size(), selectionAnchorIndex, endIndex).min().getAsInt();
|
||||
int endIndex = grouping.get().getFileIDs().indexOf(newFileID);
|
||||
int startIndex = IntStream.of(grouping.get().getFileIDs().size(), selectionAnchorIndex, endIndex).min().getAsInt();
|
||||
endIndex = IntStream.of(0, selectionAnchorIndex, endIndex).max().getAsInt();
|
||||
List<Long> subList = grouping.get().fileIds().subList(Math.max(0, startIndex), Math.min(endIndex, grouping.get().fileIds().size()) + 1);
|
||||
List<Long> subList = grouping.get().getFileIDs().subList(Math.max(0, startIndex), Math.min(endIndex, grouping.get().getFileIDs().size()) + 1);
|
||||
|
||||
selectionModel.clearAndSelectAll(subList.toArray(new Long[subList.size()]));
|
||||
selectionModel.select(newFileID);
|
||||
@ -802,7 +802,7 @@ public class GroupPane extends BorderPane {
|
||||
switch (t.getCode()) {
|
||||
case SHIFT:
|
||||
if (selectionAnchorIndex == null) {
|
||||
selectionAnchorIndex = grouping.get().fileIds().indexOf(selectionModel.lastSelectedProperty().get());
|
||||
selectionAnchorIndex = grouping.get().getFileIDs().indexOf(selectionModel.lastSelectedProperty().get());
|
||||
}
|
||||
t.consume();
|
||||
break;
|
||||
@ -880,7 +880,7 @@ public class GroupPane extends BorderPane {
|
||||
Long lastSelectFileId = selectionModel.lastSelectedProperty().get();
|
||||
|
||||
int lastSelectedIndex = lastSelectFileId != null
|
||||
? grouping.get().fileIds().indexOf(lastSelectFileId)
|
||||
? grouping.get().getFileIDs().indexOf(lastSelectFileId)
|
||||
: Optional.ofNullable(selectionAnchorIndex).orElse(0);
|
||||
|
||||
final int columns = Math.max((int) Math.floor((gridView.getWidth() - 18) / (gridView.getCellWidth() + gridView.getHorizontalCellSpacing() * 2)), 1);
|
||||
@ -889,15 +889,15 @@ public class GroupPane extends BorderPane {
|
||||
|
||||
// implement proper keyboard based multiselect
|
||||
int indexOfToBeSelectedTile = lastSelectedIndex + tileIndexMap.get(t.getCode());
|
||||
final int size = grouping.get().fileIds().size();
|
||||
final int size = grouping.get().getFileIDs().size();
|
||||
if (0 > indexOfToBeSelectedTile) {
|
||||
//don't select past begining of group
|
||||
} else if (0 <= indexOfToBeSelectedTile && indexOfToBeSelectedTile < size) {
|
||||
//normal selection within group
|
||||
makeSelection(t.isShiftDown(), grouping.get().fileIds().get(indexOfToBeSelectedTile));
|
||||
makeSelection(t.isShiftDown(), grouping.get().getFileIDs().get(indexOfToBeSelectedTile));
|
||||
} else if (indexOfToBeSelectedTile <= size - 1 + columns - (size % columns)) {
|
||||
//selection last item if selection is empty space at end of group
|
||||
makeSelection(t.isShiftDown(), grouping.get().fileIds().get(size - 1));
|
||||
makeSelection(t.isShiftDown(), grouping.get().getFileIDs().get(size - 1));
|
||||
} else {
|
||||
//don't select past end of group
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
getGroupPane().grouping().addListener((Observable observable) -> {
|
||||
syncButtonVisibility();
|
||||
if (getGroupPane().getGroup() != null) {
|
||||
getGroupPane().getGroup().fileIds().addListener((Observable observable1) -> {
|
||||
getGroupPane().getGroup().getFileIDs().addListener((Observable observable1) -> {
|
||||
syncButtonVisibility();
|
||||
});
|
||||
}
|
||||
@ -128,7 +128,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
@ThreadConfined(type = ThreadType.ANY)
|
||||
private void syncButtonVisibility() {
|
||||
try {
|
||||
final boolean hasMultipleFiles = getGroupPane().getGroup().fileIds().size() > 1;
|
||||
final boolean hasMultipleFiles = getGroupPane().getGroup().getFileIDs().size() > 1;
|
||||
Platform.runLater(() -> {
|
||||
rightButton.setVisible(hasMultipleFiles);
|
||||
leftButton.setVisible(hasMultipleFiles);
|
||||
@ -265,12 +265,12 @@ public class SlideShowView extends DrawableTileBase {
|
||||
@ThreadConfined(type = ThreadType.JFX)
|
||||
synchronized private void cycleSlideShowImage(int direction) {
|
||||
stopVideo();
|
||||
final int groupSize = getGroupPane().getGroup().fileIds().size();
|
||||
final int groupSize = getGroupPane().getGroup().getFileIDs().size();
|
||||
final Integer nextIndex = getFileID().map(fileID -> {
|
||||
final int currentIndex = getGroupPane().getGroup().fileIds().indexOf(fileID);
|
||||
final int currentIndex = getGroupPane().getGroup().getFileIDs().indexOf(fileID);
|
||||
return (currentIndex + direction + groupSize) % groupSize;
|
||||
}).orElse(0);
|
||||
setFile(getGroupPane().getGroup().fileIds().get(nextIndex));
|
||||
setFile(getGroupPane().getGroup().getFileIDs().get(nextIndex));
|
||||
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
* of y"
|
||||
*/
|
||||
private String getSupplementalText() {
|
||||
final ObservableList<Long> fileIds = getGroupPane().getGroup().fileIds();
|
||||
final ObservableList<Long> fileIds = getGroupPane().getGroup().getFileIDs();
|
||||
return getFileID().map(fileID -> " ( " + (fileIds.indexOf(fileID) + 1) + " of " + fileIds.size() + " in group )")
|
||||
.orElse("");
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Copyright 2015-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -62,9 +62,7 @@ class GroupListCell extends ListCell<DrawableGroup> {
|
||||
*/
|
||||
private final InvalidationListener seenListener = (Observable o) -> {
|
||||
final String style = getSeenStyleClass();
|
||||
Platform.runLater(() -> {
|
||||
setStyle(style);
|
||||
});
|
||||
Platform.runLater(() -> setStyle(style));
|
||||
};
|
||||
|
||||
private final ReadOnlyObjectProperty<GroupComparators<?>> sortOrder;
|
||||
@ -77,24 +75,19 @@ class GroupListCell extends ListCell<DrawableGroup> {
|
||||
|
||||
//since end of path is probably more interesting put ellipsis at front
|
||||
setTextOverrun(OverrunStyle.LEADING_ELLIPSIS);
|
||||
Platform.runLater(() -> {
|
||||
prefWidthProperty().bind(getListView().widthProperty().subtract(15));
|
||||
});
|
||||
|
||||
Platform.runLater(() -> prefWidthProperty().bind(getListView().widthProperty().subtract(15)));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
protected synchronized void updateItem(final DrawableGroup group, boolean empty) {
|
||||
//if there was a previous group, remove the listeners
|
||||
Optional.ofNullable(getItem())
|
||||
.ifPresent(oldGroup -> {
|
||||
sortOrder.removeListener(fileCountListener);
|
||||
oldGroup.fileIds().removeListener(fileCountListener);
|
||||
oldGroup.getFileIDs().removeListener(fileCountListener);
|
||||
oldGroup.seenProperty().removeListener(seenListener);
|
||||
oldGroup.uncatCountProperty().removeListener(fileCountListener);
|
||||
oldGroup.hashSetHitsCountProperty().removeListener(fileCountListener);
|
||||
});
|
||||
|
||||
super.updateItem(group, empty);
|
||||
@ -107,28 +100,27 @@ class GroupListCell extends ListCell<DrawableGroup> {
|
||||
setStyle("");
|
||||
});
|
||||
} else {
|
||||
final String text = getGroupName() + getCountsText();
|
||||
String style;
|
||||
Image icon;
|
||||
if (isNull(group)) {
|
||||
final String text = getGroupName();
|
||||
//"dummy" group in file system tree <=> a folder with no drawables
|
||||
Platform.runLater(() -> {
|
||||
setTooltip(new Tooltip(text));
|
||||
setText(text);
|
||||
setGraphic(new ImageView(EMPTY_FOLDER_ICON));
|
||||
setStyle("");
|
||||
});
|
||||
|
||||
icon = EMPTY_FOLDER_ICON;
|
||||
style = "";
|
||||
} else {
|
||||
//if number of files in this group changes (eg a file is recategorized), update counts via listener
|
||||
group.fileIds().addListener(fileCountListener);
|
||||
group.getFileIDs().addListener(fileCountListener);
|
||||
group.uncatCountProperty().addListener(fileCountListener);
|
||||
group.hashSetHitsCountProperty().addListener(fileCountListener);
|
||||
sortOrder.addListener(fileCountListener);
|
||||
//if the seen state of this group changes update its style
|
||||
group.seenProperty().addListener(seenListener);
|
||||
|
||||
//and use icon corresponding to group type
|
||||
final Image icon = group.groupKey.getAttribute().getIcon();
|
||||
final String text = getGroupName() + getCountsText();
|
||||
final String style = getSeenStyleClass();
|
||||
icon = group.getGroupKey().getIcon();
|
||||
style = getSeenStyleClass();
|
||||
}
|
||||
|
||||
Platform.runLater(() -> {
|
||||
setTooltip(new Tooltip(text));
|
||||
setGraphic(new ImageView(icon));
|
||||
@ -137,7 +129,6 @@ class GroupListCell extends ListCell<DrawableGroup> {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getGroupName() {
|
||||
return Optional.ofNullable(getItem())
|
||||
@ -166,7 +157,6 @@ class GroupListCell extends ListCell<DrawableGroup> {
|
||||
*/
|
||||
@Nonnull
|
||||
private String getCountsText() {
|
||||
|
||||
return Optional.ofNullable(getItem())
|
||||
.map(group ->
|
||||
" (" + (sortOrder.get() == GroupComparators.ALPHABETICAL
|
||||
|
@ -137,13 +137,13 @@ final public class GroupTree extends NavPanel<TreeItem<GroupTreeNode>> {
|
||||
}
|
||||
|
||||
private static List<String> groupingToPath(DrawableGroup g) {
|
||||
String path = g.groupKey.getValueDisplayName();
|
||||
if (g.groupKey.getAttribute() != DrawableAttribute.PATH) {
|
||||
String stripStart = StringUtils.strip(path, "/");
|
||||
return Arrays.asList(stripStart);
|
||||
} else {
|
||||
String path = g.getGroupByValueDislpayName();
|
||||
if (g.getGroupByAttribute() == DrawableAttribute.PATH) {
|
||||
String[] cleanPathTokens = StringUtils.stripStart(path, "/").split("/");
|
||||
return Arrays.asList(cleanPathTokens);
|
||||
} else {
|
||||
String stripStart = StringUtils.strip(path, "/");
|
||||
return Arrays.asList(stripStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
|
||||
.map(GroupTreeNode::getGroup)
|
||||
.ifPresent(group -> {
|
||||
sortOrder.addListener(fileCountListener);
|
||||
group.fileIds().removeListener(fileCountListener);
|
||||
group.getFileIDs().removeListener(fileCountListener);
|
||||
group.hashSetHitsCountProperty().removeListener(fileCountListener);
|
||||
group.seenProperty().removeListener(seenListener);
|
||||
group.uncatCountProperty().removeListener(fileCountListener);
|
||||
@ -124,7 +124,7 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
|
||||
|
||||
} else {
|
||||
//if number of files in this group changes (eg a file is recategorized), update counts via listener
|
||||
treeNode.getGroup().fileIds().addListener(fileCountListener);
|
||||
treeNode.getGroup().getFileIDs().addListener(fileCountListener);
|
||||
treeNode.getGroup().uncatCountProperty().addListener(fileCountListener);
|
||||
treeNode.getGroup().hashSetHitsCountProperty().addListener(fileCountListener);
|
||||
sortOrder.addListener(fileCountListener);
|
||||
@ -132,7 +132,7 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
|
||||
treeNode.getGroup().seenProperty().addListener(seenListener);
|
||||
|
||||
//and use icon corresponding to group type
|
||||
final Image icon = treeNode.getGroup().groupKey.getAttribute().getIcon();
|
||||
final Image icon = treeNode.getGroup().getGroupKey().getIcon();
|
||||
final String text = getGroupName() + getCountsText();
|
||||
final String style = getSeenStyleClass();
|
||||
Platform.runLater(() -> {
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Loading…
x
Reference in New Issue
Block a user