fix bugs updating tags/categpries in slideshowview and metadata pane

make new abstract base calss DrawableUIBase and move fileid and file object access to it.
This commit is contained in:
jmillman 2015-06-22 13:33:07 -04:00
parent 13ad8aaaeb
commit f1000486b7
8 changed files with 161 additions and 181 deletions

View File

@ -37,11 +37,9 @@ import org.sleuthkit.datamodel.TskCoreException;
public class DeleteFollowUpTagAction extends Action { public class DeleteFollowUpTagAction extends Action {
private static final Logger LOGGER = Logger.getLogger(DeleteFollowUpTagAction.class.getName()); private static final Logger LOGGER = Logger.getLogger(DeleteFollowUpTagAction.class.getName());
private final long fileID;
public DeleteFollowUpTagAction(final ImageGalleryController controller, final DrawableFile<?> file) { public DeleteFollowUpTagAction(final ImageGalleryController controller, final DrawableFile<?> file) {
super("Delete Follow Up Tag"); super("Delete Follow Up Tag");
this.fileID = file.getId();
setEventHandler((ActionEvent t) -> { setEventHandler((ActionEvent t) -> {
new SwingWorker<Void, Void>() { new SwingWorker<Void, Void>() {

View File

@ -251,7 +251,7 @@ public class CategoryManager {
incrementCategoryCount(newCat); incrementCategoryCount(newCat);
} }
fireChange(Collections.singleton(addedTag.getId()), newCat); fireChange(Collections.singleton(addedTag.getContent().getId()), newCat);
} }
} }
@Subscribe @Subscribe
@ -263,7 +263,7 @@ public class CategoryManager {
if (deletedCat != Category.ZERO) { if (deletedCat != Category.ZERO) {
decrementCategoryCount(deletedCat); decrementCategoryCount(deletedCat);
} }
fireChange(Collections.singleton(deleted.getId()), null); fireChange(Collections.singleton(deleted.getContent().getId()), null);
} }
} }
} }

View File

@ -32,7 +32,7 @@ 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.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableViewBase.globalSelectionModel; import static org.sleuthkit.autopsy.imagegallery.gui.DrawableTileBase.globalSelectionModel;
import org.sleuthkit.datamodel.AbstractContent; import org.sleuthkit.datamodel.AbstractContent;
/** /**
@ -43,7 +43,7 @@ import org.sleuthkit.datamodel.AbstractContent;
* *
* TODO: refactor this to extend from {@link Control}? -jm * TODO: refactor this to extend from {@link Control}? -jm
*/ */
public class DrawableTile extends DrawableViewBase { public class DrawableTile extends DrawableTileBase {
private static final DropShadow LAST_SELECTED_EFFECT = new DropShadow(10, Color.BLUE); private static final DropShadow LAST_SELECTED_EFFECT = new DropShadow(10, Color.BLUE);
@ -67,7 +67,6 @@ public class DrawableTile extends DrawableViewBase {
assert imageBorder != null : "fx:id=\"imageAnchor\" was not injected: check your FXML file 'DrawableTile.fxml'."; assert imageBorder != null : "fx:id=\"imageAnchor\" was not injected: check your FXML file 'DrawableTile.fxml'.";
assert imageView != null : "fx:id=\"imageView\" was not injected: check your FXML file 'DrawableTile.fxml'."; assert imageView != null : "fx:id=\"imageView\" was not injected: check your FXML file 'DrawableTile.fxml'.";
assert nameLabel != null : "fx:id=\"nameLabel\" was not injected: check your FXML file 'DrawableTile.fxml'."; assert nameLabel != null : "fx:id=\"nameLabel\" was not injected: check your FXML file 'DrawableTile.fxml'.";
//set up properties and binding //set up properties and binding
setCache(true); setCache(true);
setCacheHint(CacheHint.SPEED); setCacheHint(CacheHint.SPEED);
@ -87,9 +86,11 @@ public class DrawableTile extends DrawableViewBase {
public DrawableTile(GroupPane gp) { public DrawableTile(GroupPane gp) {
super(gp); super(gp);
FXMLConstructor.construct(this, "DrawableTile.fxml"); FXMLConstructor.construct(this, "DrawableTile.fxml");
} }
@Override @Override
@ThreadConfined(type = ThreadType.JFX) @ThreadConfined(type = ThreadType.JFX)
protected void clearContent() { protected void clearContent() {

View File

@ -22,8 +22,6 @@ package org.sleuthkit.autopsy.imagegallery.gui;
import com.google.common.eventbus.Subscribe; 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 static java.util.Objects.nonNull;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.application.Platform; import javafx.application.Platform;
@ -39,7 +37,6 @@ import javafx.scene.control.Tooltip;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Border; import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke; import javafx.scene.layout.BorderStroke;
@ -66,13 +63,11 @@ import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel; import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent;
import org.sleuthkit.autopsy.imagegallery.actions.AddDrawableTagAction; import org.sleuthkit.autopsy.imagegallery.actions.AddDrawableTagAction;
import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction;
import org.sleuthkit.autopsy.imagegallery.actions.DeleteFollowUpTagAction; import org.sleuthkit.autopsy.imagegallery.actions.DeleteFollowUpTagAction;
import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter; import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter;
import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent;
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.DrawableFile;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
@ -84,9 +79,9 @@ import org.sleuthkit.datamodel.TskCoreException;
* of {@link DrawableView}s should implement the interface directly * of {@link DrawableView}s should implement the interface directly
* *
*/ */
public abstract class DrawableViewBase extends AnchorPane implements DrawableView { public abstract class DrawableTileBase extends DrawableUIBase {
private static final Logger LOGGER = Logger.getLogger(DrawableViewBase.class.getName()); private static final Logger LOGGER = Logger.getLogger(DrawableTileBase.class.getName());
private static final Border UNSELECTED_BORDER = new Border(new BorderStroke(Color.GRAY, BorderStrokeStyle.SOLID, new CornerRadii(2), new BorderWidths(3))); private static final Border UNSELECTED_BORDER = new Border(new BorderStroke(Color.GRAY, BorderStrokeStyle.SOLID, new CornerRadii(2), new BorderWidths(3)));
@ -99,6 +94,7 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
protected static final Image followUpGray = new Image("org/sleuthkit/autopsy/imagegallery/images/flag_gray.png"); protected static final Image followUpGray = new Image("org/sleuthkit/autopsy/imagegallery/images/flag_gray.png");
protected static final FileIDSelectionModel globalSelectionModel = FileIDSelectionModel.getInstance(); protected static final FileIDSelectionModel globalSelectionModel = FileIDSelectionModel.getInstance();
private static ContextMenu contextMenu;
/** /**
* displays the icon representing video files * displays the icon representing video files
@ -130,50 +126,16 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
@FXML @FXML
protected BorderPane imageBorder; protected BorderPane imageBorder;
static private ContextMenu contextMenu;
volatile private Optional<DrawableFile<?>> fileOpt = Optional.empty();
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 DrawableTileBase} is embedded in
*/ */
final private GroupPane groupPane; final private GroupPane groupPane;
private boolean registered = false; volatile private boolean registered = false;
private final ImageGalleryController controller;
GroupPane getGroupPane() { protected DrawableTileBase(GroupPane groupPane) {
return groupPane; super(groupPane.getController());
}
protected DrawableViewBase(GroupPane groupPane) {
this.groupPane = groupPane; this.groupPane = groupPane;
this.controller = groupPane.getController();
globalSelectionModel.getSelected().addListener((Observable observable) -> { globalSelectionModel.getSelected().addListener((Observable observable) -> {
updateSelectionState(); updateSelectionState();
}); });
@ -213,7 +175,7 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
groupContextMenu.hide(); groupContextMenu.hide();
} }
contextMenu = buildContextMenu(file); contextMenu = buildContextMenu(file);
contextMenu.show(DrawableViewBase.this, t.getScreenX(), t.getScreenY()); contextMenu.show(DrawableTileBase.this, t.getScreenX(), t.getScreenY());
break; break;
} }
}); });
@ -224,9 +186,9 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
private ContextMenu buildContextMenu(DrawableFile<?> file) { 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(getController()).getPopupMenu());
menuItems.add(new AddDrawableTagAction(controller).getPopupMenu()); menuItems.add(new AddDrawableTagAction(getController()).getPopupMenu());
final MenuItem extractMenuItem = new MenuItem("Extract File(s)"); final MenuItem extractMenuItem = new MenuItem("Extract File(s)");
extractMenuItem.setOnAction((ActionEvent t) -> { extractMenuItem.setOnAction((ActionEvent t) -> {
@ -274,6 +236,10 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
}); });
} }
GroupPane getGroupPane() {
return groupPane;
}
@ThreadConfined(type = ThreadType.UI) @ThreadConfined(type = ThreadType.UI)
protected abstract void clearContent(); protected abstract void clearContent();
@ -283,31 +249,29 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
protected abstract String getTextForLabel(); protected abstract String getTextForLabel();
@SuppressWarnings("deprecation")
protected void initialize() { protected void initialize() {
followUpToggle.setOnAction((ActionEvent event) -> { followUpToggle.setOnAction((ActionEvent event) -> {
getFile().ifPresent(file -> { getFile().ifPresent(file -> {
if (followUpToggle.isSelected() == true) { if (followUpToggle.isSelected() == true) {
try { try {
final TagName followUpTagName = controller.getTagsManager().getFollowUpTagName();
globalSelectionModel.clearAndSelect(file.getId()); globalSelectionModel.clearAndSelect(file.getId());
new AddDrawableTagAction(controller).addTag(followUpTagName, ""); new AddDrawableTagAction(getController()).addTag(getController().getTagsManager().getFollowUpTagName(), "");
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to add Follow Up tag. Could not load TagName.", ex); LOGGER.log(Level.SEVERE, "Failed to add Follow Up tag. Could not load TagName.", ex);
} }
} else { } else {
new DeleteFollowUpTagAction(controller, file).handle(event); new DeleteFollowUpTagAction(getController(), file).handle(event);
} }
}); });
}); });
} }
protected boolean hasFollowUp() { protected boolean hasFollowUp() {
if (getFile().isPresent()) { if (getFileID().isPresent()) {
try { try {
TagName followUpTagName = getController().getTagsManager().getFollowUpTagName(); TagName followUpTagName = getController().getTagsManager().getFollowUpTagName();
Collection<TagName> tagNames = DrawableAttribute.TAGS.getValue(getFile().get()); return DrawableAttribute.TAGS.getValue(getFile().get()).stream()
return tagNames.stream().anyMatch((tn) -> tn.equals(followUpTagName)); .anyMatch(followUpTagName::equals);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "failed to get follow up tag name ", ex); LOGGER.log(Level.WARNING, "failed to get follow up tag name ", ex);
return true; return true;
@ -318,29 +282,17 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
} }
@Override @Override
public void setFile(final Long newFileID) { protected void setFileHelper(final Long newFileID) {
if (fileIDOpt.isPresent()) { setFileIDOpt(Optional.ofNullable(newFileID));
if (Objects.equals(newFileID, fileIDOpt.get()) == false) {
setFileHelper(newFileID);
}
} else {
if (nonNull(newFileID)) {
setFileHelper(newFileID);
}
}
}
private void setFileHelper(final Long newFileID) {
fileIDOpt = Optional.ofNullable(newFileID);
disposeContent(); disposeContent();
if (fileIDOpt.isPresent() == false || Case.isCaseOpen() == false) { if (getFileID().isPresent() == false || Case.isCaseOpen() == false) {
if (registered == true) { if (registered == true) {
getController().getCategoryManager().unregisterListener(this); getController().getCategoryManager().unregisterListener(this);
getController().getTagsManager().unregisterListener(this); getController().getTagsManager().unregisterListener(this);
registered = false; registered = false;
} }
fileOpt = Optional.empty(); setFileOpt(Optional.empty());
Platform.runLater(() -> { Platform.runLater(() -> {
clearContent(); clearContent();
}); });
@ -350,10 +302,10 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
getController().getTagsManager().registerListener(this); getController().getTagsManager().registerListener(this);
registered = true; registered = true;
} }
fileOpt = Optional.empty(); setFileOpt(Optional.empty());
updateSelectionState(); updateSelectionState();
updateCategoryBorder(); updateCategory();
updateFollowUpIcon(); updateFollowUpIcon();
updateUI(); updateUI();
Platform.runLater(getContentUpdateRunnable()); Platform.runLater(getContentUpdateRunnable());
@ -397,10 +349,10 @@ 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 -> { getFileID().ifPresent(fileID -> {
try { try {
if (fileID == evt.getAddedTag().getContent().getId() if (fileID == evt.getAddedTag().getContent().getId()
&& evt.getAddedTag().getName() == getController().getTagsManager().getFollowUpTagName()) { && evt.getAddedTag().getName().equals(getController().getTagsManager().getFollowUpTagName())) {
Platform.runLater(() -> { Platform.runLater(() -> {
followUpImageView.setImage(followUpIcon); followUpImageView.setImage(followUpIcon);
@ -417,10 +369,10 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
@Override @Override
public void handleTagDeleted(ContentTagDeletedEvent evt) { public void handleTagDeleted(ContentTagDeletedEvent evt) {
fileIDOpt.ifPresent(fileID -> { getFileID().ifPresent(fileID -> {
try { try {
if (fileID == evt.getDeletedTag().getContent().getId() if (fileID == evt.getDeletedTag().getContent().getId()
&& evt.getDeletedTag().getName() == controller.getTagsManager().getFollowUpTagName()) { && evt.getDeletedTag().getName().equals(getController().getTagsManager().getFollowUpTagName())) {
updateFollowUpIcon(); updateFollowUpIcon();
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
@ -436,19 +388,4 @@ public abstract class DrawableViewBase extends AnchorPane implements DrawableVie
followUpToggle.setSelected(hasFollowUp); followUpToggle.setSelected(hasFollowUp);
}); });
} }
@Subscribe
@Override
public void handleCategoryChanged(CategoryChangeEvent evt) {
fileIDOpt.ifPresent(fileID -> {
if (evt.getFileIDs().contains(fileID)) {
updateCategoryBorder();
}
});
}
@Override
public ImageGalleryController getController() {
return controller;
}
} }

View File

@ -0,0 +1,97 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.imagegallery.gui;
import java.util.Objects;
import static java.util.Objects.nonNull;
import java.util.Optional;
import java.util.logging.Level;
import javafx.scene.layout.AnchorPane;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
import org.sleuthkit.datamodel.TskCoreException;
/**
*
*/
abstract public class DrawableUIBase extends AnchorPane implements DrawableView {
private final ImageGalleryController controller;
volatile private Optional<DrawableFile<?>> fileOpt = Optional.empty();
volatile private Optional<Long> fileIDOpt = Optional.empty();
public DrawableUIBase(ImageGalleryController controller) {
this.controller = controller;
}
@Override
public ImageGalleryController getController() {
return controller;
}
@Override
public Optional<Long> getFileID() {
return fileIDOpt;
}
void setFileIDOpt(Optional<Long> fileIDOpt) {
this.fileIDOpt = fileIDOpt;
}
void setFileOpt(Optional<DrawableFile<?>> fileOpt) {
this.fileOpt = fileOpt;
}
@Override
public Optional<DrawableFile<?>> getFile() {
if (fileIDOpt.isPresent()) {
if (fileOpt.isPresent() && fileOpt.get().getId() == fileIDOpt.get()) {
return fileOpt;
} else {
try {
fileOpt = Optional.of(getController().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();
}
}
protected abstract void setFileHelper(Long newFileID);
@Override
public void setFile(Long newFileID) {
if (getFileID().isPresent()) {
if (Objects.equals(newFileID, getFileID().get()) == false) {
setFileHelper(newFileID);
}
} else if (nonNull(newFileID)) {
setFileHelper(newFileID);
}
}
}

View File

@ -68,7 +68,13 @@ public interface DrawableView {
* @param evt the CategoryChangeEvent to handle * @param evt the CategoryChangeEvent to handle
*/ */
@Subscribe @Subscribe
void handleCategoryChanged(CategoryChangeEvent evt); default void handleCategoryChanged(CategoryChangeEvent evt) {
getFileID().ifPresent(fileID -> {
if (evt.getFileIDs().contains(fileID)) {
updateCategory();
}
});
}
@Subscribe @Subscribe
void handleTagAdded(ContentTagAddedEvent evt); void handleTagAdded(ContentTagAddedEvent evt);
@ -116,16 +122,12 @@ public interface DrawableView {
} }
@ThreadConfined(type = ThreadConfined.ThreadType.ANY) @ThreadConfined(type = ThreadConfined.ThreadType.ANY)
default Category updateCategoryBorder() { default Category updateCategory() {
if (getFile() != null) { if (getFile().isPresent()) {
final Category category = getFile().map(DrawableFile::getCategory).orElse(Category.ZERO); 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 : getCategoryBorder(category);
? HASH_BORDER
: getCategoryBorder(category);
Platform.runLater(() -> { Platform.runLater(() -> {
getCategoryBorderRegion().setBorder(border); getCategoryBorderRegion().setBorder(border);
getCategoryBorderRegion().requestLayout();
}); });
return category; return category;
} else { } else {

View File

@ -23,9 +23,7 @@ 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 java.util.Objects;
import static java.util.Objects.nonNull;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
@ -39,7 +37,6 @@ import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView; import javafx.scene.control.TableView;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import static javafx.scene.layout.Region.USE_COMPUTED_SIZE; import static javafx.scene.layout.Region.USE_COMPUTED_SIZE;
@ -53,24 +50,15 @@ 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.CategoryChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Shows details of the selected file. * Shows details of the selected file.
*/ */
public class MetaDataPane extends AnchorPane implements DrawableView { public class MetaDataPane extends DrawableUIBase {
private static final Logger LOGGER = Logger.getLogger(MetaDataPane.class.getName()); private static final Logger LOGGER = Logger.getLogger(MetaDataPane.class.getName());
private final ImageGalleryController controller;
@Override
public ImageGalleryController getController() {
return controller;
}
@FXML @FXML
private ImageView imageView; private ImageView imageView;
@ -141,56 +129,14 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
tableView.getColumns().setAll(Arrays.asList(attributeColumn, valueColumn)); tableView.getColumns().setAll(Arrays.asList(attributeColumn, valueColumn));
//listen for selection change //listen for selection change
controller.getSelectionModel().lastSelectedProperty().addListener((observable, oldFileID, newFileID) -> { getController().getSelectionModel().lastSelectedProperty().addListener((observable, oldFileID, newFileID) -> {
setFile(newFileID); setFile(newFileID);
}); });
} }
volatile private Optional<DrawableFile<?>> fileOpt = Optional.empty();
volatile private Optional<Long> fileIDOpt = Optional.empty();
@Override @Override
public Optional<Long> getFileID() { synchronized protected void setFileHelper(Long newFileID) {
return fileIDOpt; setFileIDOpt(Optional.ofNullable(newFileID));
}
@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();
}
}
@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) { if (newFileID == null) {
Platform.runLater(() -> { Platform.runLater(() -> {
imageView.setImage(null); imageView.setImage(null);
@ -204,7 +150,7 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
} }
public MetaDataPane(ImageGalleryController controller) { public MetaDataPane(ImageGalleryController controller) {
this.controller = controller; super(controller);
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MetaDataPane.fxml")); FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MetaDataPane.fxml"));
fxmlLoader.setRoot(this); fxmlLoader.setRoot(this);
@ -224,12 +170,12 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
Platform.runLater(() -> { Platform.runLater(() -> {
imageView.setImage(icon); imageView.setImage(icon);
tableView.getItems().clear();
tableView.getItems().setAll(attributesList); tableView.getItems().setAll(attributesList);
}); });
updateCategoryBorder(); updateCategory();
}); });
} }
@Override @Override
@ -248,11 +194,13 @@ public class MetaDataPane extends AnchorPane implements DrawableView {
}); });
} }
@Subscribe
@Override @Override
public void handleTagAdded(ContentTagAddedEvent evt) { public void handleTagAdded(ContentTagAddedEvent evt) {
handleTagChanged(evt.getAddedTag().getContent().getId()); handleTagChanged(evt.getAddedTag().getContent().getId());
} }
@Subscribe
@Override @Override
public void handleTagDeleted(ContentTagDeletedEvent evt) { public void handleTagDeleted(ContentTagDeletedEvent evt) {
handleTagChanged(evt.getDeletedTag().getContent().getId()); handleTagChanged(evt.getDeletedTag().getContent().getId());

View File

@ -58,8 +58,6 @@ 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.CAT_BORDER_WIDTH;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableView.HASH_BORDER;
import static org.sleuthkit.autopsy.imagegallery.gui.DrawableView.getCategoryBorder;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -68,7 +66,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* GroupPane. TODO: Extract a subclass for video files in slideshow mode-jm * GroupPane. TODO: Extract a subclass for video files in slideshow mode-jm
* TODO: reduce coupling to GroupPane * TODO: reduce coupling to GroupPane
*/ */
public class SlideShowView extends DrawableViewBase { public class SlideShowView extends DrawableTileBase {
private static final Logger LOGGER = Logger.getLogger(SlideShowView.class.getName()); private static final Logger LOGGER = Logger.getLogger(SlideShowView.class.getName());
@ -223,6 +221,7 @@ public class SlideShowView extends DrawableViewBase {
SlideShowView(GroupPane gp) { SlideShowView(GroupPane gp) {
super(gp); super(gp);
FXMLConstructor.construct(this, "SlideShow.fxml"); FXMLConstructor.construct(this, "SlideShow.fxml");
} }
@ -237,6 +236,7 @@ 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);
getFileID().ifPresent((Long id) -> { getFileID().ifPresent((Long id) -> {
getGroupPane().makeSelection(false, id); getGroupPane().makeSelection(false, id);
}); });
@ -288,7 +288,7 @@ public class SlideShowView extends DrawableViewBase {
@ThreadConfined(type = ThreadType.JFX) @ThreadConfined(type = ThreadType.JFX)
private void cycleSlideShowImage(int d) { private void cycleSlideShowImage(int d) {
stopVideo(); stopVideo();
if (getFileID() != null) { if (getFileID().isPresent()) {
int index = getGroupPane().getGrouping().fileIds().indexOf(getFileID()); int index = getGroupPane().getGrouping().fileIds().indexOf(getFileID());
final int size = getGroupPane().getGrouping().fileIds().size(); final int size = getGroupPane().getGrouping().fileIds().size();
index = (index + d) % size; index = (index + d) % size;
@ -312,20 +312,17 @@ public class SlideShowView extends DrawableViewBase {
@Override @Override
@ThreadConfined(type = ThreadType.ANY) @ThreadConfined(type = ThreadType.ANY)
public Category updateCategoryBorder() { public Category updateCategory() {
return getFile().map(file -> { if (getFile().isPresent()) {
final Category category = file.getCategory(); final Category category = super.updateCategory();
final Border border1 = hasHashHit() && (category == Category.ZERO)
? HASH_BORDER
: getCategoryBorder(category);
ToggleButton toggleForCategory = getToggleForCategory(category); ToggleButton toggleForCategory = getToggleForCategory(category);
Platform.runLater(() -> { Platform.runLater(() -> {
getCategoryBorderRegion().setBorder(border1);
toggleForCategory.setSelected(true); toggleForCategory.setSelected(true);
}); });
return category; return category;
}).orElse(Category.ZERO); } else {
return Category.ZERO;
}
} }
private ToggleButton getToggleForCategory(Category category) { private ToggleButton getToggleForCategory(Category category) {