From a20f0400666ab498ca6b8bd113dd74a51a01f5e3 Mon Sep 17 00:00:00 2001 From: jmillman Date: Tue, 9 Jun 2015 14:34:53 -0400 Subject: [PATCH] use event bus for category change events --- .../imagegallery/ImageGalleryController.java | 219 +++++++++--------- .../datamodel/CategoryChangeEvent.java | 39 ++++ ...ategoryCache.java => CategoryManager.java} | 34 +-- .../imagegallery/gui/DrawableTile.java | 3 +- .../imagegallery/gui/DrawableView.java | 8 +- .../imagegallery/gui/MetaDataPane.java | 9 +- .../gui/SingleDrawableViewBase.java | 9 +- .../imagegallery/gui/SlideShowView.java | 3 +- .../imagegallery/gui/SummaryTablePane.java | 13 +- 9 files changed, 185 insertions(+), 152 deletions(-) create mode 100644 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java rename ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/{CategoryCache.java => CategoryManager.java} (78%) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index 334b3f9a6c..349f44b5c5 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.imagegallery; import java.beans.PropertyChangeEvent; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -83,25 +82,25 @@ import org.sleuthkit.datamodel.TskData; * control. */ public final class ImageGalleryController { - + private static final Logger LOGGER = Logger.getLogger(ImageGalleryController.class.getName()); - + private final Region infoOverLayBackground = new Region() { { setBackground(new Background(new BackgroundFill(Color.GREY, CornerRadii.EMPTY, Insets.EMPTY))); setOpacity(.4); } }; - + private static ImageGalleryController instance; - + public static synchronized ImageGalleryController getDefault() { if (instance == null) { instance = new ImageGalleryController(); } return instance; } - + private final History historyManager = new History<>(); /** @@ -109,73 +108,73 @@ public final class ImageGalleryController { * not listen to speed up ingest */ private final SimpleBooleanProperty listeningEnabled = new SimpleBooleanProperty(false); - + private final ReadOnlyIntegerWrapper queueSizeProperty = new ReadOnlyIntegerWrapper(0); - + private final ReadOnlyBooleanWrapper regroupDisabled = new ReadOnlyBooleanWrapper(false); - + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) private final ReadOnlyBooleanWrapper stale = new ReadOnlyBooleanWrapper(false); - + private final ReadOnlyBooleanWrapper metaDataCollapsed = new ReadOnlyBooleanWrapper(false); - + private final FileIDSelectionModel selectionModel = FileIDSelectionModel.getInstance(); - + private DBWorkerThread dbWorkerThread; - + private DrawableDB db; - + private final GroupManager groupManager = new GroupManager(this); - + private StackPane fullUIStackPane; - + private StackPane centralStackPane; - + private Node infoOverlay; private final HashSetManager hashSetManager = new HashSetManager(); private final CategoryManager categoryManager = new CategoryManager(); - + public ReadOnlyBooleanProperty getMetaDataCollapsed() { return metaDataCollapsed.getReadOnlyProperty(); } - + public void setMetaDataCollapsed(Boolean metaDataCollapsed) { this.metaDataCollapsed.set(metaDataCollapsed); } - + private GroupViewState getViewState() { return historyManager.getCurrentState(); } - + public ReadOnlyBooleanProperty regroupDisabled() { return regroupDisabled.getReadOnlyProperty(); } - + public ReadOnlyObjectProperty viewState() { return historyManager.currentState(); } - + public synchronized FileIDSelectionModel getSelectionModel() { - + return selectionModel; } - + public GroupManager getGroupManager() { return groupManager; } - + public DrawableDB getDatabase() { return db; } - + synchronized public void setListeningEnabled(boolean enabled) { listeningEnabled.set(enabled); } - + synchronized boolean isListeningEnabled() { return listeningEnabled.get(); } - + @ThreadConfined(type = ThreadConfined.ThreadType.ANY) void setStale(Boolean b) { Platform.runLater(() -> { @@ -185,18 +184,18 @@ public final class ImageGalleryController { new PerCaseProperties(Case.getCurrentCase()).setConfigSetting(ImageGalleryModule.getModuleName(), PerCaseProperties.STALE, b.toString()); } } - + public ReadOnlyBooleanProperty stale() { return stale.getReadOnlyProperty(); } - + @ThreadConfined(type = ThreadConfined.ThreadType.JFX) boolean isStale() { return stale.get(); } - + private ImageGalleryController() { - + listeningEnabled.addListener((observable, oldValue, newValue) -> { //if we just turned on listening and a case is open and that case is not up to date if (newValue && !oldValue && Case.existsCurrentCase() && ImageGalleryModule.isDrawableDBStale(Case.getCurrentCase())) { @@ -204,28 +203,28 @@ public final class ImageGalleryController { queueDBWorkerTask(new CopyAnalyzedFiles()); } }); - + groupManager.getAnalyzedGroups().addListener((Observable o) -> { if (Case.isCaseOpen()) { checkForGroups(); } }); - + groupManager.getUnSeenGroups().addListener((Observable observable) -> { //if there are unseen groups and none being viewed if (groupManager.getUnSeenGroups().isEmpty() == false && (getViewState() == null || getViewState().getGroup() == null)) { advance(GroupViewState.tile(groupManager.getUnSeenGroups().get(0))); } }); - + viewState().addListener((Observable observable) -> { selectionModel.clearSelection(); }); - + regroupDisabled.addListener((Observable observable) -> { checkForGroups(); }); - + IngestManager.getInstance().addIngestModuleEventListener((PropertyChangeEvent evt) -> { Platform.runLater(this::updateRegroupDisabled); }); @@ -234,27 +233,27 @@ public final class ImageGalleryController { }); // metaDataCollapsed.bind(Toolbar.getDefault().showMetaDataProperty()); } - + public ReadOnlyBooleanProperty getCanAdvance() { return historyManager.getCanAdvance(); } - + public ReadOnlyBooleanProperty getCanRetreat() { return historyManager.getCanRetreat(); } - + public void advance(GroupViewState newState) { historyManager.advance(newState); } - + public GroupViewState advance() { return historyManager.advance(); } - + public GroupViewState retreat() { return historyManager.retreat(); } - + private void updateRegroupDisabled() { regroupDisabled.set(getFileUpdateQueueSizeProperty().get() > 0 || IngestManager.getInstance().isIngestRunning()); } @@ -276,7 +275,7 @@ public final class ImageGalleryController { new NoGroupsDialog("No groups are fully analyzed yet, but ingest is still ongoing. Please Wait.", new ProgressIndicator())); } - + } else if (getFileUpdateQueueSizeProperty().get() > 0) { replaceNotification(fullUIStackPane, new NoGroupsDialog("No groups are fully analyzed yet, but image / video data is still being populated. Please Wait.", @@ -290,19 +289,19 @@ public final class ImageGalleryController { replaceNotification(fullUIStackPane, new NoGroupsDialog("There are no images/videos in the added datasources.")); } - + } else if (!groupManager.isRegrouping()) { replaceNotification(centralStackPane, new NoGroupsDialog("There are no fully analyzed groups to display:" + " the current Group By setting resulted in no groups, " + "or no groups are fully analyzed but ingest is not running.")); } - + } else { clearNotification(); } } - + private void clearNotification() { //remove the ingest spinner if (fullUIStackPane != null) { @@ -313,27 +312,27 @@ public final class ImageGalleryController { centralStackPane.getChildren().remove(infoOverlay); } } - + private void replaceNotification(StackPane stackPane, Node newNode) { clearNotification(); - + infoOverlay = new StackPane(infoOverLayBackground, newNode); if (stackPane != null) { stackPane.getChildren().add(infoOverlay); } } - + private void restartWorker() { if (dbWorkerThread != null) { // Keep using the same worker thread if one exists return; } dbWorkerThread = new DBWorkerThread(); - + getFileUpdateQueueSizeProperty().addListener((Observable o) -> { Platform.runLater(this::updateRegroupDisabled); }); - + Thread th = new Thread(dbWorkerThread); th.setDaemon(false); // we want it to go away when it is done th.start(); @@ -346,7 +345,7 @@ public final class ImageGalleryController { */ public synchronized void setCase(Case theNewCase) { this.db = DrawableDB.getDrawableDB(ImageGalleryModule.getModuleOutputDir(theNewCase), this); - + setListeningEnabled(ImageGalleryModule.isEnabledforCase(theNewCase)); setStale(ImageGalleryModule.isDrawableDBStale(theNewCase)); @@ -358,7 +357,7 @@ public final class ImageGalleryController { hashSetManager.setDb(db); categoryManager.setDb(db); db.initializeImageList(); - SummaryTablePane.getDefault().handleCategoryChanged(Collections.emptyList()); + SummaryTablePane.getDefault().refresh(); } /** @@ -373,7 +372,7 @@ public final class ImageGalleryController { historyManager.clear(); }); Category.clearTagNames(); - + Toolbar.getDefault().reset(); groupManager.clear(); if (db != null) { @@ -395,21 +394,21 @@ public final class ImageGalleryController { } dbWorkerThread.addTask(innerTask); } - + public DrawableFile getFileFromId(Long fileID) throws TskCoreException { return db.getFileFromID(fileID); } - + public void setStacks(StackPane fullUIStack, StackPane centralStack) { fullUIStackPane = fullUIStack; this.centralStackPane = centralStack; Platform.runLater(this::checkForGroups); } - + public final ReadOnlyIntegerProperty getFileUpdateQueueSizeProperty() { return queueSizeProperty.getReadOnlyProperty(); } - + public ReadOnlyDoubleProperty regroupProgress() { return groupManager.regroupProgress(); } @@ -481,11 +480,11 @@ public final class ImageGalleryController { } }); } - + public HashSetManager getHashSetManager() { return hashSetManager; } - + public CategoryManager getCategoryManager() { return categoryManager; } @@ -526,7 +525,7 @@ public final class ImageGalleryController { queueSizeProperty.set(workQueue.size()); }); } - + @Override public void run() { @@ -537,22 +536,22 @@ public final class ImageGalleryController { } try { InnerTask it = workQueue.take(); - + if (it.cancelled == false) { it.run(); } - + Platform.runLater(() -> { queueSizeProperty.set(workQueue.size()); }); - + } catch (InterruptedException ex) { Exceptions.printStackTrace(ex); } } } } - + public SleuthkitCase getSleuthKitCase() throws IllegalStateException { if (Case.isCaseOpen()) { return Case.getCurrentCase().getSleuthkitCase(); @@ -565,55 +564,55 @@ public final class ImageGalleryController { * Abstract base class for task to be done on {@link DBWorkerThread} */ static public abstract class InnerTask implements Runnable { - + public double getProgress() { return progress.get(); } - + public final void updateProgress(Double workDone) { this.progress.set(workDone); } - + public String getMessage() { return message.get(); } - + public final void updateMessage(String Status) { this.message.set(Status); } SimpleObjectProperty state = new SimpleObjectProperty<>(Worker.State.READY); SimpleDoubleProperty progress = new SimpleDoubleProperty(this, "pregress"); SimpleStringProperty message = new SimpleStringProperty(this, "status"); - + public SimpleDoubleProperty progressProperty() { return progress; } - + public SimpleStringProperty messageProperty() { return message; } - + public Worker.State getState() { return state.get(); } - + protected void updateState(Worker.State newState) { state.set(newState); } - + public ReadOnlyObjectProperty stateProperty() { return new ReadOnlyObjectWrapper<>(state.get()); } - + protected InnerTask() { } - + protected volatile boolean cancelled = false; - + public void cancel() { updateState(Worker.State.CANCELLED); } - + protected boolean isCancelled() { return getState() == Worker.State.CANCELLED; } @@ -623,25 +622,25 @@ public final class ImageGalleryController { * Abstract base class for tasks associated with a file in the database */ static public abstract class FileTask extends InnerTask { - + private final AbstractFile file; - + public AbstractFile getFile() { return file; } - + public FileTask(AbstractFile f) { super(); this.file = f; } - + } /** * task that updates one file in database with results from ingest */ private class UpdateFileTask extends FileTask { - + public UpdateFileTask(AbstractFile f) { super(f); } @@ -668,7 +667,7 @@ public final class ImageGalleryController { * task that updates one file in database with results from ingest */ private class RemoveFileTask extends FileTask { - + public RemoveFileTask(AbstractFile f) { super(f); } @@ -687,7 +686,7 @@ public final class ImageGalleryController { Logger.getLogger(RemoveFileTask.class.getName()).log(Level.SEVERE, "Case was closed out from underneath RemoveFile task"); } } - + } } @@ -699,16 +698,16 @@ public final class ImageGalleryController { * adds them to the Drawable DB */ private class CopyAnalyzedFiles extends InnerTask { - + final private String DRAWABLE_QUERY = "name LIKE '%." + StringUtils.join(ImageGalleryModule.getAllSupportedExtensions(), "' or name LIKE '%.") + "'"; - + private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("populating analyzed image/video database"); - + @Override public void run() { progressHandle.start(); updateMessage("populating analyzed image/video database"); - + try { //grab all files with supported extension or detected mime types final List files = getSleuthKitCase().findAllFilesWhere(DRAWABLE_QUERY + " or tsk_files.obj_id in (select tsk_files.obj_id from tsk_files , blackboard_artifacts, blackboard_attributes" @@ -718,7 +717,7 @@ public final class ImageGalleryController { + " and blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG.getTypeID() + " and blackboard_attributes.value_text in ('" + StringUtils.join(ImageGalleryModule.getSupportedMimes(), "','") + "'))"); progressHandle.switchToDeterminate(files.size()); - + updateProgress(0.0); //do in transaction @@ -732,7 +731,7 @@ public final class ImageGalleryController { } final Boolean hasMimeType = ImageGalleryModule.hasSupportedMimeType(f); final boolean known = f.getKnown() == TskData.FileKnown.KNOWN; - + if (known) { db.removeFile(f.getId(), tr); //remove known files } else { @@ -752,38 +751,38 @@ public final class ImageGalleryController { } } } - + units++; final int prog = units; progressHandle.progress(f.getName(), units); updateProgress(prog - 1 / (double) files.size()); updateMessage(f.getName()); } - + progressHandle.finish(); - + progressHandle = ProgressHandleFactory.createHandle("commiting image/video database"); updateMessage("commiting image/video database"); updateProgress(1.0); - + progressHandle.start(); db.commitTransaction(tr, true); - + } catch (TskCoreException ex) { Logger.getLogger(CopyAnalyzedFiles.class.getName()).log(Level.WARNING, "failed to transfer all database contents", ex); } catch (IllegalStateException ex) { Logger.getLogger(CopyAnalyzedFiles.class.getName()).log(Level.SEVERE, "Case was closed out from underneath CopyDataSource task", ex); } - + progressHandle.finish(); - + updateMessage( ""); updateProgress( -1.0); setStale(false); } - + } /** @@ -794,7 +793,7 @@ public final class ImageGalleryController { * netbeans and ImageGallery progress/status */ class PrePopulateDataSourceFiles extends InnerTask { - + private final Content dataSource; /** @@ -804,7 +803,7 @@ public final class ImageGalleryController { */ // (name like '.jpg' or name like '.png' ...) private final String DRAWABLE_QUERY = "(name LIKE '%." + StringUtils.join(ImageGalleryModule.getAllSupportedExtensions(), "' or name LIKE '%.") + "') "; - + private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("prepopulating image/video database"); /** @@ -830,7 +829,7 @@ public final class ImageGalleryController { final List files; try { List fsObjIds = new ArrayList<>(); - + String fsQuery; if (dataSource instanceof Image) { Image image = (Image) dataSource; @@ -844,7 +843,7 @@ public final class ImageGalleryController { else { fsQuery = "(fs_obj_id IS NULL) "; } - + files = getSleuthKitCase().findAllFilesWhere(fsQuery + " and " + DRAWABLE_QUERY); progressHandle.switchToDeterminate(files.size()); @@ -862,21 +861,21 @@ public final class ImageGalleryController { final int prog = units; progressHandle.progress(f.getName(), units); } - + progressHandle.finish(); progressHandle = ProgressHandleFactory.createHandle("commiting image/video database"); - + progressHandle.start(); db.commitTransaction(tr, false); - + } catch (TskCoreException ex) { Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.WARNING, "failed to transfer all database contents", ex); } catch (IllegalStateException | NullPointerException ex) { Logger.getLogger(PrePopulateDataSourceFiles.class.getName()).log(Level.WARNING, "Case was closed out from underneath prepopulating database"); } - + progressHandle.finish(); } } - + } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java new file mode 100644 index 0000000000..57ab451b8e --- /dev/null +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryChangeEvent.java @@ -0,0 +1,39 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2015 Basis Technology Corp. + * Contact: carrier sleuthkit 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.datamodel; + +import java.util.Collection; +import java.util.Collections; + +/** + * + */ +public class CategoryChangeEvent { + + private final Collection ids; + + public Collection getIds() { + return Collections.unmodifiableCollection(ids); + } + + public CategoryChangeEvent(Collection ids) { + this.ids = ids; + } + +} diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryCache.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java similarity index 78% rename from ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryCache.java rename to ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java index d3d1d9baf3..c24c8ba9f7 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryCache.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java @@ -3,12 +3,11 @@ package org.sleuthkit.autopsy.imagegallery.datamodel; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.eventbus.EventBus; import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +import java.util.Collections; import java.util.concurrent.atomic.LongAdder; import java.util.logging.Level; -import javax.annotation.concurrent.GuardedBy; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; @@ -19,6 +18,7 @@ public class CategoryManager { private static final java.util.logging.Logger LOGGER = Logger.getLogger(CategoryManager.class.getName()); private DrawableDB db; + private final EventBus categoryEventBus = new EventBus("Category Event Bus"); public void setDb(DrawableDB db) { this.db = db; @@ -94,35 +94,19 @@ public class CategoryManager { } return longAdder; } - @GuardedBy("listeners") - private final Set listeners = new HashSet<>(); public void fireChange(Collection ids) { - Set listenersCopy = new HashSet<>(); - synchronized (listeners) { - listenersCopy.addAll(listeners); - } - for (CategoryListener list : listenersCopy) { - list.handleCategoryChanged(ids); - } + + categoryEventBus.post(new CategoryChangeEvent(ids)); } - public void registerListener(CategoryListener aThis) { - synchronized (listeners) { - listeners.add(aThis); - } + public void registerListener(Object aThis) { + categoryEventBus.register(aThis); } - public void unregisterListener(CategoryListener aThis) { - synchronized (listeners) { - listeners.remove(aThis); - } + public void unregisterListener(Object aThis) { + categoryEventBus.unregister(aThis); } - public static interface CategoryListener { - - public void handleCategoryChanged(Collection ids); - - } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java index 1d72c6d712..39c2224ea3 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableTile.java @@ -34,7 +34,6 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.TagUtils; -import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; /** * GUI component that represents a single image as a tile with an icon, a label @@ -44,7 +43,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; * * TODO: refactor this to extend from {@link Control}? -jm */ -public class DrawableTile extends SingleDrawableViewBase implements CategoryManager.CategoryListener, TagUtils.TagListener { +public class DrawableTile extends SingleDrawableViewBase implements TagUtils.TagListener { private static final DropShadow LAST_SELECTED_EFFECT = new DropShadow(10, Color.BLUE); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java index 27115a5e65..f9269f23cb 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/DrawableView.java @@ -1,5 +1,6 @@ package org.sleuthkit.autopsy.imagegallery.gui; +import com.google.common.eventbus.Subscribe; import java.util.Collection; import java.util.logging.Level; import javafx.application.Platform; @@ -14,6 +15,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.imagegallery.TagUtils; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; @@ -21,7 +23,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; * TODO: extract common interface out of {@link SingleImageView} and * {@link MetaDataPane} */ -public interface DrawableView extends CategoryManager.CategoryListener, TagUtils.TagListener { +public interface DrawableView extends TagUtils.TagListener { //TODO: do this all in css? -jm static final int CAT_BORDER_WIDTH = 10; @@ -52,8 +54,8 @@ public interface DrawableView extends CategoryManager.CategoryListener, TagUtils Long getFileID(); - @Override - void handleCategoryChanged(Collection ids); + @Subscribe + void handleCategoryChanged(CategoryChangeEvent evt); @Override void handleTagsChanged(Collection ids); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java index fdfcdf2efe..fc8a19ccd8 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/MetaDataPane.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.gui; +import com.google.common.eventbus.Subscribe; import java.io.IOException; import java.net.URL; import java.util.Arrays; @@ -51,6 +52,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.TagUtils; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; @@ -60,7 +62,7 @@ import org.sleuthkit.datamodel.TskCoreException; /** * */ -public class MetaDataPane extends AnchorPane implements CategoryManager.CategoryListener, TagUtils.TagListener, DrawableView { +public class MetaDataPane extends AnchorPane implements TagUtils.TagListener, DrawableView { private static final Logger LOGGER = Logger.getLogger(MetaDataPane.class.getName()); @@ -237,9 +239,10 @@ public class MetaDataPane extends AnchorPane implements CategoryManager.Category return imageBorder; } + @Subscribe @Override - public void handleCategoryChanged(Collection ids) { - if (getFile() != null && ids.contains(getFileID())) { + public void handleCategoryChanged(CategoryChangeEvent evt) { + if (getFile() != null && evt.getIds().contains(getFileID())) { updateUI(); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java index 02ff0c90fb..b3be4ec54e 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SingleDrawableViewBase.java @@ -19,6 +19,7 @@ */ package org.sleuthkit.autopsy.imagegallery.gui; +import com.google.common.eventbus.Subscribe; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -71,6 +72,8 @@ import org.sleuthkit.autopsy.imagegallery.TagUtils; import org.sleuthkit.autopsy.imagegallery.actions.AddDrawableTagAction; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction; import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.grouping.GroupKey; @@ -396,9 +399,9 @@ public abstract class SingleDrawableViewBase extends AnchorPane implements Drawa return imageBorder; } - @Override - public void handleCategoryChanged(Collection ids) { - if (ids.contains(fileID)) { + @Subscribe + public void handleCategoryChanged(CategoryChangeEvent evt) { + if (evt.getIds().contains(fileID)) { updateCategoryBorder(); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SlideShowView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SlideShowView.java index dcfc12613a..7b60d837b7 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SlideShowView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SlideShowView.java @@ -53,7 +53,6 @@ import org.sleuthkit.autopsy.imagegallery.FileIDSelectionModel; import org.sleuthkit.autopsy.imagegallery.TagUtils; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; -import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.ImageFile; import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile; @@ -65,7 +64,7 @@ import org.sleuthkit.datamodel.TskCoreException; * GroupPane. TODO: Extract a subclass for video files in slideshow mode-jm * TODO: reduce coupling to GroupPane */ -public class SlideShowView extends SingleDrawableViewBase implements TagUtils.TagListener, CategoryManager.CategoryListener { +public class SlideShowView extends SingleDrawableViewBase implements TagUtils.TagListener { private static final Logger LOGGER = Logger.getLogger(SlideShowView.class.getName()); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java index 4dbc8a3537..d027c679a3 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java @@ -18,8 +18,8 @@ */ package org.sleuthkit.autopsy.imagegallery.gui; +import com.google.common.eventbus.Subscribe; import java.util.Arrays; -import java.util.Collection; import java.util.logging.Level; import javafx.application.Platform; import javafx.beans.property.SimpleObjectProperty; @@ -38,13 +38,14 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryChangeEvent; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.datamodel.TskCoreException; /** * Displays summary statistics (counts) for each group */ -public class SummaryTablePane extends AnchorPane implements CategoryManager.CategoryListener { +public class SummaryTablePane extends AnchorPane { private static SummaryTablePane instance; @@ -95,8 +96,12 @@ public class SummaryTablePane extends AnchorPane implements CategoryManager.Cate /** * listen to Category updates and rebuild the table */ - @Override - public void handleCategoryChanged(Collection ids) { + @Subscribe + public void handleCategoryChanged(CategoryChangeEvent evt) { + refresh(); + } + + public void refresh() { final ObservableList> data = FXCollections.observableArrayList(); if (Case.isCaseOpen()) { for (Category cat : Category.values()) {