From e9bb6ed8f10f45c4bea993b78f3c62c91304870a Mon Sep 17 00:00:00 2001 From: millmanorama Date: Thu, 1 Nov 2018 12:04:30 +0100 Subject: [PATCH] sync all filters with data from case --- .../autopsy/timeline/FilteredEventsModel.java | 49 ++++++++++--------- .../autopsy/timeline/TimeLineController.java | 2 +- .../timeline/ui/filtering/FilterSetPanel.java | 18 +++---- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java b/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java index cb5dc7f628..de69ad585b 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/FilteredEventsModel.java @@ -32,16 +32,13 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import javafx.beans.Observable; +import javafx.beans.InvalidationListener; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.collections.FXCollections; -import javafx.collections.ListChangeListener; -import javafx.collections.MapChangeListener; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; import javafx.collections.ObservableSet; -import javafx.collections.SetChangeListener; import static org.apache.commons.lang3.StringUtils.isBlank; import org.joda.time.DateTimeZone; import org.joda.time.Interval; @@ -159,26 +156,19 @@ public final class FilteredEventsModel { minCache = CacheBuilder.newBuilder() .build(new CacheLoaderImpl<>(ignored -> eventManager.getMinTime())); - datasourcesMap.addListener((MapChangeListener.Change change) -> { - DataSourceFilter dataSourceFilter = new DataSourceFilter(change.getValueAdded().getName(), change.getKey()); - RootFilterState rootFilter = filterProperty().get().copyOf(); - rootFilter.getDataSourcesFilterState().getFilter().addSubFilter(dataSourceFilter); - requestedFilter.set(rootFilter); - }); - hashSets.addListener((SetChangeListener.Change< ? extends String> change) -> { - HashSetFilter hashSetFilter = new HashSetFilter(change.getElementAdded()); + InvalidationListener filterSyncListener = observable -> { RootFilterState rootFilter = filterProperty().get(); - rootFilter.getHashHitsFilterState().getFilter().addSubFilter(hashSetFilter); + syncFilters(rootFilter); requestedFilter.set(rootFilter); - }); - tagNames.addListener((ListChangeListener.Change change) -> { - RootFilterState rootFilter = filterProperty().get(); - syncTagsFilter(rootFilter); - requestedFilter.set(rootFilter); - }); + }; + + datasourcesMap.addListener(filterSyncListener); + getHashSets().addListener(filterSyncListener); + getTagNames().addListener(filterSyncListener); + requestedFilter.set(getDefaultFilter()); - requestedZoomState.addListener((Observable observable) -> { + requestedZoomState.addListener(observable -> { final ZoomState zoomState = requestedZoomState.get(); if (zoomState != null) { @@ -269,9 +259,10 @@ public final class FilteredEventsModel { } /** - * "sync" the given tags filter with the tagnames in use: Disable filters - * for tags that are not in use in the case, and add new filters for tags - * that don't have them. New filters are selected by default. + * "sync" the given root filter with the state of the casee: Disable filters + * for tags that are not in use in the case, and add new filters for tags, + * hashsets, and datasources. that don't have them. New filters are selected + * by default. * * @param rootFilterState the filter state to modify so it is consistent * with the tags in use in the case @@ -281,7 +272,17 @@ public final class FilteredEventsModel { rootFilterState.getTagsFilterState().getFilter().addSubFilter(new TagNameFilter(tagName)); }); for (FilterState filterState : rootFilterState.getTagsFilterState().getSubFilterStates()) { - filterState.setDisabled(tagNames.contains(filterState.getFilter().getTagName()) == false); + tagFilterState.setDisabled(tagNames.contains(tagFilterState.getFilter().getTagName()) == false); + } + + DataSourcesFilter dataSourcesFilter = rootFilter.getDataSourcesFilterState().getFilter(); + for (Map.Entry entry : datasourcesMap.entrySet()) { + dataSourcesFilter.addSubFilter(new DataSourceFilter(entry.getValue().getName(), entry.getKey())); + } + + HashHitsFilter hashSetsFilter = rootFilter.getHashHitsFilterState().getFilter(); + for (String hashSet : getHashSets()) { + hashSetsFilter.addSubFilter(new HashSetFilter(hashSet)); } } diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java index 7da596dd90..d0f1ac3fcd 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineController.java @@ -285,7 +285,7 @@ public class TimeLineController { */ historyManager.currentState().addListener(( observable, oldState, newState) -> { ZoomState historyManagerState = newState; - filteredEvents.syncTagsFilter(historyManagerState.getFilterState()); + filteredEvents.syncFilters(historyManagerState.getFilterState()); currentParams.set(historyManagerState); }); diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterSetPanel.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterSetPanel.java index b1605abd7c..84bd48dbc2 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterSetPanel.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/filtering/FilterSetPanel.java @@ -21,10 +21,8 @@ package org.sleuthkit.autopsy.timeline.ui.filtering; import java.util.Arrays; import javafx.application.Platform; import javafx.beans.InvalidationListener; -import javafx.beans.Observable; import javafx.beans.binding.Bindings; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; +import javafx.beans.binding.BooleanBinding; import javafx.collections.FXCollections; import javafx.collections.ObservableMap; import javafx.fxml.FXML; @@ -46,6 +44,7 @@ import org.sleuthkit.autopsy.timeline.FXMLConstructor; import org.sleuthkit.autopsy.timeline.FilteredEventsModel; import org.sleuthkit.autopsy.timeline.TimeLineController; import org.sleuthkit.autopsy.timeline.actions.ResetFilters; +import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.CompoundFilterState; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.FilterState; import org.sleuthkit.autopsy.timeline.ui.filtering.datamodel.RootFilterState; import org.sleuthkit.datamodel.timeline.TimelineFilter; @@ -119,8 +118,8 @@ final public class FilterSetPanel extends BorderPane { legendColumn.setCellFactory(col -> new LegendCell(this.controller)); //type is the only filter expanded initialy - expansionMap.put(controller.getEventsModel().getFilterState().getFilter(), true); - expansionMap.put(controller.getEventsModel().getFilterState().getEventTypeFilterState().getFilter(), true); + expansionMap.put(filteredEvents.getFilterState().getFilter(), true); + expansionMap.put(filteredEvents.getFilterState().getEventTypeFilterState().getFilter(), true); InvalidationListener applyFiltersListener = observable -> applyFilters(); @@ -128,12 +127,7 @@ final public class FilterSetPanel extends BorderPane { filteredEvents.descriptionLODProperty().addListener(applyFiltersListener); filteredEvents.timeRangeProperty().addListener(applyFiltersListener); - filteredEvents.filterProperty().addListener(new InvalidationListener() { - @Override - public void invalidated(Observable observable) { - refresh(); - } - }); + filteredEvents.filterProperty().addListener(observable -> refresh()); refresh(); hiddenDescriptionsListView.setItems(controller.getQuickHideFilters()); @@ -173,7 +167,7 @@ final public class FilterSetPanel extends BorderPane { } private void refresh() { - FilterTreeItem filterTreeItem = new FilterTreeItem(filteredEvents.getFilterState().copyOf(), expansionMap); + FilterTreeItem filterTreeItem = new FilterTreeItem(filteredEvents.filterProperty().getValue(), expansionMap); Platform.runLater(() -> { filterTreeTable.setRoot(filterTreeItem); });