From f018c82a14b99bed8d1cc6c1a34af33ad8ecc694 Mon Sep 17 00:00:00 2001 From: Luis Nassif Date: Wed, 10 Apr 2024 21:08:45 -0300 Subject: [PATCH 01/57] '#39: fix a NPE when dragging node with right mouse button --- iped-app/src/main/java/iped/app/ui/FiltersPanel.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index cff131815d..1d9e11d3eb 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -209,9 +209,12 @@ public void itemStateChanged(ItemEvent e) { filtersTree.addMouseListener(new MouseAdapter() { public void showPopupMenu(MouseEvent e) { - Object o = filtersTree.getPathForLocation(e.getX(), e.getY()).getLastPathComponent(); - filtererMenu.setContext(o); - filtererMenu.show((JComponent) e.getSource(), e.getX(), e.getY()); + TreePath tp = filtersTree.getPathForLocation(e.getX(), e.getY()); + if (tp != null) { + Object o = tp.getLastPathComponent(); + filtererMenu.setContext(o); + filtererMenu.show((JComponent) e.getSource(), e.getX(), e.getY()); + } } @Override From 8c88e0039440ac594c389cc509891487e34546d8 Mon Sep 17 00:00:00 2001 From: Luis Nassif Date: Thu, 11 Apr 2024 23:24:33 -0300 Subject: [PATCH 02/57] '#39: fix NPE by avoiding wrong clone, change map key to FilterNode --- .../filterdecisiontree/CombinedFilterer.java | 25 ++++++------- .../filterdecisiontree/OperandPopupMenu.java | 9 +++-- .../app/ui/filters/FilterTransferHandler.java | 35 +++++-------------- 3 files changed, 23 insertions(+), 46 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java index 3dbf5da88a..64b63438d5 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java @@ -36,7 +36,7 @@ public class CombinedFilterer implements IResultSetFilterer, IFilterChangeListener { OperandNode rootNode = new OperandNode(Operand.OR); - private final Map cachedBitSet = new HashMap(); + private final Map cachedBitSet = new HashMap<>(); int queueCount = 0; @@ -62,8 +62,8 @@ public IMultiSearchResult filterResult(IMultiSearchResult src) throws ParseExcep }; } - public void removePreCachedFilter(IFilter filter) { - cachedBitSet.remove(filter); + public void removePreCachedFilter(FilterNode node) { + cachedBitSet.remove(node); } /** @@ -167,8 +167,9 @@ public RoaringBitmap[] get(long timeout, TimeUnit unit) throws InterruptedExcept } - public void preCacheFilter(IFilter filter) { - cachedBitSet.put(filter, new FutureBitSetResult(this, filter)); + public void preCacheFilter(FilterNode node) { + IFilter filter = node.getFilter(); + cachedBitSet.put(node, new FutureBitSetResult(this, filter)); if (filter instanceof IMutableFilter) { ((IMutableFilter) filter).addFilterChangeListener(this); } @@ -370,17 +371,15 @@ public RoaringBitmap[] getBitSet(MultiSearchResult input, OperandNode op, Future } } - for (Iterator iterator = op.getChildren().iterator(); iterator.hasNext();) { + for (DecisionNode node : op.getChildren()) { if (cancelCheck != null && cancelCheck.isCancelled()) { return null; } - DecisionNode node = (DecisionNode) iterator.next(); - RoaringBitmap[] fbitset = null; if (node instanceof FilterNode) { try { - fbitset = cachedBitSet.get(((FilterNode) node).getFilter()).get(); + fbitset = cachedBitSet.get(((FilterNode) node)).get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } @@ -533,8 +532,8 @@ public boolean hasFiltersApplied() { return false; } - public void invertPreCached(IFilter op) { - FutureBitSetResult fbitset = cachedBitSet.get(op); + public void invertPreCached(FilterNode node) { + FutureBitSetResult fbitset = cachedBitSet.get(node); fbitset.invert(); } @@ -553,8 +552,4 @@ public void invalidateCache() { cbs = null; } - public void preCacheFilterClone(IFilter filter, IFilter filterClonedSrc) { - cachedBitSet.put(filter, cachedBitSet.get(filterClonedSrc)); - } - } diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java index 79608472a1..6a0d7b9a27 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java @@ -14,7 +14,6 @@ import iped.app.ui.SliderMenuItem; import iped.app.ui.filterdecisiontree.OperandNode.Operand; import iped.data.IItemId; -import iped.viewers.api.IFilter; import iped.viewers.api.IItemRef; import iped.viewers.api.IQuantifiableFilter; @@ -97,13 +96,13 @@ public void actionPerformed(ActionEvent e) { if (e.getSource() == removeMenuitem) { ((DecisionNode) op).getParent().remove(op); if (op instanceof FilterNode) { - logicFilterer.removePreCachedFilter((IFilter) ((FilterNode) op).getFilter()); + logicFilterer.removePreCachedFilter((FilterNode) op); } } if (e.getSource() == inverMenuitem) { ((DecisionNode) op).invert(); if (op instanceof FilterNode) { - logicFilterer.invertPreCached(((FilterNode) op).getFilter()); + logicFilterer.invertPreCached((FilterNode) op); } logicFilterer.invalidateCache(); } @@ -162,8 +161,8 @@ public void enableRemove() { @Override public void setVisible(boolean b) { if (!b && sliderMenuItem.hasSliderChanged()) { - logicFilterer.removePreCachedFilter((IFilter) ((FilterNode) op).getFilter()); - logicFilterer.preCacheFilter((IFilter) ((FilterNode) op).getFilter()); + logicFilterer.removePreCachedFilter((FilterNode) op); + logicFilterer.preCacheFilter((FilterNode) op); logicFilterer.startSearchResult(App.get().getResults()); diff --git a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java index 0940cc4fc8..f26179667d 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java +++ b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java @@ -173,41 +173,24 @@ public boolean importData(TransferSupport support) { } if (dest != null) { FilterNode filterNode = (FilterNode) data.getTransferData(filterNodeFlavor); - IFilter filter = null; - IFilter filterClonedSrc = null; if (filterNode != null) { if (support.getDropAction() == COPY) { - filterClonedSrc = filter; - filter = (IFilter) clone(((FilterNode) filterNode).getFilter()); - if (filter != null) { - dest.addFilter(new FilterNode(filter)); - } else { - return false; - } - } else { - if (support.getDropAction() == MOVE) { - dest.addFilter(filterNode); - tree.expandPath(destPath.pathByAddingChild(filterNode)); - } + filterNode = new FilterNode(filterNode.getFilter()); + } else if (support.getDropAction() != MOVE) { + filterNode = null; } } else { - filter = (IFilter) data.getTransferData(filterFlavor); + IFilter filter = (IFilter) data.getTransferData(filterFlavor); if (filter != null) { - FilterNode fn = new FilterNode(filter); - dest.addFilter(fn); - tree.expandPath(destPath.pathByAddingChild(fn)); + filterNode = new FilterNode(filter); } } - if (filter != null) { + if (filterNode != null) { + dest.addFilter(filterNode); + tree.expandPath(destPath.pathByAddingChild(filterNode)); tree.updateUI(); try { - if (filterClonedSrc == null) { - combinedFilterer.preCacheFilter(filter); - } else { - if (filter != filterClonedSrc) { - combinedFilterer.preCacheFilterClone(filter, filterClonedSrc); - } - } + combinedFilterer.preCacheFilter(filterNode); } catch (Exception e) { if (e.getCause() instanceof QueryNodeException) { JOptionPane.showMessageDialog(tree.getRootPane(), Messages.get("FiltersPanel.addQueryFilterError")); From 02c580f255e30f94a643a8c261b126cb9dc4248c Mon Sep 17 00:00:00 2001 From: Luis Nassif Date: Fri, 12 Apr 2024 12:02:20 -0300 Subject: [PATCH 03/57] '#39: fix DecisionNode clone method call --- .../iped/app/ui/filterdecisiontree/DecisionNode.java | 11 +++++++++++ .../iped/app/ui/filters/FilterTransferHandler.java | 6 +----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java index 5b2d668c36..9c03e64f18 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java @@ -32,4 +32,15 @@ public void invert() { this.inverted = !inverted; } + @Override + public DecisionNode clone() { + DecisionNode clone = new DecisionNode(); + clone.parent = this.parent; + clone.inverted = this.inverted; + for (DecisionNode child : this.children) { + clone.children.add(child.clone()); + } + return clone; + } + } diff --git a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java index f26179667d..bd31cf1a78 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java +++ b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java @@ -202,7 +202,7 @@ public boolean importData(TransferSupport support) { OperandNode operand = (OperandNode) data.getTransferData(operandNodeFlavor); if (operand != null) { if (support.getDropAction() == COPY) { - DecisionNode dn = (DecisionNode) clone(operand); + DecisionNode dn = operand.clone(); if (dn != null) { dest.addDecisionNode(dn); } else { @@ -224,8 +224,4 @@ public boolean importData(TransferSupport support) { } - private Object clone(Object object) { - return object; - } - } From b3477e0d8fb1116f2a0583aadeec33a19b46bc8c Mon Sep 17 00:00:00 2001 From: Luis Nassif Date: Fri, 12 Apr 2024 12:30:08 -0300 Subject: [PATCH 04/57] '#39: try to keep previous logic before commit 8c88e00 --- .../java/iped/app/ui/filters/FilterTransferHandler.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java index bd31cf1a78..3fcfdda289 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java +++ b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java @@ -176,7 +176,11 @@ public boolean importData(TransferSupport support) { if (filterNode != null) { if (support.getDropAction() == COPY) { filterNode = new FilterNode(filterNode.getFilter()); - } else if (support.getDropAction() != MOVE) { + } else { + if (support.getDropAction() == MOVE) { + dest.addFilter(filterNode); + tree.expandPath(destPath.pathByAddingChild(filterNode)); + } filterNode = null; } } else { @@ -185,7 +189,7 @@ public boolean importData(TransferSupport support) { filterNode = new FilterNode(filter); } } - if (filterNode != null) { + if (filterNode != null && filterNode.getFilter() != null) { dest.addFilter(filterNode); tree.expandPath(destPath.pathByAddingChild(filterNode)); tree.updateUI(); From d4a1d7b80be17b293165209d3665fc738237e67f Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 13:36:04 -0400 Subject: [PATCH 05/57] '#39 updates lastClickedPath also when clicking for start dragging from Combined Filterer Tree. --- iped-app/src/main/java/iped/app/ui/FiltersPanel.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 1d9e11d3eb..a7c3dafb2d 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -244,6 +244,13 @@ public void mouseReleased(MouseEvent e) { structuredFiltererTree.setDropMode(DropMode.ON); filtersTree.setTransferHandler(fth); + structuredFiltererTree.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + lastClickedPath = structuredFiltererTree.getPathForLocation(e.getX(), e.getY()); + } + }); + structuredFiltererTree.addMouseListener(new MouseAdapter() { public void showPopupMenu(MouseEvent e) { Object o = structuredFiltererTree.getPathForLocation(e.getX(), e.getY()).getLastPathComponent(); From 945ad1303469dc3723e2f9d6658b781500b7cb81 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 13:43:17 -0400 Subject: [PATCH 06/57] '#39 refactors FilterNode classes in a way to keep track of its correspondent CombinedFilterTreeModel where it is created, so it can update the map of Filters with corresponding nodes set when removing or adding one of its children. --- .../iped/app/ui/CombinedFilterTreeModel.java | 16 ++++++++++++++++ .../app/ui/filterdecisiontree/DecisionNode.java | 17 ++++++++++++++++- .../app/ui/filterdecisiontree/FilterNode.java | 4 +++- .../app/ui/filterdecisiontree/OperandNode.java | 15 +++++++++++++-- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java b/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java index 6451d7c1e4..f92a3cc363 100644 --- a/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java +++ b/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java @@ -1,19 +1,27 @@ package iped.app.ui; +import java.util.HashMap; +import java.util.Set; + import javax.swing.event.TreeModelListener; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import iped.app.ui.filterdecisiontree.CombinedFilterer; +import iped.app.ui.filterdecisiontree.DecisionNode; import iped.app.ui.filterdecisiontree.OperandNode; +import iped.app.ui.filterdecisiontree.OperandNode.Operand; +import iped.viewers.api.IFilter; import iped.viewers.api.IFilterer; public class CombinedFilterTreeModel implements TreeModel { String rootName = "Filters"; private IFilterer[] filterers; + HashMap> filtersToNodeMap = new HashMap>(); public CombinedFilterTreeModel(CombinedFilterer logicFilterer) { + logicFilterer.setRootNode(new OperandNode(Operand.OR, this)); this.rootName = logicFilterer.getFilterName(); this.filterers = new IFilterer[1]; this.filterers[0] = logicFilterer; @@ -109,4 +117,12 @@ public void setRootName(String rootName) { this.rootName = rootName; } + public boolean hasFilter(IFilter iFilter) { + return filtersToNodeMap.get(iFilter).size() > 0; + } + + public HashMap> getFiltersToNodeMap() { + return filtersToNodeMap; + } + } \ No newline at end of file diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java index 9c03e64f18..ecef7679bd 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java @@ -2,11 +2,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; + +import iped.app.ui.CombinedFilterTreeModel; public class DecisionNode { DecisionNode parent; List children = new ArrayList(); boolean inverted = false; + protected CombinedFilterTreeModel model; + + public DecisionNode(CombinedFilterTreeModel model) { + this.model = model; + } public DecisionNode getParent() { return parent; @@ -17,6 +25,13 @@ public List getChildren() { } public void remove(DecisionNode value) { + if (value instanceof FilterNode) { + FilterNode filterNode = (FilterNode) value; + Set nodes = model.getFiltersToNodeMap().get(filterNode.getFilter()); + if (nodes != null) { + nodes.remove(filterNode); + } + } children.remove(value); } @@ -34,7 +49,7 @@ public void invert() { @Override public DecisionNode clone() { - DecisionNode clone = new DecisionNode(); + DecisionNode clone = new DecisionNode(model); clone.parent = this.parent; clone.inverted = this.inverted; for (DecisionNode child : this.children) { diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java index 4b839e8c67..b419e36dd1 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java @@ -1,11 +1,13 @@ package iped.app.ui.filterdecisiontree; +import iped.app.ui.CombinedFilterTreeModel; import iped.viewers.api.IFilter; public class FilterNode extends DecisionNode { IFilter filter; - public FilterNode(IFilter filter) { + public FilterNode(IFilter filter, CombinedFilterTreeModel model) { + super(model); this.filter = filter; } diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java index 68493d11a7..4706d7cfb1 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java @@ -1,5 +1,9 @@ package iped.app.ui.filterdecisiontree; +import java.util.HashSet; +import java.util.Set; + +import iped.app.ui.CombinedFilterTreeModel; import iped.app.ui.Messages; public class OperandNode extends DecisionNode { @@ -13,7 +17,8 @@ public enum Operand { static String ANDSTR = Messages.get("Operand.AND"); static String ORSTR = Messages.get("Operand.OR"); - public OperandNode(Operand op) { + public OperandNode(Operand op, CombinedFilterTreeModel model) { + super(model); this.operand = op; } @@ -26,12 +31,18 @@ public String toString() { } public void addOperand(Operand op) { - OperandNode newOp = new OperandNode(op); + OperandNode newOp = new OperandNode(op, model); newOp.parent = this; children.add(newOp); } public void addFilter(FilterNode filterNode) { + Set nodes = model.getFiltersToNodeMap().get(filterNode.getFilter()); + if(nodes == null) { + nodes = new HashSet(); + model.getFiltersToNodeMap().put(filterNode.getFilter(), nodes); + } + nodes.add(filterNode); filterNode.parent = this; children.add(filterNode); } From 897e2914c670cbbf6bd9511d840d4f0e08c90c0d Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 13:46:01 -0400 Subject: [PATCH 07/57] '#39 returns cachedBitSet map from CombinedFilterer to its previous structure Map, as the remove of an item in this cache now only occurs when no other FilterNode refers to the same filter. --- .../filterdecisiontree/CombinedFilterer.java | 40 +++++++++++++------ .../filterdecisiontree/OperandPopupMenu.java | 15 ++++--- .../app/ui/filters/FilterTransferHandler.java | 38 +++++++++++++----- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java index 64b63438d5..2641e8018e 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java @@ -34,9 +34,9 @@ import iped.viewers.api.IResultSetFilterer; public class CombinedFilterer implements IResultSetFilterer, IFilterChangeListener { - OperandNode rootNode = new OperandNode(Operand.OR); + OperandNode rootNode; - private final Map cachedBitSet = new HashMap<>(); + private final Map cachedBitSet = new HashMap(); int queueCount = 0; @@ -62,8 +62,8 @@ public IMultiSearchResult filterResult(IMultiSearchResult src) throws ParseExcep }; } - public void removePreCachedFilter(FilterNode node) { - cachedBitSet.remove(node); + public void removePreCachedFilter(IFilter filter) { + cachedBitSet.remove(filter); } /** @@ -164,17 +164,23 @@ public RoaringBitmap[] get() throws InterruptedException, ExecutionException { public RoaringBitmap[] get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return null; } - } - public void preCacheFilter(FilterNode node) { - IFilter filter = node.getFilter(); - cachedBitSet.put(node, new FutureBitSetResult(this, filter)); + public void preCacheFilter(IFilter filter, FutureBitSetResult fbs) { + cachedBitSet.put(filter, fbs); if (filter instanceof IMutableFilter) { ((IMutableFilter) filter).addFilterChangeListener(this); } } + public void preCacheFilter(IFilter filter) { + preCacheFilter(filter, new FutureBitSetResult(this, filter)); + } + + public void preCacheFilterClone(IFilter filter, IFilter filterClonedSrc) { + preCacheFilter(filter, cachedBitSet.get(filterClonedSrc)); + } + static public RoaringBitmap getAllSetBitSet(int length) { RoaringBitmap bs = new RoaringBitmap(); bs.flip(0l, length); @@ -289,6 +295,8 @@ public CombinedBitSet(MultiSearchResult input, OperandNode op) { public void run() { try { result = getBitSet(input, op, self); + } catch (Exception e) { + e.printStackTrace(); } finally { resultFinished.release(); } @@ -371,16 +379,18 @@ public RoaringBitmap[] getBitSet(MultiSearchResult input, OperandNode op, Future } } - for (DecisionNode node : op.getChildren()) { + for (Iterator iterator = op.getChildren().iterator(); iterator.hasNext();) { if (cancelCheck != null && cancelCheck.isCancelled()) { return null; } + DecisionNode node = (DecisionNode) iterator.next(); + RoaringBitmap[] fbitset = null; if (node instanceof FilterNode) { try { - fbitset = cachedBitSet.get(((FilterNode) node)).get(); - } catch (InterruptedException | ExecutionException e) { + fbitset = cachedBitSet.get(((FilterNode) node).getFilter()).get(); + } catch (Exception e) { e.printStackTrace(); } } else if (node instanceof OperandNode) { @@ -532,8 +542,8 @@ public boolean hasFiltersApplied() { return false; } - public void invertPreCached(FilterNode node) { - FutureBitSetResult fbitset = cachedBitSet.get(node); + public void invertPreCached(IFilter op) { + FutureBitSetResult fbitset = cachedBitSet.get(op); fbitset.invert(); } @@ -552,4 +562,8 @@ public void invalidateCache() { cbs = null; } + public void setRootNode(OperandNode rootNode) { + this.rootNode = rootNode; + } + } diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java index 6a0d7b9a27..fa66f0cf8a 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java @@ -9,11 +9,13 @@ import javax.swing.JTree; import iped.app.ui.App; +import iped.app.ui.CombinedFilterTreeModel; import iped.app.ui.FiltererMenu; import iped.app.ui.Messages; import iped.app.ui.SliderMenuItem; import iped.app.ui.filterdecisiontree.OperandNode.Operand; import iped.data.IItemId; +import iped.viewers.api.IFilter; import iped.viewers.api.IItemRef; import iped.viewers.api.IQuantifiableFilter; @@ -94,15 +96,18 @@ public void actionPerformed(ActionEvent e) { } } if (e.getSource() == removeMenuitem) { - ((DecisionNode) op).getParent().remove(op); + ((DecisionNode) op).getParent().remove(op); if (op instanceof FilterNode) { - logicFilterer.removePreCachedFilter((FilterNode) op); + if (!((CombinedFilterTreeModel) filtersTree.getModel()) + .hasFilter((IFilter) ((FilterNode) op).getFilter())) { + logicFilterer.removePreCachedFilter((IFilter) ((FilterNode) op).getFilter()); + } } } if (e.getSource() == inverMenuitem) { ((DecisionNode) op).invert(); if (op instanceof FilterNode) { - logicFilterer.invertPreCached((FilterNode) op); + logicFilterer.invertPreCached(((FilterNode) op).getFilter()); } logicFilterer.invalidateCache(); } @@ -161,8 +166,8 @@ public void enableRemove() { @Override public void setVisible(boolean b) { if (!b && sliderMenuItem.hasSliderChanged()) { - logicFilterer.removePreCachedFilter((FilterNode) op); - logicFilterer.preCacheFilter((FilterNode) op); + logicFilterer.removePreCachedFilter((IFilter) ((FilterNode) op).getFilter()); + logicFilterer.preCacheFilter((IFilter) ((FilterNode) op).getFilter()); logicFilterer.startSearchResult(App.get().getResults()); diff --git a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java index 3fcfdda289..24f21cc0c0 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java +++ b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java @@ -13,6 +13,7 @@ import javax.swing.tree.TreePath; import iped.app.ui.App; +import iped.app.ui.CombinedFilterTreeModel; import iped.app.ui.FiltersPanel; import iped.app.ui.Messages; import iped.app.ui.filterdecisiontree.CombinedFilterer; @@ -119,7 +120,7 @@ public void exportAsDrag(JComponent comp, InputEvent e, int action) { @Override public int getSourceActions(JComponent c) { - return MOVE; + return COPY_OR_MOVE; } @Override @@ -173,28 +174,41 @@ public boolean importData(TransferSupport support) { } if (dest != null) { FilterNode filterNode = (FilterNode) data.getTransferData(filterNodeFlavor); + IFilter filter = null; + IFilter filterClonedSrc = null; if (filterNode != null) { if (support.getDropAction() == COPY) { - filterNode = new FilterNode(filterNode.getFilter()); + filterClonedSrc = filter; + filter = (IFilter) clone(((FilterNode) filterNode).getFilter()); + if (filter != null) { + dest.addFilter(new FilterNode(filter, (CombinedFilterTreeModel) tree.getModel())); + } else { + return false; + } } else { if (support.getDropAction() == MOVE) { dest.addFilter(filterNode); tree.expandPath(destPath.pathByAddingChild(filterNode)); } - filterNode = null; } } else { - IFilter filter = (IFilter) data.getTransferData(filterFlavor); + filter = (IFilter) data.getTransferData(filterFlavor); if (filter != null) { - filterNode = new FilterNode(filter); + FilterNode fn = new FilterNode(filter, (CombinedFilterTreeModel) tree.getModel()); + dest.addFilter(fn); + tree.expandPath(destPath.pathByAddingChild(fn)); } } - if (filterNode != null && filterNode.getFilter() != null) { - dest.addFilter(filterNode); - tree.expandPath(destPath.pathByAddingChild(filterNode)); + if (filter != null) { tree.updateUI(); try { - combinedFilterer.preCacheFilter(filterNode); + if (filterClonedSrc == null) { + combinedFilterer.preCacheFilter(filter); + } else { + if (filter != filterClonedSrc) { + combinedFilterer.preCacheFilterClone(filter, filterClonedSrc); + } + } } catch (Exception e) { if (e.getCause() instanceof QueryNodeException) { JOptionPane.showMessageDialog(tree.getRootPane(), Messages.get("FiltersPanel.addQueryFilterError")); @@ -206,7 +220,7 @@ public boolean importData(TransferSupport support) { OperandNode operand = (OperandNode) data.getTransferData(operandNodeFlavor); if (operand != null) { if (support.getDropAction() == COPY) { - DecisionNode dn = operand.clone(); + DecisionNode dn = (DecisionNode) clone(operand); if (dn != null) { dest.addDecisionNode(dn); } else { @@ -228,4 +242,8 @@ public boolean importData(TransferSupport support) { } + private Object clone(Object object) { + return object; + } + } From e0ee88af5a78726009580f6d2f183ef0928b4390 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 14:12:55 -0400 Subject: [PATCH 08/57] '#39 Properly implements clone methods of DecisionNode subclasses, so they can be cloned when dragging with CTRL button pressed (COPY operation). --- .../app/ui/filterdecisiontree/DecisionNode.java | 10 ++-------- .../app/ui/filterdecisiontree/FilterNode.java | 9 +++++++++ .../app/ui/filterdecisiontree/OperandNode.java | 17 +++++++++++++++++ .../app/ui/filters/FilterTransferHandler.java | 2 +- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java index ecef7679bd..54754c1e3b 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java @@ -48,14 +48,8 @@ public void invert() { } @Override - public DecisionNode clone() { - DecisionNode clone = new DecisionNode(model); - clone.parent = this.parent; - clone.inverted = this.inverted; - for (DecisionNode child : this.children) { - clone.children.add(child.clone()); - } - return clone; + public Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); } } diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java index b419e36dd1..09772befa0 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java @@ -20,4 +20,13 @@ public String toString() { return filter.toString(); } + @Override + public DecisionNode clone() { + FilterNode clone = new FilterNode(filter, model); + clone.parent = this.parent; + clone.inverted = this.inverted; + model.getFiltersToNodeMap().get(filter).add(this); + return clone; + } + } diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java index 4706d7cfb1..3c83f17a99 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java @@ -55,4 +55,21 @@ public void addDecisionNode(DecisionNode dnode) { public Operand getOperand() { return operand; } + + @Override + public DecisionNode clone() { + OperandNode clone = new OperandNode(this.operand, model); + clone.parent = this.parent; + clone.inverted = this.inverted; + for (DecisionNode child : this.children) { + try { + DecisionNode dn = (DecisionNode) child.clone(); + dn.parent = clone; + clone.children.add(dn); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + } + return clone; + } } diff --git a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java index 24f21cc0c0..ee2aa7c918 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java +++ b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java @@ -220,7 +220,7 @@ public boolean importData(TransferSupport support) { OperandNode operand = (OperandNode) data.getTransferData(operandNodeFlavor); if (operand != null) { if (support.getDropAction() == COPY) { - DecisionNode dn = (DecisionNode) clone(operand); + DecisionNode dn = (DecisionNode) operand.clone(); if (dn != null) { dest.addDecisionNode(dn); } else { From 4da3cdfc73e3bb90b7a238b2e54caf25b6fd456f Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 14:27:57 -0400 Subject: [PATCH 09/57] '#39 Alters field names to be similar with correspondent CombinedFilterer class name. --- .../main/java/iped/app/ui/FiltersPanel.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index a7c3dafb2d..0639594ced 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -45,8 +45,8 @@ public class FiltersPanel extends JPanel implements ClearFilterListener, IQueryF { private JTree filtersTree; private JScrollPane filtersTreePane; - private JTree structuredFiltererTree; - private JScrollPane structuredFiltererTreePane; + private JTree combinedFiltererTree; + private JScrollPane combinedFiltererTreePane; private JSplitPane splitPane; private CombinedFilterer combinedFilterer; @@ -126,8 +126,8 @@ public void mouseMoved(MouseEvent e) { filterManager.addResultSetFilterer(combinedFilterer); filterManager.setFilterEnabled(combinedFilterer, false); - structuredFiltererTree = new JTree(new CombinedFilterTreeModel(combinedFilterer)); - structuredFiltererTree.setCellRenderer(new DefaultTreeCellRenderer() { + combinedFiltererTree = new JTree(new CombinedFilterTreeModel(combinedFilterer)); + combinedFiltererTree.setCellRenderer(new DefaultTreeCellRenderer() { JLabel nlabel = new JLabel(invertIcon); JPanel p = new JPanel(new BorderLayout()); @@ -195,13 +195,13 @@ public void itemStateChanged(ItemEvent e) { } }); structuredFiltererTreePanel.add(ckStructuredFilterer, BorderLayout.NORTH); - structuredFiltererTreePane = new JScrollPane(structuredFiltererTree); - structuredFiltererTreePanel.add(structuredFiltererTreePane, BorderLayout.CENTER); + combinedFiltererTreePane = new JScrollPane(combinedFiltererTree); + structuredFiltererTreePanel.add(combinedFiltererTreePane, BorderLayout.CENTER); splitPane.setBottomComponent(structuredFiltererTreePanel); this.setLayout(new BorderLayout()); this.add(splitPane, BorderLayout.CENTER); - operandMenu = new OperandPopupMenu(structuredFiltererTree, combinedFilterer); + operandMenu = new OperandPopupMenu(combinedFiltererTree, combinedFilterer); filtererMenu = new FiltererMenu(); @@ -234,26 +234,26 @@ public void mouseReleased(MouseEvent e) { } }); - structuredFiltererTree.setDragEnabled(true); - structuredFiltererTree.setRootVisible(true); + combinedFiltererTree.setDragEnabled(true); + combinedFiltererTree.setRootVisible(true); FiltersPanel self = this; FilterTransferHandler fth = new FilterTransferHandler(this, combinedFilterer); - structuredFiltererTree.setTransferHandler(fth); - structuredFiltererTree.setDropMode(DropMode.ON); + combinedFiltererTree.setTransferHandler(fth); + combinedFiltererTree.setDropMode(DropMode.ON); filtersTree.setTransferHandler(fth); - structuredFiltererTree.addMouseListener(new MouseAdapter() { + combinedFiltererTree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { - lastClickedPath = structuredFiltererTree.getPathForLocation(e.getX(), e.getY()); + lastClickedPath = combinedFiltererTree.getPathForLocation(e.getX(), e.getY()); } }); - structuredFiltererTree.addMouseListener(new MouseAdapter() { + combinedFiltererTree.addMouseListener(new MouseAdapter() { public void showPopupMenu(MouseEvent e) { - Object o = structuredFiltererTree.getPathForLocation(e.getX(), e.getY()).getLastPathComponent(); + Object o = combinedFiltererTree.getPathForLocation(e.getX(), e.getY()).getLastPathComponent(); if (o instanceof CombinedFilterer || o instanceof DecisionNode) { if (o instanceof CombinedFilterer) { operandMenu.setDecisionNode(((CombinedFilterer) o).getRootNode()); From 14e403c27ce46d56e8f0fd4a1cdd7f833cb83b30 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 14:31:06 -0400 Subject: [PATCH 10/57] '#39 Allow only on filter node selection at a time in combined filterer tree. --- iped-app/src/main/java/iped/app/ui/FiltersPanel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 0639594ced..3419f21513 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -24,6 +24,7 @@ import javax.swing.JTree; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; import org.apache.lucene.search.Query; @@ -127,6 +128,7 @@ public void mouseMoved(MouseEvent e) { filterManager.setFilterEnabled(combinedFilterer, false); combinedFiltererTree = new JTree(new CombinedFilterTreeModel(combinedFilterer)); + combinedFiltererTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); combinedFiltererTree.setCellRenderer(new DefaultTreeCellRenderer() { JLabel nlabel = new JLabel(invertIcon); From 7e31973de1fb8ea0b4c791b0f1a11edc924b08b9 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 14:57:03 -0400 Subject: [PATCH 11/57] '#39 Implement code to avoid NPE --- .../src/main/java/iped/app/ui/CombinedFilterTreeModel.java | 6 +++++- .../java/iped/app/ui/filterdecisiontree/DecisionNode.java | 3 +++ .../java/iped/app/ui/filterdecisiontree/FilterNode.java | 7 ++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java b/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java index f92a3cc363..0367d0f1e1 100644 --- a/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java +++ b/iped-app/src/main/java/iped/app/ui/CombinedFilterTreeModel.java @@ -118,7 +118,11 @@ public void setRootName(String rootName) { } public boolean hasFilter(IFilter iFilter) { - return filtersToNodeMap.get(iFilter).size() > 0; + Set nodes = filtersToNodeMap.get(iFilter); + if (nodes != null) { + return filtersToNodeMap.get(iFilter).size() > 0; + } + return false; } public HashMap> getFiltersToNodeMap() { diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java index 54754c1e3b..45a652f242 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/DecisionNode.java @@ -30,6 +30,9 @@ public void remove(DecisionNode value) { Set nodes = model.getFiltersToNodeMap().get(filterNode.getFilter()); if (nodes != null) { nodes.remove(filterNode); + if (nodes.size() == 0) { + model.getFiltersToNodeMap().remove(filterNode.getFilter()); + } } } children.remove(value); diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java index 09772befa0..8a482ab639 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/FilterNode.java @@ -1,5 +1,7 @@ package iped.app.ui.filterdecisiontree; +import java.util.Set; + import iped.app.ui.CombinedFilterTreeModel; import iped.viewers.api.IFilter; @@ -25,7 +27,10 @@ public DecisionNode clone() { FilterNode clone = new FilterNode(filter, model); clone.parent = this.parent; clone.inverted = this.inverted; - model.getFiltersToNodeMap().get(filter).add(this); + Set nodes = model.getFiltersToNodeMap().get(filter); + if (nodes != null) { + nodes.add(this); + } return clone; } From df8043de5767e3d0d4c281f02b6dc486bde74bb1 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 18 Apr 2024 15:03:32 -0400 Subject: [PATCH 12/57] '#39 Adds a centered tip message informing about drag and drop filter operations to combine them. --- .../iped-desktop-messages.properties | 1 + .../iped-desktop-messages_de_DE.properties | 1 + .../iped-desktop-messages_es_AR.properties | 1 + .../iped-desktop-messages_it_IT.properties | 1 + .../iped-desktop-messages_pt_BR.properties | 1 + .../main/java/iped/app/ui/FiltersPanel.java | 25 ++++++++++++++++++- 6 files changed, 29 insertions(+), 1 deletion(-) diff --git a/iped-app/resources/localization/iped-desktop-messages.properties b/iped-app/resources/localization/iped-desktop-messages.properties index dadf70c1c9..163bd8e0ce 100644 --- a/iped-app/resources/localization/iped-desktop-messages.properties +++ b/iped-app/resources/localization/iped-desktop-messages.properties @@ -414,6 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter iped.app.ui.TreeListener.filtererName=Evidence Tree Filter iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them. FilterValue.Duplicates=Duplicate Filter Result FilterValue.SimilarDocument=Similar Documents FilterValue.SimilarFace=Similar Faces: diff --git a/iped-app/resources/localization/iped-desktop-messages_de_DE.properties b/iped-app/resources/localization/iped-desktop-messages_de_DE.properties index 698172eca2..bb1bbe2089 100644 --- a/iped-app/resources/localization/iped-desktop-messages_de_DE.properties +++ b/iped-app/resources/localization/iped-desktop-messages_de_DE.properties @@ -414,6 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter (TBT) iped.app.ui.TreeListener.filtererName=Evidence Tree Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter (TBT) +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them.(TBT) FilterValue.Duplicates=Duplicate Filter Result (TBT) FilterValue.SimilarDocument=Similar Documents (TBT) FilterValue.SimilarFace=Similar Faces: (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_es_AR.properties b/iped-app/resources/localization/iped-desktop-messages_es_AR.properties index 5444c2d333..13194b2261 100644 --- a/iped-app/resources/localization/iped-desktop-messages_es_AR.properties +++ b/iped-app/resources/localization/iped-desktop-messages_es_AR.properties @@ -414,6 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter (TBT) iped.app.ui.TreeListener.filtererName=Evidence Tree Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter (TBT) +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them.(TBT) FilterValue.Duplicates=Duplicate Filter Result (TBT) FilterValue.SimilarDocument=Similar Documents (TBT) FilterValue.SimilarFace=Similar Faces: (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_it_IT.properties b/iped-app/resources/localization/iped-desktop-messages_it_IT.properties index 7d2decec81..e73246d1f5 100644 --- a/iped-app/resources/localization/iped-desktop-messages_it_IT.properties +++ b/iped-app/resources/localization/iped-desktop-messages_it_IT.properties @@ -414,6 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter (TBT) iped.app.ui.TreeListener.filtererName=Evidence Tree Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter (TBT) +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them.(TBT) FilterValue.Duplicates=Duplicate Filter Result (TBT) FilterValue.SimilarDocument=Similar Documents (TBT) FilterValue.SimilarFace=Similar Faces: (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties b/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties index 9b6866765c..a3552ab658 100644 --- a/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties +++ b/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties @@ -414,6 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Filtro de Visão em Timeline iped.app.ui.TreeListener.filtererName=Filtro da Árvore de Evidências iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Filtro Combinado iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Aplicar Filtro Combinado +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Arreste e solte filtros nos nós da árvore para combiná-los. FilterValue.Duplicates=Resultado do Filtro de Duplicados FilterValue.SimilarDocument=Documentos Similares FilterValue.SimilarFace=Faces Similares: diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 3419f21513..7112bcba6d 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -3,7 +3,11 @@ import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; import java.awt.Image; +import java.awt.Rectangle; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; @@ -127,7 +131,26 @@ public void mouseMoved(MouseEvent e) { filterManager.addResultSetFilterer(combinedFilterer); filterManager.setFilterEnabled(combinedFilterer, false); - combinedFiltererTree = new JTree(new CombinedFilterTreeModel(combinedFilterer)); + combinedFiltererTree = new JTree(new CombinedFilterTreeModel(combinedFilterer)) { + String dragHereMsg = Messages.get("iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip"); + + @Override + protected void paintComponent(Graphics g) { + // TODO Auto-generated method stub + super.paintComponent(g); + if (((CombinedFilterTreeModel) getModel()).getFiltersToNodeMap().size() == 0) { + drawCenteredString(g, dragHereMsg, this.getBounds(), g.getFont()); + } + } + + public void drawCenteredString(Graphics g, String text, Rectangle rect, Font font) { + FontMetrics metrics = g.getFontMetrics(font); + int x = rect.x + (rect.width - metrics.stringWidth(text)) / 2; + int y = rect.y + ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent(); + g.setFont(font); + g.drawString(text, x, y); + } + }; combinedFiltererTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); combinedFiltererTree.setCellRenderer(new DefaultTreeCellRenderer() { From a7f8461032815fdd67263c9d40bb81b8fe2f0c70 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 19 Apr 2024 07:28:40 -0400 Subject: [PATCH 13/57] '#39 Case insensitive search from table header search menu text field. --- iped-app/src/main/java/iped/app/ui/controls/IPEDSearchList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/controls/IPEDSearchList.java b/iped-app/src/main/java/iped/app/ui/controls/IPEDSearchList.java index 5d33b6246d..a35f9ca553 100644 --- a/iped-app/src/main/java/iped/app/ui/controls/IPEDSearchList.java +++ b/iped-app/src/main/java/iped/app/ui/controls/IPEDSearchList.java @@ -181,7 +181,7 @@ public void keyReleased(KeyEvent e) { @Override public void keyReleased(KeyEvent e) { - String text = txFilter.getText(); + String text = txFilter.getText().toLowerCase(); if (text.length() > 0) { if (fl != null) { fl.cancel(); From 8e42673b2558033885d9d88fbb657206416f4584 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 19 Apr 2024 08:17:27 -0400 Subject: [PATCH 14/57] '#39 Creates interface IFilter method to return a more detailed textual description, used in the tootip of the filter in the tree. --- .../app/metadata/ValueCountQueryFilter.java | 20 +++++++++++++++++ .../main/java/iped/app/ui/FiltersPanel.java | 22 ++++++++++++++++++- .../main/java/iped/viewers/api/IFilter.java | 3 +++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java b/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java index 5e4bfad937..8182694b0e 100644 --- a/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java +++ b/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java @@ -14,6 +14,7 @@ public class ValueCountQueryFilter implements IQueryFilter { StringBuffer queryStr = null; StringBuffer name = null; + StringBuffer textualDetail = null; Set values = null; String filterField; private Query query; @@ -26,6 +27,25 @@ public ValueCountQueryFilter(String filterField, Set selectedValues) } } + @Override + public String getTextualDetails() { + if (textualDetail == null) { + textualDetail = new StringBuffer(); + textualDetail.append(filterField); + textualDetail.append(":["); + boolean first = true; + for (ValueCount value : values) { + if (!first) { + textualDetail.append(","); + } + textualDetail.append(value.getVal()); + first = false; + } + textualDetail.append("]"); + } + return textualDetail.toString(); + } + public String toString() { if (name == null) { name = new StringBuffer(); diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 7112bcba6d..3c9611e47a 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -26,6 +26,7 @@ import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTree; +import javax.swing.ToolTipManager; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; @@ -80,6 +81,7 @@ public TreePath getLastClickedPath() { public void install(FilterManager filterManager) { this.filterManager = filterManager; filtersTree = new JTree(); + CheckBoxTreeCellRenderer treeCellRenderer = new CheckBoxTreeCellRenderer(filtersTree, new Predicate() { @Override public boolean test(Object t) { @@ -96,7 +98,20 @@ public boolean test(Object t) { } return false; } - }); + }) { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + Component result = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (value instanceof IFilter) { + IFilter filter = (IFilter) value; + String toolTip = filter.getTextualDetails(); + ((JComponent)result).setToolTipText(toolTip); + } + + return result; + } + }; filtersTree.setCellRenderer(treeCellRenderer); filtersTree.setCellEditor(treeCellRenderer); filtersTree.setEditable(true); @@ -183,11 +198,16 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean Image newimg = ((IMiniaturizable) filter).getThumb().getScaledInstance(16, 16, java.awt.Image.SCALE_SMOOTH); label.setIcon(new ImageIcon(newimg)); } + String toolTip = filter.getTextualDetails(); + p.setToolTipText(toolTip); + } else { + p.setToolTipText(null); } return p; } }); + ToolTipManager.sharedInstance().registerComponent(combinedFiltererTree); splitPane = new JSplitPane(); diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilter.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilter.java index 5dee216a8b..ddc85d71c9 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilter.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilter.java @@ -6,4 +6,7 @@ * @author patrick.pdb */ public interface IFilter { + public default String getTextualDetails() { + return null; + }; } From 75c0b8c85ed05f3a82a02d916e35e3eed7e25581 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 19 Apr 2024 09:08:39 -0400 Subject: [PATCH 15/57] '#39 adding some comments --- .../iped/app/ui/filterdecisiontree/CombinedFilterer.java | 6 ++++++ .../src/main/java/iped/viewers/api/IBitmapFilter.java | 6 ++++++ .../src/main/java/iped/viewers/api/IQueryFilter.java | 5 +++++ .../src/main/java/iped/viewers/api/IResultSetFilter.java | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java index 2641e8018e..8ae02f397f 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java @@ -33,6 +33,12 @@ import iped.viewers.api.IResultSetFilter; import iped.viewers.api.IResultSetFilterer; +/** + * A resultSet filterer that uses a defined decision tree made up of filters + * combined by logical operands to filter the resultSet. + * + * @author patrick.pdb + */ public class CombinedFilterer implements IResultSetFilterer, IFilterChangeListener { OperandNode rootNode; diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IBitmapFilter.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IBitmapFilter.java index 3c34474cd7..cc7db76d07 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IBitmapFilter.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IBitmapFilter.java @@ -2,6 +2,12 @@ import org.roaringbitmap.RoaringBitmap; +/** + * A filter that exposes a RoaringBitmap that can be used to filter the + * resultSet + * + * @author patrick.pdb + */ public interface IBitmapFilter extends IFilter { RoaringBitmap[] getBitmap(); diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IQueryFilter.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IQueryFilter.java index cf3dc939ce..a988f8a4e8 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IQueryFilter.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IQueryFilter.java @@ -2,6 +2,11 @@ import org.apache.lucene.search.Query; +/** + * A filter that exposes a lucene query to be used to filter the result set + * + * @author patrick.pdb + */ public interface IQueryFilter extends IFilter { Query getQuery(); } diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IResultSetFilter.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IResultSetFilter.java index 2a52e7103b..414e21cb88 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IResultSetFilter.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IResultSetFilter.java @@ -6,6 +6,12 @@ import iped.exception.QueryNodeException; import iped.search.IMultiSearchResult; +/** + * Represents a filter that exposes a method that gets the input resultSet and + * returns a filtered resultSet + * + * @author patrick.pdb + */ public interface IResultSetFilter extends IFilter { IMultiSearchResult filterResult(IMultiSearchResult src) throws ParseException, QueryNodeException, IOException; } From d6cd081eb4af80c50115e86795eead78bf837b24 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 19 Apr 2024 13:45:58 -0400 Subject: [PATCH 16/57] '#39 Add support for disable Filterer on Filterers tree via its checkbox without removing its defined filters, which are restored when checkbox is checked again. --- iped-app/src/main/java/iped/app/ui/App.java | 4 +- .../iped/app/ui/CategoryTreeListener.java | 2 +- .../main/java/iped/app/ui/ComboFilterer.java | 122 ++++++++++++++++++ .../main/java/iped/app/ui/FilterManager.java | 105 +-------------- .../main/java/iped/app/ui/FiltersPanel.java | 38 +++++- .../java/iped/app/ui/TimelineListener.java | 2 +- .../ui/controls/CheckBoxTreeCellRenderer.java | 26 ++-- .../java/iped/viewers/api/IFilterManager.java | 5 + .../main/java/iped/viewers/api/IFilterer.java | 1 - 9 files changed, 180 insertions(+), 125 deletions(-) create mode 100644 iped-app/src/main/java/iped/app/ui/ComboFilterer.java create mode 100644 iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index d554d2161f..b4bf1d2ac2 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1980,7 +1980,7 @@ public boolean hasFilters() { @Override public boolean hasFiltersApplied() { - return false; + return hasFilters(); } @Override @@ -2098,7 +2098,7 @@ public boolean hasFilters() { @Override public boolean hasFiltersApplied() { - return false; + return filter != null; } @Override diff --git a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java index 64df016a2a..31b6063209 100644 --- a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java @@ -166,7 +166,7 @@ public String toString() { @Override public boolean hasFiltersApplied() { - return false; + return categoryList.size() > 0; } public String toString() { diff --git a/iped-app/src/main/java/iped/app/ui/ComboFilterer.java b/iped-app/src/main/java/iped/app/ui/ComboFilterer.java new file mode 100644 index 0000000000..1d866d2c71 --- /dev/null +++ b/iped-app/src/main/java/iped/app/ui/ComboFilterer.java @@ -0,0 +1,122 @@ +package iped.app.ui; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JComboBox; + +import org.apache.lucene.search.Query; + +import iped.engine.search.MultiSearchResult; +import iped.engine.search.QueryBuilder; +import iped.exception.ParseException; +import iped.exception.QueryNodeException; +import iped.search.IMultiSearchResult; +import iped.viewers.api.IFilter; +import iped.viewers.api.IMutableFilter; +import iped.viewers.api.IQueryFilter; +import iped.viewers.api.IQueryFilterer; +import iped.viewers.api.IResultSetFilter; +import iped.viewers.api.IResultSetFilterer; + +public class ComboFilterer implements IQueryFilterer, IResultSetFilterer { + private JComboBox comboFilter; + FilterManager fm; + + public ComboFilterer(FilterManager fm, JComboBox comboFilter) { + this.comboFilter = comboFilter; + this.fm = fm; + } + + @Override + public List getDefinedFilters() { + List result = new ArrayList(); + if (comboFilter.getSelectedIndex() != -1 && !App.FILTRO_TODOS.equals(comboFilter.getSelectedItem())) { + if (!App.FILTRO_SELECTED.equals(comboFilter.getSelectedItem())) { + result.add(new IQueryFilter() { + String filterName = (String) comboFilter.getSelectedItem(); + String filterExpression = fm.getFilterExpression((String) comboFilter.getSelectedItem()); + private Query query; + + @Override + public Query getQuery() { + if (query == null) { + try { + query = new QueryBuilder(App.get().appCase).getQuery(filterExpression); + } catch (ParseException | QueryNodeException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return query; + } + + @Override + public String toString() { + return filterName; + } + }); + } else { + result.add(getFilter()); + } + } + return result; + } + + class CheckedFilter implements IResultSetFilter, IMutableFilter { + @Override + public IMultiSearchResult filterResult(IMultiSearchResult src) + throws ParseException, QueryNodeException, IOException { + return (MultiSearchResult) App.get().appCase.getMultiBookmarks().filterChecked(src); + } + + public String toString() { + return App.FILTRO_SELECTED; + } + } + + @Override + public IFilter getFilter() { + if (App.FILTRO_SELECTED.equals(comboFilter.getSelectedItem())) { + return new CheckedFilter(); + } + return null; + } + + @Override + public boolean hasFiltersApplied() { + return comboFilter.getSelectedIndex() > 0; + } + + @Override + public Query getQuery() { + if (comboFilter.getSelectedIndex() == -1 || App.FILTRO_TODOS.equals(comboFilter.getSelectedItem()) + || App.FILTRO_SELECTED.equals(comboFilter.getSelectedItem())) { + return null; + } + + Query result = null; + try { + result = new QueryBuilder(App.get().appCase) + .getQuery(fm.getFilterExpression((String) comboFilter.getSelectedItem())); + } catch (ParseException | QueryNodeException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return result; + } + + @Override + public boolean hasFilters() { + return comboFilter.getSelectedIndex() != -1 && !App.FILTRO_TODOS.equals(comboFilter.getSelectedItem()); + } + + @Override + public void clearFilter() { + App.get().appletListener.clearAllFilters = true; + App.get().filterComboBox.setSelectedIndex(0); + App.get().appletListener.clearAllFilters = false; + } +} diff --git a/iped-app/src/main/java/iped/app/ui/FilterManager.java b/iped-app/src/main/java/iped/app/ui/FilterManager.java index 6b6a3857b3..b238f26884 100644 --- a/iped-app/src/main/java/iped/app/ui/FilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/FilterManager.java @@ -34,26 +34,22 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import org.apache.lucene.search.Query; import org.roaringbitmap.RoaringBitmap; import iped.data.IItemId; import iped.engine.data.IPEDMultiSource; import iped.engine.search.MultiSearchResult; -import iped.engine.search.QueryBuilder; import iped.exception.ParseException; import iped.exception.QueryNodeException; -import iped.search.IMultiSearchResult; import iped.utils.UTF8Properties; import iped.viewers.api.IFilter; +import iped.viewers.api.IFilterManager; import iped.viewers.api.IFilterer; -import iped.viewers.api.IMutableFilter; -import iped.viewers.api.IQueryFilter; import iped.viewers.api.IQueryFilterer; import iped.viewers.api.IResultSetFilter; import iped.viewers.api.IResultSetFilterer; -public class FilterManager implements ActionListener, ListSelectionListener { +public class FilterManager implements ActionListener, ListSelectionListener, IFilterManager { HashMap cachedFilterBitsets = new HashMap(); boolean useCachedBitmaps = false; @@ -405,100 +401,3 @@ public RoaringBitmap[] getCachedBitmaps(IResultSetFilter rsFilter) { } } -class ComboFilterer implements IQueryFilterer, IResultSetFilterer { - private JComboBox comboFilter; - FilterManager fm; - - public ComboFilterer(FilterManager fm, JComboBox comboFilter) { - this.comboFilter = comboFilter; - this.fm = fm; - } - - @Override - public List getDefinedFilters() { - List result = new ArrayList(); - if (comboFilter.getSelectedIndex() != -1 && !App.FILTRO_TODOS.equals(comboFilter.getSelectedItem())) { - if (!App.FILTRO_SELECTED.equals(comboFilter.getSelectedItem())) { - result.add(new IQueryFilter() { - String filterName = (String) comboFilter.getSelectedItem(); - String filterExpression = fm.getFilterExpression((String) comboFilter.getSelectedItem()); - private Query query; - - @Override - public Query getQuery() { - if (query == null) { - try { - query = new QueryBuilder(App.get().appCase).getQuery(filterExpression); - } catch (ParseException | QueryNodeException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return query; - } - - @Override - public String toString() { - return filterName; - } - }); - } else { - result.add(getFilter()); - } - } - return result; - } - - class CheckedFilter implements IResultSetFilter, IMutableFilter { - @Override - public IMultiSearchResult filterResult(IMultiSearchResult src) throws ParseException, QueryNodeException, IOException { - return (MultiSearchResult) App.get().appCase.getMultiBookmarks().filterChecked(src); - } - - public String toString() { - return App.FILTRO_SELECTED; - } - } - - @Override - public IFilter getFilter() { - if (App.FILTRO_SELECTED.equals(comboFilter.getSelectedItem())) { - return new CheckedFilter(); - } - return null; - } - - @Override - public boolean hasFiltersApplied() { - return comboFilter.getSelectedIndex() != -1; - } - - @Override - public Query getQuery() { - if (comboFilter.getSelectedIndex() == -1 || App.FILTRO_TODOS.equals(comboFilter.getSelectedItem()) || App.FILTRO_SELECTED.equals(comboFilter.getSelectedItem())) { - return null; - } - - Query result = null; - try { - result = new QueryBuilder(App.get().appCase).getQuery(fm.getFilterExpression((String) comboFilter.getSelectedItem())); - } catch (ParseException | QueryNodeException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return result; - } - - @Override - public boolean hasFilters() { - return comboFilter.getSelectedIndex() != -1 && !App.FILTRO_TODOS.equals(comboFilter.getSelectedItem()); - } - - @Override - public void clearFilter() { - App.get().appletListener.clearAllFilters = true; - App.get().filterComboBox.setSelectedIndex(0); - App.get().appletListener.clearAllFilters = false; - } -} diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 3c9611e47a..08260caad2 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -1,6 +1,7 @@ package iped.app.ui; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Font; @@ -8,6 +9,8 @@ import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; @@ -82,23 +85,27 @@ public void install(FilterManager filterManager) { this.filterManager = filterManager; filtersTree = new JTree(); - CheckBoxTreeCellRenderer treeCellRenderer = new CheckBoxTreeCellRenderer(filtersTree, new Predicate() { + Predicate filtererEnabledPredicate = new Predicate() { @Override public boolean test(Object t) { if (t instanceof IFilterer) { - return filterManager.isFiltererEnabled((IFilterer) t); + return filterManager.isFiltererEnabled((IFilterer) t) && (((IFilterer) t).hasFiltersApplied()); } return false; - } - }, new Predicate() { + }; + }; + + Predicate filtererVisiblePredicate = new Predicate() { @Override public boolean test(Object t) { if (t instanceof IFilterer) { - return ((IFilterer) t).hasFilters(); + return true; } return false; - } - }) { + }; + }; + CheckBoxTreeCellRenderer treeCellRenderer = new CheckBoxTreeCellRenderer(filtersTree, + filtererEnabledPredicate, filtererVisiblePredicate) { @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { @@ -109,9 +116,26 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean ((JComponent)result).setToolTipText(toolTip); } + if (value instanceof IFilterer) { + result.setBackground((((IFilterer) value).hasFiltersApplied()) ? ENABLED_BK_COLOR : Color.white); + } + return result; } }; + treeCellRenderer.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + IFilterer filterer = (IFilterer) e.getSource(); + if (filterer.hasFiltersApplied()) { + filterManager.setFilterEnabled(filterer, !filterManager.isFiltererEnabled(filterer)); + App.get().filtersPanel.updateUI(); + App.get().getAppListener().updateFileListing(); + } else { + App.get().filtersPanel.updateUI(); + } + } + }); filtersTree.setCellRenderer(treeCellRenderer); filtersTree.setCellEditor(treeCellRenderer); filtersTree.setEditable(true); diff --git a/iped-app/src/main/java/iped/app/ui/TimelineListener.java b/iped-app/src/main/java/iped/app/ui/TimelineListener.java index 07ad61d7cd..5babc00e69 100644 --- a/iped-app/src/main/java/iped/app/ui/TimelineListener.java +++ b/iped-app/src/main/java/iped/app/ui/TimelineListener.java @@ -135,7 +135,7 @@ public boolean hasFilters() { @Override public boolean hasFiltersApplied() { - return false; + return isTimelineViewEnabled(); } } diff --git a/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java b/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java index b95ab79b18..e6b7506ddf 100644 --- a/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java +++ b/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java @@ -15,12 +15,12 @@ import javax.swing.JPanel; import javax.swing.JTree; import javax.swing.event.CellEditorListener; +import javax.swing.event.EventListenerList; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeCellEditor; import org.apache.tika.mime.MediaType; -import iped.app.ui.App; import iped.app.ui.IconManager; import iped.engine.data.Category; import iped.viewers.api.IFilterer; @@ -35,6 +35,8 @@ public class CheckBoxTreeCellRenderer extends DefaultTreeCellRenderer implements public static final Color ENABLED_BK_COLOR = new Color(255, 150, 150); + protected EventListenerList listenerList = new EventListenerList(); + Predicate checkedPredicate; Predicate visiblePredicate; @@ -81,16 +83,16 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean if (visiblePredicate == null || visiblePredicate.test(value)) { JCheckBox checkbox = new JCheckBox(); checkbox.setSelected(checkedPredicate.test(value)); - checkbox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - ((IFilterer) value).clearFilter(); - App.get().filtersPanel.updateUI(); - App.get().getAppListener().updateFileListing(); - } - }); + for(ActionListener al: listenerList.getListeners(ActionListener.class)) { + checkbox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + e.setSource(value); + al.actionPerformed(e); + } + }); + } JPanel ckPanel = new JPanel(new BorderLayout()); - ckPanel.setBackground(checkbox.isSelected() ? ENABLED_BK_COLOR : Color.white); ckPanel.add(checkbox, BorderLayout.WEST); ckPanel.add(label, BorderLayout.CENTER); return ckPanel; @@ -139,4 +141,8 @@ public void removeCellEditorListener(CellEditorListener l) { public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { return getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, true); } + + public void addActionListener(ActionListener actionListener) { + listenerList.add(ActionListener.class, actionListener); + } } diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java new file mode 100644 index 0000000000..7ec1a1910d --- /dev/null +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java @@ -0,0 +1,5 @@ +package iped.viewers.api; + +public interface IFilterManager { + +} diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java index 58a978444a..1fadb885f0 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java @@ -23,5 +23,4 @@ default public String getFilterName() { return this.getClass().getName(); } } - } From aca03c167721ad9754fbb4a57f03cb510b25c5ff Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 22 Apr 2024 09:24:22 -0400 Subject: [PATCH 17/57] '#39 Corrects AppListener to only use text from SearchFilterer (it was being added twice). Implement getQuery in SearchFilterer. --- iped-app/src/main/java/iped/app/ui/App.java | 6 ++++++ iped-app/src/main/java/iped/app/ui/AppListener.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index b4bf1d2ac2..709cf63b6e 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1985,6 +1985,12 @@ public boolean hasFiltersApplied() { @Override public Query getQuery() { + String searchText = App.get().queryComboBox.getSelectedItem().toString(); + try { + return new QueryBuilder(appCase).getQuery(searchText); + } catch (Exception e) { + e.printStackTrace(); + } return null; } diff --git a/iped-app/src/main/java/iped/app/ui/AppListener.java b/iped-app/src/main/java/iped/app/ui/AppListener.java index 1e264dde09..8e9eb084f4 100644 --- a/iped-app/src/main/java/iped/app/ui/AppListener.java +++ b/iped-app/src/main/java/iped/app/ui/AppListener.java @@ -87,7 +87,7 @@ public Future updateFileListing(Query query) { try { UICaseSearcherFilter task; if (query == null) - task = new UICaseSearcherFilter(searchText); + task = new UICaseSearcherFilter(""); else task = new UICaseSearcherFilter(query); From 3fddcb61006872a0587f09629e83d6f54fa8bdc0 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 22 Apr 2024 09:26:36 -0400 Subject: [PATCH 18/57] '#39 use hasFilters instead of hasFiltersApplied to execute filter de/activation through checkbox --- iped-app/src/main/java/iped/app/ui/FiltersPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 08260caad2..476747a2d1 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -127,7 +127,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean @Override public void actionPerformed(ActionEvent e) { IFilterer filterer = (IFilterer) e.getSource(); - if (filterer.hasFiltersApplied()) { + if (filterer.hasFilters()) { filterManager.setFilterEnabled(filterer, !filterManager.isFiltererEnabled(filterer)); App.get().filtersPanel.updateUI(); App.get().getAppListener().updateFileListing(); From 7bf55741f19c009b5d1497d29fadd124879f5f03 Mon Sep 17 00:00:00 2001 From: Luis Nassif Date: Mon, 29 Apr 2024 20:50:17 -0300 Subject: [PATCH 19/57] '#39: removes unneeded interface --- iped-app/src/main/java/iped/app/ui/FilterManager.java | 3 +-- .../src/main/java/iped/viewers/api/IFilterManager.java | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java diff --git a/iped-app/src/main/java/iped/app/ui/FilterManager.java b/iped-app/src/main/java/iped/app/ui/FilterManager.java index b238f26884..231f88f4c0 100644 --- a/iped-app/src/main/java/iped/app/ui/FilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/FilterManager.java @@ -43,13 +43,12 @@ import iped.exception.QueryNodeException; import iped.utils.UTF8Properties; import iped.viewers.api.IFilter; -import iped.viewers.api.IFilterManager; import iped.viewers.api.IFilterer; import iped.viewers.api.IQueryFilterer; import iped.viewers.api.IResultSetFilter; import iped.viewers.api.IResultSetFilterer; -public class FilterManager implements ActionListener, ListSelectionListener, IFilterManager { +public class FilterManager implements ActionListener, ListSelectionListener { HashMap cachedFilterBitsets = new HashMap(); boolean useCachedBitmaps = false; diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java deleted file mode 100644 index 7ec1a1910d..0000000000 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterManager.java +++ /dev/null @@ -1,5 +0,0 @@ -package iped.viewers.api; - -public interface IFilterManager { - -} From 93418adc0e6183c558ae698f1dd7b8f05b069276 Mon Sep 17 00:00:00 2001 From: Luis Nassif Date: Mon, 29 Apr 2024 20:58:35 -0300 Subject: [PATCH 20/57] '#39: code formatting --- .../src/main/java/iped/app/ui/controls/CSelButton.java | 2 +- .../iped/app/ui/controls/CheckBoxTreeCellRenderer.java | 2 +- .../src/main/java/iped/app/ui/controls/HoverButton.java | 9 ++++----- .../java/iped/app/ui/filterdecisiontree/OperandNode.java | 2 +- .../iped/app/ui/filterdecisiontree/OperandPopupMenu.java | 5 ++--- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/controls/CSelButton.java b/iped-app/src/main/java/iped/app/ui/controls/CSelButton.java index 0a81448c74..bcd897e7bf 100644 --- a/iped-app/src/main/java/iped/app/ui/controls/CSelButton.java +++ b/iped-app/src/main/java/iped/app/ui/controls/CSelButton.java @@ -17,7 +17,7 @@ public void setSelected(boolean isSelected) { public boolean isSelected() { return isSelected; } - + public void toggle() { setSelected(!isSelected); } diff --git a/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java b/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java index e6b7506ddf..479fdbc495 100644 --- a/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java +++ b/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java @@ -83,7 +83,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean if (visiblePredicate == null || visiblePredicate.test(value)) { JCheckBox checkbox = new JCheckBox(); checkbox.setSelected(checkedPredicate.test(value)); - for(ActionListener al: listenerList.getListeners(ActionListener.class)) { + for (ActionListener al : listenerList.getListeners(ActionListener.class)) { checkbox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { diff --git a/iped-app/src/main/java/iped/app/ui/controls/HoverButton.java b/iped-app/src/main/java/iped/app/ui/controls/HoverButton.java index f59201e381..6ca6c350d4 100644 --- a/iped-app/src/main/java/iped/app/ui/controls/HoverButton.java +++ b/iped-app/src/main/java/iped/app/ui/controls/HoverButton.java @@ -12,11 +12,10 @@ import iped.utils.UiUtil; /** - * A flat button with no background or border. - * Border and background are only painted when the mouse is over it, - * and with a brighter color when it is pressed. - * It is "theme aware", so colors will change if a new theme is activated. - * Currently it only displays icons, but it could handle text. + * A flat button with no background or border. Border and background are only + * painted when the mouse is over it, and with a brighter color when it is + * pressed. It is "theme aware", so colors will change if a new theme is + * activated. Currently it only displays icons, but it could handle text. */ public class HoverButton extends JButton { private static final long serialVersionUID = 7827182813873015956L; diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java index 3c83f17a99..a3e1225df7 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandNode.java @@ -38,7 +38,7 @@ public void addOperand(Operand op) { public void addFilter(FilterNode filterNode) { Set nodes = model.getFiltersToNodeMap().get(filterNode.getFilter()); - if(nodes == null) { + if (nodes == null) { nodes = new HashSet(); model.getFiltersToNodeMap().put(filterNode.getFilter(), nodes); } diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java index fa66f0cf8a..66d4c557c1 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/OperandPopupMenu.java @@ -96,10 +96,9 @@ public void actionPerformed(ActionEvent e) { } } if (e.getSource() == removeMenuitem) { - ((DecisionNode) op).getParent().remove(op); + ((DecisionNode) op).getParent().remove(op); if (op instanceof FilterNode) { - if (!((CombinedFilterTreeModel) filtersTree.getModel()) - .hasFilter((IFilter) ((FilterNode) op).getFilter())) { + if (!((CombinedFilterTreeModel) filtersTree.getModel()).hasFilter((IFilter) ((FilterNode) op).getFilter())) { logicFilterer.removePreCachedFilter((IFilter) ((FilterNode) op).getFilter()); } } From b7e9fe7d7d2f4eb5882b1227538d82aa20fe28a6 Mon Sep 17 00:00:00 2001 From: Luis Nassif Date: Mon, 29 Apr 2024 21:08:36 -0300 Subject: [PATCH 21/57] '#39: minor change in tooltip message --- .../resources/localization/iped-desktop-messages.properties | 2 +- .../localization/iped-desktop-messages_de_DE.properties | 2 +- .../localization/iped-desktop-messages_es_AR.properties | 2 +- .../localization/iped-desktop-messages_it_IT.properties | 2 +- .../localization/iped-desktop-messages_pt_BR.properties | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iped-app/resources/localization/iped-desktop-messages.properties b/iped-app/resources/localization/iped-desktop-messages.properties index d78f671c62..7b3318fc3c 100644 --- a/iped-app/resources/localization/iped-desktop-messages.properties +++ b/iped-app/resources/localization/iped-desktop-messages.properties @@ -414,7 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter iped.app.ui.TreeListener.filtererName=Evidence Tree Filter iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter -iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them. +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters into node tree to combine them. FilterValue.Duplicates=Duplicate Filter Result FilterValue.SimilarDocument=Similar Documents FilterValue.SimilarFace=Similar Faces: diff --git a/iped-app/resources/localization/iped-desktop-messages_de_DE.properties b/iped-app/resources/localization/iped-desktop-messages_de_DE.properties index 22cee68d2b..f6f295d750 100644 --- a/iped-app/resources/localization/iped-desktop-messages_de_DE.properties +++ b/iped-app/resources/localization/iped-desktop-messages_de_DE.properties @@ -414,7 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter (TBT) iped.app.ui.TreeListener.filtererName=Evidence Tree Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter (TBT) -iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them.(TBT) +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters into node tree to combine them.(TBT) FilterValue.Duplicates=Duplicate Filter Result (TBT) FilterValue.SimilarDocument=Similar Documents (TBT) FilterValue.SimilarFace=Similar Faces: (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_es_AR.properties b/iped-app/resources/localization/iped-desktop-messages_es_AR.properties index d362ffbdf0..89983c8a8e 100644 --- a/iped-app/resources/localization/iped-desktop-messages_es_AR.properties +++ b/iped-app/resources/localization/iped-desktop-messages_es_AR.properties @@ -414,7 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter (TBT) iped.app.ui.TreeListener.filtererName=Evidence Tree Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter (TBT) -iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them.(TBT) +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters into node tree to combine them.(TBT) FilterValue.Duplicates=Duplicate Filter Result (TBT) FilterValue.SimilarDocument=Similar Documents (TBT) FilterValue.SimilarFace=Similar Faces: (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_it_IT.properties b/iped-app/resources/localization/iped-desktop-messages_it_IT.properties index 1333e85625..2985056d5a 100644 --- a/iped-app/resources/localization/iped-desktop-messages_it_IT.properties +++ b/iped-app/resources/localization/iped-desktop-messages_it_IT.properties @@ -414,7 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Timeline Filter (TBT) iped.app.ui.TreeListener.filtererName=Evidence Tree Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Combined Filter (TBT) iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Apply Combined Filter (TBT) -iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters in tree nodes to combine them.(TBT) +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Drag and drop filters into node tree to combine them.(TBT) FilterValue.Duplicates=Duplicate Filter Result (TBT) FilterValue.SimilarDocument=Similar Documents (TBT) FilterValue.SimilarFace=Similar Faces: (TBT) diff --git a/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties b/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties index 9fd9d6d432..220a67e88f 100644 --- a/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties +++ b/iped-app/resources/localization/iped-desktop-messages_pt_BR.properties @@ -414,7 +414,7 @@ iped.app.ui.TimelineListener.filtererName=Filtro de Visão em Timeline iped.app.ui.TreeListener.filtererName=Filtro da Árvore de Evidências iped.app.ui.filterdecisiontree.CombinedFilterer.filtererName=Filtro Combinado iped.app.ui.filterdecisiontree.CombinedFilterer.tooltip=Aplicar Filtro Combinado -iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Arreste e solte filtros nos nós da árvore para combiná-los. +iped.app.ui.filterdecisiontree.CombinedFilterer.dragAndDropTooltip=Arreste e solte filtros na árvore de nós para combiná-los. FilterValue.Duplicates=Resultado do Filtro de Duplicados FilterValue.SimilarDocument=Documentos Similares FilterValue.SimilarFace=Faces Similares: From fe3e81539209a9e35d0f81f788276e6421dead21 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 2 May 2024 10:59:21 -0400 Subject: [PATCH 22/57] '#2163 Corrects search filterer to not consider the standard tip as filter. --- iped-app/src/main/java/iped/app/ui/App.java | 44 ++++++++++++--------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index 709cf63b6e..ff608cdc27 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1941,24 +1941,26 @@ class SearchFilterer implements IQueryFilterer { @Override public List getDefinedFilters() { ArrayList result = new ArrayList(); - String filterText = (String) queryComboBox.getSelectedItem(); - Query query; - try { - query = new QueryBuilder(appCase).getQuery(filterText); - result.add(new IQueryFilter() { - String title = filterText; + String filterText = queryComboBox.getSelectedItem().toString(); + if (!SEARCH_TOOL_TIP.equals(filterText)) { + Query query; + try { + query = new QueryBuilder(appCase).getQuery(filterText); + result.add(new IQueryFilter() { + String title = filterText; - @Override - public Query getQuery() { - return query; - } + @Override + public Query getQuery() { + return query; + } - public String toString() { - return title; - } - }); - } catch (ParseException | QueryNodeException e) { - e.printStackTrace(); + public String toString() { + return title; + } + }); + } catch (ParseException | QueryNodeException e) { + e.printStackTrace(); + } } return result; } @@ -1966,7 +1968,7 @@ public String toString() { @Override public boolean hasFilters() { if (App.get().queryComboBox.getSelectedItem() != null) { - String searchText = App.get().queryComboBox.getSelectedItem().toString(); + String searchText = queryComboBox.getSelectedItem().toString(); if (searchText.equals(BookmarksController.HISTORY_DIV) || searchText.equals(App.SEARCH_TOOL_TIP)) { return false; } @@ -1985,9 +1987,13 @@ public boolean hasFiltersApplied() { @Override public Query getQuery() { - String searchText = App.get().queryComboBox.getSelectedItem().toString(); + String searchText = queryComboBox.getSelectedItem().toString(); try { - return new QueryBuilder(appCase).getQuery(searchText); + if (!SEARCH_TOOL_TIP.equals(searchText)) { + return new QueryBuilder(appCase).getQuery(searchText); + } else { + return null; + } } catch (Exception e) { e.printStackTrace(); } From 20c2073904c2aa6c38b1ff55a881e8b7a39e4665 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Thu, 2 May 2024 11:44:04 -0400 Subject: [PATCH 23/57] '#2163 Adds a menu entry to the table header menu to represent the filter defined via FieldValuePopup, so it can be also cleared from there. --- .../iped/app/ui/TableHeaderFilterManager.java | 14 +++++++++++ .../table/MetadataValueSearchList.java | 23 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java b/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java index 9b949d0c47..e75780e2aa 100644 --- a/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java @@ -36,6 +36,8 @@ public class TableHeaderFilterManager implements IResultSetFilterer, IQueryFilte private HashMap> selectedValues = new HashMap>(); private HashMap panels = new HashMap(); private HashMap definedFilters = new HashMap(); + + // store the filters defined by the FieldValuePopupMenu private HashMap otherFilters = new HashMap(); static public TableHeaderFilterManager get() { @@ -124,6 +126,8 @@ public void addFilter(String field, Set selected) { field = escape(field); selectedValues.put(field, selected); definedFilters.put(field, new ValueCountQueryFilter(field, selected)); + + // clear any other filter defined otherFilters.remove(field); App.get().getFilterManager().notifyFilterChange(); } @@ -133,7 +137,10 @@ public void addEqualsFilter(String field, String value) { field = escape(field); definedFilters.put(field, filter); selectedValues.remove(field); + + // clear any other filter defined otherFilters.remove(field); + otherFilters.put(field, value); App.get().getFilterManager().notifyFilterChange(); } @@ -142,7 +149,10 @@ public void addStartsWithFilter(String field, String value) { field = escape(field); definedFilters.put(field, filter); selectedValues.remove(field); + + // clear any other filter defined otherFilters.remove(field); + otherFilters.put(field, value); App.get().getFilterManager().notifyFilterChange(); } @@ -281,4 +291,8 @@ public void clearFilter() { MetadataValueSearchList.clearSelectedValues(); App.get().getFilterManager().notifyFilterChange(); } + + public HashMap getOtherFilters() { + return otherFilters; + } } diff --git a/iped-app/src/main/java/iped/app/ui/controls/table/MetadataValueSearchList.java b/iped-app/src/main/java/iped/app/ui/controls/table/MetadataValueSearchList.java index f938ac540a..91bbe3eb94 100644 --- a/iped-app/src/main/java/iped/app/ui/controls/table/MetadataValueSearchList.java +++ b/iped-app/src/main/java/iped/app/ui/controls/table/MetadataValueSearchList.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.HashSet; +import java.util.Map.Entry; import java.util.Set; import javax.swing.JButton; @@ -53,7 +54,7 @@ public MetadataValueSearchList(String field) { } lastFilteredValuesPerField.put(field, selected); - metadataSearch = TableHeaderFilterManager.get().getMetadataSearch(field); + metadataSearch = fm.getMetadataSearch(field); Dimension minDim = new Dimension(150, 18); JMenuItem emptyMenu = new JCheckBoxMenuItem(FieldValuePopupMenu.EMPTY_STR); @@ -92,6 +93,26 @@ public void actionPerformed(ActionEvent e) { } }); menu.add(nonEmptyMenu); + + for (Entry otherFilter : fm.getOtherFilters().entrySet()) { + JMenuItem otherFiltermenu = new JCheckBoxMenuItem(otherFilter.getValue()); + otherFiltermenu.setMinimumSize(minDim); + otherFiltermenu.setPreferredSize(minDim); + otherFiltermenu.setSelected(true); + otherFiltermenu.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (!otherFiltermenu.isSelected()) { + fm.removeFilter(otherFilter.getKey()); + } + menu.setVisible(false); + App.get().getAppListener().updateFileListing(); + App.get().setDockablesColors(); + } + }); + menu.add(otherFiltermenu); + } + menu.add(new JSeparator()); menu.add(this); From fa8b377b224ec780cf9b69a43fa8199668b6c625 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 3 May 2024 07:18:10 -0400 Subject: [PATCH 24/57] '#2163 Implements enabling/disabling filterer via filters panel for timeline and duplicate filterers. --- .../app/timelinegraph/IpedChartPanel.java | 36 ++++++++++++---- .../popups/ChartPanelPopupMenu.java | 6 +-- .../TimelineFilterSelectionPopupMenu.java | 3 +- iped-app/src/main/java/iped/app/ui/App.java | 27 ++++++++++-- .../main/java/iped/app/ui/AppListener.java | 10 +++-- .../main/java/iped/app/ui/FilterManager.java | 16 +++++-- .../viewers/api/ActionListenerControl.java | 42 +++++++++++++++++++ .../main/java/iped/viewers/api/IFilterer.java | 7 +++- 8 files changed, 120 insertions(+), 27 deletions(-) create mode 100644 iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/ActionListenerControl.java diff --git a/iped-app/src/main/java/iped/app/timelinegraph/IpedChartPanel.java b/iped-app/src/main/java/iped/app/timelinegraph/IpedChartPanel.java index b2be800512..da5f76229b 100644 --- a/iped-app/src/main/java/iped/app/timelinegraph/IpedChartPanel.java +++ b/iped-app/src/main/java/iped/app/timelinegraph/IpedChartPanel.java @@ -69,6 +69,7 @@ import iped.jfextensions.chart.ChartPanel; import iped.jfextensions.model.Minute; import iped.utils.IconUtil; +import iped.viewers.api.IFilterer; public class IpedChartPanel extends ChartPanel implements KeyListener { private Rectangle2D filterIntervalRectangle; // represents the filter selection rectangle while drawing/defining a interval @@ -83,7 +84,7 @@ public class IpedChartPanel extends ChartPanel implements KeyListener { HashMap, ChartTimePeriodConstraint> timePeriodConstraints = new HashMap, ChartTimePeriodConstraint>(); - JButton apllyFilters; + JButton applyFilters; private int filterMask = InputEvent.SHIFT_DOWN_MASK; private int panMask = InputEvent.CTRL_DOWN_MASK; @@ -157,18 +158,32 @@ public IpedChartPanel(IpedChart chart, IpedChartsPanel ipedChartsPanel) { IpedChartPanel self = this; + ipedChartsPanel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + App.get().setDockablesColors(); + if (e.getID() == IFilterer.ENABLE_FILTER_EVENT) { + ipedChartsPanel.setApplyFilters(true); + } else { + ipedChartsPanel.setApplyFilters(false); + } + App.get().filtersPanel.updateUI(); + } + }); + this.setLayout(new FlowLayout(FlowLayout.LEFT)); ImageIcon icon = new ImageIcon(IconUtil.class.getResource(resPath + "down.png")); Image img = icon.getImage(); - apllyFilters = new JButton(new ImageIcon(img.getScaledInstance(12, 12, java.awt.Image.SCALE_SMOOTH))); - apllyFilters.setMaximumSize(new Dimension(16, 16)); - apllyFilters.addActionListener(new ActionListener() { + applyFilters = new JButton(new ImageIcon(img.getScaledInstance(12, 12, java.awt.Image.SCALE_SMOOTH))); + applyFilters.setMaximumSize(new Dimension(16, 16)); + applyFilters.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - chartPanelPopupMenu.show(apllyFilters, apllyFilters.getX() - 2, apllyFilters.getY() + apllyFilters.getHeight() - 8); + chartPanelPopupMenu.show(applyFilters, applyFilters.getX() - 2, + applyFilters.getY() + applyFilters.getHeight() - 8); } }); - this.add(apllyFilters); + this.add(applyFilters); this.addChartMouseListener(new ChartMouseListener() { @Override @@ -855,7 +870,7 @@ public void removeAllFilters(boolean updateResult) { } App app = (App) ipedChartsPanel.getGUIProvider(); - app.setDockablesColors(); + this.repaint(); } @@ -918,7 +933,6 @@ public void filterSelection() { if (!isClearing) { app.getAppListener().updateFileListing(); } - app.setDockablesColors(); } public HashSet getExcludedEvents() { @@ -1030,4 +1044,10 @@ public void updateUI() { } } } + + public void applyFilters(boolean selected) { + App app = (App) this.getIpedChartsPanel().getGUIProvider(); + app.getFilterManager().setFilterEnabled(this.getIpedChartsPanel(), selected); + this.filterSelection(); + } } diff --git a/iped-app/src/main/java/iped/app/timelinegraph/popups/ChartPanelPopupMenu.java b/iped-app/src/main/java/iped/app/timelinegraph/popups/ChartPanelPopupMenu.java index a903b76c9e..d8072b6a20 100644 --- a/iped-app/src/main/java/iped/app/timelinegraph/popups/ChartPanelPopupMenu.java +++ b/iped-app/src/main/java/iped/app/timelinegraph/popups/ChartPanelPopupMenu.java @@ -10,7 +10,6 @@ import iped.app.timelinegraph.IpedChartPanel; import iped.app.timelinegraph.dialog.IntervalDefinitionDialog; -import iped.app.ui.App; import iped.app.ui.Messages; public class ChartPanelPopupMenu extends JPopupMenu implements ActionListener { @@ -63,10 +62,7 @@ public void actionPerformed(ActionEvent e) { if (e.getSource() == applyFiltersMenu) { if (!ipedChartPanel.hasNoFilter()) { - ipedChartPanel.getIpedChartsPanel().setApplyFilters(applyFiltersMenu.isSelected()); - App app = (App) ipedChartPanel.getIpedChartsPanel().getGUIProvider(); - ipedChartPanel.filterSelection(); - app.setDockablesColors(); + ipedChartPanel.applyFilters(applyFiltersMenu.isSelected()); } } if (e.getSource() == clearAllFiltersMenu) { diff --git a/iped-app/src/main/java/iped/app/timelinegraph/popups/TimelineFilterSelectionPopupMenu.java b/iped-app/src/main/java/iped/app/timelinegraph/popups/TimelineFilterSelectionPopupMenu.java index 178089a219..2d191aa597 100644 --- a/iped-app/src/main/java/iped/app/timelinegraph/popups/TimelineFilterSelectionPopupMenu.java +++ b/iped-app/src/main/java/iped/app/timelinegraph/popups/TimelineFilterSelectionPopupMenu.java @@ -62,8 +62,7 @@ public void actionPerformed(ActionEvent e) { } if (e.getSource() == filterSelection) { - ipedChartPanel.getIpedChartsPanel().setApplyFilters(true); - ipedChartPanel.filterSelection(); + ipedChartPanel.applyFilters(true); } if (e.getSource() == selectItems) { diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index ff608cdc27..d82dc92f24 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -307,7 +307,7 @@ public class App extends JFrame implements WindowListener, IMultiSearchResultPro private SimilarImagesQueryFilterer similarImagesFilterer; - private DuplicatesFilterer duplicatesFilterer; + public DuplicatesFilterer duplicatesFilterer; public FiltersPanel filtersPanel; @@ -515,6 +515,12 @@ public void createGUI() { filterComboBox.addItem(App.FILTRO_TODOS); filterComboBox.setToolTipText(Messages.getString("App.FilterTip")); //$NON-NLS-1$ filterManager = new FilterManager(filterComboBox); + filterManager.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setDockablesColors(); + } + }); similarDocumentFilterer = new SimilarDocumentFilterer(); @@ -784,6 +790,19 @@ protected void changed() { resultsTable.addKeyListener(new ResultTableListener()); duplicatesFilterer = new DuplicatesFilterer(); + duplicatesFilterer.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + if (event.getID() == IFilterer.DISABLE_FILTER_EVENT) { + App.get().filterDuplicates.setForeground(App.get().topPanel.getBackground()); + filterDuplicates.setSelected(false); + } + if (event.getID() == IFilterer.ENABLE_FILTER_EVENT) { + App.get().filterDuplicates.setForeground(App.get().alertColor); + filterDuplicates.setSelected(true); + } + } + }); filterManager.addQueryFilterer(new SearchFilterer()); filterManager.addQueryFilterer(categoryListener); @@ -1264,8 +1283,8 @@ public void setDockablesColors() { for (int i = 0; i < dockingControl.getCDockableCount(); i++) { DefaultSingleCDockable tabDock = (DefaultSingleCDockable) dockingControl.getCDockable(i); Component c = tabDock.getContentPane().getComponent(0); - if (c instanceof IQueryFilterer) { - setTabColor(tabDock, !((IQueryFilterer) c).hasFiltersApplied()); + if (c instanceof IFilterer) { + setTabColor(tabDock, !filterManager.isFiltererEnabled(((IFilterer) c))); } } @@ -1784,7 +1803,7 @@ public IFilter getFilter() { @Override public boolean hasFilters() { - return filterDuplicates.isSelected(); + return true; } @Override diff --git a/iped-app/src/main/java/iped/app/ui/AppListener.java b/iped-app/src/main/java/iped/app/ui/AppListener.java index c71a19d63a..4a553c0484 100644 --- a/iped-app/src/main/java/iped/app/ui/AppListener.java +++ b/iped-app/src/main/java/iped/app/ui/AppListener.java @@ -141,11 +141,13 @@ public void actionPerformed(ActionEvent evt) { } if (evt.getSource() == App.get().filterDuplicates) { - if (!App.get().filterDuplicates.isSelected()) - App.get().filterDuplicates.setForeground(App.get().topPanel.getBackground()); - else - App.get().filterDuplicates.setForeground(App.get().alertColor); + if (!App.get().filterDuplicates.isSelected()) { + App.get().filterManager.setFilterEnabled(App.get().duplicatesFilterer, false); + } else { + App.get().filterManager.setFilterEnabled(App.get().duplicatesFilterer, true); + } + App.get().filtersPanel.updateUI(); updateFileList = true; } diff --git a/iped-app/src/main/java/iped/app/ui/FilterManager.java b/iped-app/src/main/java/iped/app/ui/FilterManager.java index 231f88f4c0..8f38e02829 100644 --- a/iped-app/src/main/java/iped/app/ui/FilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/FilterManager.java @@ -42,13 +42,15 @@ import iped.exception.ParseException; import iped.exception.QueryNodeException; import iped.utils.UTF8Properties; +import iped.viewers.api.ActionListenerControl; import iped.viewers.api.IFilter; import iped.viewers.api.IFilterer; import iped.viewers.api.IQueryFilterer; import iped.viewers.api.IResultSetFilter; import iped.viewers.api.IResultSetFilterer; -public class FilterManager implements ActionListener, ListSelectionListener { +public class FilterManager implements ActionListener, ListSelectionListener, ActionListenerControl { + HashMap cachedFilterBitsets = new HashMap(); boolean useCachedBitmaps = false; @@ -264,6 +266,7 @@ public void actionPerformed(ActionEvent e) { if (e.getSource() == butDelete && filter != null) { filters.remove(filter); } + populateList(); updateFilter(); try { @@ -292,12 +295,12 @@ public List getResultSetFilterers() { public void addQueryFilterer(IQueryFilterer qf) { queryFilterers.add(qf); - filterers.put(qf, true); + filterers.put(qf, false); } public void addResultSetFilterer(IResultSetFilterer rsf) { resultSetFilterers.add(rsf); - filterers.put(rsf, true); + filterers.put(rsf, false); } public Set getFilterers() { @@ -330,6 +333,13 @@ public MultiSearchResult applyFilter(IResultSetFilter rsFilter, MultiSearchResul public void setFilterEnabled(IFilterer t, boolean selected) { filterers.put(t, selected); + if (selected) { + t.fireActionListener(new ActionEvent(t, IFilterer.ENABLE_FILTER_EVENT, "Enable")); + this.actionPerformed(new ActionEvent(t, IFilterer.ENABLE_FILTER_EVENT, "Enable")); + } else { + t.fireActionListener(new ActionEvent(t, IFilterer.DISABLE_FILTER_EVENT, "Disable")); + this.actionPerformed(new ActionEvent(t, IFilterer.DISABLE_FILTER_EVENT, "Enable")); + } } public MultiSearchResult applyExcludeFilter(RoaringBitmap[] resultBitSet, MultiSearchResult input) { diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/ActionListenerControl.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/ActionListenerControl.java new file mode 100644 index 0000000000..15b7d56fd1 --- /dev/null +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/ActionListenerControl.java @@ -0,0 +1,42 @@ +package iped.viewers.api; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.HashSet; + +public interface ActionListenerControl { + HashMap> listenerLists = new HashMap(); + + public default void addActionListener(ActionListener listener) { + HashSet listenerList = listenerLists.get(this); + if (listenerList == null) { + listenerList = new HashSet<>(); + listenerLists.put(this, listenerList); + } + listenerList.add(listener); + } + + public default void removeActionListener(ActionListener listener) { + HashSet listenerList = listenerLists.get(this); + if (listenerList == null) { + listenerList = new HashSet<>(); + listenerLists.put(this, listenerList); + } + listenerList.remove(listener); + } + + public default HashSet getActionListenerList() { + return listenerLists.get(this); + } + + default void fireActionListener(ActionEvent actionEvent) { + HashSet listenerList = getActionListenerList(); + if (listenerList != null) { + for (ActionListener l : listenerList) { + l.actionPerformed(actionEvent); + } + } + } + +} diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java index 1fadb885f0..ae0a70b264 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java @@ -8,7 +8,10 @@ * @author patrick.pdb * */ -public interface IFilterer extends ClearFilterListener { +public interface IFilterer extends ClearFilterListener, ActionListenerControl { + + public static final int ENABLE_FILTER_EVENT = 0; + public static final int DISABLE_FILTER_EVENT = 1; List getDefinedFilters(); @@ -23,4 +26,6 @@ default public String getFilterName() { return this.getClass().getName(); } } + + } From d49950ee6d0bfc4478b6ebb5ac122c84ebf62e81 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 3 May 2024 10:43:25 -0400 Subject: [PATCH 25/57] '#2163 Implementation of disable/enable filterer through filterer tree panel category, metadata, table header, evidence tree and bookmark; --- iped-app/src/main/java/iped/app/ui/App.java | 16 ++++++++++------ .../src/main/java/iped/app/ui/FilterManager.java | 7 ++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index d82dc92f24..5babca1a98 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1284,16 +1284,20 @@ public void setDockablesColors() { DefaultSingleCDockable tabDock = (DefaultSingleCDockable) dockingControl.getCDockable(i); Component c = tabDock.getContentPane().getComponent(0); if (c instanceof IFilterer) { - setTabColor(tabDock, !filterManager.isFiltererEnabled(((IFilterer) c))); + setTabColor(tabDock, + !filterManager.isFiltererEnabled(((IFilterer) c)) || !((IFilterer) c).hasFilters()); } } - setTabColor(categoriesTabDock, categoriesDefaultColor); - setTabColor(metadataTabDock, metadataDefaultColor); - setTabColor(evidenceTabDock, evidenceDefaultColor); - setTabColor(bookmarksTabDock, bookmarksDefaultColor); + setTabColor(categoriesTabDock, + !filterManager.isFiltererEnabled(categoryListener) || !categoryListener.hasFilters()); + setTabColor(metadataTabDock, !filterManager.isFiltererEnabled(metadataPanel) || !metadataPanel.hasFilters()); + setTabColor(evidenceTabDock, !filterManager.isFiltererEnabled(treeListener) || !treeListener.hasFilters()); + setTabColor(bookmarksTabDock, + !filterManager.isFiltererEnabled(bookmarksListener) || !bookmarksListener.hasFilters()); setTabColor(graphDock, graphDefaultColor); - setTabColor(tableTabDock, tableDefaultColor); + setTabColor(tableTabDock, !filterManager.isFiltererEnabled(TableHeaderFilterManager.get()) + || !TableHeaderFilterManager.get().hasFilters()); } private void setTabColor(DefaultSingleCDockable dock, boolean isDefault) { diff --git a/iped-app/src/main/java/iped/app/ui/FilterManager.java b/iped-app/src/main/java/iped/app/ui/FilterManager.java index 8f38e02829..f1b3851f9a 100644 --- a/iped-app/src/main/java/iped/app/ui/FilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/FilterManager.java @@ -295,12 +295,12 @@ public List getResultSetFilterers() { public void addQueryFilterer(IQueryFilterer qf) { queryFilterers.add(qf); - filterers.put(qf, false); + filterers.put(qf, true); } public void addResultSetFilterer(IResultSetFilterer rsf) { resultSetFilterers.add(rsf); - filterers.put(rsf, false); + filterers.put(rsf, true); } public Set getFilterers() { @@ -338,8 +338,9 @@ public void setFilterEnabled(IFilterer t, boolean selected) { this.actionPerformed(new ActionEvent(t, IFilterer.ENABLE_FILTER_EVENT, "Enable")); } else { t.fireActionListener(new ActionEvent(t, IFilterer.DISABLE_FILTER_EVENT, "Disable")); - this.actionPerformed(new ActionEvent(t, IFilterer.DISABLE_FILTER_EVENT, "Enable")); + this.actionPerformed(new ActionEvent(t, IFilterer.DISABLE_FILTER_EVENT, "Disable")); } + App.get().setDockablesColors(); } public MultiSearchResult applyExcludeFilter(RoaringBitmap[] resultBitSet, MultiSearchResult input) { From a4d498c0b25c0635ffe010f205530db2352006f1 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 3 May 2024 10:46:25 -0400 Subject: [PATCH 26/57] '#2163 Use same rule to color tab backgraund in filterer tree node background coloring. --- iped-app/src/main/java/iped/app/ui/FiltersPanel.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 476747a2d1..b300a8c599 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -117,7 +117,10 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean } if (value instanceof IFilterer) { - result.setBackground((((IFilterer) value).hasFiltersApplied()) ? ENABLED_BK_COLOR : Color.white); + result.setBackground( + (((IFilterer) value).hasFilters() && filterManager.isFiltererEnabled((IFilterer) value)) + ? ENABLED_BK_COLOR + : Color.white); } return result; From 796f257998fb2e175902118744fbde7ef598c045 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Fri, 3 May 2024 10:56:32 -0400 Subject: [PATCH 27/57] '#2163 Updates tab colors when clear filterer filters from popup menu. --- iped-app/src/main/java/iped/app/ui/FiltererMenu.java | 1 + 1 file changed, 1 insertion(+) diff --git a/iped-app/src/main/java/iped/app/ui/FiltererMenu.java b/iped-app/src/main/java/iped/app/ui/FiltererMenu.java index f9227c658d..9dd2ae5fc9 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltererMenu.java +++ b/iped-app/src/main/java/iped/app/ui/FiltererMenu.java @@ -43,6 +43,7 @@ public FiltererMenu() { public void actionPerformed(ActionEvent e) { if (e.getSource() == clearMenuitem) { ((IFilterer) selected).clearFilter(); + App.get().setDockablesColors(); } JTable table; From c277b397a0da5aec854d9eb6480b784d6a59a434 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 7 May 2024 11:19:57 -0400 Subject: [PATCH 28/57] '#2163 Sets initial value for duplicate filter as disable (as it will always have a filter defined). --- iped-app/src/main/java/iped/app/ui/App.java | 2 +- .../src/main/java/iped/app/ui/FilterManager.java | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index 5babca1a98..e43349f7bf 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -812,7 +812,7 @@ public void actionPerformed(ActionEvent event) { filterManager.addQueryFilterer(TableHeaderFilterManager.get()); filterManager.addResultSetFilterer(bookmarksListener); filterManager.addResultSetFilterer(FilterSelectedEdges.getInstance()); - filterManager.addResultSetFilterer(duplicatesFilterer); + filterManager.addResultSetFilterer(duplicatesFilterer, false); filterManager.addResultSetFilterer(similarImagesFilterer); filterManager.addResultSetFilterer(similarFacesSearchFilterer); filterManager.addResultSetFilterer(timelineListener); diff --git a/iped-app/src/main/java/iped/app/ui/FilterManager.java b/iped-app/src/main/java/iped/app/ui/FilterManager.java index f1b3851f9a..9ebf1a204f 100644 --- a/iped-app/src/main/java/iped/app/ui/FilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/FilterManager.java @@ -298,11 +298,6 @@ public void addQueryFilterer(IQueryFilterer qf) { filterers.put(qf, true); } - public void addResultSetFilterer(IResultSetFilterer rsf) { - resultSetFilterers.add(rsf); - filterers.put(rsf, true); - } - public Set getFilterers() { return filterers.keySet(); } @@ -409,5 +404,15 @@ public RoaringBitmap[] getCachedBitmaps(IResultSetFilter rsFilter) { } return cachedFilterBitsets.get(rsFilter); } + + public void addResultSetFilterer(IResultSetFilterer rsf, boolean b) { + resultSetFilterers.add(rsf); + filterers.put(rsf, b); + } + + public void addResultSetFilterer(IResultSetFilterer rsf) { + resultSetFilterers.add(rsf); + filterers.put(rsf, true); + } } From cde98c53aec5af5624a4b7cbd1e657b74601f24a Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 28 May 2024 10:21:03 -0400 Subject: [PATCH 29/57] '#2163 Removes old conflicting code to set category tab color if any filter is defined. --- iped-app/src/main/java/iped/app/ui/App.java | 7 ------- .../src/main/java/iped/app/ui/CategoryTreeListener.java | 5 ++--- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index e43349f7bf..d998e00ae2 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1230,7 +1230,6 @@ private DefaultSingleCDockable createDockable(String id, String title, JComponen return dockable; } - private boolean categoriesDefaultColor = true; private boolean metadataDefaultColor = true; private boolean evidenceDefaultColor = true; private boolean bookmarksDefaultColor = true; @@ -1251,12 +1250,6 @@ public void setGraphDefaultColor(boolean defaultColor) { } } - public void setCategoriesDefaultColor(boolean defaultColor) { - if (categoriesDefaultColor != defaultColor) { - categoriesDefaultColor = defaultColor; - setDockablesColors(); - } - } public void setMetadataDefaultColor(boolean defaultColor) { if (metadataDefaultColor != defaultColor) { diff --git a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java index 31b6063209..c9d085a51a 100644 --- a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java @@ -48,7 +48,6 @@ public void valueChanged(TreeSelectionEvent evt) { root = new TreePath(App.get().categoryTree.getModel().getRoot()); if (System.currentTimeMillis() - collapsed < 100) { - // if(evt.getPath().getLastPathComponent().equals(App.get().categoryTree.getModel().getRoot())) App.get().categoryTree.setSelectionPaths(selection.toArray(new TreePath[0])); return; } @@ -62,13 +61,11 @@ public void valueChanged(TreeSelectionEvent evt) { } if (selection.contains(root) || selection.isEmpty()) { - App.get().setCategoriesDefaultColor(true); categoryList.clear(); query = null; queryStr = null; } else { - App.get().setCategoriesDefaultColor(false); queryStr = ""; Builder builder = new Builder(); @@ -80,6 +77,8 @@ public void valueChanged(TreeSelectionEvent evt) { query = builder.build(); } + App.get().setDockablesColors(); + if (!clearing) App.get().appletListener.updateFileListing(); From 95c75bc5a74282f2c510953566e8f5efaa76791c Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 28 May 2024 10:25:56 -0400 Subject: [PATCH 30/57] '#2163 Implements missing implementation of new hasFiltersApplied method of MetadataPanel filterer. --- iped-app/src/main/java/iped/app/ui/MetadataPanel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java index 1dbd9fd7bf..b6dfd1d692 100644 --- a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java +++ b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java @@ -651,8 +651,7 @@ public boolean hasFilters() { @Override public boolean hasFiltersApplied() { - // TODO Auto-generated method stub - return false; + return isFiltering(); } } From 087ea23b29da487feb34360632b050e2c79f1ef2 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 28 May 2024 10:33:27 -0400 Subject: [PATCH 31/57] '#2163 Implements hasFiltersApplied of FilterSelectedEdges --- iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java b/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java index 63f7aa8ac3..e591894968 100644 --- a/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java +++ b/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java @@ -188,7 +188,7 @@ public boolean hasFilters() { @Override public boolean hasFiltersApplied() { - return false; + return selectedEdges.size() > 0; } @Override From 55429bbb9de2ed3570d7da0022f325d000d7a5b6 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 28 May 2024 10:36:02 -0400 Subject: [PATCH 32/57] '#2163 adds comments on some interface methods definitions to explain their difference. --- .../src/main/java/iped/viewers/api/IFilterer.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java index ae0a70b264..04506841b0 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java @@ -15,8 +15,18 @@ public interface IFilterer extends ClearFilterListener, ActionListenerControl { List getDefinedFilters(); + /** + * Informs if there is at least one filter defined by the filterer + * + * @return + */ public boolean hasFilters(); + /** + * Informs if the defined filters inside the filterer are to be applied (used) + * + * @return + */ public boolean hasFiltersApplied(); default public String getFilterName() { From 70dd932ad386060cfa49a395f903ec549d7e1af5 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 28 May 2024 11:08:17 -0400 Subject: [PATCH 33/57] '#2163 Removes unnecessary and complicated wrapping desing of FiltersPanel with its internal combinedFilterer. Implements hasAppliedFilters of combinedFilterer to reflect on Filters Panel color. --- iped-app/src/main/java/iped/app/ui/App.java | 2 + .../main/java/iped/app/ui/FiltersPanel.java | 39 ++++--------------- .../filterdecisiontree/CombinedFilterer.java | 2 +- .../app/ui/filters/FilterTransferHandler.java | 2 +- 4 files changed, 11 insertions(+), 34 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index d2e666d240..268fa4f6b5 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1281,6 +1281,8 @@ public void setDockablesColors() { } } + setTabColor(filtersTabDock, !filterManager.isFiltererEnabled(filtersPanel.getCombinedFilterer()) + || !filtersPanel.getCombinedFilterer().hasFilters()); setTabColor(categoriesTabDock, !filterManager.isFiltererEnabled(categoryListener) || !categoryListener.hasFilters()); setTabColor(metadataTabDock, !filterManager.isFiltererEnabled(metadataPanel) || !metadataPanel.hasFilters()); diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index b300a8c599..600dd82f15 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -17,7 +17,6 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.net.URL; -import java.util.List; import java.util.function.Predicate; import javax.swing.DropMode; @@ -34,8 +33,6 @@ import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; -import org.apache.lucene.search.Query; - import iped.app.ui.controls.CheckBoxTreeCellRenderer; import iped.app.ui.filterdecisiontree.CombinedFilterer; import iped.app.ui.filterdecisiontree.DecisionNode; @@ -48,9 +45,8 @@ import iped.viewers.api.IFilter; import iped.viewers.api.IFilterer; import iped.viewers.api.IMiniaturizable; -import iped.viewers.api.IQueryFilterer; -public class FiltersPanel extends JPanel implements ClearFilterListener, IQueryFilterer// internal combinedfilterer wrapper to reflect on panel color +public class FiltersPanel extends JPanel implements ClearFilterListener { private JTree filtersTree; private JScrollPane filtersTreePane; @@ -169,6 +165,12 @@ public void mouseMoved(MouseEvent e) { filtersTree.setModel(new FiltersTreeModel(filterManager.getFilterers())); combinedFilterer = new CombinedFilterer(); + combinedFilterer.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + App.get().setDockablesColors(); + } + }); filterManager.addResultSetFilterer(combinedFilterer); filterManager.setFilterEnabled(combinedFilterer, false); @@ -387,31 +389,4 @@ public void clearFilter() { public CombinedFilterer getCombinedFilterer() { return combinedFilterer; } - - @Override - public List getDefinedFilters() { - // does not expose filters as it is not actually registered as result set - // filterer - return null; - } - - @Override - public boolean hasFilters() { - // does not expose filters as it is not actually registered as result set - // filterer - return false; - } - - @Override - public boolean hasFiltersApplied() { - // Wraps combofilterer - return ckStructuredFilterer != null && ckStructuredFilterer.isSelected(); - } - - @Override - public Query getQuery() { - // does not expose filters as it is not actually registered as result set - // filterer - return null; - } } \ No newline at end of file diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java index 8ae02f397f..cd759101da 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java @@ -545,7 +545,7 @@ public boolean hasFilters() { @Override public boolean hasFiltersApplied() { - return false; + return rootNode.getChildren().size() > 0; } public void invertPreCached(IFilter op) { diff --git a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java index ee2aa7c918..c6a90df183 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java +++ b/iped-app/src/main/java/iped/app/ui/filters/FilterTransferHandler.java @@ -145,7 +145,7 @@ protected void exportDone(JComponent source, Transferable data, int action) { combinedFilterer.startSearchResult(App.get().getResults()); - if (filtersPanel.hasFiltersApplied()) { + if (filtersPanel.getCombinedFilterer().hasFiltersApplied()) { App.get().getAppListener().updateFileListing(); } } catch (Exception e) { From 1e535b135f29a9c0689edc22d0c97c1cef00059b Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 28 May 2024 11:42:48 -0400 Subject: [PATCH 34/57] '#2163 Implements clear filter code to sync with clearAllFilters button. --- iped-app/src/main/java/iped/app/ui/App.java | 1 + iped-app/src/main/java/iped/app/ui/FiltersPanel.java | 9 ++++++--- .../app/ui/filterdecisiontree/CombinedFilterer.java | 12 +++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index 268fa4f6b5..71efee05f3 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -826,6 +826,7 @@ public void accept(IFilterer filterer) { }); filtersPanel.install(filterManager); + clearAllFilters.addClearListener(filtersPanel.getCombinedFilterer()); filtersPanel.updateUI(); hitsTable.getSelectionModel().addListSelectionListener(new HitsTableListener(TextViewer.font)); diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 600dd82f15..b4b103c474 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -41,12 +41,11 @@ import iped.app.ui.filterdecisiontree.OperandNode.Operand; import iped.app.ui.filterdecisiontree.OperandPopupMenu; import iped.app.ui.filters.FilterTransferHandler; -import iped.viewers.api.ClearFilterListener; import iped.viewers.api.IFilter; import iped.viewers.api.IFilterer; import iped.viewers.api.IMiniaturizable; -public class FiltersPanel extends JPanel implements ClearFilterListener +public class FiltersPanel extends JPanel { private JTree filtersTree; private JScrollPane filtersTreePane; @@ -165,6 +164,7 @@ public void mouseMoved(MouseEvent e) { filtersTree.setModel(new FiltersTreeModel(filterManager.getFilterers())); combinedFilterer = new CombinedFilterer(); + combinedFilterer.setFiltersPanel(this); combinedFilterer.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -377,7 +377,6 @@ public void updateUI() { } - @Override public void clearFilter() { ckStructuredFilterer.setSelected(false); ckStructuredFilterer.setBackground(ckStructuredFilterer.getParent().getBackground()); @@ -389,4 +388,8 @@ public void clearFilter() { public CombinedFilterer getCombinedFilterer() { return combinedFilterer; } + + public boolean isCombinedFiltererApplied() { + return ckStructuredFilterer.isSelected(); + } } \ No newline at end of file diff --git a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java index cd759101da..7a7e54d5b7 100644 --- a/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java +++ b/iped-app/src/main/java/iped/app/ui/filterdecisiontree/CombinedFilterer.java @@ -18,6 +18,7 @@ import iped.app.ui.App; import iped.app.ui.CaseSearcherFilter; +import iped.app.ui.FiltersPanel; import iped.app.ui.filterdecisiontree.OperandNode.Operand; import iped.data.IItemId; import iped.engine.data.IPEDMultiSource; @@ -48,6 +49,8 @@ public class CombinedFilterer implements IResultSetFilterer, IFilterChangeListen private CombinedBitSet cbs; + private FiltersPanel filtersPanel; + @Override public List getDefinedFilters() { ArrayList result = new ArrayList(); @@ -545,7 +548,7 @@ public boolean hasFilters() { @Override public boolean hasFiltersApplied() { - return rootNode.getChildren().size() > 0; + return rootNode.getChildren().size() > 0 && filtersPanel.isCombinedFiltererApplied(); } public void invertPreCached(IFilter op) { @@ -560,8 +563,7 @@ public void onFilterChange(IMutableFilter filter) { @Override public void clearFilter() { - // TODO Auto-generated method stub - + filtersPanel.clearFilter(); } public void invalidateCache() { @@ -572,4 +574,8 @@ public void setRootNode(OperandNode rootNode) { this.rootNode = rootNode; } + public void setFiltersPanel(FiltersPanel filtersPanel) { + this.filtersPanel = filtersPanel; + } + } From f58d09b819d09c96e22d3fb5abd9ea577917153a Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 28 May 2024 12:23:09 -0400 Subject: [PATCH 35/57] '#2163 Search Filter getQuery returns null if query text is correspondent to empty query, avoiding clearFilterButton to reconize it as a filter and remains visible. --- iped-app/src/main/java/iped/app/ui/App.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index 71efee05f3..d3da39defe 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -2012,7 +2012,8 @@ public boolean hasFiltersApplied() { public Query getQuery() { String searchText = queryComboBox.getSelectedItem().toString(); try { - if (!SEARCH_TOOL_TIP.equals(searchText)) { + if (!SEARCH_TOOL_TIP.equals(searchText) + && !("".equals(searchText) || "*".equals(searchText) || "*:*".equals(searchText))) { return new QueryBuilder(appCase).getQuery(searchText); } else { return null; From 8eef37f6f6b96a6e875454224c6eb0b7d465ec38 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Wed, 29 May 2024 11:15:30 -0400 Subject: [PATCH 36/57] '#2163 Design method for restoration of defined filters of a filter from another source. Implements the restoration for Category filterer CategoryTreeListener. --- .../iped/app/ui/CategoryTreeListener.java | 92 ++++++++++++++----- .../main/java/iped/app/ui/FiltersPanel.java | 16 +++- .../main/java/iped/viewers/api/IFilterer.java | 10 ++ 3 files changed, 91 insertions(+), 27 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java index c9d085a51a..c76b8c533c 100644 --- a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java @@ -5,6 +5,7 @@ import java.util.LinkedHashSet; import java.util.List; +import javax.swing.JTree; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; import javax.swing.event.TreeSelectionEvent; @@ -130,35 +131,78 @@ public void recursiveCategoryQuery(Category cat, StringBuffer buff) { } } + class CategoryFilter implements IQueryFilter { + private Category category; + + public CategoryFilter(Category category) { + this.category = category; + + } + + @Override + public Query getQuery() { + String name = IndexItem.normalize(category.getName(), true); + StringBuffer queryStr = new StringBuffer(); + queryStr.append(" category:\""); + queryStr.append(name); + queryStr.append("\""); + recursiveCategoryQuery(category, queryStr); + + Query query; + try { + query = new QueryBuilder(App.get().appCase).getQuery(queryStr.toString()); + return query; + } catch (ParseException | QueryNodeException e) { + e.printStackTrace(); + } + return null; + } + + public String toString() { + return IndexItem.normalize(category.getName(), true); + } + + public Category getCategory() { + return category; + } + } + + @Override + public void restoreDefineFilters(List filtersToRestore) { + if (filtersToRestore == null) { + return; + } + categoryList.clear(); + selection.clear(); + + for (IFilter filter : filtersToRestore) { + if (filter instanceof CategoryFilter) { + CategoryFilter catFilter = (CategoryFilter) filter; + categoryList.add(catFilter.getCategory()); + select(catFilter.getCategory()); + } + } + } + + private void select(Category category) { + JTree tree = (JTree) App.get().categoryTree; + int rowCount = tree.getRowCount(); + for (int i = 0; i < rowCount; i++) { + TreePath path = tree.getPathForRow(i); + if (path.getLastPathComponent().equals(category)) { + tree.addSelectionRow(i); + selection.add(path); + break; + } + } + } + @Override public List getDefinedFilters() { CategoryTreeListener self = this; List result = new ArrayList(); for (Category category : categoryList) { - result.add(new IQueryFilter() { - @Override - public Query getQuery() { - String name = IndexItem.normalize(category.getName(), true); - StringBuffer queryStr = new StringBuffer(); - queryStr.append(" category:\""); - queryStr.append(name); - queryStr.append("\""); - recursiveCategoryQuery(category, queryStr); - - Query query; - try { - query = new QueryBuilder(App.get().appCase).getQuery(queryStr.toString()); - return query; - } catch (ParseException | QueryNodeException e) { - e.printStackTrace(); - } - return null; - } - - public String toString() { - return IndexItem.normalize(category.getName(), true); - } - }); + result.add(new CategoryFilter(category)); } return result; } diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index b4b103c474..4d3813e9c7 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -17,6 +17,8 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.net.URL; +import java.util.HashMap; +import java.util.List; import java.util.function.Predicate; import javax.swing.DropMode; @@ -65,6 +67,8 @@ public class FiltersPanel extends JPanel private volatile TreePath lastClickedPath; + HashMap> lastFilters = new HashMap>(); + public FiltersPanel() { invertUrl = this.getClass().getResource("negative.png"); invertIcon = new ImageIcon(invertUrl); @@ -121,16 +125,22 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean return result; } }; + treeCellRenderer.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { IFilterer filterer = (IFilterer) e.getSource(); if (filterer.hasFilters()) { - filterManager.setFilterEnabled(filterer, !filterManager.isFiltererEnabled(filterer)); - App.get().filtersPanel.updateUI(); + lastFilters.put(filterer, filterer.getDefinedFilters()); + filterer.clearFilter(); App.get().getAppListener().updateFileListing(); } else { - App.get().filtersPanel.updateUI(); + List clastFilters = lastFilters.get(filterer); + if (clastFilters != null) { + filterer.restoreDefineFilters(clastFilters); + App.get().getAppListener().updateFileListing(); + App.get().filtersPanel.updateUI(); + } } } }); diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java index 04506841b0..cd3094f42b 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java @@ -29,6 +29,16 @@ public interface IFilterer extends ClearFilterListener, ActionListenerControl { */ public boolean hasFiltersApplied(); + /** + * Restores internal state elements to represent the defined filters passed as + * parameter + * + * @return + */ + default public void restoreDefineFilters(List filtersToRestore) { + return; + } + default public String getFilterName() { try { return Messages.get(this.getClass().getName().replace("$", ".") + ".filtererName"); From fbc18048109e335d833c3028aa8d33961f93c047 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Wed, 29 May 2024 13:36:05 -0400 Subject: [PATCH 37/57] '#2163 Implements restoreDefinedFilters for filterers declared in App class and corrects this method name. --- iped-app/src/main/java/iped/app/ui/App.java | 98 ++++++++++++++++--- .../main/java/iped/app/ui/AppListener.java | 8 +- .../iped/app/ui/CategoryTreeListener.java | 2 +- .../main/java/iped/app/ui/FiltersPanel.java | 2 +- .../main/java/iped/viewers/api/IFilterer.java | 4 +- 5 files changed, 90 insertions(+), 24 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index d3da39defe..a76f33d8da 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -811,7 +811,7 @@ public void actionPerformed(ActionEvent event) { filterManager.addQueryFilterer(TableHeaderFilterManager.get()); filterManager.addResultSetFilterer(bookmarksListener); filterManager.addResultSetFilterer(FilterSelectedEdges.getInstance()); - filterManager.addResultSetFilterer(duplicatesFilterer, false); + filterManager.addResultSetFilterer(duplicatesFilterer); filterManager.addResultSetFilterer(similarImagesFilterer); filterManager.addResultSetFilterer(similarFacesSearchFilterer); filterManager.addResultSetFilterer(timelineListener); @@ -1768,6 +1768,16 @@ public void setItem(IItemId itemId, IItem similarImagesFilterer) { item = similarImagesFilterer; imageFilter = new SimilarImageFilter(itemId, item); } + + @Override + public void restoreDefinedFilters(List filtersToRestore) { + for (IFilter filter : filtersToRestore) { + if (filter instanceof SimilarImageFilter) { + imageFilter = (SimilarImageFilter) filter; + break; + } + } + } }; class DuplicateFilter implements IResultSetFilter, IMutableFilter { @@ -1787,6 +1797,9 @@ public IMultiSearchResult filterResult(IMultiSearchResult src) throws ParseExcep IResultSetFilter duplicateFilter = new DuplicateFilter(); class DuplicatesFilterer implements IResultSetFilterer { + + IResultSetFilter cduplicateFilter = duplicateFilter; + @Override public List getDefinedFilters() { ArrayList result = new ArrayList(); @@ -1807,7 +1820,7 @@ public IFilter getFilter() { @Override public boolean hasFilters() { - return true; + return cduplicateFilter != null; } @Override @@ -1818,9 +1831,18 @@ public boolean hasFiltersApplied() { @Override public void clearFilter() { appletListener.clearAllFilters = true; + cduplicateFilter = null; if (filterDuplicates.isSelected()) filterDuplicates.doClick(); appletListener.clearAllFilters = false; + this.fireActionListener(new ActionEvent(this, IFilterer.DISABLE_FILTER_EVENT, "DESELECTED")); + } + + @Override + public void restoreDefinedFilters(List filtersToRestore) { + cduplicateFilter = duplicateFilter; + filterDuplicates.setSelected(true); + this.fireActionListener(new ActionEvent(this, IFilterer.ENABLE_FILTER_EVENT, "SELECTED")); } } @@ -1958,6 +1980,34 @@ public void clearFilter() { SimilarFacesFilterActions.clear(false); } + @Override + public void restoreDefinedFilters(List filtersToRestore) { + for (IFilter filter : filtersToRestore) { + if (filter instanceof SimilarFacesSearchFilter) { + filter = (SimilarFacesSearchFilter) filter; + break; + } + } + } + + } + + class SearchFilter implements IQueryFilter { + String filterText; + + public SearchFilter(String filterText) { + this.filterText = filterText; + } + + @Override + public Query getQuery() { + return query; + } + + public String toString() { + return filterText; + } + } class SearchFilterer implements IQueryFilterer { @@ -1969,18 +2019,7 @@ public List getDefinedFilters() { Query query; try { query = new QueryBuilder(appCase).getQuery(filterText); - result.add(new IQueryFilter() { - String title = filterText; - - @Override - public Query getQuery() { - return query; - } - - public String toString() { - return title; - } - }); + result.add(new SearchFilter(filterText)); } catch (ParseException | QueryNodeException e) { e.printStackTrace(); } @@ -2031,6 +2070,17 @@ public void clearFilter() { appletListener.clearAllFilters = false; } + @Override + public void restoreDefinedFilters(List filtersToRestore) { + for (IFilter filter : filtersToRestore) { + if (filter instanceof SearchFilter) { + filter = (SearchFilter) filter; + queryComboBox.setSelectedItem(((SearchFilter) filter).filterText); + break; + } + } + } + } public IItem getSimilarImagesQueryRefItem() { @@ -2173,9 +2223,29 @@ public void setPercent(int percent) { this.percent = percent; filter = null; } + + @Override + public void restoreDefinedFilters(List filtersToRestore) { + for (IFilter filter : filtersToRestore) { + if (filter instanceof SimilarDocumentFilter) { + filter = (SimilarDocumentFilter) filter; + break; + } + } + } } public AppListener getAppletListener() { return appletListener; } + + public void selectFilterDuplicates(boolean selected) { + if (selected) { + duplicatesFilterer.cduplicateFilter = duplicateFilter; + duplicatesFilterer.fireActionListener(new ActionEvent(this, IFilterer.ENABLE_FILTER_EVENT, "SELECTED")); + } else { + duplicatesFilterer.cduplicateFilter = null; + duplicatesFilterer.fireActionListener(new ActionEvent(this, IFilterer.DISABLE_FILTER_EVENT, "DESELECTED")); + } + } } diff --git a/iped-app/src/main/java/iped/app/ui/AppListener.java b/iped-app/src/main/java/iped/app/ui/AppListener.java index 4a553c0484..c37b76ab04 100644 --- a/iped-app/src/main/java/iped/app/ui/AppListener.java +++ b/iped-app/src/main/java/iped/app/ui/AppListener.java @@ -141,12 +141,8 @@ public void actionPerformed(ActionEvent evt) { } if (evt.getSource() == App.get().filterDuplicates) { - if (!App.get().filterDuplicates.isSelected()) { - App.get().filterManager.setFilterEnabled(App.get().duplicatesFilterer, false); - } else { - App.get().filterManager.setFilterEnabled(App.get().duplicatesFilterer, true); - } - + App.get().selectFilterDuplicates(App.get().filterDuplicates.isSelected()); + updateFileListing(); App.get().filtersPanel.updateUI(); updateFileList = true; } diff --git a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java index c76b8c533c..ea6236b35a 100644 --- a/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/CategoryTreeListener.java @@ -168,7 +168,7 @@ public Category getCategory() { } @Override - public void restoreDefineFilters(List filtersToRestore) { + public void restoreDefinedFilters(List filtersToRestore) { if (filtersToRestore == null) { return; } diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 4d3813e9c7..43dbbe2f59 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -137,7 +137,7 @@ public void actionPerformed(ActionEvent e) { } else { List clastFilters = lastFilters.get(filterer); if (clastFilters != null) { - filterer.restoreDefineFilters(clastFilters); + filterer.restoreDefinedFilters(clastFilters); App.get().getAppListener().updateFileListing(); App.get().filtersPanel.updateUI(); } diff --git a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java index cd3094f42b..a5a7c60691 100644 --- a/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java +++ b/iped-viewers/iped-viewers-api/src/main/java/iped/viewers/api/IFilterer.java @@ -35,8 +35,8 @@ public interface IFilterer extends ClearFilterListener, ActionListenerControl { * * @return */ - default public void restoreDefineFilters(List filtersToRestore) { - return; + default public void restoreDefinedFilters(List filtersToRestore){ + } default public String getFilterName() { From c2eea3966a935606edede386f4525da7cf0a1c7a Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 3 Jun 2024 13:27:22 -0400 Subject: [PATCH 38/57] '#2163 Implements restore filters of MetadataPanel filterer. --- .../app/metadata/ValueCountQueryFilter.java | 8 + .../main/java/iped/app/ui/MetadataPanel.java | 178 ++++++++++++++++-- 2 files changed, 175 insertions(+), 11 deletions(-) diff --git a/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java b/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java index 8182694b0e..b6513e675f 100644 --- a/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java +++ b/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java @@ -102,4 +102,12 @@ public Query getQuery() { return query; } + public String getFilterField() { + return filterField; + } + + public Set getValues() { + return values; + } + } diff --git a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java index b6dfd1d692..0b4857cbdf 100644 --- a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java +++ b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java @@ -18,6 +18,8 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import javax.swing.Box; @@ -27,6 +29,7 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSlider; +import javax.swing.ListModel; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -99,11 +102,13 @@ public class MetadataPanel extends JPanel implements ActionListener, ListSelecti ValueCount[] array, filteredArray; - boolean updatingProps = false, updatingList = false, clearing = false; + boolean updatingProps = false, updatingList = false, clearing = false, isRestoringFields = false; volatile boolean updatingResult = false; private MetadataSearch ms = new MetadataSearch(); + private FuturePopulateList futurePopulateList; + private static final long serialVersionUID = 1L; public MetadataPanel() { @@ -273,16 +278,78 @@ public void run() { }.start(); } + class FuturePopulateList implements Future { + Boolean listPopulatedEnded = false; + Semaphore sem = new Semaphore(1); + ArrayList actions = new ArrayList(); + + FuturePopulateList() { + try { + sem.acquire(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + sem.release(); + return false; + } + + @Override + public boolean isCancelled() { + return !listPopulatedEnded; + } + + @Override + public boolean isDone() { + sem.release(); + return listPopulatedEnded; + } + + @Override + public Boolean get() throws InterruptedException, ExecutionException { + try { + sem.acquire(); + sem.release(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return listPopulatedEnded; + } + + @Override + public Boolean get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException { + return null; + } + + public void finish() { + listPopulatedEnded = true; + + sem.release(); + + for (Runnable action : actions) { + action.run(); + } + } + + public void addAction(Runnable r) { + actions.add(r); + } + }; + private void populateList() { setWaitVisible(true); - final boolean updateResult = !list.isSelectionEmpty(); + final boolean updateResult = !list.isSelectionEmpty() || isRestoringFields; Future future = null; if (updateResult) { updatingResult = true; future = App.get().appletListener.futureUpdateFileListing(); } Future finalfuture = future; - + ms.setLogScale(scale.getValue() == 1); ms.setNoRanges(scale.getValue() == -1); @@ -310,7 +377,9 @@ public void run() { countValues(); } catch (IOException e) { - e.printStackTrace(); + if (futurePopulateList != null) { + futurePopulateList.cancel(true); + } } finally { setWaitVisible(false); } @@ -322,7 +391,7 @@ public void run() { private void updateList(final ValueCount[] sortedArray) { SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { + public void run() { updatingList = true; List selection = list.getSelectedValuesList(); HashSet selSet = new HashSet(); @@ -337,6 +406,7 @@ public void run() { list.setSelectedIndices(selIdx); } updatingList = false; + futurePopulateList.finish(); // System.out.println("finish"); updateTabColor(); @@ -480,13 +550,13 @@ private String removeIllegalChars(String s) { @Override public void clearFilter() { clearing = true; + groups.setSelectedIndex(-1); list.setListData(new ValueCount[0]); clearing = false; } @Override public void stateChanged(ChangeEvent e) { - if (e.getSource() == sort) { if (!sort.getValueIsAdjusting()) sortAndUpdateList(filteredArray); @@ -612,11 +682,6 @@ public List getDefinedFilters() { if (isFiltering()) { ValueCount sample = selectedValues.iterator().next(); result.add(new ValueCountQueryFilter(field, selectedValues)); - /* - * if(sample instanceof RangeCount) { result.add(new ValueCountQueryFilter(field - * , selectedValues)); }else { result.add(new ValueCountFilter(field , - * selectedValues)); } - */ } return result; } @@ -654,4 +719,95 @@ public boolean hasFiltersApplied() { return isFiltering(); } + @Override + public void restoreDefinedFilters(List filtersToRestore) { + for (IFilter filter : filtersToRestore) { + if (filter instanceof ValueCountQueryFilter) { + ValueCountQueryFilter vcqFilter = (ValueCountQueryFilter) filter; + String field = vcqFilter.getFilterField(); + int i = 0; + fields: for (String[] fieldsInGroup : ColumnsManager.getInstance().fieldGroups) { + for (String fieldInGroup : fieldsInGroup) { + if (fieldInGroup.equals(field)) { + groups.setSelectedIndex(i); + + if (futurePopulateList != null) { + FuturePopulateList oldFuturePopulateList = futurePopulateList; + futurePopulateList = new FuturePopulateList(); + oldFuturePopulateList.cancel(true); + } else { + futurePopulateList = new FuturePopulateList(); + } + + futurePopulateList.addAction(new Runnable() { + @Override + public void run() { + Thread t = new Thread(new Runnable() { + + @Override + public void run() { + try { + if (futurePopulateList.get()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + int[] is = new int[vcqFilter.getValues().size()]; + ListModel dm = list.getModel(); + int j = 0; + for (int k = 0, c = dm.getSize(); k < c + && j < is.length; k++) { + if (vcqFilter.getValues() + .contains(dm.getElementAt(k))) { + is[j] = k; + j++; + } + } + setSelectedIndices(is); + } + }); + } + futurePopulateList = null; + App.get().filtersPanel.updateUI(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + } + } + }); + t.start(); + } + }); + + isRestoringFields = true; + props.setSelectedItem(field); + isRestoringFields = false; + + break fields; + } + } + i++; + } + break; + } + } + + } + + private void setSelectedIndices(int[] is) { + ArrayList temp = new ArrayList(); + for (ListSelectionListener sl : list.getListSelectionListeners()) { + temp.add(sl); + } + for (ListSelectionListener sl : temp) { + list.removeListSelectionListener(sl); + } + list.setSelectedIndices(is); + for (ListSelectionListener sl : temp) { + list.addListSelectionListener(sl); + } + } } From 10dba2d99a8ce392e87b8fa807a4ef01f647bf56 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 3 Jun 2024 14:44:44 -0400 Subject: [PATCH 39/57] '#2163 Implements restoreDefinedFilters for evidence tree filterer. --- .../main/java/iped/app/ui/TreeListener.java | 137 ++++++++++++++++-- .../java/iped/app/ui/filters/QueryFilter.java | 2 +- 2 files changed, 123 insertions(+), 16 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/TreeListener.java b/iped-app/src/main/java/iped/app/ui/TreeListener.java index 338b468a8a..1843d3983f 100644 --- a/iped-app/src/main/java/iped/app/ui/TreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/TreeListener.java @@ -23,6 +23,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -54,6 +55,9 @@ public class TreeListener extends MouseAdapter implements TreeSelectionListener, ActionListener, TreeExpansionListener, IQueryFilterer { private Query treeQuery, recursiveTreeQuery; + PathFilter currentFilter; + private PathFilter currentRecursiveFilter; + boolean rootSelected = false; HashSet selection = new HashSet(); private long collapsedTime = 0; @@ -84,14 +88,21 @@ public void valueChanged(TreeSelectionEvent evt) { } } - definedFilters = null; + definedFilters = new ArrayList(); + if (rootSelected || selection.isEmpty()) { + currentFilter = null; + treeQuery = new TermQuery(new Term(IndexItem.ISROOT, "true")); //$NON-NLS-1$ recursiveTreeQuery = null; } else { String treeQueryStr = ""; //$NON-NLS-1$ BooleanQuery.Builder recursiveQueryBuilder = new BooleanQuery.Builder(); + currentFilter = new PathFilter(); + currentRecursiveFilter = new PathFilter(); + currentRecursiveFilter.setRecursive(true); + for (TreePath path : selection) { Document doc = ((Node) path.getLastPathComponent()).getDoc(); @@ -105,11 +116,25 @@ public void valueChanged(TreeSelectionEvent evt) { subQuery.add(new TermQuery(new Term(IndexItem.PARENTIDs, parentId)), Occur.MUST); subQuery.add(new TermQuery(new Term(IndexItem.EVIDENCE_UUID, sourceUUID)), Occur.MUST); recursiveQueryBuilder.add(subQuery.build(), Occur.SHOULD); + + currentFilter.addParentId(sourceUUID, parentId); + currentRecursiveFilter.addParentId(sourceUUID, parentId); } recursiveTreeQuery = recursiveQueryBuilder.build(); + currentRecursiveFilter.setQuery(recursiveTreeQuery); + + if (selection.size() > 0) { + if (App.get().recursiveTreeList.isSelected()) { + definedFilters.add(currentRecursiveFilter); + } else { + definedFilters.add(currentFilter); + } + } try { treeQuery = new QueryBuilder(App.get().appCase).getQuery(treeQueryStr); + currentFilter.setQuery(recursiveTreeQuery); + } catch (ParseException | QueryNodeException e) { e.printStackTrace(); } @@ -205,29 +230,65 @@ private void showTreeMenu(MouseEvent e) { @Override public void clearFilter() { clearing = true; - App.get().tree.clearSelection(); + + TreeSelectionListener[] listeners = App.get().tree.getTreeSelectionListeners(); + for (TreeSelectionListener lis : listeners) { + App.get().tree.removeTreeSelectionListener(lis); + } + + try { + definedFilters = null; + App.get().tree.clearSelection(); + } finally { + for (TreeSelectionListener lis : listeners) { + App.get().tree.addTreeSelectionListener(lis); + } + } clearing = false; } - @Override - public List getDefinedFilters() { - TreeListener self = this; - if (definedFilters == null) { - definedFilters = new ArrayList(); - if (selection.size() >= 1) { - if (App.get().recursiveTreeList.isSelected()) { - definedFilters.add(new QueryFilter(self.recursiveTreeQuery)); - } else { - definedFilters.add(new QueryFilter(self.treeQuery)); - } + class PathFilter extends QueryFilter { + boolean recursive = false; + HashMap> evidenceParentIdMap = new HashMap>(); + + public void setRecursive(boolean recursive) { + this.recursive = recursive; + } + + public void setQuery(Query q) { + this.query = q; + } + + public PathFilter(Query query) { + super(query); + } + + public PathFilter() { + super(null); + } + + public boolean isRecursive() { + return recursive; + } + + public void addParentId(String evidenceUUID, String parentId) { + List parentIds = evidenceParentIdMap.get(evidenceUUID); + if (parentIds == null) { + parentIds = new ArrayList(); + evidenceParentIdMap.put(evidenceUUID, parentIds); } + parentIds.add(parentId); } + } + + @Override + public List getDefinedFilters() { return definedFilters; } @Override public boolean hasFiltersApplied() { - return recursiveTreeQuery != null; + return definedFilters != null && ((PathFilter) definedFilters.get(0)).evidenceParentIdMap.size() > 0; } @Override @@ -244,7 +305,53 @@ public String toString() { @Override public boolean hasFilters() { - return recursiveTreeQuery != null; + return definedFilters != null && ((PathFilter) definedFilters.get(0)).evidenceParentIdMap.size() > 0; + } + + @Override + public void restoreDefinedFilters(List filtersToRestore) { + TreeSelectionListener[] listeners = App.get().tree.getTreeSelectionListeners(); + for (TreeSelectionListener lis : listeners) { + App.get().tree.removeTreeSelectionListener(lis); + } + + try { + definedFilters = new ArrayList(); + App.get().tree.clearSelection(); + for (IFilter filter : filtersToRestore) { + if (filter instanceof PathFilter) { + PathFilter pathFilter = (PathFilter) filter; + App.get().recursiveTreeList.setSelected(pathFilter.isRecursive()); + + for (int i = 0; i < App.get().tree.getRowCount(); i++) { + TreePath tp = App.get().tree.getPathForRow(i); + Node node = (Node) tp.getLastPathComponent(); + if (checkSelection(node, pathFilter)) { + App.get().tree.addSelectionPath(tp); + } + + } + + definedFilters.add(pathFilter); + + } + } + } finally { + for (TreeSelectionListener lis : listeners) { + App.get().tree.addTreeSelectionListener(lis); + } + } + } + + private boolean checkSelection(Node node, PathFilter pathFilter) { + Document doc = node.getDoc(); + String evidenceUUID = doc.get(IndexItem.EVIDENCE_UUID); + List parentIds = pathFilter.evidenceParentIdMap.get(evidenceUUID); + if (parentIds != null) { + String parentId = doc.get(IndexItem.ID); + return parentIds.contains(parentId); + } + return false; } } diff --git a/iped-app/src/main/java/iped/app/ui/filters/QueryFilter.java b/iped-app/src/main/java/iped/app/ui/filters/QueryFilter.java index 3ef2995dca..3a9b07c3c9 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/QueryFilter.java +++ b/iped-app/src/main/java/iped/app/ui/filters/QueryFilter.java @@ -7,7 +7,7 @@ import iped.viewers.api.IQueryFilter; public class QueryFilter implements IQueryFilter { - Query query; + protected Query query; String title = null; public QueryFilter(Query query) { From df5d08649e224c5e8c88bf89147c7d0d96627918 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 3 Jun 2024 14:50:11 -0400 Subject: [PATCH 40/57] '#2163 Corrects NPE on evidence filterer --- iped-app/src/main/java/iped/app/ui/TreeListener.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/TreeListener.java b/iped-app/src/main/java/iped/app/ui/TreeListener.java index 1843d3983f..3ee22d2fa8 100644 --- a/iped-app/src/main/java/iped/app/ui/TreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/TreeListener.java @@ -238,6 +238,7 @@ public void clearFilter() { try { definedFilters = null; + selection.clear(); App.get().tree.clearSelection(); } finally { for (TreeSelectionListener lis : listeners) { @@ -288,7 +289,8 @@ public List getDefinedFilters() { @Override public boolean hasFiltersApplied() { - return definedFilters != null && ((PathFilter) definedFilters.get(0)).evidenceParentIdMap.size() > 0; + return definedFilters != null && definedFilters.size() > 0 + && ((PathFilter) definedFilters.get(0)).evidenceParentIdMap.size() > 0; } @Override @@ -305,7 +307,8 @@ public String toString() { @Override public boolean hasFilters() { - return definedFilters != null && ((PathFilter) definedFilters.get(0)).evidenceParentIdMap.size() > 0; + return definedFilters != null && definedFilters.size() > 0 + && ((PathFilter) definedFilters.get(0)).evidenceParentIdMap.size() > 0; } @Override From 77d3e11e9118fcf724a6cd2824495a1a35015d19 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 10:29:09 -0400 Subject: [PATCH 41/57] '#2163 Removes unnecessary field and corrects getQuery method to return a value only if a filter is defined. --- .../main/java/iped/app/ui/TreeListener.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/TreeListener.java b/iped-app/src/main/java/iped/app/ui/TreeListener.java index 3ee22d2fa8..32cf17e9ca 100644 --- a/iped-app/src/main/java/iped/app/ui/TreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/TreeListener.java @@ -61,7 +61,6 @@ public class TreeListener extends MouseAdapter implements TreeSelectionListener, boolean rootSelected = false; HashSet selection = new HashSet(); private long collapsedTime = 0; - private boolean clearing = false; private ArrayList definedFilters; @Override @@ -185,8 +184,7 @@ public void actionPerformed(ActionEvent e) { App.get().setEvidenceDefaultColor(false); } - if (!clearing) - App.get().appletListener.updateFileListing(); + App.get().appletListener.updateFileListing(); if (selection.size() == 1 && selection.iterator().next().getPathCount() > 2) { int luceneId = ((Node) selection.iterator().next().getLastPathComponent()).docId; @@ -229,8 +227,6 @@ private void showTreeMenu(MouseEvent e) { @Override public void clearFilter() { - clearing = true; - TreeSelectionListener[] listeners = App.get().tree.getTreeSelectionListeners(); for (TreeSelectionListener lis : listeners) { App.get().tree.removeTreeSelectionListener(lis); @@ -245,7 +241,6 @@ public void clearFilter() { App.get().tree.addTreeSelectionListener(lis); } } - clearing = false; } class PathFilter extends QueryFilter { @@ -295,10 +290,13 @@ public boolean hasFiltersApplied() { @Override public Query getQuery() { - if (App.get().recursiveTreeList.isSelected()) - return recursiveTreeQuery; - else - return treeQuery; + if (definedFilters != null) { + if (App.get().recursiveTreeList.isSelected()) + return recursiveTreeQuery; + else + return treeQuery; + } + return null; } public String toString() { From 2686d8a5a58b6dd81f611c0ab9e463731b7b32a3 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 10:52:42 -0400 Subject: [PATCH 42/57] '#2163 updates internal control field 'selection' on restoreDefinedFilters. --- iped-app/src/main/java/iped/app/ui/TreeListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/iped-app/src/main/java/iped/app/ui/TreeListener.java b/iped-app/src/main/java/iped/app/ui/TreeListener.java index 32cf17e9ca..3717f6475e 100644 --- a/iped-app/src/main/java/iped/app/ui/TreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/TreeListener.java @@ -329,6 +329,7 @@ public void restoreDefinedFilters(List filtersToRestore) { Node node = (Node) tp.getLastPathComponent(); if (checkSelection(node, pathFilter)) { App.get().tree.addSelectionPath(tp); + selection.add(tp); } } From b46dff96c24ec6cc69dfed63b196d333efb4cb2d Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 13:00:24 -0400 Subject: [PATCH 43/57] '#2163 Implements restoreFilters for Bookmarks filterer. --- .../iped/app/ui/BookmarksTreeListener.java | 74 ++++++++++++++++--- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/BookmarksTreeListener.java b/iped-app/src/main/java/iped/app/ui/BookmarksTreeListener.java index d4fb0fe1f5..c8f88d4091 100644 --- a/iped-app/src/main/java/iped/app/ui/BookmarksTreeListener.java +++ b/iped-app/src/main/java/iped/app/ui/BookmarksTreeListener.java @@ -32,7 +32,6 @@ public class BookmarksTreeListener implements TreeSelectionListener, TreeExpansi private HashSet selection = new HashSet<>(); private volatile boolean updatingSelection = false; private long collapsed = 0; - private boolean clearing = false; HashMap definedFilters = new HashMap(); @@ -76,8 +75,7 @@ public void valueChanged(TreeSelectionEvent evt) { } } - if (!clearing) - App.get().appletListener.updateFileListing(); + App.get().appletListener.updateFileListing(); if (selection.contains(BookmarksTreeModel.ROOT) || selection.isEmpty()) { App.get().setBookmarksDefaultColor(true); @@ -149,9 +147,20 @@ public void treeCollapsed(TreeExpansionEvent event) { @Override public void clearFilter() { - clearing = true; - App.get().bookmarksTree.clearSelection(); - clearing = false; + TreeSelectionListener[] listeners = App.get().bookmarksTree.getTreeSelectionListeners(); + for (TreeSelectionListener lis : listeners) { + App.get().bookmarksTree.removeTreeSelectionListener(lis); + } + + try { + selection.clear(); + definedFilters.clear(); + App.get().bookmarksTree.clearSelection(); + } finally { + for (TreeSelectionListener lis : listeners) { + App.get().bookmarksTree.addTreeSelectionListener(lis); + } + } } NoBookMarkFilter noBookMarkFilter = new NoBookMarkFilter(); @@ -162,12 +171,10 @@ public List getDefinedFilters() { BookmarksTreeListener self = this; Set bookmarkSelection = getSelectedBookmarkNames(); if ((!bookmarkSelection.isEmpty() || isNoBookmarksSelected()) && !isRootSelected()) { - if ((!bookmarkSelection.isEmpty() || isNoBookmarksSelected()) && !isRootSelected()) { - result.addAll(definedFilters.values()); + result.addAll(definedFilters.values()); - if (isNoBookmarksSelected()) { - result.add(noBookMarkFilter); - } + if (isNoBookmarksSelected()) { + result.add(noBookMarkFilter); } } return result; @@ -207,6 +214,51 @@ public boolean hasFilters() { public boolean hasFiltersApplied() { return selection.size() > 0 && !isRootSelected(); } + + @Override + public void restoreDefinedFilters(List filtersToRestore) { + TreeSelectionListener[] listeners = App.get().bookmarksTree.getTreeSelectionListeners(); + for (TreeSelectionListener lis : listeners) { + App.get().bookmarksTree.removeTreeSelectionListener(lis); + } + + definedFilters.clear(); + + try { + for (IFilter filter : filtersToRestore) { + if (filter instanceof BookMarkFilter) { + for (String bookmark : ((BookMarkFilter) filter).bookmark) { + for (int i = 0; i < App.get().bookmarksTree.getRowCount(); i++) { + TreePath tp = App.get().bookmarksTree.getPathForRow(i); + Object node = (Object) tp.getLastPathComponent(); + if (bookmark.equals(node.toString())) { + App.get().bookmarksTree.addSelectionPath(tp); + } + } + HashSet oneBookmark = new HashSet<>(); + oneBookmark.add(bookmark); + definedFilters.put(bookmark, new BookMarkFilter(oneBookmark)); + selection.add(bookmark); + } + } + if (filter.toString().equals(noBookMarkFilter.toString())) { + for (int i = 0; i < App.get().bookmarksTree.getRowCount(); i++) { + TreePath tp = App.get().bookmarksTree.getPathForRow(i); + Object node = (Object) tp.getLastPathComponent(); + if (node.toString().equals(filter.toString())) { + App.get().bookmarksTree.addSelectionPath(tp); + selection.add(node); + } + } + } + } + + } finally { + for (TreeSelectionListener lis : listeners) { + App.get().bookmarksTree.addTreeSelectionListener(lis); + } + } + } } class BookMarkFilter implements IResultSetFilter, IMutableFilter, IBitmapFilter { From 32c22bdc8f335dfdc9afb909b0c72a62c5c2fc37 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 13:06:04 -0400 Subject: [PATCH 44/57] '#2163 corrects hasFilters from DuplicatesFilterer --- iped-app/src/main/java/iped/app/ui/App.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index a76f33d8da..44a1aa4812 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1820,7 +1820,7 @@ public IFilter getFilter() { @Override public boolean hasFilters() { - return cduplicateFilter != null; + return filterDuplicates.isSelected(); } @Override From c324e7ee2cdc4216b1fc322ff2ccb6819139d8b5 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 13:44:45 -0400 Subject: [PATCH 45/57] '#2163 Code to avoid enabling filterer from filterpanel without any defined filter defined by the filterer before. --- .../main/java/iped/app/ui/FiltersPanel.java | 5 +++++ .../ui/controls/CheckBoxTreeCellRenderer.java | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index 43dbbe2f59..c1cd064934 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -140,6 +140,11 @@ public void actionPerformed(ActionEvent e) { filterer.restoreDefinedFilters(clastFilters); App.get().getAppListener().updateFileListing(); App.get().filtersPanel.updateUI(); + } else { + CheckBoxTreeCellRenderer.TreeCellCheckBoxActionEvent te = (CheckBoxTreeCellRenderer.TreeCellCheckBoxActionEvent) e; + if (te.getCheckBox().isSelected()) { + te.getCheckBox().setSelected(false); + } } } } diff --git a/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java b/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java index 479fdbc495..9c0b7baa33 100644 --- a/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java +++ b/iped-app/src/main/java/iped/app/ui/controls/CheckBoxTreeCellRenderer.java @@ -57,6 +57,20 @@ public String getValueString(Object value) { return value.toString(); } + public class TreeCellCheckBoxActionEvent extends ActionEvent { + JCheckBox checkBox = null; + + public TreeCellCheckBoxActionEvent(JCheckBox checkBox, Object source, int id, String command) { + super(source, id, command); + this.checkBox = checkBox; + } + + public JCheckBox getCheckBox() { + return checkBox; + } + + } + @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { @@ -87,8 +101,9 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean checkbox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - e.setSource(value); - al.actionPerformed(e); + al.actionPerformed( + new TreeCellCheckBoxActionEvent(checkbox, value, e.getID(), + e.getActionCommand())); } }); } From 5fa2d11e211ccdfc90bb5b04deba5ab5698551b6 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 13:57:43 -0400 Subject: [PATCH 46/57] '#2163 corrects similar documents and similar image filter restoration. --- iped-app/src/main/java/iped/app/ui/App.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index 44a1aa4812..81b49fe19b 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -2229,6 +2229,8 @@ public void restoreDefinedFilters(List filtersToRestore) { for (IFilter filter : filtersToRestore) { if (filter instanceof SimilarDocumentFilter) { filter = (SimilarDocumentFilter) filter; + SimilarDocumentFilter simFilter = (SimilarDocumentFilter) filter; + setItem(simFilter.getItemRefId(), simFilter.getItem()); break; } } From c606d3e22119468c884badbec851a3906ce6c7c1 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 13:59:09 -0400 Subject: [PATCH 47/57] '#2163 corrects similar image filterer restoration. --- iped-app/src/main/java/iped/app/ui/App.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iped-app/src/main/java/iped/app/ui/App.java b/iped-app/src/main/java/iped/app/ui/App.java index 81b49fe19b..2915856284 100644 --- a/iped-app/src/main/java/iped/app/ui/App.java +++ b/iped-app/src/main/java/iped/app/ui/App.java @@ -1774,6 +1774,8 @@ public void restoreDefinedFilters(List filtersToRestore) { for (IFilter filter : filtersToRestore) { if (filter instanceof SimilarImageFilter) { imageFilter = (SimilarImageFilter) filter; + SimilarImageFilter simFilter = (SimilarImageFilter) filter; + setItem(simFilter.getItemRefId(), simFilter.getItemRef()); break; } } From e8b19e389fc9bd2ad47bedf78e7a0313e6c31951 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 15:45:16 -0400 Subject: [PATCH 48/57] '#2163 Implementation of restore filters for Table Header Filterers. --- .../app/metadata/ValueCountQueryFilter.java | 8 +- .../main/java/iped/app/ui/MetadataPanel.java | 2 +- .../iped/app/ui/TableHeaderFilterManager.java | 93 +++++++++++++++---- .../java/iped/app/ui/filters/ValueFilter.java | 8 ++ 4 files changed, 90 insertions(+), 21 deletions(-) diff --git a/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java b/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java index b6513e675f..661ee502e3 100644 --- a/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java +++ b/iped-app/src/main/java/iped/app/metadata/ValueCountQueryFilter.java @@ -17,10 +17,12 @@ public class ValueCountQueryFilter implements IQueryFilter { StringBuffer textualDetail = null; Set values = null; String filterField; + MetadataSearch metadataSearch; private Query query; - public ValueCountQueryFilter(String filterField, Set selectedValues) { + public ValueCountQueryFilter(MetadataSearch metadataSearch, String filterField, Set selectedValues) { this.filterField = filterField; + this.metadataSearch = metadataSearch; values = new HashSet(); if (selectedValues != null) { values.addAll(selectedValues); @@ -110,4 +112,8 @@ public Set getValues() { return values; } + public MetadataSearch getMetadataSearch() { + return metadataSearch; + } + } diff --git a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java index 0b4857cbdf..14c494ec7d 100644 --- a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java +++ b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java @@ -681,7 +681,7 @@ public List getDefinedFilters() { selectedValues.addAll(list.getSelectedValuesList()); if (isFiltering()) { ValueCount sample = selectedValues.iterator().next(); - result.add(new ValueCountQueryFilter(field, selectedValues)); + result.add(new ValueCountQueryFilter(ms, field, selectedValues)); } return result; } diff --git a/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java b/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java index e75780e2aa..338ccb900e 100644 --- a/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java @@ -17,6 +17,7 @@ import iped.app.ui.controls.table.MetadataValueSearchList; import iped.app.ui.filters.EqualsFilter; import iped.app.ui.filters.StartsWithFilter; +import iped.app.ui.filters.ValueFilter; import iped.engine.search.MultiSearchResult; import iped.engine.search.QueryBuilder; import iped.engine.task.index.IndexItem; @@ -60,28 +61,46 @@ public void removeFilter(String field) { App.get().getFilterManager().notifyFilterChange(); } - private void addQueryFilter(String escapedField, String filterExpression) { - otherFilters.put(escapedField, filterExpression); - definedFilters.put(escapedField, new IQueryFilter() { - private Query query; + class TableHeaderFilter implements IQueryFilter { + private Query query; + private String filterExpression; + private String escapedField; + MetadataSearch metadataSearch; - @Override - public Query getQuery() { - if (query == null) { - try { - query = new QueryBuilder(App.get().appCase).getQuery(filterExpression); - } catch (ParseException | QueryNodeException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + public TableHeaderFilter(MetadataSearch metadataSearch, String escapedField, String filterExpression) { + this.filterExpression = filterExpression; + this.escapedField = escapedField; + this.metadataSearch = metadataSearch; + } + + @Override + public Query getQuery() { + if (query == null) { + try { + query = new QueryBuilder(App.get().appCase).getQuery(filterExpression); + } catch (ParseException | QueryNodeException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } - return query; } + return query; + } - public String toString() { - return filterExpression; - } - }); + public String toString() { + return filterExpression; + } + + public MetadataSearch getMetadataSearch() { + return metadataSearch; + } + // TODO Auto-generated method stub + + } + + private void addQueryFilter(String escapedField, String filterExpression) { + otherFilters.put(escapedField, filterExpression); + definedFilters.put(escapedField, + new TableHeaderFilter(panels.get(escapedField), escapedField, filterExpression)); selectedValues.remove(escapedField); App.get().getFilterManager().notifyFilterChange(); } @@ -125,7 +144,7 @@ public void removeNonEmptyFilter(String field) { public void addFilter(String field, Set selected) { field = escape(field); selectedValues.put(field, selected); - definedFilters.put(field, new ValueCountQueryFilter(field, selected)); + definedFilters.put(field, new ValueCountQueryFilter(panels.get(field), field, selected)); // clear any other filter defined otherFilters.remove(field); @@ -295,4 +314,40 @@ public void clearFilter() { public HashMap getOtherFilters() { return otherFilters; } + + @Override + public void restoreDefinedFilters(List filtersToRestore) { + definedFilters.clear(); + otherFilters.clear(); + selectedValues.clear(); + panels.clear(); + for (IFilter filter : filtersToRestore) { + String escapedField = null; + if (filter instanceof TableHeaderFilter) { + escapedField = ((TableHeaderFilter) filter).escapedField; + otherFilters.put(escapedField, ((TableHeaderFilter) filter).filterExpression); + definedFilters.put(escapedField, filter); + selectedValues.remove(escapedField); + panels.put(escapedField, ((TableHeaderFilter) filter).getMetadataSearch()); + } + + if (filter instanceof ValueCountQueryFilter) { + ValueCountQueryFilter vcqFilter = (ValueCountQueryFilter) filter; + escapedField = vcqFilter.getFilterField(); + definedFilters.put(escapedField, filter); + selectedValues.put(escapedField, vcqFilter.getValues()); + otherFilters.remove(escapedField); + panels.put(escapedField, vcqFilter.getMetadataSearch()); + } + + if (filter instanceof ValueFilter) { + ValueFilter eqFilter = (ValueFilter) filter; + escapedField = escape(eqFilter.getField()); + definedFilters.put(escapedField, filter); + otherFilters.put(escapedField, eqFilter.getValue()); + } + } + App.get().getFilterManager().notifyFilterChange(); + } + } diff --git a/iped-app/src/main/java/iped/app/ui/filters/ValueFilter.java b/iped-app/src/main/java/iped/app/ui/filters/ValueFilter.java index e1987c3d7b..2c41dc3d16 100644 --- a/iped-app/src/main/java/iped/app/ui/filters/ValueFilter.java +++ b/iped-app/src/main/java/iped/app/ui/filters/ValueFilter.java @@ -99,4 +99,12 @@ public IMultiSearchResult filterResult(IMultiSearchResult src) throws IOExceptio return r; } + public String getField() { + return field; + } + + public String getValue() { + return value; + } + } From 039a51f9deb394cb05e4171c548c6e5c8c19998b Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 15:49:11 -0400 Subject: [PATCH 49/57] '#2163 forces updateFileListing at the end of setSelectedIndices method. --- iped-app/src/main/java/iped/app/ui/MetadataPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java index 14c494ec7d..0e7d055d6c 100644 --- a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java +++ b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java @@ -809,5 +809,6 @@ private void setSelectedIndices(int[] is) { for (ListSelectionListener sl : temp) { list.addListSelectionListener(sl); } + App.get().appletListener.updateFileListing(); } } From 5a6309c31f1b1785902ba4138965929a41a0ee4c Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Tue, 4 Jun 2024 15:50:28 -0400 Subject: [PATCH 50/57] '#2163 repositions update file listing outside setSelectedIndices, right after its call. --- iped-app/src/main/java/iped/app/ui/MetadataPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java index 0e7d055d6c..b4758e5a8f 100644 --- a/iped-app/src/main/java/iped/app/ui/MetadataPanel.java +++ b/iped-app/src/main/java/iped/app/ui/MetadataPanel.java @@ -763,6 +763,7 @@ public void run() { } } setSelectedIndices(is); + App.get().appletListener.updateFileListing(); } }); } @@ -809,6 +810,5 @@ private void setSelectedIndices(int[] is) { for (ListSelectionListener sl : temp) { list.addListSelectionListener(sl); } - App.get().appletListener.updateFileListing(); } } From b77a2f4391ebb417063b2caf3c663f4a395c6493 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Wed, 5 Jun 2024 06:43:46 -0400 Subject: [PATCH 51/57] '#2163 Force call to setDockableColores after filterer checkbox click. --- iped-app/src/main/java/iped/app/ui/FiltersPanel.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java index c1cd064934..4a7b4d45b9 100644 --- a/iped-app/src/main/java/iped/app/ui/FiltersPanel.java +++ b/iped-app/src/main/java/iped/app/ui/FiltersPanel.java @@ -134,12 +134,15 @@ public void actionPerformed(ActionEvent e) { lastFilters.put(filterer, filterer.getDefinedFilters()); filterer.clearFilter(); App.get().getAppListener().updateFileListing(); + App.get().filtersPanel.updateUI(); + App.get().setDockablesColors(); } else { List clastFilters = lastFilters.get(filterer); if (clastFilters != null) { filterer.restoreDefinedFilters(clastFilters); App.get().getAppListener().updateFileListing(); App.get().filtersPanel.updateUI(); + App.get().setDockablesColors(); } else { CheckBoxTreeCellRenderer.TreeCellCheckBoxActionEvent te = (CheckBoxTreeCellRenderer.TreeCellCheckBoxActionEvent) e; if (te.getCheckBox().isSelected()) { From 3434d2db0ebbe4e861a6bbacb6bfe184073ed4c1 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Wed, 5 Jun 2024 07:17:35 -0400 Subject: [PATCH 52/57] '#2163 Creates a map to store the correspondence between a query escaped name of the field and its original name, that needs to be recovered when restoring defined filters. --- .../main/java/iped/app/ui/TableHeaderFilterManager.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java b/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java index 338ccb900e..ddadc5fe72 100644 --- a/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java +++ b/iped-app/src/main/java/iped/app/ui/TableHeaderFilterManager.java @@ -40,6 +40,7 @@ public class TableHeaderFilterManager implements IResultSetFilterer, IQueryFilte // store the filters defined by the FieldValuePopupMenu private HashMap otherFilters = new HashMap(); + private HashMap escapedFields = new HashMap(); static public TableHeaderFilterManager get() { return singleton; @@ -189,7 +190,9 @@ public MetadataSearch getMetadataSearch(String field) { MetadataSearch result = panels.get(field); if (result == null) { result = new MetadataSearch(); - panels.put(field, result); + String escapedField = escape(field); + panels.put(escapedField, result); + escapedFields.put(escapedField, field); } return result; } @@ -271,12 +274,12 @@ public IMultiSearchResult filterResult(IMultiSearchResult src) throws ParseExcep for (String filterField : panels.keySet()) { MetadataSearch internalMetadataSearch = panels.get(filterField); Set ords = new HashSet<>(); - Set values = selectedValues.get(escape(filterField)); + Set values = selectedValues.get(filterField); if (values != null && values.size() > 0) { for (ValueCount value : values) { ords.add(value.getOrd()); } - result = internalMetadataSearch.getIdsWithOrd(result, filterField, ords); + result = internalMetadataSearch.getIdsWithOrd(result, escapedFields.get(filterField), ords); if (result.getLength() <= 0) { return result; } From c2793dc1c14e3613f53831389a4f72d6f2685022 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 17 Jun 2024 12:10:30 -0400 Subject: [PATCH 53/57] '#2163 Implementation of restoreDefinedFilters of Timeline filterer. --- .../app/timelinegraph/IpedChartsPanel.java | 102 ++++++++++++------ 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/iped-app/src/main/java/iped/app/timelinegraph/IpedChartsPanel.java b/iped-app/src/main/java/iped/app/timelinegraph/IpedChartsPanel.java index 2304f9a2fb..79d84dd959 100644 --- a/iped-app/src/main/java/iped/app/timelinegraph/IpedChartsPanel.java +++ b/iped-app/src/main/java/iped/app/timelinegraph/IpedChartsPanel.java @@ -1084,48 +1084,64 @@ public void resetZoom() { refreshChart(true); } + public class TimeRangeFilter implements IQueryFilter { + private Query query; + Date[] dates; + + public TimeRangeFilter(Date[] dates) { + this.dates = dates; + } + + public String toString() { + String timeFilter = domainAxis.ISO8601DateFormatUTC(dates[0]); + timeFilter += " TO "; + timeFilter += domainAxis.ISO8601DateFormatUTC(dates[1]); + return timeFilter; + } + + @Override + public Query getQuery() { + if (query == null) { + String timeFilter = "timeStamp:["; + timeFilter += domainAxis.ISO8601DateFormatUTC(dates[0]); + timeFilter += " TO "; + timeFilter += domainAxis.ISO8601DateFormatUTC(dates[1]); + timeFilter += "]"; + + try { + query = new QueryBuilder(App.get().appCase).getQuery(timeFilter); + } catch (ParseException | QueryNodeException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return query; + } + } + + public class EventTypeFilter implements IFilter { + String event; + + public EventTypeFilter(String event) { + this.event = event; + } + + public String toString() { + return "-eventType:" + event; + } + } + @Override public List getDefinedFilters() { ArrayList result = new ArrayList(); if (chartPanel.definedFilters.size() > 0) { for (Date[] dates : chartPanel.definedFilters) { - result.add(new IQueryFilter() { - private Query query; - - public String toString() { - String timeFilter = domainAxis.ISO8601DateFormatUTC(dates[0]); - timeFilter += " TO "; - timeFilter += domainAxis.ISO8601DateFormatUTC(dates[1]); - return timeFilter; - } - - @Override - public Query getQuery() { - if (query == null) { - String timeFilter = "timeStamp:["; - timeFilter += domainAxis.ISO8601DateFormatUTC(dates[0]); - timeFilter += " TO "; - timeFilter += domainAxis.ISO8601DateFormatUTC(dates[1]); - timeFilter += "]"; - - try { - query = new QueryBuilder(App.get().appCase).getQuery(timeFilter); - } catch (ParseException | QueryNodeException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return query; - } - }); + result.add(new TimeRangeFilter(dates)); } } + for (String event : chartPanel.excludedEvents) { - result.add(new IFilter() { - public String toString() { - return "-eventType:" + event; - } - }); + result.add(new EventTypeFilter(event)); } return result; @@ -1144,4 +1160,22 @@ public static String[] getOrdToEventName() { return ordToEventName; } + public void restoreDefinedFilters(List filtersToRestore) { + boolean hasFilters = false; + for (IFilter filter : filtersToRestore) { + hasFilters = true; + if (filter instanceof TimeRangeFilter) { + chartPanel.definedFilters.add(((TimeRangeFilter) filter).dates); + } + if (filter instanceof EventTypeFilter) { + chartPanel.excludedEvents.add(((EventTypeFilter) filter).event); + } + } + if (hasFilters) { + applyFilters = true; + App.get().getFilterManager().setFilterEnabled(this, true); + } + + } + } \ No newline at end of file From fc2c5df4132bdfd53ec286b34202ac86da8bab53 Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 17 Jun 2024 15:14:32 -0400 Subject: [PATCH 54/57] '#2163 restore filters implementation for GraphAnalisys. --- .../java/iped/app/graph/FilterSelectedEdges.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java b/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java index e591894968..1472a5ff4d 100644 --- a/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java +++ b/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java @@ -199,6 +199,18 @@ public void clearFilter() { public void setGraph(Graph graph) { this.graph = graph; } + + @Override + public void restoreDefinedFilters(List filtersToRestore) { + for (Iterator iterator = filtersToRestore.iterator(); iterator.hasNext();) { + IFilter iFilter = (IFilter) iterator.next(); + if (iFilter instanceof EdgeFilter) { + EdgeFilter efilter = (EdgeFilter) iFilter; + this.graph = efilter.graph; + this.selectedEdges = efilter.selectedEdges; + } + } + } } class EdgeFilter implements IResultSetFilter { From 9af46bb1f2a4df0f28df406c530f30671ef526ec Mon Sep 17 00:00:00 2001 From: "patrick.pdb" Date: Mon, 17 Jun 2024 15:18:18 -0400 Subject: [PATCH 55/57] '#2163 Repaints links tab in red when filters are restored. --- iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java | 1 + 1 file changed, 1 insertion(+) diff --git a/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java b/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java index 1472a5ff4d..6e0e928064 100644 --- a/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java +++ b/iped-app/src/main/java/iped/app/graph/FilterSelectedEdges.java @@ -210,6 +210,7 @@ public void restoreDefinedFilters(List filtersToRestore) { this.selectedEdges = efilter.selectedEdges; } } + updateResults(); } } From 5b72dc6cd4a786c01d4a8577d6feaed12e8135b5 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 27 Jun 2024 18:41:59 -0400 Subject: [PATCH 56/57] '#2251 and '#2163 apply duplicate filter as last filterer. --- .../java/iped/app/ui/CaseSearcherFilter.java | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java b/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java index a45496211c..e7eb607e26 100644 --- a/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java +++ b/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java @@ -37,6 +37,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import iped.app.ui.App.DuplicatesFilterer; import iped.engine.data.IPEDMultiSource; import iped.engine.data.IPEDSource; import iped.engine.data.ItemId; @@ -182,6 +183,8 @@ public MultiSearchResult doInBackground() { allItemsCache = new SoftReference(result.clone()); } + IResultSetFilterer dupFilterer = null; + result.setIPEDSource(ipedCase); if (applyUIFilters && filterManager != null) { @@ -193,27 +196,11 @@ public MultiSearchResult doInBackground() { } IResultSetFilterer iRSFilterer = (IResultSetFilterer) iterator.next(); - if (filterManager.isFiltererEnabled(iRSFilterer)) { - IFilter rsFilter = iRSFilterer.getFilter(); - - if (rsFilter != null) { - if (rsFilter instanceof IBitmapFilter) {// if the filter exposes a internal bitmap - addBitmapFilter((IBitmapFilter) rsFilter); - } else { - RoaringBitmap[] cachedBitmaps = filterManager.getCachedBitmaps((IResultSetFilter) rsFilter); - if (cachedBitmaps != null) { // if filtermanager returned a cached bitmap - addBitmapFilter(cachedBitmaps); - } else { - MultiSearchResult newresult = filterManager.applyFilter((IResultSetFilter) rsFilter, result); - if (newresult != result) { - numFilters++; - result = newresult; - result.setIPEDSource(ipedCase); - } - } - } - } + if(iRSFilterer instanceof DuplicatesFilterer) { + dupFilterer=iRSFilterer; + continue;//Duplicate filterer must be applied as last filterer } + applyFilterer(iRSFilterer, result); } } @@ -236,6 +223,11 @@ public MultiSearchResult doInBackground() { result.setIPEDSource(ipedCase); } } + + if(dupFilterer!=null) { + applyFilterer(dupFilterer, result); + } + } catch (Throwable e) { if (!(e instanceof CancellationException)) { @@ -256,7 +248,31 @@ public MultiSearchResult doInBackground() { } - @Override + private void applyFilterer(IResultSetFilterer iRSFilterer, MultiSearchResult result2) { + if (filterManager.isFiltererEnabled(iRSFilterer)) { + IFilter rsFilter = iRSFilterer.getFilter(); + + if (rsFilter != null) { + if (rsFilter instanceof IBitmapFilter) {// if the filter exposes a internal bitmap + addBitmapFilter((IBitmapFilter) rsFilter); + } else { + RoaringBitmap[] cachedBitmaps = filterManager.getCachedBitmaps((IResultSetFilter) rsFilter); + if (cachedBitmaps != null) { // if filtermanager returned a cached bitmap + addBitmapFilter(cachedBitmaps); + } else { + MultiSearchResult newresult = filterManager.applyFilter((IResultSetFilter) rsFilter, result); + if (newresult != result) { + numFilters++; + result = newresult; + result.setIPEDSource(ipedCase); + } + } + } + } + } + } + + @Override public void done() { for (CaseSearchFilterListener caseSearchFilterListener : listeners) { if (isCancelled()) { @@ -360,6 +376,6 @@ public void addBitmapFilter(RoaringBitmap[] lunionsArray) { } else { unionsArray[i].and(lunionsArray[i]); } - } + } } } From 8b2878df96f21d139a7c0281c3f74df0668fbf75 Mon Sep 17 00:00:00 2001 From: Patrick Dalla Bernardina Date: Thu, 27 Jun 2024 23:38:22 -0400 Subject: [PATCH 57/57] Revert "'#2251 and '#2163 apply duplicate filter as last filterer." This reverts commit 5b72dc6cd4a786c01d4a8577d6feaed12e8135b5. --- .../java/iped/app/ui/CaseSearcherFilter.java | 60 +++++++------------ 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java b/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java index e7eb607e26..a45496211c 100644 --- a/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java +++ b/iped-app/src/main/java/iped/app/ui/CaseSearcherFilter.java @@ -37,7 +37,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import iped.app.ui.App.DuplicatesFilterer; import iped.engine.data.IPEDMultiSource; import iped.engine.data.IPEDSource; import iped.engine.data.ItemId; @@ -183,8 +182,6 @@ public MultiSearchResult doInBackground() { allItemsCache = new SoftReference(result.clone()); } - IResultSetFilterer dupFilterer = null; - result.setIPEDSource(ipedCase); if (applyUIFilters && filterManager != null) { @@ -196,11 +193,27 @@ public MultiSearchResult doInBackground() { } IResultSetFilterer iRSFilterer = (IResultSetFilterer) iterator.next(); - if(iRSFilterer instanceof DuplicatesFilterer) { - dupFilterer=iRSFilterer; - continue;//Duplicate filterer must be applied as last filterer + if (filterManager.isFiltererEnabled(iRSFilterer)) { + IFilter rsFilter = iRSFilterer.getFilter(); + + if (rsFilter != null) { + if (rsFilter instanceof IBitmapFilter) {// if the filter exposes a internal bitmap + addBitmapFilter((IBitmapFilter) rsFilter); + } else { + RoaringBitmap[] cachedBitmaps = filterManager.getCachedBitmaps((IResultSetFilter) rsFilter); + if (cachedBitmaps != null) { // if filtermanager returned a cached bitmap + addBitmapFilter(cachedBitmaps); + } else { + MultiSearchResult newresult = filterManager.applyFilter((IResultSetFilter) rsFilter, result); + if (newresult != result) { + numFilters++; + result = newresult; + result.setIPEDSource(ipedCase); + } + } + } + } } - applyFilterer(iRSFilterer, result); } } @@ -223,11 +236,6 @@ public MultiSearchResult doInBackground() { result.setIPEDSource(ipedCase); } } - - if(dupFilterer!=null) { - applyFilterer(dupFilterer, result); - } - } catch (Throwable e) { if (!(e instanceof CancellationException)) { @@ -248,31 +256,7 @@ public MultiSearchResult doInBackground() { } - private void applyFilterer(IResultSetFilterer iRSFilterer, MultiSearchResult result2) { - if (filterManager.isFiltererEnabled(iRSFilterer)) { - IFilter rsFilter = iRSFilterer.getFilter(); - - if (rsFilter != null) { - if (rsFilter instanceof IBitmapFilter) {// if the filter exposes a internal bitmap - addBitmapFilter((IBitmapFilter) rsFilter); - } else { - RoaringBitmap[] cachedBitmaps = filterManager.getCachedBitmaps((IResultSetFilter) rsFilter); - if (cachedBitmaps != null) { // if filtermanager returned a cached bitmap - addBitmapFilter(cachedBitmaps); - } else { - MultiSearchResult newresult = filterManager.applyFilter((IResultSetFilter) rsFilter, result); - if (newresult != result) { - numFilters++; - result = newresult; - result.setIPEDSource(ipedCase); - } - } - } - } - } - } - - @Override + @Override public void done() { for (CaseSearchFilterListener caseSearchFilterListener : listeners) { if (isCancelled()) { @@ -376,6 +360,6 @@ public void addBitmapFilter(RoaringBitmap[] lunionsArray) { } else { unionsArray[i].and(lunionsArray[i]); } - } + } } }