(still buggy)show unseen status and improve next unseen action; reset changes that broke regrouping

This commit is contained in:
jmillman 2015-06-03 16:49:40 -04:00
parent 7e260f6818
commit b2d2b3e746
6 changed files with 82 additions and 22 deletions

View File

@ -19,8 +19,8 @@
package org.sleuthkit.autopsy.imagegallery.actions; package org.sleuthkit.autopsy.imagegallery.actions;
import java.util.Optional; import java.util.Optional;
import javafx.beans.binding.Bindings; import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.binding.ObjectExpression;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import org.controlsfx.control.action.Action; import org.controlsfx.control.action.Action;
@ -38,17 +38,36 @@ public class NextUnseenGroup extends Action {
super("Next Unseen group"); super("Next Unseen group");
this.controller = controller; this.controller = controller;
setGraphic(new ImageView("/org/sleuthkit/autopsy/imagegallery/images/control-double.png")); setGraphic(new ImageView("/org/sleuthkit/autopsy/imagegallery/images/control-double.png"));
disabledProperty().bind(Bindings.isEmpty(controller.getGroupManager().getUnSeenGroups()));
controller.getGroupManager().getUnSeenGroups().addListener((Observable observable) -> {
updateDisabledStatus();
});
setEventHandler((ActionEvent t) -> { setEventHandler((ActionEvent t) -> {
Optional.ofNullable(controller.viewState()) Optional.ofNullable(controller.viewState())
.map((ReadOnlyObjectProperty<GroupViewState> t1) -> t1.get()) .map(ObjectExpression<GroupViewState>::getValue)
.map(GroupViewState::getGroup) .map(GroupViewState::getGroup)
.ifPresent(controller.getGroupManager()::markGroupSeen); .ifPresent(controller.getGroupManager()::markGroupSeen);
if (controller.getGroupManager().getUnSeenGroups().isEmpty() == false) { if (controller.getGroupManager().getUnSeenGroups().size() <= 1) {
setText("Mark Group Seen");
setGraphic(new ImageView("/org/sleuthkit/autopsy/imagegallery/images/control-stop.png"));
if (!controller.getGroupManager().getUnSeenGroups().isEmpty()) {
controller.advance(GroupViewState.tile(controller.getGroupManager().getUnSeenGroups().get(0)));
}
} else {
setText("Next Unseen group");
setGraphic(new ImageView("/org/sleuthkit/autopsy/imagegallery/images/control-double.png"));
setDisabled(false);
controller.advance(GroupViewState.tile(controller.getGroupManager().getUnSeenGroups().get(0))); controller.advance(GroupViewState.tile(controller.getGroupManager().getUnSeenGroups().get(0)));
} }
updateDisabledStatus();
}); });
updateDisabledStatus();
}
private void updateDisabledStatus() {
disabledProperty().set(controller.getGroupManager().getUnSeenGroups().isEmpty());
} }
} }

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.imagegallery.grouping;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -35,7 +36,6 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
private static final Logger LOGGER = Logger.getLogger(DrawableGroup.class.getName()); private static final Logger LOGGER = Logger.getLogger(DrawableGroup.class.getName());
public static String getBlankGroupName() { public static String getBlankGroupName() {
return "unknown"; return "unknown";
} }
@ -44,6 +44,7 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
//cache the number of files in this groups with hashset hits //cache the number of files in this groups with hashset hits
private int hashSetHitsCount = -1; private int hashSetHitsCount = -1;
private final ReadOnlyBooleanWrapper seen = new ReadOnlyBooleanWrapper(false);
synchronized public ObservableList<Long> fileIds() { synchronized public ObservableList<Long> fileIds() {
return fileIDs; return fileIDs;
@ -148,4 +149,16 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
public int compareTo(DrawableGroup other) { public int compareTo(DrawableGroup other) {
return this.groupKey.getValueDisplayName().compareTo(other.groupKey.getValueDisplayName()); return this.groupKey.getValueDisplayName().compareTo(other.groupKey.getValueDisplayName());
} }
void setSeen() {
this.seen.set(true);
}
public ReadOnlyBooleanWrapper seenProperty() {
return seen;
}
public boolean isSeen() {
return seen.get();
}
} }

View File

@ -81,18 +81,27 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
/** /**
* map from {@link GroupKey}s to {@link DrawableGroup}s. All groups (even * map from {@link GroupKey}s to {@link DrawableGroup}s. All groups (even
* not fully analyzed or not visible groups) could be in this map * not
* fully analyzed or not visible groups could be in this map
*/ */
private final Map<GroupKey<?>, DrawableGroup> groupMap = new HashMap<>(); private final Map<GroupKey<?>, DrawableGroup> groupMap = new HashMap<>();
/** list of all analyzed groups */ /**
* list of all analyzed groups
*/
@ThreadConfined(type = ThreadType.JFX) @ThreadConfined(type = ThreadType.JFX)
private final ObservableList<DrawableGroup> analyzedGroups = FXCollections.observableArrayList(); private final ObservableList<DrawableGroup> analyzedGroups = FXCollections.observableArrayList();
/** list of unseen groups */ private final ObservableList<DrawableGroup> publicAnalyzedGroupsWrapper = FXCollections.unmodifiableObservableList(analyzedGroups);
/**
* list of unseen groups
*/
@ThreadConfined(type = ThreadType.JFX) @ThreadConfined(type = ThreadType.JFX)
private final ObservableList<DrawableGroup> unSeenGroups = FXCollections.observableArrayList(); private final ObservableList<DrawableGroup> unSeenGroups = FXCollections.observableArrayList();
// private final SortedList<Grouping> sortedUnSeenGroups = new SortedList<>(unSeenGroups);
private final ObservableList<DrawableGroup> publicSortedUnseenGroupsWrapper = FXCollections.unmodifiableObservableList(unSeenGroups);
private ReGroupTask<?> groupByTask; private ReGroupTask<?> groupByTask;
/* --- current grouping/sorting attributes --- */ /* --- current grouping/sorting attributes --- */
@ -101,7 +110,7 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
private volatile DrawableAttribute<?> groupBy = DrawableAttribute.PATH; private volatile DrawableAttribute<?> groupBy = DrawableAttribute.PATH;
private volatile SortOrder sortOrder = SortOrder.ASCENDING; private volatile SortOrder sortOrder = SortOrder.ASCENDING;
private final ReadOnlyDoubleWrapper regroupProgress = new ReadOnlyDoubleWrapper(); private ReadOnlyDoubleWrapper regroupProgress = new ReadOnlyDoubleWrapper();
public void setDB(DrawableDB db) { public void setDB(DrawableDB db) {
this.db = db; this.db = db;
@ -110,13 +119,12 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
} }
public ObservableList<DrawableGroup> getAnalyzedGroups() { public ObservableList<DrawableGroup> getAnalyzedGroups() {
return FXCollections.unmodifiableObservableList(analyzedGroups); return publicAnalyzedGroupsWrapper;
} }
@ThreadConfined(type = ThreadType.JFX) @ThreadConfined(type = ThreadType.JFX)
public ObservableList<DrawableGroup> getUnSeenGroups() { public ObservableList<DrawableGroup> getUnSeenGroups() {
return FXCollections.unmodifiableObservableList(unSeenGroups); return publicSortedUnseenGroupsWrapper;
} }
/** /**
@ -253,7 +261,9 @@ public class GroupManager implements FileUpdateEvent.FileUpdateListener {
* @param group the {@link DrawableGroup} to mark as seen * @param group the {@link DrawableGroup} to mark as seen
*/ */
public void markGroupSeen(DrawableGroup group) { public void markGroupSeen(DrawableGroup group) {
db.markGroupSeen(group.getGroupKey()); db.markGroupSeen(group.getGroupKey());
group.setSeen();
synchronized (unSeenGroups) { synchronized (unSeenGroups) {
unSeenGroups.remove(group); unSeenGroups.remove(group);
} }

View File

@ -50,7 +50,8 @@ class GroupTreeCell extends TreeCell<TreeNode> {
* reference to listener that allows us to remove it from a group when a new * reference to listener that allows us to remove it from a group when a new
* group is assigned to this Cell * group is assigned to this Cell
*/ */
private InvalidationListener listener; private InvalidationListener fileListener;
private InvalidationListener seenListener;
public GroupTreeCell() { public GroupTreeCell() {
//TODO: move this to .css file //TODO: move this to .css file
@ -70,8 +71,9 @@ class GroupTreeCell extends TreeCell<TreeNode> {
if (Objects.nonNull(listener)) { if (Objects.nonNull(listener)) {
Optional.ofNullable(getItem()) Optional.ofNullable(getItem())
.map(TreeNode::getGroup) .map(TreeNode::getGroup)
.ifPresent((DrawableGroup t) -> { .ifPresent(group -> {
t.fileIds().removeListener(listener); group.fileIds().removeListener(fileListener);
group.seenProperty().removeListener(seenListener);
}); });
} }
@ -82,6 +84,7 @@ class GroupTreeCell extends TreeCell<TreeNode> {
setTooltip(null); setTooltip(null);
setText(null); setText(null);
setGraphic(null); setGraphic(null);
setStyle("");
}); });
} else { } else {
final String groupName = StringUtils.defaultIfBlank(tNode.getPath(), DrawableGroup.getBlankGroupName()); final String groupName = StringUtils.defaultIfBlank(tNode.getPath(), DrawableGroup.getBlankGroupName());
@ -92,30 +95,45 @@ class GroupTreeCell extends TreeCell<TreeNode> {
setTooltip(new Tooltip(groupName)); setTooltip(new Tooltip(groupName));
setText(groupName); setText(groupName);
setGraphic(new ImageView(EMPTY_FOLDER_ICON)); setGraphic(new ImageView(EMPTY_FOLDER_ICON));
setStyle("");
}); });
} else { } else {
listener = (Observable o) -> { fileListener = (Observable o) -> {
final String countsText = getCountsText(); final String countsText = getCountsText();
Platform.runLater(() -> { Platform.runLater(() -> {
setText(groupName + countsText); setText(groupName + countsText);
}); });
}; };
//if number of files in this group changes (eg file is recategorized), update counts via listener //if number of files in this group changes (eg file is recategorized), update counts via listener
tNode.getGroup().fileIds().addListener(listener); tNode.getGroup().fileIds().addListener(fileListener);
seenListener = (Observable observable) -> {
final String style = getSeenStyle();
Platform.runLater(() -> {
setStyle(style);
});
};
tNode.getGroup().seenProperty().addListener(seenListener);
//... and use icon corresponding to group type //... and use icon corresponding to group type
final Image icon = tNode.getGroup().groupKey.getAttribute().getIcon(); final Image icon = tNode.getGroup().groupKey.getAttribute().getIcon();
final String countsText = getCountsText(); final String countsText = getCountsText();
final String style = getSeenStyle();
Platform.runLater(() -> { Platform.runLater(() -> {
setTooltip(new Tooltip(groupName)); setTooltip(new Tooltip(groupName));
setGraphic(new ImageView(icon)); setGraphic(new ImageView(icon));
setText(groupName + countsText); setText(groupName + countsText);
setStyle(style);
}); });
} }
} }
} }
private String getSeenStyle() {
return getItem().getGroup().isSeen() ? "" : "-fx-font-weight:bold;";
}
private synchronized String getCountsText() { private synchronized String getCountsText() {
final String counts = Optional.ofNullable(getItem()) final String counts = Optional.ofNullable(getItem())
.map(TreeNode::getGroup) .map(TreeNode::getGroup)

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B