mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
fix events tree; more cleanup
This commit is contained in:
parent
5ab1fc3395
commit
f949a00093
@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.common.collect.ImmutableSortedSet;
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
@ -33,9 +32,9 @@ import org.sleuthkit.autopsy.timeline.utils.IntervalUtils;
|
|||||||
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a set of other events clustered together. All the
|
* Represents a set of other events clustered together. All the sub events
|
||||||
* sub events should have the same type and matching descriptions at the
|
* should have the same type and matching descriptions at the designated 'zoom
|
||||||
* designated 'zoom level', and be 'close together' in time.
|
* level', and be 'close together' in time.
|
||||||
*/
|
*/
|
||||||
@Immutable
|
@Immutable
|
||||||
public class EventCluster implements MultiEvent<EventStripe> {
|
public class EventCluster implements MultiEvent<EventStripe> {
|
||||||
@ -120,7 +119,7 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<EventStripe> getParentBundle() {
|
public Optional<EventStripe> getParent() {
|
||||||
return Optional.ofNullable(parent);
|
return Optional.ofNullable(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,9 +180,6 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
|||||||
* EventBundle as the parent.
|
* EventBundle as the parent.
|
||||||
*/
|
*/
|
||||||
public EventCluster withParent(EventStripe parent) {
|
public EventCluster withParent(EventStripe parent) {
|
||||||
if (Objects.nonNull(this.parent)) {
|
|
||||||
throw new IllegalStateException("Event Cluster already has a parent!");
|
|
||||||
}
|
|
||||||
return new EventCluster(span, type, eventIDs, hashHits, tagged, description, lod, parent);
|
return new EventCluster(span, type, eventIDs, hashHits, tagged, description, lod, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,5 +188,8 @@ public class EventCluster implements MultiEvent<EventStripe> {
|
|||||||
return ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis)).add(this).build();
|
return ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis)).add(this).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EventCluster{" + "description=" + description + ", eventIDs=" + eventIDs.size() + '}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,10 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSortedSet;
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import org.python.google.common.base.Objects;
|
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
||||||
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
|
||||||
|
|
||||||
@ -39,10 +39,10 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
|||||||
public static EventStripe merge(EventStripe u, EventStripe v) {
|
public static EventStripe merge(EventStripe u, EventStripe v) {
|
||||||
Preconditions.checkNotNull(u);
|
Preconditions.checkNotNull(u);
|
||||||
Preconditions.checkNotNull(v);
|
Preconditions.checkNotNull(v);
|
||||||
Preconditions.checkArgument(Objects.equal(u.description, v.description));
|
Preconditions.checkArgument(Objects.equals(u.description, v.description));
|
||||||
Preconditions.checkArgument(Objects.equal(u.lod, v.lod));
|
Preconditions.checkArgument(Objects.equals(u.lod, v.lod));
|
||||||
Preconditions.checkArgument(Objects.equal(u.type, v.type));
|
Preconditions.checkArgument(Objects.equals(u.type, v.type));
|
||||||
Preconditions.checkArgument(Objects.equal(u.parent, v.parent));
|
Preconditions.checkArgument(Objects.equals(u.parent, v.parent));
|
||||||
return new EventStripe(u, v);
|
return new EventStripe(u, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,8 +82,10 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
|||||||
private final ImmutableSet<Long> hashHits;
|
private final ImmutableSet<Long> hashHits;
|
||||||
|
|
||||||
public EventStripe withParent(EventCluster parent) {
|
public EventStripe withParent(EventCluster parent) {
|
||||||
EventStripe eventStripe = new EventStripe(parent, this.type, this.description, this.lod, clusters, eventIDs, tagged, hashHits);
|
if (java.util.Objects.nonNull(this.parent)) {
|
||||||
return eventStripe;
|
throw new IllegalStateException("Event Stripe already has a parent!");
|
||||||
|
}
|
||||||
|
return new EventStripe(parent, this.type, this.description, this.lod, clusters, eventIDs, tagged, hashHits);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventStripe(EventCluster parent, EventType type, String description, DescriptionLoD lod, SortedSet<EventCluster> clusters, ImmutableSet<Long> eventIDs, ImmutableSet<Long> tagged, ImmutableSet<Long> hashHits) {
|
private EventStripe(EventCluster parent, EventType type, String description, DescriptionLoD lod, SortedSet<EventCluster> clusters, ImmutableSet<Long> eventIDs, ImmutableSet<Long> tagged, ImmutableSet<Long> hashHits) {
|
||||||
@ -98,9 +100,10 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
|||||||
this.hashHits = hashHits;
|
this.hashHits = hashHits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventStripe(EventCluster cluster, EventCluster parent) {
|
public EventStripe(EventCluster cluster) {
|
||||||
|
|
||||||
this.clusters = ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis))
|
this.clusters = ImmutableSortedSet.orderedBy(Comparator.comparing(EventCluster::getStartMillis))
|
||||||
.add(cluster).build();
|
.add(cluster.withParent(this)).build();
|
||||||
|
|
||||||
type = cluster.getEventType();
|
type = cluster.getEventType();
|
||||||
description = cluster.getDescription();
|
description = cluster.getDescription();
|
||||||
@ -108,7 +111,7 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
|||||||
eventIDs = cluster.getEventIDs();
|
eventIDs = cluster.getEventIDs();
|
||||||
tagged = cluster.getEventIDsWithTags();
|
tagged = cluster.getEventIDsWithTags();
|
||||||
hashHits = cluster.getEventIDsWithHashHits();
|
hashHits = cluster.getEventIDsWithHashHits();
|
||||||
this.parent = parent;
|
this.parent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventStripe(EventStripe u, EventStripe v) {
|
private EventStripe(EventStripe u, EventStripe v) {
|
||||||
@ -132,14 +135,22 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
|||||||
.addAll(u.getEventIDsWithHashHits())
|
.addAll(u.getEventIDsWithHashHits())
|
||||||
.addAll(v.getEventIDsWithHashHits())
|
.addAll(v.getEventIDsWithHashHits())
|
||||||
.build();
|
.build();
|
||||||
parent = u.getParentBundle().orElse(v.getParentBundle().orElse(null));
|
parent = u.getParent().orElse(v.getParent().orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<EventCluster> getParentBundle() {
|
public Optional<EventCluster> getParent() {
|
||||||
return Optional.ofNullable(parent);
|
return Optional.ofNullable(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<EventStripe> getParentStripe() {
|
||||||
|
if (getParent().isPresent()) {
|
||||||
|
return getParent().get().getParent();
|
||||||
|
} else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
@ -191,8 +202,7 @@ public final class EventStripe implements MultiEvent<EventCluster> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "EventStripe{" + "description=" + description + ", eventIDs=" + eventIDs.size() + '}'; //NON-NLS
|
return "EventStripe{" + "description=" + description + ", eventIDs=" + (Objects.isNull(eventIDs) ? 0 : eventIDs.size()) + '}'; //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ public interface MultiEvent<ParentType extends MultiEvent<?>> extends TimeLineEv
|
|||||||
|
|
||||||
long getStartMillis();
|
long getStartMillis();
|
||||||
|
|
||||||
Optional<ParentType> getParentBundle();
|
Optional<ParentType> getParent();
|
||||||
|
|
||||||
default int getSize() {
|
default int getSize() {
|
||||||
return getEventIDs().size();
|
return getEventIDs().size();
|
||||||
|
@ -1050,7 +1050,7 @@ public class EventDB {
|
|||||||
|
|
||||||
switch (Version.getBuildType()) {
|
switch (Version.getBuildType()) {
|
||||||
case DEVELOPMENT:
|
case DEVELOPMENT:
|
||||||
LOGGER.log(Level.INFO, "executing timeline query: {0}", query); //NON-NLS
|
// LOGGER.log(Level.INFO, "executing timeline query: {0}", query); //NON-NLS
|
||||||
break;
|
break;
|
||||||
case RELEASE:
|
case RELEASE:
|
||||||
default:
|
default:
|
||||||
@ -1097,8 +1097,7 @@ public class EventDB {
|
|||||||
Set<Long> hashHits = SQLHelper.unGroupConcat(rs.getString("hash_hits"), Long::valueOf); //NON-NLS
|
Set<Long> hashHits = SQLHelper.unGroupConcat(rs.getString("hash_hits"), Long::valueOf); //NON-NLS
|
||||||
Set<Long> tagged = SQLHelper.unGroupConcat(rs.getString("taggeds"), Long::valueOf); //NON-NLS
|
Set<Long> tagged = SQLHelper.unGroupConcat(rs.getString("taggeds"), Long::valueOf); //NON-NLS
|
||||||
|
|
||||||
return new EventCluster(interval, type, eventIDs, hashHits, tagged,
|
return new EventCluster(interval, type, eventIDs, hashHits, tagged, description, descriptionLOD);
|
||||||
description, descriptionLOD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1159,7 +1158,7 @@ public class EventDB {
|
|||||||
|
|
||||||
for (EventCluster eventCluster : aggEvents) {
|
for (EventCluster eventCluster : aggEvents) {
|
||||||
stripeDescMap.merge(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()),
|
stripeDescMap.merge(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()),
|
||||||
new EventStripe(eventCluster, null), EventStripe::merge);
|
new EventStripe(eventCluster), EventStripe::merge);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stripeDescMap.values().stream().sorted(Comparator.comparing(EventStripe::getStartMillis)).collect(Collectors.toList());
|
return stripeDescMap.values().stream().sorted(Comparator.comparing(EventStripe::getStartMillis)).collect(Collectors.toList());
|
||||||
|
@ -111,7 +111,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ObservableList<EventStripe> getEventStripes() {
|
public ObservableList<EventStripe> getEventStripes() {
|
||||||
return chart.getEventStripes();
|
return chart.getAllNestedEventStripes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectionModel(MultipleSelectionModel<TreeItem<TimeLineEvent>> selectionModel) {
|
public void setSelectionModel(MultipleSelectionModel<TreeItem<TimeLineEvent>> selectionModel) {
|
||||||
|
@ -67,6 +67,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
|||||||
private final ObservableList<EventNodeBase<?>> selectedNodes;
|
private final ObservableList<EventNodeBase<?>> selectedNodes;
|
||||||
private final DetailsChartLayoutSettings layoutSettings = new DetailsChartLayoutSettings();
|
private final DetailsChartLayoutSettings layoutSettings = new DetailsChartLayoutSettings();
|
||||||
private final TimeLineController controller;
|
private final TimeLineController controller;
|
||||||
|
private ObservableList<EventStripe> nestedEventStripes = FXCollections.observableArrayList();
|
||||||
|
|
||||||
DetailsChart(TimeLineController controller, DateAxis detailsChartDateAxis, DateAxis pinnedDateAxis, Axis<EventStripe> verticalAxis, ObservableList<EventNodeBase<?>> selectedNodes) {
|
DetailsChart(TimeLineController controller, DateAxis detailsChartDateAxis, DateAxis pinnedDateAxis, Axis<EventStripe> verticalAxis, ObservableList<EventNodeBase<?>> selectedNodes) {
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
@ -99,6 +100,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
|||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
void addStripe(EventStripe stripe) {
|
void addStripe(EventStripe stripe) {
|
||||||
eventStripes.add(stripe);
|
eventStripes.add(stripe);
|
||||||
|
nestedEventStripes.add(stripe);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearGuideLine(GuideLine guideLine) {
|
void clearGuideLine(GuideLine guideLine) {
|
||||||
@ -120,6 +122,15 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
|||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
void reset() {
|
void reset() {
|
||||||
eventStripes.clear();
|
eventStripes.clear();
|
||||||
|
nestedEventStripes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableList<EventStripe> getAllNestedEventStripes() {
|
||||||
|
return nestedEventStripes;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObservableList<EventStripe> getEventStripes() {
|
||||||
|
return eventStripes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DetailIntervalSelector extends IntervalSelector<DateTime> {
|
private static class DetailIntervalSelector extends IntervalSelector<DateTime> {
|
||||||
@ -244,7 +255,7 @@ public final class DetailsChart extends Control implements TimeLineChart<DateTim
|
|||||||
return new DetailsChartSkin(this);
|
return new DetailsChartSkin(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObservableList<EventStripe> getEventStripes() {
|
ObservableList<EventStripe> getRootEventStripes() {
|
||||||
return eventStripes;
|
return eventStripes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
@ -119,12 +120,11 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
|||||||
* @param requestedDescrLoD
|
* @param requestedDescrLoD
|
||||||
* @param expand
|
* @param expand
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages(value = "EventStripeNode.loggedTask.name=Load sub clusters")
|
@NbBundle.Messages(value = "EventClusterNode.loggedTask.name=Load sub events")
|
||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
private synchronized void loadSubBundles(DescriptionLoD.RelativeDetail relativeDetail) {
|
private synchronized void loadSubStripes(DescriptionLoD.RelativeDetail relativeDetail) {
|
||||||
getChartLane().setCursor(Cursor.WAIT);
|
getChartLane().setCursor(Cursor.WAIT);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make new ZoomParams to query with
|
* make new ZoomParams to query with
|
||||||
*
|
*
|
||||||
@ -137,45 +137,50 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
|||||||
final EventTypeZoomLevel eventTypeZoomLevel = eventsModel.eventTypeZoomProperty().get();
|
final EventTypeZoomLevel eventTypeZoomLevel = eventsModel.eventTypeZoomProperty().get();
|
||||||
final ZoomParams zoomParams = new ZoomParams(subClusterSpan, eventTypeZoomLevel, subClusterFilter, getDescriptionLoD());
|
final ZoomParams zoomParams = new ZoomParams(subClusterSpan, eventTypeZoomLevel, subClusterFilter, getDescriptionLoD());
|
||||||
|
|
||||||
Task<List<EventStripe>> loggedTask = new LoggedTask<List<EventStripe>>(Bundle.EventStripeNode_loggedTask_name(), false) {
|
Task<List<EventStripe>> loggedTask = new LoggedTask<List<EventStripe>>(Bundle.EventClusterNode_loggedTask_name(), false) {
|
||||||
|
|
||||||
private volatile DescriptionLoD loadedDescriptionLoD = getDescriptionLoD().withRelativeDetail(relativeDetail);
|
private volatile DescriptionLoD loadedDescriptionLoD = getDescriptionLoD().withRelativeDetail(relativeDetail);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<EventStripe> call() throws Exception {
|
protected List<EventStripe> call() throws Exception {
|
||||||
List<EventStripe> bundles;
|
List<EventStripe> stripes;
|
||||||
DescriptionLoD next = loadedDescriptionLoD;
|
DescriptionLoD next = loadedDescriptionLoD;
|
||||||
do {
|
do {
|
||||||
loadedDescriptionLoD = next;
|
loadedDescriptionLoD = next;
|
||||||
if (loadedDescriptionLoD == getEventBundle().getDescriptionLoD()) {
|
if (loadedDescriptionLoD == getEvent().getDescriptionLoD()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
bundles = eventsModel.getEventStripes(zoomParams.withDescrLOD(loadedDescriptionLoD));
|
stripes = eventsModel.getEventStripes(zoomParams.withDescrLOD(loadedDescriptionLoD));
|
||||||
|
|
||||||
next = loadedDescriptionLoD.withRelativeDetail(relativeDetail);
|
next = loadedDescriptionLoD.withRelativeDetail(relativeDetail);
|
||||||
} while (bundles.size() == 1 && nonNull(next));
|
} while (stripes.size() == 1 && nonNull(next));
|
||||||
|
|
||||||
// return list of EventStripes representing sub-bundles
|
// return list of EventStripes representing sub-bundles
|
||||||
return bundles.stream()
|
return stripes.stream()
|
||||||
.map(eventStripe -> eventStripe.withParent(getEventCluster()))
|
.map(new Function<EventStripe, EventStripe>() {
|
||||||
|
|
||||||
|
public EventStripe apply(EventStripe eventStripe) {
|
||||||
|
return eventStripe.withParent(getEvent());
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void succeeded() {
|
protected void succeeded() {
|
||||||
try {
|
try {
|
||||||
List<EventStripe> bundles = get();
|
List<EventStripe> newSubStripes = get();
|
||||||
|
|
||||||
//clear the existing subnodes
|
//clear the existing subnodes
|
||||||
List<TimeLineEvent> transform = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList());
|
List<TimeLineEvent> oldSubStripes = subNodes.stream().flatMap(new StripeFlattener()).collect(Collectors.toList());
|
||||||
// getChartLane().getParentChart().getEventStripes().removeAll(transform);
|
getChartLane().getParentChart().getAllNestedEventStripes().removeAll(oldSubStripes);
|
||||||
subNodes.clear();
|
subNodes.clear();
|
||||||
if (bundles.isEmpty()) {
|
if (newSubStripes.isEmpty()) {
|
||||||
getChildren().setAll(subNodePane, infoHBox);
|
getChildren().setAll(subNodePane, infoHBox);
|
||||||
setDescriptionLOD(getEventBundle().getDescriptionLoD());
|
setDescriptionLOD(getEvent().getDescriptionLoD());
|
||||||
} else {
|
} else {
|
||||||
// getChartLane().getParentChart().getEventStripes().addAll(bundles);
|
getChartLane().getParentChart().getAllNestedEventStripes().addAll(newSubStripes);
|
||||||
subNodes.addAll(Lists.transform(bundles, EventClusterNode.this::createChildNode));
|
subNodes.addAll(Lists.transform(newSubStripes, EventClusterNode.this::createChildNode));
|
||||||
getChildren().setAll(new VBox(infoHBox, subNodePane));
|
getChildren().setAll(new VBox(infoHBox, subNodePane));
|
||||||
setDescriptionLOD(loadedDescriptionLoD);
|
setDescriptionLOD(loadedDescriptionLoD);
|
||||||
}
|
}
|
||||||
@ -202,10 +207,6 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventCluster getEventCluster() {
|
|
||||||
return getEventBundle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void layoutChildren() {
|
protected void layoutChildren() {
|
||||||
double chartX = getChartLane().getXAxis().getDisplayPosition(new DateTime(getStartMillis()));
|
double chartX = getChartLane().getXAxis().getDisplayPosition(new DateTime(getStartMillis()));
|
||||||
@ -222,7 +223,7 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
|||||||
RootFilter getSubClusterFilter() {
|
RootFilter getSubClusterFilter() {
|
||||||
RootFilter subClusterFilter = eventsModel.filterProperty().get().copyOf();
|
RootFilter subClusterFilter = eventsModel.filterProperty().get().copyOf();
|
||||||
subClusterFilter.getSubFilters().addAll(
|
subClusterFilter.getSubFilters().addAll(
|
||||||
new DescriptionFilter(getEventBundle().getDescriptionLoD(), getDescription(), DescriptionFilter.FilterMode.INCLUDE),
|
new DescriptionFilter(getEvent().getDescriptionLoD(), getDescription(), DescriptionFilter.FilterMode.INCLUDE),
|
||||||
new TypeFilter(getEventType()));
|
new TypeFilter(getEventType()));
|
||||||
return subClusterFilter;
|
return subClusterFilter;
|
||||||
}
|
}
|
||||||
@ -251,7 +252,7 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
|||||||
setGraphic(new ImageView(PLUS));
|
setGraphic(new ImageView(PLUS));
|
||||||
setEventHandler(actionEvent -> {
|
setEventHandler(actionEvent -> {
|
||||||
if (node.getDescriptionLoD().moreDetailed() != null) {
|
if (node.getDescriptionLoD().moreDetailed() != null) {
|
||||||
node.loadSubBundles(DescriptionLoD.RelativeDetail.MORE);
|
node.loadSubStripes(DescriptionLoD.RelativeDetail.MORE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(DescriptionLoD.FULL));
|
disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(DescriptionLoD.FULL));
|
||||||
@ -269,11 +270,11 @@ final public class EventClusterNode extends MultiEventNodeBase<EventCluster, Eve
|
|||||||
setGraphic(new ImageView(MINUS));
|
setGraphic(new ImageView(MINUS));
|
||||||
setEventHandler(actionEvent -> {
|
setEventHandler(actionEvent -> {
|
||||||
if (node.getDescriptionLoD().lessDetailed() != null) {
|
if (node.getDescriptionLoD().lessDetailed() != null) {
|
||||||
node.loadSubBundles(DescriptionLoD.RelativeDetail.LESS);
|
node.loadSubStripes(DescriptionLoD.RelativeDetail.LESS);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(node.getEventCluster().getDescriptionLoD()));
|
disabledProperty().bind(node.descriptionLoDProperty().isEqualTo(node.getEvent().getDescriptionLoD()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,20 +57,19 @@ final public class EventStripeNode extends MultiEventNodeBase<EventStripe, Event
|
|||||||
|
|
||||||
if (eventStripe.getClusters().size() > 1) {
|
if (eventStripe.getClusters().size() > 1) {
|
||||||
for (EventCluster cluster : eventStripe.getClusters()) {
|
for (EventCluster cluster : eventStripe.getClusters()) {
|
||||||
subNodes.add(createChildNode(cluster));
|
subNodes.add(createChildNode(cluster.withParent(eventStripe)));
|
||||||
}
|
}
|
||||||
getChildren().addAll(new VBox(infoHBox, subNodePane));
|
getChildren().addAll(new VBox(infoHBox, subNodePane));
|
||||||
} else {
|
} else {
|
||||||
EventNodeBase<?> childNode;
|
EventNodeBase<?> childNode;
|
||||||
EventCluster cluster = Iterables.getOnlyElement(eventStripe.getClusters());
|
EventCluster cluster = Iterables.getOnlyElement(eventStripe.getClusters()).withParent(eventStripe);
|
||||||
if (cluster.getEventIDs().size() == 1) {
|
if (cluster.getEventIDs().size() == 1) {
|
||||||
SingleEventNode singleEventNode = new SingleEventNode(getChartLane(), getChartLane().getController().getEventsModel().getEventById(Iterables.getOnlyElement(cluster.getEventIDs())), this);
|
childNode = createChildNode(cluster);
|
||||||
childNode = singleEventNode;
|
|
||||||
} else {
|
} else {
|
||||||
EventClusterNode eventClusterNode = new EventClusterNode(getChartLane(), cluster, this);
|
EventClusterNode eventClusterNode = (EventClusterNode) createChildNode(cluster);
|
||||||
eventClusterNode.installActionButtons();
|
eventClusterNode.installActionButtons();
|
||||||
eventClusterNode.infoHBox.getChildren().remove(eventClusterNode.countLabel);
|
|
||||||
controlsHBox.getChildren().addAll(eventClusterNode.minusButton, eventClusterNode.plusButton);
|
controlsHBox.getChildren().addAll(eventClusterNode.minusButton, eventClusterNode.plusButton);
|
||||||
|
eventClusterNode.infoHBox.getChildren().remove(eventClusterNode.countLabel);
|
||||||
childNode = eventClusterNode;
|
childNode = eventClusterNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ final public class EventStripeNode extends MultiEventNodeBase<EventStripe, Event
|
|||||||
}
|
}
|
||||||
|
|
||||||
public EventStripe getEventStripe() {
|
public EventStripe getEventStripe() {
|
||||||
return getEventBundle();
|
return getEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -57,14 +57,14 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
|||||||
|
|
||||||
private final ReadOnlyObjectWrapper<DescriptionLoD> descLOD = new ReadOnlyObjectWrapper<>();
|
private final ReadOnlyObjectWrapper<DescriptionLoD> descLOD = new ReadOnlyObjectWrapper<>();
|
||||||
|
|
||||||
MultiEventNodeBase(DetailsChartLane<?> chartLane, BundleType eventBundle, ParentNodeType parentNode) {
|
MultiEventNodeBase(DetailsChartLane<?> chartLane, BundleType event, ParentNodeType parentNode) {
|
||||||
super(eventBundle, parentNode, chartLane);
|
super(event, parentNode, chartLane);
|
||||||
setDescriptionLOD(eventBundle.getDescriptionLoD());
|
setDescriptionLOD(event.getDescriptionLoD());
|
||||||
|
|
||||||
if (eventBundle.getEventIDsWithHashHits().isEmpty()) {
|
if (event.getEventIDsWithHashHits().isEmpty()) {
|
||||||
show(hashIV, false);
|
show(hashIV, false);
|
||||||
}
|
}
|
||||||
if (eventBundle.getEventIDsWithTags().isEmpty()) {
|
if (event.getEventIDsWithTags().isEmpty()) {
|
||||||
show(tagIV, false);
|
show(tagIV, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
|||||||
*/
|
*/
|
||||||
heightProperty().addListener(heightProp -> chartLane.requestLayout());
|
heightProperty().addListener(heightProp -> chartLane.requestLayout());
|
||||||
Platform.runLater(() ->
|
Platform.runLater(() ->
|
||||||
setLayoutX(chartLane.getXAxis().getDisplayPosition(new DateTime(eventBundle.getStartMillis())) - getLayoutXCompensation())
|
setLayoutX(chartLane.getXAxis().getDisplayPosition(new DateTime(event.getStartMillis())) - getLayoutXCompensation())
|
||||||
);
|
);
|
||||||
|
|
||||||
//initialize info hbox
|
//initialize info hbox
|
||||||
@ -105,21 +105,17 @@ public abstract class MultiEventNodeBase< BundleType extends MultiEvent<ParentTy
|
|||||||
descLOD.set(descriptionLoD);
|
descLOD.set(descriptionLoD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final BundleType getEventBundle() {
|
|
||||||
return getEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<EventNodeBase<?>> getSubNodes() {
|
public List<EventNodeBase<?>> getSubNodes() {
|
||||||
return subNodes;
|
return subNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String getDescription() {
|
final String getDescription() {
|
||||||
return getEventBundle().getDescription();
|
return getEvent().getDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Set<Long> getEventIDs() {
|
final Set<Long> getEventIDs() {
|
||||||
return getEventBundle().getEventIDs();
|
return getEvent().getEventIDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,8 +100,6 @@ public final class PrimaryDetailsChartLane extends DetailsChartLane<EventStripe>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private double getParentXForEpochMillis(Long epochMillis) {
|
private double getParentXForEpochMillis(Long epochMillis) {
|
||||||
return getXAxis().localToParent(getXForEpochMillis(epochMillis), 0).getX();
|
return getXAxis().localToParent(getXForEpochMillis(epochMillis), 0).getX();
|
||||||
}
|
}
|
||||||
|
@ -24,57 +24,49 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.scene.control.TreeItem;
|
import javafx.scene.control.TreeItem;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class EventDescriptionTreeItem extends NavTreeItem {
|
class EventDescriptionTreeItem extends EventsTreeItem {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* maps a description to the child item of this item with that description
|
* maps a description to the child item of this item with that description
|
||||||
*/
|
*/
|
||||||
private final Map<String, EventDescriptionTreeItem> childMap = new HashMap<>();
|
private final Map<String, EventDescriptionTreeItem> childMap = new HashMap<>();
|
||||||
private final TimeLineEvent bundle;
|
|
||||||
private Comparator<TreeItem<TimeLineEvent>> comparator = TreeComparator.Description;
|
private Comparator<TreeItem<TimeLineEvent>> comparator = TreeComparator.Description;
|
||||||
|
|
||||||
public TimeLineEvent getEvent() {
|
EventDescriptionTreeItem(EventStripe stripe, Comparator<TreeItem<TimeLineEvent>> comp) {
|
||||||
return bundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventDescriptionTreeItem(TimeLineEvent g, Comparator<TreeItem<TimeLineEvent>> comp) {
|
|
||||||
bundle = g;
|
|
||||||
comparator = comp;
|
comparator = comp;
|
||||||
setValue(g);
|
setValue(stripe);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getCount() {
|
|
||||||
return getValue().getSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
public void insert(Deque<MultiEvent<?>> path) {
|
public void insert(Deque<EventStripe> path) {
|
||||||
MultiEvent<?> head = path.removeFirst();
|
EventStripe head = path.removeFirst();
|
||||||
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), description -> {
|
String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse(""));
|
||||||
EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator);
|
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(substringAfter,
|
||||||
newTreeItem.setExpanded(true);
|
description -> {
|
||||||
childMap.put(description, newTreeItem);
|
EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator);
|
||||||
getChildren().add(newTreeItem);
|
newTreeItem.setExpanded(true);
|
||||||
resort(comparator, false);
|
getChildren().add(newTreeItem);
|
||||||
return newTreeItem;
|
resort(comparator, false);
|
||||||
});
|
return newTreeItem;
|
||||||
|
});
|
||||||
|
|
||||||
if (path.isEmpty() == false) {
|
if (path.isEmpty() == false) {
|
||||||
treeItem.insert(path);
|
treeItem.insert(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(Deque<MultiEvent<?>> path) {
|
void remove(Deque<EventStripe> path) {
|
||||||
MultiEvent<?> head = path.removeFirst();
|
EventStripe head = path.removeFirst();
|
||||||
EventDescriptionTreeItem descTreeItem = childMap.get(head.getDescription());
|
String substringAfter = StringUtils.substringAfter(head.getDescription(), head.getParentStripe().map(EventStripe::getDescription).orElse(""));
|
||||||
|
EventDescriptionTreeItem descTreeItem = childMap.get(substringAfter);
|
||||||
if (path.isEmpty() == false) {
|
if (path.isEmpty() == false) {
|
||||||
descTreeItem.remove(path);
|
descTreeItem.remove(path);
|
||||||
}
|
}
|
||||||
@ -94,14 +86,14 @@ class EventDescriptionTreeItem extends NavTreeItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NavTreeItem findTreeItemForEvent(TimeLineEvent t) {
|
public EventsTreeItem findTreeItemForEvent(TimeLineEvent event) {
|
||||||
|
|
||||||
if (getValue().getEventType() == t.getEventType()
|
if (getValue().getEventType() == event.getEventType()
|
||||||
&& getValue().getDescription().equals(t.getDescription())) {
|
&& getValue().getDescription().equals(event.getDescription())) {
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
for (EventDescriptionTreeItem child : childMap.values()) {
|
for (EventDescriptionTreeItem child : childMap.values()) {
|
||||||
final NavTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t);
|
final EventsTreeItem findTreeItemForEvent = child.findTreeItemForEvent(event);
|
||||||
if (findTreeItemForEvent != null) {
|
if (findTreeItemForEvent != null) {
|
||||||
return findTreeItemForEvent;
|
return findTreeItemForEvent;
|
||||||
}
|
}
|
||||||
@ -109,5 +101,4 @@ class EventDescriptionTreeItem extends NavTreeItem {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@ import java.util.Map;
|
|||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.scene.control.TreeItem;
|
import javafx.scene.control.TreeItem;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
||||||
|
|
||||||
class EventTypeTreeItem extends NavTreeItem {
|
class EventTypeTreeItem extends EventsTreeItem {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* maps a description to the child item of this item with that description
|
* maps a description to the child item of this item with that description
|
||||||
@ -37,35 +37,31 @@ class EventTypeTreeItem extends NavTreeItem {
|
|||||||
|
|
||||||
private Comparator<TreeItem<TimeLineEvent>> comparator = TreeComparator.Description;
|
private Comparator<TreeItem<TimeLineEvent>> comparator = TreeComparator.Description;
|
||||||
|
|
||||||
EventTypeTreeItem(MultiEvent<?> g, Comparator<TreeItem<TimeLineEvent>> comp) {
|
EventTypeTreeItem(EventStripe stripe, Comparator<TreeItem<TimeLineEvent>> comp) {
|
||||||
setValue(g);
|
setValue(stripe);
|
||||||
comparator = comp;
|
comparator = comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getCount() {
|
|
||||||
return getValue().getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
public void insert(Deque<MultiEvent<?>> path) {
|
public void insert(Deque<EventStripe> path) {
|
||||||
MultiEvent<?> head = path.removeFirst();
|
EventStripe head = path.removeFirst();
|
||||||
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(), description -> {
|
|
||||||
EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator);
|
EventDescriptionTreeItem treeItem = childMap.computeIfAbsent(head.getDescription(),
|
||||||
newTreeItem.setExpanded(true);
|
description -> {
|
||||||
childMap.put(head.getDescription(), newTreeItem);
|
EventDescriptionTreeItem newTreeItem = new EventDescriptionTreeItem(head, comparator);
|
||||||
getChildren().add(newTreeItem);
|
newTreeItem.setExpanded(true);
|
||||||
resort(comparator, false);
|
getChildren().add(newTreeItem);
|
||||||
return newTreeItem;
|
resort(comparator, false);
|
||||||
});
|
return newTreeItem;
|
||||||
|
});
|
||||||
|
|
||||||
if (path.isEmpty() == false) {
|
if (path.isEmpty() == false) {
|
||||||
treeItem.insert(path);
|
treeItem.insert(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(Deque<MultiEvent<?>> path) {
|
void remove(Deque<EventStripe> path) {
|
||||||
MultiEvent<?> head = path.removeFirst();
|
EventStripe head = path.removeFirst();
|
||||||
EventDescriptionTreeItem descTreeItem = childMap.get(head.getDescription());
|
EventDescriptionTreeItem descTreeItem = childMap.get(head.getDescription());
|
||||||
if (descTreeItem != null) {
|
if (descTreeItem != null) {
|
||||||
if (path.isEmpty() == false) {
|
if (path.isEmpty() == false) {
|
||||||
@ -79,11 +75,11 @@ class EventTypeTreeItem extends NavTreeItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NavTreeItem findTreeItemForEvent(TimeLineEvent t) {
|
public EventsTreeItem findTreeItemForEvent(TimeLineEvent t) {
|
||||||
if (t.getEventType().getBaseType() == getValue().getEventType().getBaseType()) {
|
if (t.getEventType().getBaseType() == getValue().getEventType().getBaseType()) {
|
||||||
|
|
||||||
for (EventDescriptionTreeItem child : childMap.values()) {
|
for (EventDescriptionTreeItem child : childMap.values()) {
|
||||||
final NavTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t);
|
final EventsTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t);
|
||||||
if (findTreeItemForEvent != null) {
|
if (findTreeItemForEvent != null) {
|
||||||
return findTreeItemForEvent;
|
return findTreeItemForEvent;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ import org.openide.util.NbBundle;
|
|||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
|
||||||
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
import org.sleuthkit.autopsy.timeline.TimeLineController;
|
||||||
|
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
||||||
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
|
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
|
||||||
@ -86,15 +87,11 @@ final public class EventsTree extends BorderPane {
|
|||||||
this.detailViewPane = detailViewPane;
|
this.detailViewPane = detailViewPane;
|
||||||
detailViewPane.setSelectionModel(eventsTree.getSelectionModel());
|
detailViewPane.setSelectionModel(eventsTree.getSelectionModel());
|
||||||
|
|
||||||
detailViewPane.getEventStripes().addListener((ListChangeListener.Change<? extends MultiEvent<?>> c) -> {
|
detailViewPane.getEventStripes().addListener((ListChangeListener.Change<? extends EventStripe> c) -> {
|
||||||
//on jfx thread
|
//on jfx thread
|
||||||
while (c.next()) {
|
while (c.next()) {
|
||||||
for (MultiEvent<?> bundle : c.getAddedSubList()) {
|
c.getRemoved().forEach(getRoot()::remove);
|
||||||
getRoot().insert(bundle);
|
c.getAddedSubList().forEach(getRoot()::insert);
|
||||||
}
|
|
||||||
for (MultiEvent<?> bundle : c.getRemoved()) {
|
|
||||||
getRoot().remove(bundle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -116,9 +113,7 @@ final public class EventsTree extends BorderPane {
|
|||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
private void setRoot() {
|
private void setRoot() {
|
||||||
RootItem root = new RootItem(TreeComparator.Type.reversed().thenComparing(sortByBox.getSelectionModel().getSelectedItem()));
|
RootItem root = new RootItem(TreeComparator.Type.reversed().thenComparing(sortByBox.getSelectionModel().getSelectedItem()));
|
||||||
for (MultiEvent<?> bundle : detailViewPane.getEventStripes()) {
|
detailViewPane.getEventStripes().forEach(root::insert);
|
||||||
root.insert(bundle);
|
|
||||||
}
|
|
||||||
eventsTree.setRoot(root);
|
eventsTree.setRoot(root);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,14 @@ import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
|||||||
* {@link EventTreeCell}. Each NavTreeItem has a EventBundle which has a type,
|
* {@link EventTreeCell}. Each NavTreeItem has a EventBundle which has a type,
|
||||||
* description , count, etc.
|
* description , count, etc.
|
||||||
*/
|
*/
|
||||||
abstract class NavTreeItem extends TreeItem<TimeLineEvent> {
|
abstract class EventsTreeItem extends TreeItem<TimeLineEvent> {
|
||||||
|
|
||||||
abstract long getCount();
|
final long getSize() {
|
||||||
|
return getValue().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
abstract void resort(Comparator<TreeItem<TimeLineEvent>> comp, Boolean recursive);
|
abstract void resort(Comparator<TreeItem<TimeLineEvent>> comp, Boolean recursive);
|
||||||
|
|
||||||
abstract NavTreeItem findTreeItemForEvent(TimeLineEvent t);
|
abstract EventsTreeItem findTreeItemForEvent(TimeLineEvent event);
|
||||||
|
|
||||||
}
|
}
|
@ -26,14 +26,14 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javafx.scene.control.TreeItem;
|
import javafx.scene.control.TreeItem;
|
||||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.MultiEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
|
||||||
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class RootItem extends NavTreeItem {
|
class RootItem extends EventsTreeItem {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* maps a description to the child item of this item with that description
|
* maps a description to the child item of this item with that description
|
||||||
@ -49,52 +49,45 @@ class RootItem extends NavTreeItem {
|
|||||||
this.comparator = comp;
|
this.comparator = comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getCount() {
|
|
||||||
return getValue().getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursive method to add a grouping at a given path.
|
* Recursive method to add a grouping at a given path.
|
||||||
*
|
*
|
||||||
* @param bundle bundle to add
|
* @param stripe stripe to add
|
||||||
*/
|
*/
|
||||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||||
public void insert(MultiEvent<?> bundle) {
|
public void insert(EventStripe stripe) {
|
||||||
|
|
||||||
EventTypeTreeItem treeItem = childMap.computeIfAbsent(bundle.getEventType().getBaseType(),
|
EventTypeTreeItem treeItem = childMap.computeIfAbsent(stripe.getEventType().getBaseType(),
|
||||||
baseType -> {
|
baseType -> {
|
||||||
EventTypeTreeItem newTreeItem = new EventTypeTreeItem(bundle, comparator);
|
EventTypeTreeItem newTreeItem = new EventTypeTreeItem(stripe, comparator);
|
||||||
newTreeItem.setExpanded(true);
|
newTreeItem.setExpanded(true);
|
||||||
getChildren().add(newTreeItem);
|
getChildren().add(newTreeItem);
|
||||||
return newTreeItem;
|
return newTreeItem;
|
||||||
});
|
});
|
||||||
treeItem.insert(getTreePath(bundle));
|
treeItem.insert(getTreePath(stripe));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(MultiEvent<?> bundle) {
|
void remove(EventStripe stripe) {
|
||||||
EventTypeTreeItem typeTreeItem = childMap.get(bundle.getEventType().getBaseType());
|
EventTypeTreeItem typeTreeItem = childMap.get(stripe.getEventType().getBaseType());
|
||||||
if (typeTreeItem != null) {
|
if (typeTreeItem != null) {
|
||||||
typeTreeItem.remove(getTreePath(bundle));
|
typeTreeItem.remove(getTreePath(stripe));
|
||||||
|
|
||||||
if (typeTreeItem.getChildren().isEmpty()) {
|
if (typeTreeItem.getChildren().isEmpty()) {
|
||||||
childMap.remove(bundle.getEventType().getBaseType());
|
childMap.remove(stripe.getEventType().getBaseType());
|
||||||
getChildren().remove(typeTreeItem);
|
getChildren().remove(typeTreeItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deque< MultiEvent<?>> getTreePath(MultiEvent<?> g) {
|
static Deque< EventStripe> getTreePath(EventStripe event) {
|
||||||
Deque<MultiEvent<?>> path = new ArrayDeque<>();
|
Deque<EventStripe> path = new ArrayDeque<>();
|
||||||
Optional<? extends MultiEvent<?>> p = Optional.of(g);
|
path.addFirst(event);
|
||||||
|
Optional<EventStripe> parentOptional = event.getParentStripe();
|
||||||
while (p.isPresent()) {
|
while (parentOptional.isPresent()) {
|
||||||
MultiEvent<?> parent = p.get();
|
EventStripe parent = parentOptional.get();
|
||||||
path.addFirst(parent);
|
path.addFirst(parent);
|
||||||
p = parent.getParentBundle();
|
parentOptional = parent.getParentStripe();
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,9 +98,9 @@ class RootItem extends NavTreeItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NavTreeItem findTreeItemForEvent(TimeLineEvent t) {
|
public EventsTreeItem findTreeItemForEvent(TimeLineEvent t) {
|
||||||
for (EventTypeTreeItem child : childMap.values()) {
|
for (EventTypeTreeItem child : childMap.values()) {
|
||||||
final NavTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t);
|
final EventsTreeItem findTreeItemForEvent = child.findTreeItemForEvent(t);
|
||||||
if (findTreeItemForEvent != null) {
|
if (findTreeItemForEvent != null) {
|
||||||
return findTreeItemForEvent;
|
return findTreeItemForEvent;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user