mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07:42 +00:00
fix implementation of Background loading of video thumbs in IG
don't transition through null file when reassigning file to DrawableTiles, prevents buildup of load tasks bring GrouPane methods in line with current nomenclature reduce calls to FileSyncListener
This commit is contained in:
parent
66e9277f5f
commit
c2eb9af862
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
@ -20,13 +20,14 @@ package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
|||||||
|
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import static java.util.Objects.isNull;
|
||||||
|
import static java.util.Objects.nonNull;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.CacheHint;
|
import javafx.scene.CacheHint;
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.control.Control;
|
import javafx.scene.control.Control;
|
||||||
import javafx.scene.control.ProgressIndicator;
|
import javafx.scene.control.ProgressIndicator;
|
||||||
import javafx.scene.effect.DropShadow;
|
import javafx.scene.effect.DropShadow;
|
||||||
@ -61,7 +62,7 @@ public class DrawableTile extends DrawableTileBase {
|
|||||||
private ImageView imageView;
|
private ImageView imageView;
|
||||||
|
|
||||||
private Task<Image> task;
|
private Task<Image> task;
|
||||||
private SoftReference<Image> thumbCache;
|
private SoftReference<Image> thumbnailCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized protected void disposeContent() {
|
synchronized protected void disposeContent() {
|
||||||
@ -69,7 +70,7 @@ public class DrawableTile extends DrawableTileBase {
|
|||||||
task.cancel(true);
|
task.cancel(true);
|
||||||
}
|
}
|
||||||
task = null;
|
task = null;
|
||||||
thumbCache = null;
|
thumbnailCache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@ -117,11 +118,66 @@ public class DrawableTile extends DrawableTileBase {
|
|||||||
@Override
|
@Override
|
||||||
synchronized protected void updateContent() {
|
synchronized protected void updateContent() {
|
||||||
|
|
||||||
Node thumbnail = getThumbnail();
|
if (getFile().isPresent() == false) {
|
||||||
Platform.runLater(() -> {
|
thumbnailCache = null;
|
||||||
imageBorder.setCenter(thumbnail);
|
Platform.runLater(() -> {
|
||||||
});
|
imageView.setImage(null);
|
||||||
|
imageBorder.setCenter(null);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Image thumbnail = isNull(thumbnailCache) ? null : thumbnailCache.get();
|
||||||
|
|
||||||
|
if (nonNull(thumbnail)) {
|
||||||
|
setImageHelper(thumbnail);
|
||||||
|
} else if (isNull(task) || task.isDone()) {
|
||||||
|
DrawableFile<?> file = getFile().get();
|
||||||
|
task = new Task<Image>() {
|
||||||
|
@Override
|
||||||
|
protected Image call() throws Exception {
|
||||||
|
if (isCancelled() == false) {
|
||||||
|
return file.getThumbnail();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void failed() {
|
||||||
|
super.failed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void succeeded() {
|
||||||
|
super.succeeded();
|
||||||
|
if (isCancelled() == false) {
|
||||||
|
try {
|
||||||
|
synchronized (DrawableTile.this) {
|
||||||
|
final Image thumbnail = get();
|
||||||
|
thumbnailCache = new SoftReference<>(thumbnail);
|
||||||
|
setImageHelper(thumbnailCache.get());
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
LOGGER.log(Level.WARNING, "failed to get thumbnail for" + file.getName(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
synchronized (DrawableTile.this) {
|
||||||
|
task = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
imageBorder.setCenter(new ProgressIndicator());
|
||||||
|
});
|
||||||
|
new Thread(task).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setImageHelper(final Image t) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
imageView.setImage(t);
|
||||||
|
imageBorder.setCenter(imageView);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -129,59 +185,4 @@ public class DrawableTile extends DrawableTileBase {
|
|||||||
return getFile().map(AbstractContent::getName).orElse("");
|
return getFile().map(AbstractContent::getName).orElse("");
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized private Node getThumbnail() {
|
|
||||||
if (getFile().isPresent() == false) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
Image thumbnail = (thumbCache == null)
|
|
||||||
? null : thumbCache.get();
|
|
||||||
|
|
||||||
if (thumbnail != null) {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
imageView.setImage(thumbnail);
|
|
||||||
});
|
|
||||||
return imageView;
|
|
||||||
} else {
|
|
||||||
if (task == null || task.isDone()) {
|
|
||||||
DrawableFile<?> file = getFile().get();
|
|
||||||
task = new Task<Image>() {
|
|
||||||
@Override
|
|
||||||
protected Image call() throws Exception {
|
|
||||||
if (isCancelled() == false) {
|
|
||||||
return file.getThumbnail();
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void failed() {
|
|
||||||
super.failed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void succeeded() {
|
|
||||||
super.succeeded();
|
|
||||||
if (isCancelled() == false) {
|
|
||||||
try {
|
|
||||||
synchronized (DrawableTile.this) {
|
|
||||||
thumbCache = new SoftReference<>(get());
|
|
||||||
}
|
|
||||||
updateContent();
|
|
||||||
|
|
||||||
} catch (InterruptedException | ExecutionException ex) {
|
|
||||||
LOGGER.log(Level.WARNING, "failed to get thumbnail for" + file.getName(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
synchronized (DrawableTile.this) {
|
|
||||||
task = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
new Thread(task).start();
|
|
||||||
}
|
|
||||||
return new ProgressIndicator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
||||||
|
|
||||||
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.logging.Level;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
@ -86,9 +85,11 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
|
|||||||
synchronized public void setFile(Long newFileID) {
|
synchronized public void setFile(Long newFileID) {
|
||||||
if (getFileID().isPresent()) {
|
if (getFileID().isPresent()) {
|
||||||
if (Objects.equals(newFileID, getFileID().get()) == false) {
|
if (Objects.equals(newFileID, getFileID().get()) == false) {
|
||||||
setFileHelper(newFileID);
|
if (Objects.nonNull(newFileID)) {
|
||||||
|
setFileHelper(newFileID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (nonNull(newFileID)) {
|
} else if (Objects.nonNull(newFileID)) {
|
||||||
setFileHelper(newFileID);
|
setFileHelper(newFileID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ public class GroupPane extends BorderPane {
|
|||||||
|
|
||||||
private final InvalidationListener filesSyncListener = (observable) -> {
|
private final InvalidationListener filesSyncListener = (observable) -> {
|
||||||
final String header = getHeaderString();
|
final String header = getHeaderString();
|
||||||
final List<Long> fileIds = getGrouping().fileIds();
|
final List<Long> fileIds = getGroup().fileIds();
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
slideShowToggle.setDisable(fileIds.isEmpty());
|
slideShowToggle.setDisable(fileIds.isEmpty());
|
||||||
gridView.getItems().setAll(fileIds);
|
gridView.getItems().setAll(fileIds);
|
||||||
@ -245,8 +245,8 @@ public class GroupPane extends BorderPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//assign last selected file or if none first file in group
|
//assign last selected file or if none first file in group
|
||||||
if (slideShowFileID == null || getGrouping().fileIds().contains(slideShowFileID) == false) {
|
if (slideShowFileID == null || getGroup().fileIds().contains(slideShowFileID) == false) {
|
||||||
slideShowPane.setFile(getGrouping().fileIds().get(0));
|
slideShowPane.setFile(getGroup().fileIds().get(0));
|
||||||
} else {
|
} else {
|
||||||
slideShowPane.setFile(slideShowFileID);
|
slideShowPane.setFile(slideShowFileID);
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ public class GroupPane extends BorderPane {
|
|||||||
this.scrollToFileID(globalSelectionModel.lastSelectedProperty().get());
|
this.scrollToFileID(globalSelectionModel.lastSelectedProperty().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DrawableGroup getGrouping() {
|
public DrawableGroup getGroup() {
|
||||||
return grouping.get();
|
return grouping.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ public class GroupPane extends BorderPane {
|
|||||||
menuItem.setOnAction(new EventHandler<ActionEvent>() {
|
menuItem.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent t) {
|
public void handle(ActionEvent t) {
|
||||||
Set<Long> fileIdSet = new HashSet<>(getGrouping().fileIds());
|
Set<Long> fileIdSet = new HashSet<>(getGroup().fileIds());
|
||||||
new CategorizeAction(controller).addTagsToFiles(controller.getTagsManager().getTagName(cat), "", fileIdSet);
|
new CategorizeAction(controller).addTagsToFiles(controller.getTagsManager().getTagName(cat), "", fileIdSet);
|
||||||
|
|
||||||
grpCatSplitMenu.setText(cat.getDisplayName());
|
grpCatSplitMenu.setText(cat.getDisplayName());
|
||||||
@ -291,7 +291,7 @@ public class GroupPane extends BorderPane {
|
|||||||
menuItem.setOnAction(new EventHandler<ActionEvent>() {
|
menuItem.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent t) {
|
public void handle(ActionEvent t) {
|
||||||
Set<Long> fileIdSet = new HashSet<>(getGrouping().fileIds());
|
Set<Long> fileIdSet = new HashSet<>(getGroup().fileIds());
|
||||||
new AddDrawableTagAction(controller).addTagsToFiles(tn, "", fileIdSet);
|
new AddDrawableTagAction(controller).addTagsToFiles(tn, "", fileIdSet);
|
||||||
|
|
||||||
grpTagSplitMenu.setText(tn.getDisplayName());
|
grpTagSplitMenu.setText(tn.getDisplayName());
|
||||||
@ -302,14 +302,14 @@ public class GroupPane extends BorderPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void selectAllFiles() {
|
private void selectAllFiles() {
|
||||||
globalSelectionModel.clearAndSelectAll(getGrouping().fileIds());
|
globalSelectionModel.clearAndSelectAll(getGroup().fileIds());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** create the string to display in the group header */
|
/** create the string to display in the group header */
|
||||||
protected String getHeaderString() {
|
protected String getHeaderString() {
|
||||||
return isNull(getGrouping()) ? ""
|
return isNull(getGroup()) ? ""
|
||||||
: StringUtils.defaultIfBlank(getGrouping().getGroupByValueDislpayName(), DrawableGroup.getBlankGroupName()) + " -- "
|
: StringUtils.defaultIfBlank(getGroup().getGroupByValueDislpayName(), DrawableGroup.getBlankGroupName()) + " -- "
|
||||||
+ getGrouping().getHashSetHitsCount() + " hash set hits / " + getGrouping().getSize() + " files";
|
+ getGroup().getHashSetHitsCount() + " hash set hits / " + getGroup().getSize() + " files";
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextMenu getContextMenu() {
|
ContextMenu getContextMenu() {
|
||||||
@ -579,11 +579,11 @@ public class GroupPane extends BorderPane {
|
|||||||
* @param grouping the new grouping assigned to this group
|
* @param grouping the new grouping assigned to this group
|
||||||
*/
|
*/
|
||||||
void setViewState(GroupViewState viewState) {
|
void setViewState(GroupViewState viewState) {
|
||||||
if (nonNull(getGrouping())) {
|
|
||||||
getGrouping().fileIds().removeListener(filesSyncListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNull(viewState) || isNull(viewState.getGroup())) {
|
if (isNull(viewState) || isNull(viewState.getGroup())) {
|
||||||
|
if (nonNull(getGroup())) {
|
||||||
|
getGroup().fileIds().removeListener(filesSyncListener);
|
||||||
|
}
|
||||||
this.grouping.set(null);
|
this.grouping.set(null);
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
@ -599,15 +599,18 @@ public class GroupPane extends BorderPane {
|
|||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (this.grouping.get() != viewState.getGroup()) {
|
if (getGroup() != viewState.getGroup()) {
|
||||||
|
if (nonNull(getGroup())) {
|
||||||
|
getGroup().fileIds().removeListener(filesSyncListener);
|
||||||
|
}
|
||||||
this.grouping.set(viewState.getGroup());
|
this.grouping.set(viewState.getGroup());
|
||||||
|
|
||||||
this.getGrouping().fileIds().addListener(filesSyncListener);
|
getGroup().fileIds().addListener(filesSyncListener);
|
||||||
|
|
||||||
final String header = getHeaderString();
|
final String header = getHeaderString();
|
||||||
|
|
||||||
gridView.getItems().setAll(getGrouping().fileIds());
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
|
gridView.getItems().setAll(getGroup().fileIds());
|
||||||
slideShowToggle.setDisable(gridView.getItems().isEmpty());
|
slideShowToggle.setDisable(gridView.getItems().isEmpty());
|
||||||
groupLabel.setText(header);
|
groupLabel.setText(header);
|
||||||
resetScrollBar();
|
resetScrollBar();
|
||||||
@ -686,6 +689,7 @@ public class GroupPane extends BorderPane {
|
|||||||
@Override
|
@Override
|
||||||
protected void updateItem(Long item, boolean empty) {
|
protected void updateItem(Long item, boolean empty) {
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
|
|
||||||
tile.setFile(item);
|
tile.setFile(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,8 +195,8 @@ public class SlideShowView extends DrawableTileBase {
|
|||||||
|
|
||||||
getGroupPane().grouping().addListener((Observable observable) -> {
|
getGroupPane().grouping().addListener((Observable observable) -> {
|
||||||
syncButtonVisibility();
|
syncButtonVisibility();
|
||||||
if (getGroupPane().getGrouping() != null) {
|
if (getGroupPane().getGroup() != null) {
|
||||||
getGroupPane().getGrouping().fileIds().addListener((Observable observable1) -> {
|
getGroupPane().getGroup().fileIds().addListener((Observable observable1) -> {
|
||||||
syncButtonVisibility();
|
syncButtonVisibility();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -206,7 +206,7 @@ public class SlideShowView extends DrawableTileBase {
|
|||||||
@ThreadConfined(type = ThreadType.ANY)
|
@ThreadConfined(type = ThreadType.ANY)
|
||||||
private void syncButtonVisibility() {
|
private void syncButtonVisibility() {
|
||||||
try {
|
try {
|
||||||
final boolean hasMultipleFiles = getGroupPane().getGrouping().fileIds().size() > 1;
|
final boolean hasMultipleFiles = getGroupPane().getGroup().fileIds().size() > 1;
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
rightButton.setVisible(hasMultipleFiles);
|
rightButton.setVisible(hasMultipleFiles);
|
||||||
leftButton.setVisible(hasMultipleFiles);
|
leftButton.setVisible(hasMultipleFiles);
|
||||||
@ -288,12 +288,12 @@ public class SlideShowView extends DrawableTileBase {
|
|||||||
@ThreadConfined(type = ThreadType.JFX)
|
@ThreadConfined(type = ThreadType.JFX)
|
||||||
synchronized private void cycleSlideShowImage(int direction) {
|
synchronized private void cycleSlideShowImage(int direction) {
|
||||||
stopVideo();
|
stopVideo();
|
||||||
final int groupSize = getGroupPane().getGrouping().fileIds().size();
|
final int groupSize = getGroupPane().getGroup().fileIds().size();
|
||||||
final Integer nextIndex = getFileID().map(fileID -> {
|
final Integer nextIndex = getFileID().map(fileID -> {
|
||||||
final int currentIndex = getGroupPane().getGrouping().fileIds().indexOf(fileID);
|
final int currentIndex = getGroupPane().getGroup().fileIds().indexOf(fileID);
|
||||||
return (currentIndex + direction + groupSize) % groupSize;
|
return (currentIndex + direction + groupSize) % groupSize;
|
||||||
}).orElse(0);
|
}).orElse(0);
|
||||||
setFile(getGroupPane().getGrouping().fileIds().get(nextIndex)
|
setFile(getGroupPane().getGroup().fileIds().get(nextIndex)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ public class SlideShowView extends DrawableTileBase {
|
|||||||
* of y"
|
* of y"
|
||||||
*/
|
*/
|
||||||
private String getSupplementalText() {
|
private String getSupplementalText() {
|
||||||
final ObservableList<Long> fileIds = getGroupPane().getGrouping().fileIds();
|
final ObservableList<Long> fileIds = getGroupPane().getGroup().fileIds();
|
||||||
return getFileID().map(fileID -> " ( " + (fileIds.indexOf(fileID) + 1) + " of " + fileIds.size() + " in group )")
|
return getFileID().map(fileID -> " ( " + (fileIds.indexOf(fileID) + 1) + " of " + fileIds.size() + " in group )")
|
||||||
.orElse("");
|
.orElse("");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user