merged Jonathans work in with ours

This commit is contained in:
Nick Davis 2016-02-05 13:16:21 -05:00
commit 1783dfe015
22 changed files with 258 additions and 116 deletions

View File

@ -19,12 +19,12 @@ LBL_Close=\u9589\u3058\u308B
DataContentViewerString.copyMenuItem.text=\u30B3\u30D4\u30FC
DataContentViewerHex.copyMenuItem.text=\u30B3\u30D4\u30FC
DataContentViewerString.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E
DataContentViewerHex.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E
DataContentViewerHex.selectAllMenuItem.text=\u5168\u3066\u9078\u629E
DataContentViewerArtifact.totalPageLabel.text=100
DataContentViewerArtifact.pageLabel2.text=\u7D50\u679C
DataContentViewerArtifact.currentPageLabel.text=1
DataContentViewerArtifact.copyMenuItem.text=\u30B3\u30D4\u30FC
DataContentViewerArtifact.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E
DataContentViewerArtifact.selectAllMenuItem.text=\u5168\u3066\u9078\u629E
DataContentViewerArtifact.pageLabel.text=\u7D50\u679C\uFF1A
AdvancedConfigurationDialog.applyButton.text=OK
DataContentViewerString.goToPageLabel.text=\u6B21\u306E\u30DA\u30FC\u30B8\u3078\u79FB\u52D5\uFF1A
@ -44,7 +44,7 @@ DataResultPanel.matchLabel.text=\u7D50\u679C
MediaViewVideoPanel.pauseButton.text=\u25BA
MediaViewVideoPanel.progressLabel.text=00\:00
MediaViewVideoPanel.infoLabel.text=\u60C5\u5831
DataContentViewerArtifact.waitText=\u30C7\u30FC\u30BF\u3092\u53D6\u8FBC\u307F\u304A\u3088\u3073\u6E96\u5099\u4E2D\u3002\u3057\u3070\u3089\u304F\u304A\u5F85\u3061\u4E0B\u3055\u3044\u2026
DataContentViewerArtifact.waitText=\u30C7\u30FC\u30BF\u3092\u53D6\u8FBC\u307F\u304A\u3088\u3073\u6E96\u5099\u4E2D\u3002\u3057\u3070\u3089\u304F\u304A\u5F85\u3061\u4E0B\u3055\u3044...
DataContentViewerArtifact.errorText=\u7D50\u679C\u3092\u53D6\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F
DataContentViewerArtifact.title=\u7D50\u679C
DataContentViewerArtifact.toolTip=\u30D5\u30A1\u30A4\u30EB\u306B\u95A2\u9023\u3059\u308B\u7D50\u679C\u3092\u8868\u793A\u3057\u307E\u3059
@ -119,7 +119,7 @@ AutopsyOptionsPanel.keepCurrentViewerRB.text=\u305D\u306E\u307E\u307E\u540C\u305
AutopsyOptionsPanel.restartRequiredLabel.text=\u3053\u306E\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF\u30FC\u3067\u306F\u6700\u5927{0}\u306E\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B9\u30EC\u30C3\u30C9\u3092\u4F7F\u7528\u3059\u3079\u304D\u3067\u3059\u3002\u6709\u52B9\u306B\u3059\u308B\u306B\u306F\u518D\u8D77\u52D5\u304C\u5FC5\u8981\u3067\u3059\u3002
AutopsyOptionsPanel.jLabelSelectFile.text=\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u3059\u308B\u5834\u5408\uFF1A
AutopsyOptionsPanel.jLabelHideKnownFiles.text=\u65E2\u77E5\u30D5\u30A1\u30A4\u30EB\uFF08NIST NSRL\u5185\u306E\uFF09\u3092\u6B21\u306B\u96A0\u3059\uFF1A
AutopsyOptionsPanel.jLabelTimeDisplay.text=\u30A2\u30A4\u30C6\u30E0\u3092\u8868\u793A\u3059\u308B\u5834\u5408\uFF1A
AutopsyOptionsPanel.jLabelTimeDisplay.text=\u6642\u9593\u3092\u8868\u793A\u3059\u308B\u5834\u5408\uFF1A
AutopsyOptionsPanel.jLabelNumThreads.text=\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u306B\u4F7F\u7528\u3059\u308B\u30B9\u30EC\u30C3\u30C9\u6570\uFF1A
FXVideoPanel.progress.bufferingCancelled=\u30E1\u30C7\u30A3\u30A2\u306E\u30D0\u30C3\u30D5\u30A1\u30EA\u30F3\u30B0\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F
FXVideoPanel.progress.bufferingInterrupted=\u30E1\u30C7\u30A3\u30A2\u306E\u30D0\u30C3\u30D5\u30A1\u30EA\u30F3\u30B0\u304C\u4E2D\u65AD\u3055\u308C\u307E\u3057\u305F
@ -156,3 +156,11 @@ MultiUserSettingsPanel.tbMsgPassword.toolTipText=\u30D1\u30B9\u30EF\u30FC\u30C9\
MultiUserSettingsPanel.tbMsgHostname.toolTipText=\u30DB\u30B9\u30C8\u540D\u307E\u305F\u306FIP\u30A2\u30C9\u30EC\u30B9
MultiUserSettingsPanel.KeywordSearchNull=\u30AD\u30FC\u30EF\u30FC\u30C9\u691C\u7D22\u30B5\u30FC\u30D3\u30B9\u3092\u898B\u3064\u3051\u308C\u3089\u308C\u307E\u305B\u3093
MultiUserSettingsPanel.InvalidPortNumber=\u7121\u52B9\u306A\u30DD\u30FC\u30C8\u756A\u53F7
CTL_OfflineHelpAction=\u30AA\u30D5\u30E9\u30A4\u30F3Autopsy\u30C9\u30AD\u30E5\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3
CTL_OnlineHelpAction=\u30AA\u30F3\u30E9\u30A4\u30F3Autopsy\u30C9\u30AD\u30E5\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3
DataResultViewerThumbnail.thumbnailSizeComboBox.large=\u30B5\u30E0\u30CD\u30A4\u30EB\uFF08\u5927\uFF09
DataResultViewerThumbnail.thumbnailSizeComboBox.medium=\u30B5\u30E0\u30CD\u30A4\u30EB\uFF08\u4E2D\uFF09
DataResultViewerThumbnail.thumbnailSizeComboBox.small=\u30B5\u30E0\u30CD\u30A4\u30EB\uFF08\u5C0F\uFF09
MediaViewImagePanel.errorLabel.OOMText=\u30D5\u30A1\u30A4\u30EB\u3092\u30E1\u30C7\u30A3\u30A2\u30D3\u30E5\u30FC\u306B\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A\u30E1\u30E2\u30EA\u4E0D\u8DB3\u3002
MediaViewImagePanel.errorLabel.text=\u30D5\u30A1\u30A4\u30EB\u3092\u30E1\u30C7\u30A3\u30A2\u30D3\u30E5\u30FC\u306B\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F\u3002
MediaViewImagePanel.externalViewerButton.text=\u5916\u90E8\u30D3\u30E5\u30FC\u30A2\u30FC\u3067\u958B\u304F

View File

@ -192,11 +192,6 @@
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="thumbnailSizeComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.DefaultComboBoxModel&lt;String&gt;(new String[] { &quot;Small Thumbnails&quot;, &quot;Medium Thumbnails&quot;, &quot;Large Thumbnails&quot; })" type="code"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="thumbnailSizeComboBoxActionPerformed"/>
</Events>

View File

@ -87,11 +87,19 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
initialize();
}
@NbBundle.Messages({"DataResultViewerThumbnail.thumbnailSizeComboBox.small=Small Thumbnails",
"DataResultViewerThumbnail.thumbnailSizeComboBox.medium=Medium Thumbnails",
"DataResultViewerThumbnail.thumbnailSizeComboBox.large=Large Thumbnails"
})
private void initialize() {
initComponents();
iconView.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
em.addPropertyChangeListener(new ExplorerManagerNodeSelectionListener());
thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>(
new String[] { Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_small(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_medium(),
Bundle.DataResultViewerThumbnail_thumbnailSizeComboBox_large() }));
curPage = -1;
totalPages = 0;
@ -166,7 +174,6 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
}
});
thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel<String>(new String[] { "Small Thumbnails", "Medium Thumbnails", "Large Thumbnails" }));
thumbnailSizeComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
thumbnailSizeComboBoxActionPerformed(evt);
@ -203,10 +210,7 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
.addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, 563, Short.MAX_VALUE)
.addGap(0, 0, 0)))
.addComponent(iconView, javax.swing.GroupLayout.DEFAULT_SIZE, 563, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(

View File

@ -84,7 +84,7 @@ public class UNCPathUtilities {
String uncPath = null;
try {
String currentDrive = Paths.get(inputPath).getRoot().toString().substring(STARTING_OFFSET, REPLACEMENT_SIZE);
String uncMapping = drives.get(currentDrive);
String uncMapping = drives.get(currentDrive.toUpperCase());
if (uncMapping != null) {
uncPath = uncMapping + inputPath.substring(REPLACEMENT_SIZE, inputPath.length());
}

View File

@ -10,7 +10,7 @@ Contains only the core ingest modules that ship with Autopsy -->
<PIPELINE type="FileAnalysis">
<MODULE>org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory</MODULE>
<MODULE>org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory</MODULE>
<MODULE>org.sleuthkit.autopsy.modules.sevenzip.ArchiveFileExtractorModuleFactory</MODULE>
<MODULE>org.sleuthkit.autopsy.modules.embeddedfileextractor.EmbeddedFileExtractorModuleFactory</MODULE>
<MODULE>org.sleuthkit.autopsy.modules.exif.ExifParserModuleFactory</MODULE>
<MODULE>org.sleuthkit.autopsy.keywordsearch.KeywordSearchModuleFactory</MODULE>
<MODULE>org.sleuthkit.autopsy.thunderbirdparser.EmailParserModuleFactory</MODULE>

View File

@ -13,7 +13,7 @@ HashDbSearchPanel.titleLabel.text=\u6B21\u306EMD5\u30CF\u30C3\u30B7\u30E5\u4ED8\
HashDbSearchPanel.errorField.text=\u30A8\u30E9\u30FC\uFF1A\u5168\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u30CF\u30C3\u30B7\u30E5\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002
HashDbSearchPanel.saveBox.text=\u30CF\u30C3\u30B7\u30E5\u3092\u8A18\u61B6
HashDbSearchPanel.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB
OpenIDE-Module-Short-Description=\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u304A\u3088\u3073\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30C4\u30FC\u30EB
OpenIDE-Module-Short-Description=\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u304A\u3088\u3073\u30CF\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30C4\u30FC\u30EB
HashDbImportDatabaseDialog.jLabel1.text=\u30CF\u30C3\u30B7\u30E5\u30BB\u30C3\u30C8\u540D\uFF1A
HashDbImportDatabaseDialog.knownBadRadioButton.text=\u65E2\u77E5\u306E\u60AA\u8CEA
HashDbImportDatabaseDialog.jLabel2.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30BF\u30A4\u30D7\uFF1A
@ -210,3 +210,4 @@ AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.noHashesToAdd=\u8F
AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.success={0}\u30CF\u30C3\u30B7\u30E5\u304C\u6B63\u3057\u304F\u8FFD\u52A0\u3055\u308C\u307E\u3057\u305F\u3002
AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash=\u6709\u52B9\u306A\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002
AddHashValuesToDatabaseProgressDialog.addHashValuesToDatabase.errorAddingValidHash.msg=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u6709\u52B9\u306A\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002
HashLookupSettingsPanel.addHashesToDatabaseButton.text=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30CF\u30C3\u30B7\u30E5\u3092\u8FFD\u52A0

View File

@ -852,6 +852,7 @@ class ReportHTML implements TableReportModule {
NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getName())).append(
"</title>\n"); //NON-NLS
index.append("<link rel=\"icon\" type=\"image/ico\" href=\"favicon.ico\" />\n"); //NON-NLS
index.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"); //NON-NLS
index.append("</head>\n"); //NON-NLS
index.append("<frameset cols=\"350px,*\">\n"); //NON-NLS
index.append("<frame src=\"nav.html\" name=\"nav\">\n"); //NON-NLS
@ -890,7 +891,8 @@ class ReportHTML implements TableReportModule {
StringBuilder nav = new StringBuilder();
nav.append("<html>\n<head>\n\t<title>").append( //NON-NLS
NbBundle.getMessage(this.getClass(), "ReportHTML.writeNav.title"))
.append("</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n</head>\n<body>\n"); //NON-NLS
.append("</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n"); //NON-NLS
nav.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n"); //NON-NLS
nav.append("<div id=\"content\">\n<h1>").append( //NON-NLS
NbBundle.getMessage(this.getClass(), "ReportHTML.writeNav.h1")).append("</h1>\n"); //NON-NLS
nav.append("<ul class=\"nav\">\n"); //NON-NLS
@ -983,6 +985,7 @@ class ReportHTML implements TableReportModule {
head.append("<html>\n<head>\n<title>").append( //NON-NLS
NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.title")).append("</title>\n"); //NON-NLS
head.append("<style type=\"text/css\">\n"); //NON-NLS
head.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"); //NON-NLS
head.append("body { padding: 0px; margin: 0px; font: 13px/20px Arial, Helvetica, sans-serif; color: #535353; }\n"); //NON-NLS
head.append("#wrapper { width: 90%; margin: 0px auto; margin-top: 35px; }\n"); //NON-NLS
head.append("h1 { color: #07A; font-size: 36px; line-height: 42px; font-weight: normal; margin: 0px; border-bottom: 1px solid #81B9DB; }\n"); //NON-NLS

View File

@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.timeline.ui.detailview.tree;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Objects;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
@ -30,6 +29,7 @@ import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeCell;
@ -72,7 +72,7 @@ final public class EventsTree extends BorderPane {
private Label eventsTreeLabel;
@FXML
private ComboBox<Comparator<TreeItem<EventBundle<?>>>> sortByBox;
private ComboBox<TreeComparator> sortByBox;
public EventsTree(TimeLineController controller) {
this.controller = controller;
@ -128,6 +128,8 @@ final public class EventsTree extends BorderPane {
sortByBox.getItems().setAll(Arrays.asList(TreeComparator.Description, TreeComparator.Count));
sortByBox.getSelectionModel().select(TreeComparator.Description);
sortByBox.setCellFactory(listView -> new TreeComparatorCell());
sortByBox.setButtonCell(new TreeComparatorCell());
sortByBox.getSelectionModel().selectedItemProperty().addListener((Observable o) -> {
getRoot().resort(TreeComparator.Type.reversed().thenComparing(sortByBox.getSelectionModel().getSelectedItem()), true);
});
@ -249,4 +251,17 @@ final public class EventsTree extends BorderPane {
}
}
}
static private class TreeComparatorCell extends ListCell<TreeComparator> {
@Override
protected void updateItem(TreeComparator item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(item.getDisplayName());
}
}
}
}

View File

@ -20,27 +20,41 @@ package org.sleuthkit.autopsy.timeline.ui.detailview.tree;
import java.util.Comparator;
import javafx.scene.control.TreeItem;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
@NbBundle.Messages({"TreeComparator.Description.displayName=Description",
"TreeComparator.Count.displayName=Count",
"TreeComparator.Type.displayName=Type"})
enum TreeComparator implements Comparator<TreeItem<EventBundle<?>>> {
Description {
Description(Bundle.TreeComparator_Description_displayName()) {
@Override
public int compare(TreeItem<EventBundle<?>> o1, TreeItem<EventBundle<?>> o2) {
return o1.getValue().getDescription().compareTo(o2.getValue().getDescription());
}
},
Count {
Count(Bundle.TreeComparator_Count_displayName()) {
@Override
public int compare(TreeItem<EventBundle<?>> o1, TreeItem<EventBundle<?>> o2) {
return Long.compare(o2.getValue().getCount(), o1.getValue().getCount());
}
},
Type {
Type(Bundle.TreeComparator_Type_displayName()) {
@Override
public int compare(TreeItem<EventBundle<?>> o1, TreeItem<EventBundle<?>> o2) {
return EventType.getComparator().compare(o1.getValue().getEventType(), o2.getValue().getEventType());
}
};
private final String displayName;
private TreeComparator(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,10 +20,8 @@ package org.sleuthkit.autopsy.imagegallery.actions;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
import javafx.scene.image.ImageView;
import org.controlsfx.control.action.Action;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.datamodel.TagName;
/**
@ -36,6 +34,6 @@ public class TagGroupAction extends Action {
Set<Long> fileIdSet = ImmutableSet.copyOf(controller.viewState().get().getGroup().getFileIDs());
new AddDrawableTagAction(controller).addTagsToFiles(tagName, "", fileIdSet);
});
setGraphic(new ImageView(DrawableAttribute.TAGS.getIcon()));
setGraphic(controller.getTagsManager().getGraphic(tagName));
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Copyright 2015-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,10 +18,8 @@
*/
package org.sleuthkit.autopsy.imagegallery.actions;
import javafx.scene.image.ImageView;
import org.controlsfx.control.action.Action;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.datamodel.TagName;
/**
@ -31,6 +29,6 @@ public class TagSelectedFilesAction extends Action {
public TagSelectedFilesAction(final TagName tagName, ImageGalleryController controller) {
super(tagName.getDisplayName(), actionEvent -> new AddDrawableTagAction(controller).addTag(tagName, ""));
setGraphic(new ImageView(DrawableAttribute.TAGS.getIcon()));
setGraphic(controller.getTagsManager().getGraphic(tagName));
}
}

View File

@ -23,9 +23,17 @@ import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import org.openide.util.NbBundle;
/**
@ -51,6 +59,9 @@ public enum Category {
FIVE(Color.GREEN, 5, Bundle.Category_five()),
ZERO(Color.LIGHTGREY, 0, Bundle.Category_zero());
private static final BorderWidths BORDER_WIDTHS_2 = new BorderWidths(2);
private static final CornerRadii CORNER_RADII_4 = new CornerRadii(4);
public static ImmutableList<Category> getNonZeroCategories() {
return nonZeroCategories;
}
@ -108,9 +119,10 @@ public enum Category {
}
public Node getGraphic() {
Rectangle rectangle = new Rectangle(16d, 16d, getColor());
rectangle.setArcHeight(8);
rectangle.setArcWidth(8);
return rectangle;
Region region = new Region();
region.setBackground(new Background(new BackgroundFill(getColor(), CORNER_RADII_4, Insets.EMPTY)));
region.setPrefSize(16, 16);
region.setBorder(new Border(new BorderStroke(getColor().darker(), BorderStrokeStyle.SOLID, CORNER_RADII_4, BORDER_WIDTHS_2)));
return region;
}
}

View File

@ -25,7 +25,9 @@ import java.util.List;
import java.util.function.Function;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.StringProperty;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
@ -39,20 +41,20 @@ import org.sleuthkit.datamodel.TagName;
* of type paramaters and multivalued attributes
*/
@NbBundle.Messages({"DrawableAttribute.md5hash=MD5 Hash",
"DrawableAttribute.name=Name",
"DrawableAttribute.analyzed=Analyzed",
"DrawableAttribute.category=Category",
"DrawableAttribute.tags=Tags",
"DrawableAttribute.path=Path",
"DrawableAttribute.createdTime=Created Time",
"DrawableAttribute.modifiedTime=Modified Time",
"DrawableAttribute.cameraMake=Camera Make",
"DrawableAttribute.cameraModel=Camera Model",
"DrawableAttribute.hashSet=Hashset",
"DrawableAttribute.intObjID=Internal Object ID",
"DrawableAttribute.width=Width",
"DrawableAttribute.height=Height",
"DrawableAttribute.mimeType=MIME type"})
"DrawableAttribute.name=Name",
"DrawableAttribute.analyzed=Analyzed",
"DrawableAttribute.category=Category",
"DrawableAttribute.tags=Tags",
"DrawableAttribute.path=Path",
"DrawableAttribute.createdTime=Created Time",
"DrawableAttribute.modifiedTime=Modified Time",
"DrawableAttribute.cameraMake=Camera Make",
"DrawableAttribute.cameraModel=Camera Model",
"DrawableAttribute.hashSet=Hashset",
"DrawableAttribute.intObjID=Internal Object ID",
"DrawableAttribute.width=Width",
"DrawableAttribute.height=Height",
"DrawableAttribute.mimeType=MIME type"})
public class DrawableAttribute<T extends Comparable<T>> {
public final static DrawableAttribute<String> MD5_HASH =
@ -82,10 +84,16 @@ public class DrawableAttribute<T extends Comparable<T>> {
* advantage. move categories into DrawableDB?
*/
public final static DrawableAttribute<Category> CATEGORY =
new DrawableAttribute<>(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(),
new DrawableAttribute<Category>(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(),
false,
"category-icon.png", //NON-NLS
f -> Collections.singleton(f.getCategory()));
f -> Collections.singleton(f.getCategory())) {
@Override
public Node getGraphicForValue(Category val) {
return val.getGraphic();
}
};
public final static DrawableAttribute<TagName> TAGS =
new DrawableAttribute<>(AttributeName.TAGS, Bundle.DrawableAttribute_tags(),
@ -195,8 +203,8 @@ public class DrawableAttribute<T extends Comparable<T>> {
* TODO: override this to load per value icons form some attributes like
* mime-type and category
*/
public Image getIconForValue(T val) {
return getIcon();
public Node getGraphicForValue(T val) {
return new ImageView(getIcon());
}
public static List<DrawableAttribute<?>> getGroupableAttrs() {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-15 Basis Technology Corp.
* Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,6 +26,9 @@ import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.openide.util.NbBundle;
@ -40,7 +43,7 @@ import org.sleuthkit.datamodel.TskCoreException;
/**
* Manages Tags, Tagging, and the relationship between Categories and Tags in
* the autopsy Db. delegates some, work to the backing {@link TagsManager}.
* the autopsy Db. Delegates some work to the backing {@link TagsManager}.
*/
@NbBundle.Messages({"DrawableTagsManager.followUp=Follow Up"})
public class DrawableTagsManager {
@ -48,11 +51,14 @@ public class DrawableTagsManager {
private static final Logger LOGGER = Logger.getLogger(DrawableTagsManager.class.getName());
private static final String FOLLOW_UP = Bundle.DrawableTagsManager_followUp();
private static Image FOLLOW_UP_IMAGE;
final private Object autopsyTagsManagerLock = new Object();
private TagsManager autopsyTagsManager;
/** Used to distribute {@link TagsChangeEvent}s */
/**
* Used to distribute {@link TagsChangeEvent}s
*/
private final EventBus tagsEventBus = new AsyncEventBus(
Executors.newSingleThreadExecutor(
new BasicThreadFactory.Builder().namingPattern("Tags Event Bus").uncaughtExceptionHandler((Thread t, Throwable e) -> { //NON-NLS
@ -60,7 +66,9 @@ public class DrawableTagsManager {
}).build()
));
/** The tag name corresponding to the "built-in" tag "Follow Up" */
/**
* The tag name corresponding to the "built-in" tag "Follow Up"
*/
private TagName followUpTagName;
public DrawableTagsManager(TagsManager autopsyTagsManager) {
@ -137,8 +145,8 @@ public class DrawableTagsManager {
* get all the TagNames that are not categories
*
* @return all the TagNames that are not categories, in alphabetical order
* by displayName, or, an empty set if there was an exception looking them
* up from the db.
* by displayName, or, an empty set if there was an exception
* looking them up from the db.
*/
@Nonnull
public List<TagName> getNonCategoryTagNames() {
@ -228,4 +236,22 @@ public class DrawableTagsManager {
autopsyTagsManager.deleteContentTag(ct);
}
}
public Node getGraphic(TagName tagname) {
try {
if (tagname.equals(getFollowUpTagName())) {
return new ImageView(getFollowUpImage());
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get \"Follow Up\" tag name from db.", ex);
}
return DrawableAttribute.TAGS.getGraphicForValue(tagname);
}
synchronized private static Image getFollowUpImage() {
if (FOLLOW_UP_IMAGE == null) {
FOLLOW_UP_IMAGE = new Image("/org/sleuthkit/autopsy/imagegallery/images/flag_red.png");
}
return FOLLOW_UP_IMAGE;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Copyright 2013-16 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.imagegallery.datamodel.grouping;
import java.util.Map;
import java.util.Objects;
import javafx.scene.image.Image;
import javafx.scene.Node;
import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.datamodel.TagName;
@ -89,7 +89,7 @@ public class GroupKey<T extends Comparable<T>> implements Comparable<GroupKey<T>
return val.compareTo(o.val);
}
public Image getIcon() {
return attr.getIconForValue(val);
public Node getGraphic() {
return attr.getGraphicForValue(val);
}
}

View File

@ -1,11 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.SplitMenuButton?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<fx:root minWidth="-1.0" orientation="HORIZONTAL" prefWidth="-1.0" type="javafx.scene.control.ToolBar" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<fx:root minWidth="-1.0" orientation="HORIZONTAL" prefWidth="-1.0" type="javafx.scene.control.ToolBar" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
<items>
<Label fx:id="groupByLabel" text="Group By:">
<labelFor>
@ -13,7 +23,7 @@
</labelFor>
</Label>
<fx:reference source="groupByBox" />
<Region prefHeight="-1.0" prefWidth="20.0" />
<Region prefHeight="-1.0" prefWidth="10.0" />
<Label fx:id="sortByLabel" text="Sort By:">
<labelFor>
<ComboBox fx:id="sortByBox" />
@ -50,26 +60,54 @@
</children>
</HBox>
<Separator orientation="VERTICAL" prefHeight="-1.0" prefWidth="20.0" />
<CheckBox fx:id="onlyAnalyzedCheckBox" allowIndeterminate="false" indeterminate="false" mnemonicParsing="false" prefWidth="16.0" selected="true" text="only analyzed groups" underline="false" visible="false" />
<Label fx:id="applyToGroupLabel" contentDisplay="RIGHT" text="Apply to Group:" textOverrun="ELLIPSIS" />
<SplitMenuButton id="tagSplitMenu" fx:id="tagGroupMenuButton" disable="true" mnemonicParsing="false" text="Follow Up" textOverrun="ELLIPSIS">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</SplitMenuButton>
<SplitMenuButton id="catSplitMenu" fx:id="catGroupMenuButton" disable="true" mnemonicParsing="false" text="Cat-0">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</SplitMenuButton>
<HBox alignment="CENTER" spacing="5.0">
<children>
<Label fx:id="tagImageViewLabel" text="Tag Group's Files:">
<graphic>
<ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../images/tag_red.png" />
</image>
</ImageView>
</graphic>
</Label>
<SplitMenuButton id="tagSplitMenu" fx:id="tagGroupMenuButton" disable="true" mnemonicParsing="false" text="Follow Up" textOverrun="ELLIPSIS">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</SplitMenuButton>
</children>
</HBox>
<HBox alignment="CENTER" spacing="5.0">
<children>
<Label fx:id="categoryImageViewLabel" text="Categorize Group's Files:">
<graphic>
<ImageView fitHeight="16.0" fitWidth="16.0" mouseTransparent="true" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../images/category-icon.png" />
</image>
</ImageView>
</graphic>
</Label>
<SplitMenuButton id="catSplitMenu" fx:id="catGroupMenuButton" disable="true" mnemonicParsing="false" text="Cat-0">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</SplitMenuButton>
</children>
</HBox>
<Separator orientation="VERTICAL" prefHeight="-1.0" prefWidth="20.0" />
<Label fx:id="thumbnailSizeLabel" text="Thumbnail Size (px):">
<labelFor>
<Slider fx:id="sizeSlider" blockIncrement="100.0" majorTickUnit="100.0" max="300.0" min="100.0" minorTickCount="0" orientation="HORIZONTAL" prefHeight="-1.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="100.0" />
</labelFor>
</Label>
<fx:reference source="sizeSlider" />
<HBox alignment="CENTER" spacing="5.0">
<children>
<Label fx:id="thumbnailSizeLabel" text="Thumbnail Size (px):">
<labelFor>
<Slider fx:id="sizeSlider" blockIncrement="100.0" majorTickUnit="100.0" max="300.0" min="100.0" minorTickCount="0" orientation="HORIZONTAL" prefHeight="-1.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="100.0" />
</labelFor>
</Label>
<fx:reference source="sizeSlider" />
</children>
</HBox>
</items>
</fx:root>

View File

@ -29,7 +29,14 @@ import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Slider;
import javafx.scene.control.SplitMenuButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.HBox;
import javax.swing.SortOrder;
@ -57,9 +64,6 @@ public class Toolbar extends ToolBar {
@FXML
private ComboBox<DrawableAttribute<?>> groupByBox;
@FXML
private CheckBox onlyAnalyzedCheckBox;
@FXML
private Slider sizeSlider;
@ -138,7 +142,7 @@ public class Toolbar extends ToolBar {
assert catGroupMenuButton != null : "fx:id=\"catSelectedMenubutton\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert descRadio != null : "fx:id=\"descRadio\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert groupByBox != null : "fx:id=\"groupByBox\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert onlyAnalyzedCheckBox != null : "fx:id=\"onlyAnalyzedCheckBox\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert orderGroup != null : "fx:id=\"orderGroup\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert sizeSlider != null : "fx:id=\"sizeSlider\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert sortByBox != null : "fx:id=\"sortByBox\" was not injected: check your FXML file 'Toolbar.fxml'.";

View File

@ -145,6 +145,8 @@ import org.sleuthkit.datamodel.TskCoreException;
public class GroupPane extends BorderPane {
private static final Logger LOGGER = Logger.getLogger(GroupPane.class.getName());
private static final BorderWidths BORDER_WIDTHS_2 = new BorderWidths(2);
private static final CornerRadii CORNER_RADII_2 = new CornerRadii(2);
private static final DropShadow DROP_SHADOW = new DropShadow(10, Color.BLUE);
@ -395,10 +397,11 @@ public class GroupPane extends BorderPane {
assert tileToggle != null : "fx:id=\"tileToggle\" was not injected: check your FXML file 'GroupHeader.fxml'.";
for (Category cat : Category.values()) {
getToggleForCategory(cat).setBorder(new Border(new BorderStroke(cat.getColor(), BorderStrokeStyle.SOLID, new CornerRadii(1), new BorderWidths(1))));
getToggleForCategory(cat).getStyleClass().remove("radio-button");
getToggleForCategory(cat).getStyleClass().add("toggle-button");
getToggleForCategory(cat).selectedProperty().addListener((ov, wasSelected, toggleSelected) -> {
ToggleButton toggleForCategory = getToggleForCategory(cat);
toggleForCategory.setBorder(new Border(new BorderStroke(cat.getColor(), BorderStrokeStyle.SOLID, CORNER_RADII_2, BORDER_WIDTHS_2)));
toggleForCategory.getStyleClass().remove("radio-button");
toggleForCategory.getStyleClass().add("toggle-button");
toggleForCategory.selectedProperty().addListener((ov, wasSelected, toggleSelected) -> {
if (toggleSelected && slideShowPane != null) {
slideShowPane.getFileID().ifPresent((fileID) -> {
selectionModel.clearAndSelect(fileID);

View File

@ -24,13 +24,17 @@ import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.scene.Node;
import javafx.scene.control.ListCell;
import javafx.scene.control.OverrunStyle;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javax.annotation.Nonnull;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
import org.sleuthkit.datamodel.TagName;
/**
*
@ -66,9 +70,10 @@ class GroupListCell extends ListCell<DrawableGroup> {
};
private final ReadOnlyObjectProperty<GroupComparators<?>> sortOrder;
private final ImageGalleryController controller;
GroupListCell(ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
GroupListCell(ImageGalleryController controller, ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
this.controller = controller;
this.sortOrder = sortOrderProperty;
getStylesheets().add(GroupTreeCell.class.getResource("GroupTreeCell.css").toExternalForm()); //NON-NLS
getStyleClass().add("groupTreeCell"); //reduce indent to 5, default is 10 which uses up a lot of space. NON-NLS
@ -102,10 +107,10 @@ class GroupListCell extends ListCell<DrawableGroup> {
} else {
final String text = getGroupName() + getCountsText();
String style;
Image icon;
Node icon;
if (isNull(group)) {
//"dummy" group in file system tree <=> a folder with no drawables
icon = EMPTY_FOLDER_ICON;
icon = new ImageView(EMPTY_FOLDER_ICON);
style = "";
} else {
//if number of files in this group changes (eg a file is recategorized), update counts via listener
@ -117,13 +122,15 @@ class GroupListCell extends ListCell<DrawableGroup> {
group.seenProperty().addListener(seenListener);
//and use icon corresponding to group type
icon = group.getGroupKey().getIcon();
icon = (group.getGroupByAttribute() == DrawableAttribute.TAGS)
? controller.getTagsManager().getGraphic((TagName) group.getGroupByValue())
: group.getGroupKey().getGraphic();
style = getSeenStyleClass();
}
Platform.runLater(() -> {
setTooltip(new Tooltip(text));
setGraphic(new ImageView(icon));
setGraphic(icon);
setText(text);
setStyle(style);
});

View File

@ -32,7 +32,6 @@ import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.ImageView;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.Beta;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
@ -73,7 +72,7 @@ final public class GroupTree extends NavPanel<TreeItem<GroupTreeNode>> {
getToolBar().visibleProperty().bind(groupedByPath.not());
getToolBar().managedProperty().bind(groupedByPath.not());
groupTree.setCellFactory(treeView -> new GroupTreeCell(getSortByBox().getSelectionModel().selectedItemProperty()));
groupTree.setCellFactory(treeView -> new GroupTreeCell(getController(), getSortByBox().getSelectionModel().selectedItemProperty()));
groupTree.setShowRoot(false);
getGroupManager().getAnalyzedGroups().addListener((ListChangeListener.Change<? extends DrawableGroup> change) -> {

View File

@ -24,6 +24,7 @@ import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.scene.Node;
import javafx.scene.control.OverrunStyle;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeCell;
@ -31,7 +32,10 @@ import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute;
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
import org.sleuthkit.datamodel.TagName;
/**
* A cell in the NavPanel tree that listens to its associated group's fileids
@ -72,8 +76,10 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
});
};
private final ReadOnlyObjectProperty<GroupComparators<?>> sortOrder;
private final ImageGalleryController controller;
GroupTreeCell(ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
GroupTreeCell(ImageGalleryController controller, ReadOnlyObjectProperty<GroupComparators<?>> sortOrderProperty) {
this.controller = controller;
this.sortOrder = sortOrderProperty;
getStylesheets().add(GroupTreeCell.class.getResource("GroupTreeCell.css").toExternalForm()); //NON-NLS
getStyleClass().add("groupTreeCell"); //reduce indent to 5, default is 10 which uses up a lot of space. NON-NLS
@ -112,7 +118,8 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
setStyle("");
});
} else {
if (isNull(treeNode.getGroup())) {
DrawableGroup group = treeNode.getGroup();
if (isNull(group)) {
final String text = getGroupName();
//"dummy" group in file system tree <=> a folder with no drawables
Platform.runLater(() -> {
@ -124,20 +131,22 @@ class GroupTreeCell extends TreeCell<GroupTreeNode> {
} else {
//if number of files in this group changes (eg a file is recategorized), update counts via listener
treeNode.getGroup().getFileIDs().addListener(fileCountListener);
treeNode.getGroup().uncatCountProperty().addListener(fileCountListener);
treeNode.getGroup().hashSetHitsCountProperty().addListener(fileCountListener);
group.getFileIDs().addListener(fileCountListener);
group.uncatCountProperty().addListener(fileCountListener);
group.hashSetHitsCountProperty().addListener(fileCountListener);
sortOrder.addListener(fileCountListener);
//if the seen state of this group changes update its style
treeNode.getGroup().seenProperty().addListener(seenListener);
group.seenProperty().addListener(seenListener);
//and use icon corresponding to group type
final Image icon = treeNode.getGroup().getGroupKey().getIcon();
Node icon = (group.getGroupByAttribute() == DrawableAttribute.TAGS)
? controller.getTagsManager().getGraphic((TagName) group.getGroupByValue())
: group.getGroupKey().getGraphic();
final String text = getGroupName() + getCountsText();
final String style = getSeenStyleClass();
Platform.runLater(() -> {
setTooltip(new Tooltip(text));
setGraphic(new ImageView(icon));
setGraphic(icon);
setText(text);
setStyle(style);
});

View File

@ -79,7 +79,7 @@ final public class HashHitGroupList extends NavPanel<DrawableGroup> {
getBorderPane().setCenter(groupList);
sorted = getController().getGroupManager().getAnalyzedGroups().filtered((DrawableGroup t) -> t.getHashSetHitsCount() > 0).sorted(getDefaultComparator());
groupList.setCellFactory(treeView -> new GroupListCell(getSortByBox().getSelectionModel().selectedItemProperty()));
groupList.setCellFactory(treeView -> new GroupListCell(getController(), getSortByBox().getSelectionModel().selectedItemProperty()));
groupList.setItems(sorted);
}