mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-04 06:50:00 +00:00
Merge pull request #2793 from millmanorama/2210-persist-sort
2210 persist sort
This commit is contained in:
@@ -26,15 +26,19 @@ import java.awt.Graphics;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.FeatureDescriptor;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.prefs.Preferences;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -43,6 +47,8 @@ import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.TableColumnModelEvent;
|
||||
import javax.swing.event.TableColumnModelListener;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import org.netbeans.swing.etable.ETableColumn;
|
||||
import org.netbeans.swing.outline.DefaultOutlineCellRenderer;
|
||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
@@ -88,6 +94,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
// the column started and where it ended up.
|
||||
private int startColumnIndex = -1;
|
||||
private int endColumnIndex = -1;
|
||||
private OutlineView ov;
|
||||
|
||||
/**
|
||||
* Creates a DataResultViewerTable object that is compatible with node
|
||||
@@ -111,7 +118,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
private void initialize() {
|
||||
initComponents();
|
||||
|
||||
OutlineView ov = ((OutlineView) this.tableScrollPanel);
|
||||
ov = ((OutlineView) this.tableScrollPanel);
|
||||
ov.setAllowedDragActions(DnDConstants.ACTION_NONE);
|
||||
|
||||
ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
@@ -216,6 +223,11 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
}
|
||||
startColumnIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
storeState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -363,13 +375,9 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
private void setupTable(final Node root) {
|
||||
|
||||
em.setRootContext(root);
|
||||
final OutlineView ov = ((OutlineView) this.tableScrollPanel);
|
||||
|
||||
if (ov == null) {
|
||||
return;
|
||||
}
|
||||
currentRoot = root;
|
||||
List<Node.Property<?>> props = loadState();
|
||||
List<Node.Property<?>> props = loadColumnOrder();
|
||||
|
||||
/**
|
||||
* OutlineView makes the first column be the result of
|
||||
@@ -390,14 +398,15 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
// Get the columns setup with respect to names and sortability
|
||||
String[] propStrings = new String[props.size() * 2];
|
||||
for (int i = 0; i < props.size(); i++) {
|
||||
props.get(i).setValue("ComparableColumnTTV", Boolean.TRUE); //NON-NLS
|
||||
final Property<?> prop = props.get(i);
|
||||
prop.setValue("ComparableColumnTTV", Boolean.TRUE); //NON-NLS
|
||||
//First property column is sorted initially
|
||||
if (i == 0) {
|
||||
props.get(i).setValue("TreeColumnTTV", Boolean.TRUE); // Identifies special property representing first (tree) column. NON-NLS
|
||||
props.get(i).setValue("SortingColumnTTV", Boolean.TRUE); // TreeTableView should be initially sorted by this property column. NON-NLS
|
||||
prop.setValue("TreeColumnTTV", Boolean.TRUE); // Identifies special property representing first (tree) column. NON-NLS
|
||||
prop.setValue("SortingColumnTTV", Boolean.TRUE); // TreeTableView should be initially sorted by this property column. NON-NLS
|
||||
}
|
||||
propStrings[2 * i] = props.get(i).getName();
|
||||
propStrings[2 * i + 1] = props.get(i).getDisplayName();
|
||||
propStrings[2 * i] = prop.getName();
|
||||
propStrings[2 * i + 1] = prop.getDisplayName();
|
||||
}
|
||||
|
||||
ov.setPropertyColumns(propStrings);
|
||||
@@ -442,6 +451,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
|
||||
}
|
||||
|
||||
loadSort();
|
||||
|
||||
/**
|
||||
* This custom renderer extends the renderer that was already being used
|
||||
* by the outline table. This renderer colors a row if the tags property
|
||||
@@ -494,19 +505,73 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
if (currentRoot == null || propertiesMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TableFilterNode tfn;
|
||||
if (currentRoot instanceof TableFilterNode) {
|
||||
tfn = (TableFilterNode) currentRoot;
|
||||
} else {
|
||||
TableFilterNode tfn = (TableFilterNode) currentRoot;
|
||||
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
|
||||
// Store the current order of the columns into settings
|
||||
for (Map.Entry<Integer, Property<?>> entry : propertiesMap.entrySet()) {
|
||||
preferences.put(getColumnPositionKey(tfn.getColumnOrderKey(), entry.getValue().getName()), String.valueOf(entry.getKey()));
|
||||
}
|
||||
final TableColumnModel columnModel = ov.getOutline().getColumnModel();
|
||||
|
||||
//store the sorting information
|
||||
int numCols = columnModel.getColumnCount();
|
||||
for (int i = 0; i < numCols; i++) {
|
||||
ETableColumn etc = (ETableColumn) columnModel.getColumn(i);
|
||||
String columnName = ov.getOutline().getColumnName(i);
|
||||
if (etc.isSorted()) {
|
||||
preferences.put(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.isAscending()));
|
||||
preferences.put(getColumnSortRankKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.getSortRank()));
|
||||
} else {
|
||||
preferences.remove(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName));
|
||||
preferences.remove(getColumnSortRankKey(tfn.getColumnOrderKey(), columnName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private final class ColumnSortInfo {
|
||||
|
||||
private final int modelIndex;
|
||||
private final int rank;
|
||||
private final boolean order;
|
||||
|
||||
private ColumnSortInfo(int modelIndex, int rank, boolean order) {
|
||||
this.modelIndex = modelIndex;
|
||||
this.rank = rank;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
private int getRank() {
|
||||
return rank;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void loadSort() {
|
||||
if (currentRoot == null || propertiesMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the current order of the columns into settings
|
||||
for (Map.Entry<Integer, Property<?>> entry : propertiesMap.entrySet()) {
|
||||
Property<?> prop = entry.getValue();
|
||||
int storeValue = entry.getKey();
|
||||
NbPreferences.forModule(this.getClass()).put(getColumnPreferenceKey(prop, tfn.getColumnOrderKey()), String.valueOf(storeValue));
|
||||
if (currentRoot instanceof TableFilterNode) {
|
||||
final String columnOrderKey = ((TableFilterNode) currentRoot).getColumnOrderKey();
|
||||
|
||||
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
|
||||
|
||||
//organize property sorting information, sorted by rank
|
||||
TreeSet<ColumnSortInfo> treeSet = new TreeSet<>(Comparator.comparing(ColumnSortInfo::getRank));
|
||||
propertiesMap.entrySet().stream()
|
||||
.forEach(entry -> {
|
||||
final String propName = entry.getValue().getName();
|
||||
//if the sort rank is undefined, it will be defaulted to 0 => unsorted.
|
||||
Integer sortRank = Integer.valueOf(preferences.get(getColumnSortRankKey(columnOrderKey, propName), "0"));
|
||||
//default to true => ascending
|
||||
Boolean sortOrder = Boolean.valueOf(preferences.get(getColumnSortOrderKey(columnOrderKey, propName), "true"));
|
||||
|
||||
treeSet.add(new ColumnSortInfo(entry.getKey(), sortRank, sortOrder));
|
||||
});
|
||||
|
||||
//apply sort information in rank order.
|
||||
treeSet.forEach(sortInfo -> ov.getOutline().setColumnSorted(sortInfo.modelIndex, sortInfo.order, sortInfo.rank));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,7 +580,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
*
|
||||
* @return a List<Node.Property<?>> of the preferences in order
|
||||
*/
|
||||
private synchronized List<Node.Property<?>> loadState() {
|
||||
private synchronized List<Node.Property<?>> loadColumnOrder() {
|
||||
// This is a set because we add properties of up to 100 child nodes, and we want unique properties
|
||||
Set<Property<?>> propertiesAcc = new LinkedHashSet<>();
|
||||
this.getAllChildPropertyHeadersRec(currentRoot, 100, propertiesAcc);
|
||||
@@ -540,8 +605,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
*/
|
||||
int offset = props.size();
|
||||
boolean noPreviousSettings = true;
|
||||
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
|
||||
|
||||
for (Property<?> prop : props) {
|
||||
Integer value = Integer.valueOf(NbPreferences.forModule(this.getClass()).get(getColumnPreferenceKey(prop, tfn.getColumnOrderKey()), "-1"));
|
||||
Integer value = Integer.valueOf(preferences.get(getColumnPositionKey(tfn.getColumnOrderKey(), prop.getName()), "-1"));
|
||||
if (value >= 0 && value < offset && !propertiesMap.containsKey(value)) {
|
||||
propertiesMap.put(value, prop);
|
||||
noPreviousSettings = false;
|
||||
@@ -573,9 +640,24 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
*
|
||||
* @return A generated key for the preference file
|
||||
*/
|
||||
private String getColumnPreferenceKey(Property<?> prop, String type) {
|
||||
return type.replaceAll("[^a-zA-Z0-9_]", "") + "."
|
||||
+ prop.getName().replaceAll("[^a-zA-Z0-9_]", "") + ".column";
|
||||
private String getColumnPositionKey(String type, String propName) {
|
||||
return getColumnKeyBase(type, propName) + ".column";
|
||||
}
|
||||
|
||||
private String getColumnSortOrderKey(String type, String propName) {
|
||||
return getColumnKeyBase(type, propName) + ".sortOrder";
|
||||
}
|
||||
|
||||
private String getColumnSortRankKey(String type, String propName) {
|
||||
return getColumnKeyBase(type, propName) + ".sortRank";
|
||||
}
|
||||
|
||||
private static String getColumnKeyBase(String type, String propName) {
|
||||
return stripNonAlphanumeric(type) + "." + stripNonAlphanumeric(propName);
|
||||
}
|
||||
|
||||
private static String stripNonAlphanumeric(String str) {
|
||||
return str.replaceAll("[^a-zA-Z0-9_]", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user