mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07:42 +00:00
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:
parent
13ad8aaaeb
commit
f1000486b7
@ -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>() {
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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 {
|
||||||
|
@ -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());
|
||||||
|
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user