mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-16 17:57:43 +00:00
Merge pull request #4708 from esaunders/4910_paging_child_factory
4910 paging child factory
This commit is contained in:
commit
d1c3dea4f0
@ -76,6 +76,7 @@ public final class UserPreferences {
|
|||||||
public static final String DISPLAY_TRANSLATED_NAMES = "DisplayTranslatedNames";
|
public static final String DISPLAY_TRANSLATED_NAMES = "DisplayTranslatedNames";
|
||||||
public static final String EXTERNAL_HEX_EDITOR_PATH = "ExternalHexEditorPath";
|
public static final String EXTERNAL_HEX_EDITOR_PATH = "ExternalHexEditorPath";
|
||||||
public static final String SOLR_MAX_JVM_SIZE = "SolrMaxJVMSize";
|
public static final String SOLR_MAX_JVM_SIZE = "SolrMaxJVMSize";
|
||||||
|
public static final String RESULTS_TABLE_PAGE_SIZE = "ResultsTablePageSize";
|
||||||
|
|
||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
private UserPreferences() {
|
private UserPreferences() {
|
||||||
@ -491,6 +492,24 @@ public final class UserPreferences {
|
|||||||
preferences.putInt(SOLR_MAX_JVM_SIZE, maxSize);
|
preferences.putInt(SOLR_MAX_JVM_SIZE, maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum number of results to display in a result table.
|
||||||
|
*
|
||||||
|
* @return Saved value or default (0) which indicates no max.
|
||||||
|
*/
|
||||||
|
public static int getResultsTablePageSize() {
|
||||||
|
return preferences.getInt(RESULTS_TABLE_PAGE_SIZE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum number of results to display in a result table.
|
||||||
|
*
|
||||||
|
* @param pageSize
|
||||||
|
*/
|
||||||
|
public static void setResultsTablePageSize(int pageSize) {
|
||||||
|
preferences.putInt(RESULTS_TABLE_PAGE_SIZE, pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the HdX path.
|
* Set the HdX path.
|
||||||
*
|
*
|
||||||
|
234
Core/src/org/sleuthkit/autopsy/datamodel/BaseChildFactory.java
Normal file
234
Core/src/org/sleuthkit/autopsy/datamodel/BaseChildFactory.java
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.datamodel;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.openide.nodes.ChildFactory;
|
||||||
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract child factory that provides paging and filtering functionality to
|
||||||
|
* subclasses.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public abstract class BaseChildFactory<T extends Content> extends ChildFactory.Detachable<T> {
|
||||||
|
|
||||||
|
private final Predicate<T> filter;
|
||||||
|
private boolean isPageChangeEvent;
|
||||||
|
|
||||||
|
private final PagingSupport pagingSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This static map is used to facilitate communication between the UI and
|
||||||
|
* the child factory.
|
||||||
|
*/
|
||||||
|
public static Map<String, EventBus> nodeNameToEventBusMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public BaseChildFactory(String nodeName) {
|
||||||
|
pagingSupport = new PagingSupport(nodeName);
|
||||||
|
pagingSupport.initialize();
|
||||||
|
isPageChangeEvent = false;
|
||||||
|
filter = new KnownAndSlackFilter<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addNotify() {
|
||||||
|
onAdd();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeNotify() {
|
||||||
|
onRemove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses implement this to construct a collection of keys.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected abstract List<T> makeKeys();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses implement this to initialize any required resources.
|
||||||
|
*/
|
||||||
|
protected abstract void onAdd();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses implement this to clean up any resources they acquired in
|
||||||
|
* onAdd()
|
||||||
|
*/
|
||||||
|
protected abstract void onRemove();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<T> toPopulate) {
|
||||||
|
// For page chage events we simply return the previously calculated
|
||||||
|
// keys, otherwise we make a new set of keys.
|
||||||
|
if (!isPageChangeEvent) {
|
||||||
|
List<T> allKeys = makeKeys();
|
||||||
|
|
||||||
|
// Filter keys
|
||||||
|
allKeys.stream().filter(filter).collect(Collectors.toList());
|
||||||
|
|
||||||
|
pagingSupport.splitKeysIntoPages(allKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
toPopulate.addAll(pagingSupport.getCurrentPage());
|
||||||
|
|
||||||
|
// Reset page change event flag
|
||||||
|
isPageChangeEvent = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event used to let subscribers know that the user has
|
||||||
|
* navigated to a different page.
|
||||||
|
*/
|
||||||
|
public static class PageChangeEvent {
|
||||||
|
|
||||||
|
private final int pageNumber;
|
||||||
|
|
||||||
|
public PageChangeEvent(int newPageNumber) {
|
||||||
|
pageNumber = newPageNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPageNumber() {
|
||||||
|
return pageNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event used to let subscribers know that the number of
|
||||||
|
* pages has changed.
|
||||||
|
*/
|
||||||
|
public static class PageCountChangeEvent {
|
||||||
|
|
||||||
|
private final int pageCount;
|
||||||
|
|
||||||
|
public PageCountChangeEvent(int newPageCount) {
|
||||||
|
pageCount = newPageCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPageCount() {
|
||||||
|
return pageCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event used to let subscribers know that paging is no
|
||||||
|
* longer required.
|
||||||
|
*/
|
||||||
|
public static class PagingDestroyedEvent {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that supplies paging related functionality to the base child
|
||||||
|
* factory class.
|
||||||
|
*/
|
||||||
|
class PagingSupport {
|
||||||
|
|
||||||
|
private final String nodeName;
|
||||||
|
private final int pageSize;
|
||||||
|
private int currentPage;
|
||||||
|
private List<List<T>> pages;
|
||||||
|
private EventBus bus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct PagingSupport instance for the given node name.
|
||||||
|
*
|
||||||
|
* @param nodeName Name of the node in the tree for which results are
|
||||||
|
* being displayed. The node name is used to allow
|
||||||
|
* communication between the UI and the ChildFactory via
|
||||||
|
* an EventBus.
|
||||||
|
*/
|
||||||
|
PagingSupport(String nodeName) {
|
||||||
|
pageSize = UserPreferences.getResultsTablePageSize();
|
||||||
|
this.currentPage = 1;
|
||||||
|
pages = new ArrayList<>();
|
||||||
|
this.nodeName = nodeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize() {
|
||||||
|
if (pageSize > 0) {
|
||||||
|
// Only configure an EventBus if paging functionality is enabled.
|
||||||
|
if (nodeNameToEventBusMap.containsKey(nodeName)) {
|
||||||
|
bus = nodeNameToEventBusMap.get(nodeName);
|
||||||
|
} else {
|
||||||
|
bus = new EventBus(nodeName);
|
||||||
|
nodeNameToEventBusMap.put(bus.identifier(), bus);
|
||||||
|
}
|
||||||
|
bus.register(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of keys at the current page.
|
||||||
|
*
|
||||||
|
* @return List of keys.
|
||||||
|
*/
|
||||||
|
List<T> getCurrentPage() {
|
||||||
|
if (!pages.isEmpty()) {
|
||||||
|
return pages.get(currentPage - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split the given collection of keys into pages based on page size.
|
||||||
|
*
|
||||||
|
* @param keys
|
||||||
|
*/
|
||||||
|
void splitKeysIntoPages(List<T> keys) {
|
||||||
|
int oldPageCount = pages.size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If pageSize is set split keys into pages, otherwise create a
|
||||||
|
* single page containing all keys.
|
||||||
|
*/
|
||||||
|
pages = Lists.partition(keys, pageSize > 0 ? pageSize : keys.size());
|
||||||
|
if (pages.size() != oldPageCount) {
|
||||||
|
// Number of pages has changed so we need to send out a notification.
|
||||||
|
bus.post(new PageCountChangeEvent(pages.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
private void subscribeToPageChange(PageChangeEvent event) {
|
||||||
|
// Receives page change events from UI components and
|
||||||
|
// triggers a refresh in the child factory.
|
||||||
|
if (event != null) {
|
||||||
|
currentPage = event.getPageNumber();
|
||||||
|
isPageChangeEvent = true;
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.datamodel;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import org.openide.util.Exceptions;
|
||||||
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Predicate that can be used to filter known and/or slack files from
|
||||||
|
* Content collections based on user preferences.
|
||||||
|
*/
|
||||||
|
class KnownAndSlackFilter<T extends Content> implements Predicate<T> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
AbstractFile af = null;
|
||||||
|
|
||||||
|
if (t instanceof BlackboardArtifact) {
|
||||||
|
try {
|
||||||
|
af = ((BlackboardArtifact) (t)).getSleuthkitCase().getAbstractFileById(((BlackboardArtifact) t).getObjectID());
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
Exceptions.printStackTrace(ex);
|
||||||
|
}
|
||||||
|
} else if (t instanceof AbstractFile) {
|
||||||
|
af = (AbstractFile) t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (af != null) {
|
||||||
|
if (af.getKnown() == TskData.FileKnown.KNOWN && UserPreferences.hideKnownFilesInViewsTree()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (af.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) && UserPreferences.hideSlackFilesInViewsTree()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user