mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge pull request #4186 from millmanorama/1054-populate_widgets_on_bg_thread
1054 make sure all db queries for widget initialization happen on bg threads.
This commit is contained in:
commit
ac4778e7f5
@ -82,7 +82,7 @@ public class SummaryTablePane extends AnchorPane {
|
||||
|
||||
//register for category events
|
||||
controller.getCategoryManager().registerListener(this);
|
||||
handleCategoryChanged(null);
|
||||
new Thread(() -> handleCategoryChanged(null)).start();
|
||||
}
|
||||
|
||||
public SummaryTablePane(ImageGalleryController controller) {
|
||||
|
@ -74,6 +74,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
|
||||
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
||||
import static org.sleuthkit.autopsy.imagegallery.utils.TaskUtils.addFXCallback;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
|
||||
/**
|
||||
@ -255,6 +256,7 @@ public class Toolbar extends ToolBar {
|
||||
evt -> {
|
||||
Platform.runLater(() -> {
|
||||
Optional<DataSource> selectedItem = dataSourceSelectionModel.getSelectedItem();
|
||||
//restore selection once the sync is done.
|
||||
syncDataSources().addListener(() -> dataSourceSelectionModel.select(selectedItem), Platform::runLater);
|
||||
});
|
||||
});
|
||||
@ -269,22 +271,19 @@ public class Toolbar extends ToolBar {
|
||||
}
|
||||
|
||||
private void initTagMenuButton() {
|
||||
ListenableFuture<TagGroupAction> future = exec.submit(() -> new TagGroupAction(controller.getTagsManager().getFollowUpTagName(), controller));
|
||||
Futures.addCallback(future, new FutureCallback<TagGroupAction>() {
|
||||
@Override
|
||||
public void onSuccess(TagGroupAction followUpGroupAction) {
|
||||
addFXCallback(exec.submit(() -> new TagGroupAction(controller.getTagsManager().getFollowUpTagName(), controller)),
|
||||
followUpGroupAction -> {
|
||||
//on fx thread
|
||||
tagGroupMenuButton.setOnAction(followUpGroupAction);
|
||||
tagGroupMenuButton.setText(followUpGroupAction.getText());
|
||||
tagGroupMenuButton.setGraphic(followUpGroupAction.getGraphic());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
},
|
||||
throwable -> {
|
||||
/*
|
||||
* The problem appears to be a timing issue where a case is
|
||||
* closed before this initialization is completed, which It
|
||||
* appears to be harmless, so we are temporarily changing this
|
||||
* log message to a WARNING.
|
||||
* appears to be harmless, so we are temporarily changing
|
||||
* this log message to a WARNING.
|
||||
*
|
||||
* TODO (JIRA-3010): SEVERE error logged by image Gallery UI
|
||||
*/
|
||||
@ -295,7 +294,7 @@ public class Toolbar extends ToolBar {
|
||||
logger.log(Level.INFO, "Unable to get tag name. Case is closed."); //NON-NLS
|
||||
}
|
||||
}
|
||||
}, Platform::runLater);
|
||||
);
|
||||
|
||||
tagGroupMenuButton.showingProperty().addListener(showing -> {
|
||||
if (tagGroupMenuButton.isShowing()) {
|
||||
@ -303,24 +302,18 @@ public class Toolbar extends ToolBar {
|
||||
return Lists.transform(controller.getTagsManager().getNonCategoryTagNames(),
|
||||
tagName -> GuiUtils.createAutoAssigningMenuItem(tagGroupMenuButton, new TagGroupAction(tagName, controller)));
|
||||
});
|
||||
Futures.addCallback(getTagsFuture, new FutureCallback<List<MenuItem>>() {
|
||||
@Override
|
||||
public void onSuccess(List<MenuItem> result) {
|
||||
tagGroupMenuButton.getItems().setAll(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
logger.log(Level.SEVERE, "Error getting non-gategory tag names.", t);
|
||||
}
|
||||
}, Platform::runLater);
|
||||
addFXCallback(getTagsFuture,
|
||||
menuItems -> tagGroupMenuButton.getItems().setAll(menuItems),
|
||||
throwable -> logger.log(Level.SEVERE, "Error getting non-gategory tag names.", throwable)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
|
||||
private ListenableFuture<List<DataSource>> syncDataSources() {
|
||||
ListenableFuture<List<DataSource>> future = exec.submit(() -> {
|
||||
ListenableFuture<List<DataSource>> dataSourcesFuture = exec.submit(() -> {
|
||||
List<DataSource> dataSourcesInCase = controller.getSleuthKitCase().getDataSources();
|
||||
synchronized (dataSourcesViewable) {
|
||||
dataSourcesViewable.clear();
|
||||
@ -331,22 +324,18 @@ public class Toolbar extends ToolBar {
|
||||
}
|
||||
return dataSourcesInCase;
|
||||
});
|
||||
Futures.addCallback(future, new FutureCallback<List<DataSource>>() {
|
||||
@Override
|
||||
public void onSuccess(List<DataSource> result) {
|
||||
List<Optional<DataSource>> newDataSources = new ArrayList<>();
|
||||
newDataSources.add(Optional.empty());
|
||||
result.forEach(dataSource -> newDataSources.add(Optional.of(dataSource)));
|
||||
addFXCallback(dataSourcesFuture,
|
||||
result -> {
|
||||
//on fx thread
|
||||
List<Optional<DataSource>> newDataSources = new ArrayList<>(Lists.transform(result, Optional::of));
|
||||
newDataSources.add(0, Optional.empty());
|
||||
dataSources.setAll(newDataSources);
|
||||
}
|
||||
},
|
||||
throwable -> logger.log(Level.SEVERE, "Unable to get datasources for current case.", throwable) //NON-NLS
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
logger.log(Level.SEVERE, "Unable to get datasources for current case.", t); //NON-NLS
|
||||
}
|
||||
}, Platform::runLater);
|
||||
);
|
||||
|
||||
return future;
|
||||
return dataSourcesFuture;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -384,8 +373,7 @@ public class Toolbar extends ToolBar {
|
||||
* selection.
|
||||
*/
|
||||
private void syncGroupControlsEnabledState(GroupViewState newViewState) {
|
||||
boolean noGroupSelected = (null == newViewState)
|
||||
|| (null == newViewState.getGroup());
|
||||
boolean noGroupSelected = (null == newViewState) || (null == newViewState.getGroup());
|
||||
Platform.runLater(() -> {
|
||||
tagGroupMenuButton.setDisable(noGroupSelected);
|
||||
catGroupMenuButton.setDisable(noGroupSelected);
|
||||
@ -402,7 +390,5 @@ public class Toolbar extends ToolBar {
|
||||
public Toolbar(ImageGalleryController controller) {
|
||||
this.controller = controller;
|
||||
FXMLConstructor.construct(this, "Toolbar.fxml"); //NON-NLS
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,12 +21,12 @@ package org.sleuthkit.autopsy.imagegallery.gui.drawableviews;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import static com.google.common.collect.Lists.transform;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import static java.util.Arrays.asList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -35,6 +35,7 @@ import java.util.Map;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.IntStream;
|
||||
import javafx.animation.Interpolator;
|
||||
@ -135,7 +136,10 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewMode;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
|
||||
import org.sleuthkit.autopsy.imagegallery.gui.GuiUtils;
|
||||
import static org.sleuthkit.autopsy.imagegallery.gui.GuiUtils.createAutoAssigningMenuItem;
|
||||
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
||||
import static org.sleuthkit.autopsy.imagegallery.utils.TaskUtils.addFXCallback;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
@ -254,7 +258,7 @@ public class GroupPane extends BorderPane {
|
||||
private final ReadOnlyObjectWrapper<DrawableGroup> grouping = new ReadOnlyObjectWrapper<>();
|
||||
|
||||
/**
|
||||
* map from fileIDs to their assigned cells in the tile view. This is used
|
||||
* Map from fileIDs to their assigned cells in the tile view. This is used
|
||||
* to determine whether fileIDs are visible or are offscreen. No entry
|
||||
* indicates the given fileID is not displayed on screen. DrawableCells are
|
||||
* responsible for adding and removing themselves from this map.
|
||||
@ -371,7 +375,7 @@ public class GroupPane extends BorderPane {
|
||||
case FIVE:
|
||||
return cat5Toggle;
|
||||
default:
|
||||
throw new IllegalArgumentException(category.name());
|
||||
throw new UnsupportedOperationException("Unknown category: " + category.name());
|
||||
}
|
||||
}
|
||||
|
||||
@ -425,51 +429,41 @@ public class GroupPane extends BorderPane {
|
||||
DoubleBinding cellSize = controller.thumbnailSizeProperty().add(75);
|
||||
gridView.cellHeightProperty().bind(cellSize);
|
||||
gridView.cellWidthProperty().bind(cellSize);
|
||||
gridView.setCellFactory((GridView<Long> param) -> new DrawableCell());
|
||||
gridView.setCellFactory(param -> new DrawableCell());
|
||||
|
||||
BooleanBinding isSelectionEmpty = Bindings.isEmpty(selectionModel.getSelected());
|
||||
catSelectedSplitMenu.disableProperty().bind(isSelectionEmpty);
|
||||
tagSelectedSplitMenu.disableProperty().bind(isSelectionEmpty);
|
||||
|
||||
TagSelectedFilesAction followUpSelectedAction = new TagSelectedFilesAction(controller.getTagsManager().getFollowUpTagName(), controller); //NON-NLS
|
||||
Platform.runLater(() -> {
|
||||
addFXCallback(exec.submit(() -> controller.getTagsManager().getFollowUpTagName()),
|
||||
followUpTagName -> {
|
||||
//on fx thread
|
||||
TagSelectedFilesAction followUpSelectedAction = new TagSelectedFilesAction(followUpTagName, controller);
|
||||
tagSelectedSplitMenu.setText(followUpSelectedAction.getText());
|
||||
tagSelectedSplitMenu.setGraphic(followUpSelectedAction.getGraphic());
|
||||
tagSelectedSplitMenu.setOnAction(followUpSelectedAction);
|
||||
tagSelectedSplitMenu.showingProperty().addListener(showing -> {
|
||||
if (tagSelectedSplitMenu.isShowing()) {
|
||||
|
||||
ListenableFuture<List<MenuItem>> getTagsFuture = exec.submit(()
|
||||
-> Lists.transform(controller.getTagsManager().getNonCategoryTagNames(),
|
||||
tagName -> GuiUtils.createAutoAssigningMenuItem(tagSelectedSplitMenu, new TagSelectedFilesAction(tagName, controller))));
|
||||
Futures.addCallback(getTagsFuture, new FutureCallback<List<MenuItem>>() {
|
||||
@Override
|
||||
public void onSuccess(List<MenuItem> result) {
|
||||
tagSelectedSplitMenu.getItems().setAll(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
logger.log(Level.SEVERE, "Error getting tag names.", throwable);
|
||||
}
|
||||
}, Platform::runLater);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
throwable -> logger.log(Level.SEVERE, "Error getting tag names.", throwable));
|
||||
|
||||
addFXCallback(exec.submit(() -> controller.getTagsManager().getNonCategoryTagNames()),
|
||||
tagNames -> {
|
||||
//on fx thread
|
||||
List<MenuItem> menuItems = transform(tagNames,
|
||||
tagName -> createAutoAssigningMenuItem(tagSelectedSplitMenu, new TagSelectedFilesAction(tagName, controller)));
|
||||
tagSelectedSplitMenu.getItems().setAll(menuItems);
|
||||
},
|
||||
throwable -> logger.log(Level.SEVERE, "Error getting tag names.", throwable)//NON-NLS
|
||||
);
|
||||
CategorizeSelectedFilesAction cat5SelectedAction = new CategorizeSelectedFilesAction(DhsImageCategory.FIVE, controller);
|
||||
|
||||
catSelectedSplitMenu.setOnAction(cat5SelectedAction);
|
||||
|
||||
catSelectedSplitMenu.setText(cat5SelectedAction.getText());
|
||||
catSelectedSplitMenu.setGraphic(cat5SelectedAction.getGraphic());
|
||||
catSelectedSplitMenu.showingProperty().addListener(showing -> {
|
||||
if (catSelectedSplitMenu.isShowing()) {
|
||||
List<MenuItem> categoryMenues = Lists.transform(Arrays.asList(DhsImageCategory.values()),
|
||||
cat -> GuiUtils.createAutoAssigningMenuItem(catSelectedSplitMenu, new CategorizeSelectedFilesAction(cat, controller)));
|
||||
|
||||
List<MenuItem> categoryMenues = transform(asList(DhsImageCategory.values()),
|
||||
cat -> createAutoAssigningMenuItem(catSelectedSplitMenu, new CategorizeSelectedFilesAction(cat, controller)));
|
||||
catSelectedSplitMenu.getItems().setAll(categoryMenues);
|
||||
}
|
||||
});
|
||||
|
||||
slideShowToggle.getStyleClass().remove("radio-button");
|
||||
slideShowToggle.getStyleClass().add("toggle-button");
|
||||
@ -681,7 +675,6 @@ public class GroupPane extends BorderPane {
|
||||
}
|
||||
|
||||
void makeSelection(Boolean shiftDown, Long newFileID) {
|
||||
|
||||
if (shiftDown) {
|
||||
//TODO: do more hear to implement slicker multiselect
|
||||
int endIndex = grouping.get().getFileIDs().indexOf(newFileID);
|
||||
@ -694,7 +687,6 @@ public class GroupPane extends BorderPane {
|
||||
} else {
|
||||
selectionAnchorIndex = null;
|
||||
selectionModel.clearAndSelect(newFileID);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import com.google.common.eventbus.Subscribe;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import static java.util.Objects.isNull;
|
||||
@ -112,9 +113,7 @@ public class MetaDataPane extends DrawableUIBase {
|
||||
});
|
||||
|
||||
copyMenuItem.setAccelerator(COPY_KEY_COMBINATION);
|
||||
copyMenuItem.setOnAction(actionEvent -> {
|
||||
copyValueToClipBoard();
|
||||
});
|
||||
copyMenuItem.setOnAction(actionEvent -> copyValueToClipBoard());
|
||||
|
||||
tableView.setContextMenu(contextMenu);
|
||||
tableView.setOnKeyPressed((KeyEvent event) -> {
|
||||
@ -220,9 +219,6 @@ public class MetaDataPane extends DrawableUIBase {
|
||||
return imageBorder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Subscribe
|
||||
@Override
|
||||
public void handleCategoryChanged(CategoryManager.CategoryChangeEvent evt) {
|
||||
@ -256,9 +252,9 @@ public class MetaDataPane extends DrawableUIBase {
|
||||
private void copyValueToClipBoard() {
|
||||
Pair<DrawableAttribute<?>, Collection<?>> selectedItem = tableView.getSelectionModel().getSelectedItem();
|
||||
if (nonNull(selectedItem)) {
|
||||
Clipboard.getSystemClipboard().setContent(Collections.singletonMap(DataFormat.PLAIN_TEXT,
|
||||
getValueDisplayString(selectedItem)));
|
||||
Clipboard.getSystemClipboard().setContent(
|
||||
singletonMap(DataFormat.PLAIN_TEXT, getValueDisplayString(selectedItem))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -131,8 +131,8 @@ public class SlideShowView extends DrawableTileBase {
|
||||
getGroupPane().grouping().addListener(observable -> {
|
||||
syncButtonVisibility();
|
||||
if (getGroupPane().getGroup() != null) {
|
||||
getGroupPane().getGroup().getFileIDs().addListener((Observable observable1) ->
|
||||
syncButtonVisibility());
|
||||
getGroupPane().getGroup().getFileIDs().addListener((Observable observable1)
|
||||
-> syncButtonVisibility());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -215,9 +215,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
mediaTask = null;
|
||||
}
|
||||
});
|
||||
myTask.setOnCancelled(cancelled -> {
|
||||
disposeContent();
|
||||
});
|
||||
myTask.setOnCancelled(cancelled -> disposeContent());
|
||||
|
||||
exec.execute(myTask);
|
||||
return progressNode;
|
||||
@ -245,7 +243,6 @@ public class SlideShowView extends DrawableTileBase {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param file the value of file
|
||||
* @param imageTask the value of imageTask
|
||||
*/
|
||||
@Override
|
||||
@ -259,9 +256,6 @@ public class SlideShowView extends DrawableTileBase {
|
||||
return maskerPane;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
protected String getTextForLabel() {
|
||||
return getFile().map(DrawableFile::getName).orElse("") + " " + getSupplementalText();
|
||||
@ -301,9 +295,6 @@ public class SlideShowView extends DrawableTileBase {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
@ThreadConfined(type = ThreadType.ANY)
|
||||
public DhsImageCategory updateCategory() {
|
||||
|
@ -18,11 +18,16 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.imagegallery.utils;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.concurrent.Task;
|
||||
|
||||
/**
|
||||
@ -46,4 +51,22 @@ public final class TaskUtils {
|
||||
return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(
|
||||
new ThreadFactoryBuilder().setNameFormat("Image Gallery " + clazz.getSimpleName() + " BG Thread").build()));
|
||||
}
|
||||
|
||||
public static <X> void addFXCallback(ListenableFuture<X> future, Consumer<X> onSuccess, Consumer<Throwable> onFailure) {
|
||||
Futures.addCallback(future, makeFutureCallBack(onSuccess, onFailure), Platform::runLater);
|
||||
}
|
||||
|
||||
public static <X> FutureCallback< X> makeFutureCallBack(Consumer<X> onSuccess, Consumer<Throwable> onFailure) {
|
||||
return new FutureCallback<X>() {
|
||||
@Override
|
||||
public void onSuccess(X result) {
|
||||
onSuccess.accept(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
onFailure.accept(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user