remove uneeded notification code; let event handlers do it all. optionalize DrawableView

This commit is contained in:
jmillman 2015-06-19 17:20:35 -04:00
parent 22868333a0
commit 13ad8aaaeb
11 changed files with 341 additions and 261 deletions

View File

@ -192,6 +192,7 @@
<package>org.sleuthkit.autopsy.coreutils</package> <package>org.sleuthkit.autopsy.coreutils</package>
<package>org.sleuthkit.autopsy.datamodel</package> <package>org.sleuthkit.autopsy.datamodel</package>
<package>org.sleuthkit.autopsy.directorytree</package> <package>org.sleuthkit.autopsy.directorytree</package>
<package>org.sleuthkit.autopsy.events</package>
<package>org.sleuthkit.autopsy.externalresults</package> <package>org.sleuthkit.autopsy.externalresults</package>
<package>org.sleuthkit.autopsy.filesearch</package> <package>org.sleuthkit.autopsy.filesearch</package>
<package>org.sleuthkit.autopsy.ingest</package> <package>org.sleuthkit.autopsy.ingest</package>

View File

@ -82,9 +82,6 @@ public class AddDrawableTagAction extends AddTagAction {
LOGGER.log(Level.SEVERE, "Error tagging result", ex); LOGGER.log(Level.SEVERE, "Error tagging result", ex);
JOptionPane.showMessageDialog(null, "Unable to tag " + fileID + ".", "Tagging Error", JOptionPane.ERROR_MESSAGE); 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; return null;
} }

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.imagegallery.actions; package org.sleuthkit.autopsy.imagegallery.actions;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.event.ActionEvent; 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.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; 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.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.TagName;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -127,33 +122,25 @@ public class CategorizeAction extends AddTagAction {
@Override @Override
public void run() { public void run() {
final GroupManager groupManager = controller.getGroupManager();
final CategoryManager categoryManager = controller.getCategoryManager(); final CategoryManager categoryManager = controller.getCategoryManager();
final DrawableTagsManager tagsManager = controller.getTagsManager(); final DrawableTagsManager tagsManager = controller.getTagsManager();
try { try {
DrawableFile<?> file = controller.getFileFromId(fileID); //drawable db DrawableFile<?> file = controller.getFileFromId(fileID); //drawable db
Category oldCat = file.getCategory();
// remove file from old category group
groupManager.removeFromGroup(new GroupKey<Category>(DrawableAttribute.CATEGORY, oldCat), fileID); //memory
//remove old category tag if necessary
List<ContentTag> 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 if (tagName != categoryManager.getTagName(Category.ZERO)) { // no tags for cat-0
tagsManager.addContentTag(file, tagName, comment); //tsk db 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) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error categorizing result", ex); LOGGER.log(Level.SEVERE, "Error categorizing result", ex);

View File

@ -26,10 +26,7 @@ import org.controlsfx.control.action.Action;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager; import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; 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.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.ContentTag;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -50,23 +47,17 @@ public class DeleteFollowUpTagAction extends Action {
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
final GroupManager groupManager = controller.getGroupManager();
final DrawableTagsManager tagsManager = controller.getTagsManager(); final DrawableTagsManager tagsManager = controller.getTagsManager();
try { try {
final TagName followUpTagName = tagsManager.getFollowUpTagName(); final TagName followUpTagName = tagsManager.getFollowUpTagName();
// remove file from old category group
groupManager.removeFromGroup(new GroupKey<TagName>(DrawableAttribute.TAGS, followUpTagName), fileID);
List<ContentTag> contentTagsByContent = tagsManager.getContentTagsByContent(file); List<ContentTag> contentTagsByContent = tagsManager.getContentTagsByContent(file);
for (ContentTag ct : contentTagsByContent) { for (ContentTag ct : contentTagsByContent) {
if (ct.getName().getDisplayName().equals(followUpTagName.getDisplayName())) { if (ct.getName().getDisplayName().equals(followUpTagName.getDisplayName())) {
tagsManager.deleteContentTag(ct); tagsManager.deleteContentTag(ct);
} }
} }
//make sure rest of ui hears category change.
// groupManager.handleFileUpdate(FileUpdateEvent.newUpdateEvent(Collections.singleton(fileID), DrawableAttribute.TAGS));
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to delete follow up tag.", ex); LOGGER.log(Level.SEVERE, "Failed to delete follow up tag.", ex);
} }

View File

@ -224,6 +224,7 @@ public class CategoryManager {
} }
@Subscribe
public void handleTagAdded(ContentTagAddedEvent event) { public void handleTagAdded(ContentTagAddedEvent event) {
ContentTag addedTag = event.getAddedTag(); ContentTag addedTag = event.getAddedTag();
if (isCategoryTagName(addedTag.getName())) { if (isCategoryTagName(addedTag.getName())) {
@ -253,7 +254,7 @@ public class CategoryManager {
fireChange(Collections.singleton(addedTag.getId()), newCat); fireChange(Collections.singleton(addedTag.getId()), newCat);
} }
} }
@Subscribe
public void handleTagDeleted(ContentTagDeletedEvent event) { public void handleTagDeleted(ContentTagDeletedEvent event) {
ContentTag deleted = event.getDeletedTag(); ContentTag deleted = event.getDeletedTag();
if (isCategoryTagName(deleted.getName())) { if (isCategoryTagName(deleted.getName())) {

View File

@ -279,8 +279,12 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
if (groupKey.getAttribute() != DrawableAttribute.CATEGORY) { if (groupKey.getAttribute() != DrawableAttribute.CATEGORY) {
if (group.fileIds().isEmpty()) { if (group.fileIds().isEmpty()) {
Platform.runLater(() -> { Platform.runLater(() -> {
analyzedGroups.remove(group); if (analyzedGroups.contains(group)) {
unSeenGroups.remove(group); analyzedGroups.remove(group);
}
if (unSeenGroups.contains(group)) {
unSeenGroups.remove(group);
}
}); });
} }
} }
@ -535,10 +539,12 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
@Subscribe @Subscribe
public void handleTagAdded(ContentTagAddedEvent evt) { public void handleTagAdded(ContentTagAddedEvent evt) {
final GroupKey<TagName> groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getAddedTag().getName()); if (groupBy == DrawableAttribute.TAGS || groupBy == DrawableAttribute.CATEGORY) {
final long fileID = evt.getAddedTag().getContent().getId(); final GroupKey<TagName> groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getAddedTag().getName());
DrawableGroup g = getGroupForKey(groupKey); final long fileID = evt.getAddedTag().getContent().getId();
addFileToGroup(g, groupKey, fileID); DrawableGroup g = getGroupForKey(groupKey);
addFileToGroup(g, groupKey, fileID);
}
} }
@ -554,9 +560,11 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
@Subscribe @Subscribe
public void handleTagDeleted(ContentTagDeletedEvent evt) { public void handleTagDeleted(ContentTagDeletedEvent evt) {
final GroupKey<TagName> groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getDeletedTag().getName()); if (groupBy == DrawableAttribute.TAGS || groupBy == DrawableAttribute.CATEGORY) {
final long fileID = evt.getDeletedTag().getContent().getId(); final GroupKey<TagName> groupKey = new GroupKey<>(DrawableAttribute.TAGS, evt.getDeletedTag().getName());
DrawableGroup g = removeFromGroup(groupKey, fileID); final long fileID = evt.getDeletedTag().getContent().getId();
DrawableGroup g = removeFromGroup(groupKey, fileID);
}
} }
@Override @Override

View File

@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType;
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableViewBase.globalSelectionModel; 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, * 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 @Override
protected Runnable getContentUpdateRunnable() { protected Runnable getContentUpdateRunnable() {
Image image = getFile().getThumbnail(); if (getFile().isPresent()) {
Image image = getFile().get().getThumbnail();
return () -> { return () -> {
imageView.setImage(image); imageView.setImage(image);
}; };
} else {
return () -> { //no-op
};
}
} }
@Override @Override
protected String getTextForLabel() { protected String getTextForLabel() {
return getFile().getName(); return getFile().map(AbstractContent::getName).orElse("");
} }
} }

View File

@ -1,6 +1,8 @@
package org.sleuthkit.autopsy.imagegallery.gui; package org.sleuthkit.autopsy.imagegallery.gui;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import java.util.Collection;
import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.layout.Border; import javafx.scene.layout.Border;
@ -51,11 +53,11 @@ public interface DrawableView {
Region getCategoryBorderRegion(); Region getCategoryBorderRegion();
DrawableFile<?> getFile(); Optional<DrawableFile<?>> getFile();
void setFile(final Long fileID); void setFile(final Long fileID);
Long getFileID(); Optional<Long> getFileID();
/** /**
* update the visual representation of the category of the assigned file. * update the visual representation of the category of the assigned file.
@ -78,7 +80,10 @@ public interface DrawableView {
default boolean hasHashHit() { default boolean hasHashHit() {
try { try {
return getFile().getHashHitSetNames().isEmpty() == false; return getFile().map(DrawableFile::getHashHitSetNames)
.map((Collection<String> t) -> t.isEmpty() == false)
.orElse(false);
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
// I think this happens when we're in the process of removing images from the view while // I think this happens when we're in the process of removing images from the view while
// also trying to update it? // also trying to update it?
@ -113,7 +118,7 @@ public interface DrawableView {
@ThreadConfined(type = ThreadConfined.ThreadType.ANY) @ThreadConfined(type = ThreadConfined.ThreadType.ANY)
default Category updateCategoryBorder() { default Category updateCategoryBorder() {
if (getFile() != null) { 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) final Border border = hasHashHit() && (category == Category.ZERO)
? HASH_BORDER ? HASH_BORDER
: getCategoryBorder(category); : getCategoryBorder(category);

View File

@ -23,6 +23,8 @@ import com.google.common.eventbus.Subscribe;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Objects; import java.util.Objects;
import static java.util.Objects.nonNull;
import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.Observable; import javafx.beans.Observable;
@ -130,9 +132,33 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
static private ContextMenu contextMenu; static private ContextMenu contextMenu;
private DrawableFile<?> file; volatile private Optional<DrawableFile<?>> fileOpt = Optional.empty();
private Long fileID; volatile private Optional<Long> fileIDOpt = Optional.empty();
@Override
public Optional<Long> getFileID() {
return fileIDOpt;
}
@Override
public Optional<DrawableFile<?>> 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 * the groupPane this {@link DrawableViewBase} is embedded in
@ -158,43 +184,44 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
@Override @Override
public void handle(MouseEvent t) { 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()) { globalSelectionModel.toggleSelection(fileID);
case PRIMARY: } else {
if (t.getClickCount() == 1) { groupPane.makeSelection(t.isShiftDown(), fileID);
if (t.isControlDown()) { }
globalSelectionModel.toggleSelection(fileID); } else if (t.getClickCount() > 1) {
} else { groupPane.activateSlideShowViewer(fileID);
groupPane.makeSelection(t.isShiftDown(), fileID);
} }
} else if (t.getClickCount() > 1) { break;
groupPane.activateSlideShowViewer(fileID); case SECONDARY:
} if (t.getClickCount() == 1) {
break; if (globalSelectionModel.isSelected(fileID) == false) {
case SECONDARY: groupPane.makeSelection(false, fileID);
}
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(); t.consume();
} }
private ContextMenu buildContextMenu() { private ContextMenu buildContextMenu(DrawableFile<?> file) {
final ArrayList<MenuItem> menuItems = new ArrayList<>(); final ArrayList<MenuItem> menuItems = new ArrayList<>();
menuItems.add(new CategorizeAction(controller).getPopupMenu()); menuItems.add(new CategorizeAction(controller).getPopupMenu());
@ -213,13 +240,13 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
MenuItem contentViewer = new MenuItem("Show Content Viewer"); MenuItem contentViewer = new MenuItem("Show Content Viewer");
contentViewer.setOnAction((ActionEvent t) -> { contentViewer.setOnAction((ActionEvent t) -> {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
new NewWindowViewAction("Show Content Viewer", new FileNode(getFile().getAbstractFile())).actionPerformed(null); new NewWindowViewAction("Show Content Viewer", new FileNode(file.getAbstractFile())).actionPerformed(null);
}); });
}); });
menuItems.add(contentViewer); menuItems.add(contentViewer);
MenuItem externalViewer = new MenuItem("Open in External Viewer"); MenuItem externalViewer = new MenuItem("Open in External Viewer");
final ExternalViewerAction externalViewerAction = new ExternalViewerAction("Open in External Viewer", new FileNode(getFile().getAbstractFile())); final ExternalViewerAction externalViewerAction = new ExternalViewerAction("Open in External Viewer", new FileNode(file.getAbstractFile()));
externalViewer.setDisable(externalViewerAction.isEnabled() == false); externalViewer.setDisable(externalViewerAction.isEnabled() == false);
externalViewer.setOnAction((ActionEvent t) -> { externalViewer.setOnAction((ActionEvent t) -> {
@ -259,116 +286,106 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
protected void initialize() { protected void initialize() {
followUpToggle.setOnAction((ActionEvent event) -> { followUpToggle.setOnAction((ActionEvent event) -> {
if (followUpToggle.isSelected() == true) { getFile().ifPresent(file -> {
try { if (followUpToggle.isSelected() == true) {
final TagName followUpTagName = controller.getTagsManager().getFollowUpTagName(); try {
globalSelectionModel.clearAndSelect(fileID); final TagName followUpTagName = controller.getTagsManager().getFollowUpTagName();
new AddDrawableTagAction(controller).addTag(followUpTagName, ""); globalSelectionModel.clearAndSelect(file.getId());
} catch (TskCoreException ex) { new AddDrawableTagAction(controller).addTag(followUpTagName, "");
LOGGER.log(Level.SEVERE, "Failed to add Follow Up tag. Could not load TagName.", ex); } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to add Follow Up tag. Could not load TagName.", ex);
}
} else {
new DeleteFollowUpTagAction(controller, file).handle(event);
} }
} else { });
new DeleteFollowUpTagAction(controller, file).handle(event);
}
}); });
} }
@Override protected boolean hasFollowUp() {
public DrawableFile<?> getFile() { if (getFile().isPresent()) {
if (fileID != null) {
if (file == null || file.getId() != fileID) {
try {
file = ImageGalleryController.getDefault().getFileFromId(fileID);
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "failed to get DrawableFile for obj_id" + fileID, ex);
file = null;
}
}
return file;
} else {
return null;
}
}
protected boolean hasFollowUp() throws TskCoreException {
String followUpTagName = getController().getTagsManager().getFollowUpTagName().getDisplayName();
Collection<TagName> tagNames = DrawableAttribute.TAGS.getValue(getFile());
return tagNames.stream().anyMatch((tn) -> tn.getDisplayName().equals(followUpTagName));
}
@Override
synchronized public Long getFileID() {
return fileID;
}
synchronized protected void updateFollowUpIcon() {
if (file != null) {
try { try {
boolean hasFollowUp = hasFollowUp(); TagName followUpTagName = getController().getTagsManager().getFollowUpTagName();
Platform.runLater(() -> { Collection<TagName> tagNames = DrawableAttribute.TAGS.getValue(getFile().get());
followUpImageView.setImage(hasFollowUp ? followUpIcon : followUpGray); return tagNames.stream().anyMatch((tn) -> tn.equals(followUpTagName));
followUpToggle.setSelected(hasFollowUp);
});
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get follow up status for file.", ex); LOGGER.log(Level.WARNING, "failed to get follow up tag name ", ex);
return true;
} }
} else {
return false;
} }
} }
@Override @Override
synchronized public void setFile(final Long fileID) { public void setFile(final Long newFileID) {
if (Objects.equals(fileID, this.fileID) == false) { if (fileIDOpt.isPresent()) {
this.fileID = fileID; if (Objects.equals(newFileID, fileIDOpt.get()) == false) {
disposeContent(); setFileHelper(newFileID);
if (this.fileID == null || Case.isCaseOpen() == false) {
if (registered == true) {
getController().getCategoryManager().unregisterListener(this);
getController().getTagsManager().unregisterListener(this);
registered = false;
}
file = null;
Platform.runLater(() -> {
clearContent();
});
} else {
if (registered == false) {
getController().getCategoryManager().registerListener(this);
getController().getTagsManager().registerListener(this);
registered = true;
}
file = null;
getFile();
updateSelectionState();
updateCategoryBorder();
updateFollowUpIcon();
updateUI();
Platform.runLater(getContentUpdateRunnable());
} }
} else {
if (nonNull(newFileID)) {
setFileHelper(newFileID);
}
}
}
private void setFileHelper(final Long newFileID) {
fileIDOpt = Optional.ofNullable(newFileID);
disposeContent();
if (fileIDOpt.isPresent() == false || Case.isCaseOpen() == false) {
if (registered == true) {
getController().getCategoryManager().unregisterListener(this);
getController().getTagsManager().unregisterListener(this);
registered = false;
}
fileOpt = Optional.empty();
Platform.runLater(() -> {
clearContent();
});
} else {
if (registered == false) {
getController().getCategoryManager().registerListener(this);
getController().getTagsManager().registerListener(this);
registered = true;
}
fileOpt = Optional.empty();
updateSelectionState();
updateCategoryBorder();
updateFollowUpIcon();
updateUI();
Platform.runLater(getContentUpdateRunnable());
} }
} }
private void updateUI() { private void updateUI() {
final boolean isVideo = getFile().isVideo(); getFile().ifPresent(file -> {
final boolean hasHashSetHits = hasHashHit(); final boolean isVideo = file.isVideo();
final String text = getTextForLabel(); final boolean hasHashSetHits = hasHashHit();
final String text = getTextForLabel();
Platform.runLater(() -> { Platform.runLater(() -> {
fileTypeImageView.setImage(isVideo ? videoIcon : null); fileTypeImageView.setImage(isVideo ? videoIcon : null);
hashHitImageView.setImage(hasHashSetHits ? hashHitIcon : null); hashHitImageView.setImage(hasHashSetHits ? hashHitIcon : null);
nameLabel.setText(text); nameLabel.setText(text);
nameLabel.setTooltip(new Tooltip(text)); nameLabel.setTooltip(new Tooltip(text));
});
}); });
} }
/** /**
* update the visual representation of the selection state of this * update the visual representation of the selection state of this
* DrawableView * DrawableView
*/ */
synchronized protected void updateSelectionState() { protected void updateSelectionState() {
final boolean selected = globalSelectionModel.isSelected(getFileID()); getFile().ifPresent(file -> {
Platform.runLater(() -> { final boolean selected = globalSelectionModel.isSelected(file.getId());
setBorder(selected ? SELECTED_BORDER : UNSELECTED_BORDER); Platform.runLater(() -> {
setBorder(selected ? SELECTED_BORDER : UNSELECTED_BORDER);
});
}); });
} }
@ -380,22 +397,54 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
@Subscribe @Subscribe
@Override @Override
public void handleTagAdded(ContentTagAddedEvent evt) { public void handleTagAdded(ContentTagAddedEvent evt) {
fileIDOpt.ifPresent(fileID -> {
try {
if (fileID == evt.getAddedTag().getContent().getId()
&& evt.getAddedTag().getName() == getController().getTagsManager().getFollowUpTagName()) {
updateFollowUpIcon(); Platform.runLater(() -> {
followUpImageView.setImage(followUpIcon);
followUpToggle.setSelected(true);
});
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get follow up status for file.", ex);
}
});
} }
@Subscribe @Subscribe
@Override @Override
public void handleTagDeleted(ContentTagDeletedEvent evt) { public void handleTagDeleted(ContentTagDeletedEvent evt) {
updateFollowUpIcon();
fileIDOpt.ifPresent(fileID -> {
try {
if (fileID == evt.getDeletedTag().getContent().getId()
&& evt.getDeletedTag().getName() == controller.getTagsManager().getFollowUpTagName()) {
updateFollowUpIcon();
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get follow up status for file.", ex);
}
});
}
private void updateFollowUpIcon() {
boolean hasFollowUp = hasFollowUp();
Platform.runLater(() -> {
followUpImageView.setImage(hasFollowUp ? followUpIcon : followUpGray);
followUpToggle.setSelected(hasFollowUp);
});
} }
@Subscribe @Subscribe
@Override @Override
synchronized public void handleCategoryChanged(CategoryChangeEvent evt) { public void handleCategoryChanged(CategoryChangeEvent evt) {
if (fileID != null && evt.getFileIDs().contains(getFileID())) { fileIDOpt.ifPresent(fileID -> {
updateCategoryBorder(); if (evt.getFileIDs().contains(fileID)) {
} updateCategoryBorder();
}
});
} }
@Override @Override

View File

@ -22,6 +22,9 @@ import com.google.common.eventbus.Subscribe;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Objects;
import static java.util.Objects.nonNull;
import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
@ -68,8 +71,6 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
return controller; return controller;
} }
private Long fileID;
@FXML @FXML
private ImageView imageView; private ImageView imageView;
@ -85,13 +86,6 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
@FXML @FXML
private BorderPane imageBorder; private BorderPane imageBorder;
private DrawableFile<?> file;
@Override
public Long getFileID() {
return fileID;
}
@FXML @FXML
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
void initialize() { void initialize() {
@ -152,29 +146,52 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
}); });
} }
volatile private Optional<DrawableFile<?>> fileOpt = Optional.empty();
volatile private Optional<Long> fileIDOpt = Optional.empty();
@Override @Override
public DrawableFile<?> getFile() { public Optional<Long> getFileID() {
if (fileID != null) { return fileIDOpt;
if (file == null || file.getId() != fileID) {
try {
file = controller.getFileFromId(fileID);
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "failed to get DrawableFile for obj_id" + fileID, ex);
return null;
}
}
} else {
return null;
}
return file;
} }
@Override @Override
public void setFile(Long fileID) { public Optional<DrawableFile<?>> getFile() {
this.fileID = fileID; 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();
}
}
if (fileID == null) { @Override
public void setFile(Long newFileID) {
if (fileIDOpt.isPresent()) {
if (Objects.equals(newFileID, fileIDOpt.get()) == false) {
setFileHelper(newFileID);
}
} else {
if (nonNull(newFileID)) {
setFileHelper(newFileID);
}
}
setFileHelper(newFileID);
}
private void setFileHelper(Long newFileID) {
fileIDOpt = Optional.of(newFileID);
if (newFileID == null) {
Platform.runLater(() -> { Platform.runLater(() -> {
imageView.setImage(null); imageView.setImage(null);
tableView.getItems().clear(); tableView.getItems().clear();
@ -182,12 +199,7 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
}); });
} else { } else {
try { updateUI();
file = controller.getFileFromId(fileID);
updateUI();
} catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "Failed to get drawable file from ID", ex);
}
} }
} }
@ -206,15 +218,18 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
} }
public void updateUI() { public void updateUI() {
final Image icon = getFile().getThumbnail(); getFile().ifPresent(file -> {
final ObservableList<Pair<DrawableAttribute<?>, ? extends Object>> attributesList = getFile().getAttributesList(); final Image icon = file.getThumbnail();
final ObservableList<Pair<DrawableAttribute<?>, ? extends Object>> attributesList = file.getAttributesList();
Platform.runLater(() -> { Platform.runLater(() -> {
imageView.setImage(icon); imageView.setImage(icon);
tableView.getItems().setAll(attributesList); tableView.getItems().setAll(attributesList);
});
updateCategoryBorder();
}); });
updateCategoryBorder();
} }
@Override @Override
@ -226,23 +241,28 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
@Subscribe @Subscribe
@Override @Override
public void handleCategoryChanged(CategoryChangeEvent evt) { public void handleCategoryChanged(CategoryChangeEvent evt) {
if (getFile() != null && evt.getFileIDs().contains(getFileID())) { getFileID().ifPresent(fileID -> {
updateUI(); if (evt.getFileIDs().contains(fileID)) {
} updateUI();
}
});
} }
@Override @Override
public void handleTagAdded(ContentTagAddedEvent evt) { public void handleTagAdded(ContentTagAddedEvent evt) {
if (getFile() != null && evt.getAddedTag().getContent().getId() == getFileID()) { handleTagChanged(evt.getAddedTag().getContent().getId());
updateUI();
}
} }
@Override @Override
public void handleTagDeleted(ContentTagDeletedEvent evt) { public void handleTagDeleted(ContentTagDeletedEvent evt) {
if (getFile() != null && evt.getDeletedTag().getContent().getId() == getFileID()) { handleTagChanged(evt.getDeletedTag().getContent().getId());
updateUI();
}
} }
private void handleTagChanged(Long tagFileID) {
getFileID().ifPresent(fileID -> {
if (Objects.equals(tagFileID, fileID)) {
updateUI();
}
});
}
} }

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.imagegallery.gui; package org.sleuthkit.autopsy.imagegallery.gui;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.function.Function;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.Observable; import javafx.beans.Observable;
@ -48,14 +49,15 @@ import org.openide.util.Exceptions;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType;
import org.sleuthkit.autopsy.imagegallery.DrawableTagsManager;
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel; import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction;
import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
import org.sleuthkit.autopsy.imagegallery.datamodel.ImageFile; import org.sleuthkit.autopsy.imagegallery.datamodel.ImageFile;
import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile; import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableView.CAT_BORDER_WIDTH;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableView.HASH_BORDER; import static org.sleuthkit.autopsy.imagegallery.gui.DrawableView.HASH_BORDER;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableView.getCategoryBorder; import static org.sleuthkit.autopsy.imagegallery.gui.DrawableView.getCategoryBorder;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
@ -235,9 +237,9 @@ public class SlideShowView extends DrawableViewBase {
@Override @Override
synchronized public void setFile(final Long fileID) { synchronized public void setFile(final Long fileID) {
super.setFile(fileID); super.setFile(fileID);
if (this.getFileID() != null) { getFileID().ifPresent((Long id) -> {
getGroupPane().makeSelection(false, this.getFileID()); getGroupPane().makeSelection(false, id);
} });
} }
@Override @Override
@ -254,24 +256,33 @@ public class SlideShowView extends DrawableViewBase {
@Override @Override
protected Runnable getContentUpdateRunnable() { protected Runnable getContentUpdateRunnable() {
if (getFile().isVideo()) {
return () -> { return getFile().map(new Function<DrawableFile<?>, Runnable>() {
imageBorder.setCenter(MediaControl.create((VideoFile<?>) getFile()));
}; @Override
} else { public Runnable apply(DrawableFile<?> file) {
ImageView imageView = new ImageView(((ImageFile<?>) getFile()).getFullSizeImage());
imageView.setPreserveRatio(true); if (file.isVideo()) {
imageView.fitWidthProperty().bind(imageBorder.widthProperty().subtract(CAT_BORDER_WIDTH * 2)); return () -> {
imageView.fitHeightProperty().bind(this.heightProperty().subtract(CAT_BORDER_WIDTH * 4).subtract(footer.heightProperty()).subtract(toolBar.heightProperty())); imageBorder.setCenter(MediaControl.create((VideoFile<?>) file));
return () -> { };
imageBorder.setCenter(imageView); } else {
}; ImageView imageView = new ImageView(((ImageFile<?>) file).getFullSizeImage());
} imageView.setPreserveRatio(true);
imageView.fitWidthProperty().bind(imageBorder.widthProperty().subtract(CAT_BORDER_WIDTH * 2));
imageView.fitHeightProperty().bind(heightProperty().subtract(CAT_BORDER_WIDTH * 4).subtract(footer.heightProperty()).subtract(toolBar.heightProperty()));
return () -> {
imageBorder.setCenter(imageView);
};
}
}
}).orElse(() -> {
});
} }
@Override @Override
protected String getTextForLabel() { protected String getTextForLabel() {
return getFile().getName() + " " + getSupplementalText(); return getFile().map(file -> file.getName() + " " + getSupplementalText()).orElse("");
} }
@ThreadConfined(type = ThreadType.JFX) @ThreadConfined(type = ThreadType.JFX)
@ -302,18 +313,19 @@ public class SlideShowView extends DrawableViewBase {
@Override @Override
@ThreadConfined(type = ThreadType.ANY) @ThreadConfined(type = ThreadType.ANY)
public Category updateCategoryBorder() { public Category updateCategoryBorder() {
final Category category = getFile().getCategory(); return getFile().map(file -> {
final Border border = hasHashHit() && (category == Category.ZERO) final Category category = file.getCategory();
? HASH_BORDER final Border border1 = hasHashHit() && (category == Category.ZERO)
: getCategoryBorder(category); ? HASH_BORDER
ToggleButton toggleForCategory = getToggleForCategory(category); : getCategoryBorder(category);
ToggleButton toggleForCategory = getToggleForCategory(category);
Platform.runLater(() -> {
getCategoryBorderRegion().setBorder(border1);
toggleForCategory.setSelected(true);
});
return category;
}).orElse(Category.ZERO);
Platform.runLater(() -> {
getCategoryBorderRegion().setBorder(border);
toggleForCategory.setSelected(true);
});
return category;
} }
private ToggleButton getToggleForCategory(Category category) { private ToggleButton getToggleForCategory(Category category) {
@ -345,10 +357,13 @@ public class SlideShowView extends DrawableViewBase {
@Override @Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) { public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
if (t1) { getFileID().ifPresent(fileID -> {
FileIDSelectionModel.getInstance().clearAndSelect(getFileID()); if (t1) {
new CategorizeAction(getController()).addTag(getController().getTagsManager().getTagName(cat), ""); FileIDSelectionModel.getInstance().clearAndSelect(fileID);
} new CategorizeAction(getController()).addTag(getController().getTagsManager().getTagName(cat), "");
}
});
} }
} }
} }