diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index ac5f32a1ac..463e1c1903 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -192,6 +192,7 @@
org.sleuthkit.autopsy.coreutils
org.sleuthkit.autopsy.datamodel
org.sleuthkit.autopsy.directorytree
+ org.sleuthkit.autopsy.events
org.sleuthkit.autopsy.externalresults
org.sleuthkit.autopsy.filesearch
org.sleuthkit.autopsy.ingest
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java
index be9343f4de..3c115d9134 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddDrawableTagAction.java
@@ -82,9 +82,6 @@ public class AddDrawableTagAction extends AddTagAction {
LOGGER.log(Level.SEVERE, "Error tagging result", ex);
JOptionPane.showMessageDialog(null, "Unable to tag " + fileID + ".", "Tagging Error", JOptionPane.ERROR_MESSAGE);
}
-
-// //make sure rest of ui hears category change.
-// controller.getGroupManager().handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.TAGS));
}
return null;
}
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java
index 067a5cf967..afe2b3bb5d 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java
@@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.imagegallery.actions;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javafx.event.ActionEvent;
@@ -34,11 +33,7 @@ import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager;
-import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
-import org.sleuthkit.autopsy.imagegallery.grouping.GroupKey;
-import org.sleuthkit.autopsy.imagegallery.grouping.GroupManager;
-import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
@@ -127,33 +122,25 @@ public class CategorizeAction extends AddTagAction {
@Override
public void run() {
- final GroupManager groupManager = controller.getGroupManager();
final CategoryManager categoryManager = controller.getCategoryManager();
final DrawableTagsManager tagsManager = controller.getTagsManager();
try {
DrawableFile> file = controller.getFileFromId(fileID); //drawable db
- Category oldCat = file.getCategory();
- // remove file from old category group
- groupManager.removeFromGroup(new GroupKey(DrawableAttribute.CATEGORY, oldCat), fileID); //memory
-
- //remove old category tag if necessary
- List allContentTags = tagsManager.getContentTagsByContent(file); //tsk db
-
- //JMTODO: move this to CategoryManager
- for (ContentTag ct : allContentTags) {
- if (CategoryManager.isCategoryTagName(ct.getName())) {
- tagsManager.deleteContentTag(ct); //tsk db
-// categoryManager.decrementCategoryCount(Category.fromDisplayName(ct.getName().getDisplayName())); //memory/drawable db
- }
- }
-// categoryManager.incrementCategoryCount(Category.fromDisplayName(tagName.getDisplayName())); //memory/drawable db
if (tagName != categoryManager.getTagName(Category.ZERO)) { // no tags for cat-0
tagsManager.addContentTag(file, tagName, comment); //tsk db
+ } else {
+ tagsManager.getContentTagsByContent(file).stream()
+ .filter(tag -> CategoryManager.isCategoryTagName(tag.getName()))
+ .forEach((ct) -> {
+ try {
+ tagsManager.deleteContentTag(ct);
+ } catch (TskCoreException ex) {
+ LOGGER.log(Level.SEVERE, "Error removing old categories result", ex);
+ }
+ });
}
-// //make sure rest of ui hears category change.
-// groupManager.handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.CATEGORY)); //memory/ui
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error categorizing result", ex);
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java
index aab8a9c827..74082fcd1c 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteFollowUpTagAction.java
@@ -26,10 +26,7 @@ import org.controlsfx.control.action.Action;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
-import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
-import org.sleuthkit.autopsy.imagegallery.grouping.GroupKey;
-import org.sleuthkit.autopsy.imagegallery.grouping.GroupManager;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
@@ -50,23 +47,17 @@ public class DeleteFollowUpTagAction extends Action {
@Override
protected Void doInBackground() throws Exception {
- final GroupManager groupManager = controller.getGroupManager();
final DrawableTagsManager tagsManager = controller.getTagsManager();
try {
final TagName followUpTagName = tagsManager.getFollowUpTagName();
- // remove file from old category group
- groupManager.removeFromGroup(new GroupKey(DrawableAttribute.TAGS, followUpTagName), fileID);
-
+
List contentTagsByContent = tagsManager.getContentTagsByContent(file);
for (ContentTag ct : contentTagsByContent) {
if (ct.getName().getDisplayName().equals(followUpTagName.getDisplayName())) {
tagsManager.deleteContentTag(ct);
}
}
-
- //make sure rest of ui hears category change.
-// groupManager.handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.TAGS));
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to delete follow up tag.", ex);
}
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java
index b6a11d2b25..466278f588 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java
@@ -224,6 +224,7 @@ public class CategoryManager {
}
+ @Subscribe
public void handleTagAdded(ContentTagAddedEvent event) {
ContentTag addedTag = event.getAddedTag();
if (isCategoryTagName(addedTag.getName())) {
@@ -253,7 +254,7 @@ public class CategoryManager {
fireChange(Collections.singleton(addedTag.getId()), newCat);
}
}
-
+ @Subscribe
public void handleTagDeleted(ContentTagDeletedEvent event) {
ContentTag deleted = event.getDeletedTag();
if (isCategoryTagName(deleted.getName())) {
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java
index 733baf2813..9ac899742c 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/grouping/GroupManager.java
@@ -279,8 +279,12 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
if (groupKey.getAttribute() != DrawableAttribute.CATEGORY) {
if (group.fileIds().isEmpty()) {
Platform.runLater(() -> {
- analyzedGroups.remove(group);
- unSeenGroups.remove(group);
+ if (analyzedGroups.contains(group)) {
+ analyzedGroups.remove(group);
+ }
+ if (unSeenGroups.contains(group)) {
+ unSeenGroups.remove(group);
+ }
});
}
}
@@ -535,10 +539,12 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
@Subscribe
public void handleTagAdded(ContentTagAddedEvent evt) {
- final GroupKey groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getAddedTag().getName());
- final long fileID = evt.getAddedTag().getContent().getId();
- DrawableGroup g = getGroupForKey(groupKey);
- addFileToGroup(g, groupKey, fileID);
+ if (groupBy == DrawableAttribute.TAGS || groupBy == DrawableAttribute.CATEGORY) {
+ final GroupKey groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getAddedTag().getName());
+ final long fileID = evt.getAddedTag().getContent().getId();
+ DrawableGroup g = getGroupForKey(groupKey);
+ addFileToGroup(g, groupKey, fileID);
+ }
}
@@ -554,9 +560,11 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
@Subscribe
public void handleTagDeleted(ContentTagDeletedEvent evt) {
- final GroupKey groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getDeletedTag().getName());
- final long fileID = evt.getDeletedTag().getContent().getId();
- DrawableGroup g = removeFromGroup(groupKey, fileID);
+ if (groupBy == DrawableAttribute.TAGS || groupBy == DrawableAttribute.CATEGORY) {
+ final GroupKey groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getDeletedTag().getName());
+ final long fileID = evt.getDeletedTag().getContent().getId();
+ DrawableGroup g = removeFromGroup(groupKey, fileID);
+ }
}
@Override
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java
index 75332ba158..96f05dd9c1 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java
@@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType;
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableViewBase.globalSelectionModel;
+import org.sleuthkit.datamodel.AbstractContent;
/**
* GUI component that represents a single image as a tile with an icon, a label,
@@ -109,15 +110,20 @@ public class DrawableTile extends DrawableViewBase {
@Override
protected Runnable getContentUpdateRunnable() {
- Image image = getFile().getThumbnail();
+ if (getFile().isPresent()) {
+ Image image = getFile().get().getThumbnail();
- return () -> {
- imageView.setImage(image);
- };
+ return () -> {
+ imageView.setImage(image);
+ };
+ } else {
+ return () -> { //no-op
+ };
+ }
}
@Override
protected String getTextForLabel() {
- return getFile().getName();
+ return getFile().map(AbstractContent::getName).orElse("");
}
}
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java
index 9b442273d1..e4e6faf1de 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java
@@ -1,6 +1,8 @@
package org.sleuthkit.autopsy.imagegallery.gui;
import com.google.common.eventbus.Subscribe;
+import java.util.Collection;
+import java.util.Optional;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.scene.layout.Border;
@@ -51,11 +53,11 @@ public interface DrawableView {
Region getCategoryBorderRegion();
- DrawableFile> getFile();
+ Optional> getFile();
void setFile(final Long fileID);
- Long getFileID();
+ Optional getFileID();
/**
* update the visual representation of the category of the assigned file.
@@ -78,7 +80,10 @@ public interface DrawableView {
default boolean hasHashHit() {
try {
- return getFile().getHashHitSetNames().isEmpty() == false;
+ return getFile().map(DrawableFile::getHashHitSetNames)
+ .map((Collection t) -> t.isEmpty() == false)
+ .orElse(false);
+
} catch (NullPointerException ex) {
// I think this happens when we're in the process of removing images from the view while
// also trying to update it?
@@ -113,7 +118,7 @@ public interface DrawableView {
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
default Category updateCategoryBorder() {
if (getFile() != null) {
- final Category category = getFile().getCategory();
+ final Category category = getFile().map(DrawableFile::getCategory).orElse(Category.ZERO);
final Border border = hasHashHit() && (category == Category.ZERO)
? HASH_BORDER
: getCategoryBorder(category);
diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java
index ea88d2dfbb..a1ee32a108 100644
--- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java
+++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableViewBase.java
@@ -23,6 +23,8 @@ import com.google.common.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
+import static java.util.Objects.nonNull;
+import java.util.Optional;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.beans.Observable;
@@ -130,9 +132,33 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
static private ContextMenu contextMenu;
- private DrawableFile> file;
+ volatile private Optional> fileOpt = Optional.empty();
- private Long fileID;
+ volatile private Optional fileIDOpt = Optional.empty();
+
+ @Override
+ public Optional getFileID() {
+ return fileIDOpt;
+ }
+
+ @Override
+ public Optional> getFile() {
+ if (fileIDOpt.isPresent()) {
+ if (fileOpt.isPresent() && fileOpt.get().getId() == fileIDOpt.get()) {
+ return fileOpt;
+ } else {
+ try {
+ fileOpt = Optional.of(ImageGalleryController.getDefault().getFileFromId(fileIDOpt.get()));
+ } catch (TskCoreException ex) {
+ Logger.getAnonymousLogger().log(Level.WARNING, "failed to get DrawableFile for obj_id" + fileIDOpt.get(), ex);
+ fileOpt = Optional.empty();
+ }
+ return fileOpt;
+ }
+ } else {
+ return Optional.empty();
+ }
+ }
/**
* the groupPane this {@link DrawableViewBase} is embedded in
@@ -158,43 +184,44 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
@Override
public void handle(MouseEvent t) {
+ getFile().ifPresent(file -> {
+ final long fileID = file.getId();
+ switch (t.getButton()) {
+ case PRIMARY:
+ if (t.getClickCount() == 1) {
+ if (t.isControlDown()) {
- switch (t.getButton()) {
- case PRIMARY:
- if (t.getClickCount() == 1) {
- if (t.isControlDown()) {
- globalSelectionModel.toggleSelection(fileID);
- } else {
- groupPane.makeSelection(t.isShiftDown(), fileID);
+ globalSelectionModel.toggleSelection(fileID);
+ } else {
+ groupPane.makeSelection(t.isShiftDown(), fileID);
+ }
+ } else if (t.getClickCount() > 1) {
+ groupPane.activateSlideShowViewer(fileID);
}
- } else if (t.getClickCount() > 1) {
- groupPane.activateSlideShowViewer(fileID);
- }
- break;
- case SECONDARY:
-
- if (t.getClickCount() == 1) {
- if (globalSelectionModel.isSelected(fileID) == false) {
- groupPane.makeSelection(false, fileID);
+ break;
+ case SECONDARY:
+ if (t.getClickCount() == 1) {
+ if (globalSelectionModel.isSelected(fileID) == false) {
+ groupPane.makeSelection(false, fileID);
+ }
}
- }
+ if (contextMenu != null) {
+ contextMenu.hide();
+ }
+ final ContextMenu groupContextMenu = groupPane.getContextMenu();
+ if (groupContextMenu != null) {
+ groupContextMenu.hide();
+ }
+ contextMenu = buildContextMenu(file);
+ contextMenu.show(DrawableViewBase.this, t.getScreenX(), t.getScreenY());
+ break;
+ }
+ });
- if (contextMenu != null) {
- contextMenu.hide();
- }
- final ContextMenu groupContextMenu = groupPane.getContextMenu();
- if (groupContextMenu != null) {
- groupContextMenu.hide();
- }
- contextMenu = buildContextMenu();
- contextMenu.show(DrawableViewBase.this, t.getScreenX(), t.getScreenY());
-
- break;
- }
t.consume();
}
- private ContextMenu buildContextMenu() {
+ private ContextMenu buildContextMenu(DrawableFile> file) {
final ArrayList