From d6f4cd052e332acc0e951f1a71ebf9051c3bc557 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:30:24 -0400 Subject: [PATCH] GP-3764 - Added the ability to filter only on Data Type names --- .../data_type_manager_window.html | 7 +++ .../core/datamgr/DataTypesProvider.java | 35 +++++++----- .../core/datamgr/FilterOnNameOnlyAction.java | 54 +++++++++++++++++++ .../IncludeDataTypesInFilterAction.java | 3 ++ .../datamgr/tree/DataTypeArchiveGTree.java | 41 ++++++++++++-- .../internal/DefaultGTreeDataTransformer.java | 8 ++- 6 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/FilterOnNameOnlyAction.java diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_window.html b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_window.html index 2435a6bd29..45cc545521 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_window.html +++ b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_window.html @@ -327,6 +327,13 @@ fields of Enum names and values, and Function parameter data types and names. You may turn this feature off if you find that your search yields too many results for data types that have common names, such as byte.

+ + +

The Filter on Name Only action, when toggled on, will trigger the + filter field to search only using data type names. When toggled off, filtering will + be done using the display text of the node, which may include additional information, such + as an associated archive. +

Data Type Conflict Resolution Mode

diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java index 8e5b69ba96..45937ce705 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java @@ -94,7 +94,9 @@ public class DataTypesProvider extends ComponentProviderAdapter { private ToggleDockingAction filterPointersAction; private ToggleDockingAction previewWindowAction; private ToggleDockingAction includeDataMembersInSearchAction; + private FilterOnNameOnlyAction filterOnNameOnlyAction; private boolean includeDataMembersInFilter; + private boolean filterOnNameOnly; public DataTypesProvider(DataTypeManagerPlugin plugin, String providerName) { this(plugin, providerName, false); @@ -199,6 +201,9 @@ public class DataTypesProvider extends ComponentProviderAdapter { includeDataMembersInSearchAction = new IncludeDataTypesInFilterAction(plugin, this, "5"); addLocalAction(includeDataMembersInSearchAction); + filterOnNameOnlyAction = new FilterOnNameOnlyAction(plugin, this, "6"); + addLocalAction(filterOnNameOnlyAction); + addLocalAction(new ApplyFunctionDataTypesAction(plugin)); // Tree addLocalAction(new CaptureFunctionDataTypesAction(plugin)); // Tree addLocalAction(new SetFavoriteDataTypeAction(plugin)); // Data Type @@ -820,23 +825,24 @@ public class DataTypesProvider extends ComponentProviderAdapter { return selectedDataTypes; } - // this is a callback from the action--we need this to prevent callbacks, as the other - // version of this method will update the action, which would trigger a callback + // this is called from the action public void setIncludeDataTypeMembersInFilterCallback(boolean newValue) { includeDataMembersInFilter = newValue; - archiveGTree.setIncludeDataTypeMembersInSearch(includeDataMembersInFilter); + archiveGTree.updateDataTransformer(this); + } + + // this is called from the action + public void setFilterOnNameOnlyCallback(boolean newValue) { + filterOnNameOnly = newValue; + archiveGTree.updateDataTransformer(this); } public void setIncludeDataTypeMembersInFilter(boolean newValue) { - includeDataMembersInFilter = newValue; - archiveGTree.setIncludeDataTypeMembersInSearch(includeDataMembersInFilter); + includeDataMembersInSearchAction.setSelected(newValue); + } - // make sure the action is in sync - ToggleDockingAction action = includeDataMembersInSearchAction; - boolean selected = action.isSelected(); - if (selected != includeDataMembersInFilter) { - action.setSelected(includeDataMembersInFilter); - } + public void setFilterOnNameOnly(boolean newValue) { + filterOnNameOnlyAction.setSelected(newValue); } public void setFilteringArrays(boolean b) { @@ -847,10 +853,14 @@ public class DataTypesProvider extends ComponentProviderAdapter { archiveGTree.enablePointerFilter(b); } - boolean includeDataMembersInSearch() { + public boolean isIncludeDataMembersInSearch() { return includeDataMembersInFilter; } + public boolean isFilterOnNameOnly() { + return filterOnNameOnly; + } + @Override public JComponent getComponent() { return splitPane; @@ -978,4 +988,5 @@ public class DataTypesProvider extends ComponentProviderAdapter { navigationHistory.add(new DataTypeUrl(dt)); contextChanged(); } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/FilterOnNameOnlyAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/FilterOnNameOnlyAction.java new file mode 100644 index 0000000000..5cca5770d1 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/FilterOnNameOnlyAction.java @@ -0,0 +1,54 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.datamgr; + +import docking.action.MenuData; +import docking.action.ToggleDockingAction; +import docking.widgets.tree.GTreeNode; +import ghidra.util.HelpLocation; + +/** + * Allows user to filter on only the data type name. When off, all information returned by + * {@link GTreeNode#getDisplayText()} is used for filtering. + */ +public class FilterOnNameOnlyAction extends ToggleDockingAction { + + private final DataTypesProvider provider; + + public FilterOnNameOnlyAction(DataTypeManagerPlugin plugin, DataTypesProvider provider, + String menuSubGroup) { + super("Filter on Name Only", plugin.getName()); + this.provider = provider; + + setMenuBarData(new MenuData(new String[] { "Filter on Name Only" }, null, "VeryLast", + MenuData.NO_MNEMONIC, menuSubGroup)); + setDescription("Selected indicates to use only the data type name when filtering."); + + setEnabled(true); + setSelected(false); // default to off! + + setHelpLocation(new HelpLocation("DataTypeManagerPlugin", "Filter_Name_Only")); + } + + @Override + public void setSelected(boolean newValue) { + if (isSelected() == newValue) { + return; + } + super.setSelected(newValue); + provider.setFilterOnNameOnlyCallback(newValue); + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/IncludeDataTypesInFilterAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/IncludeDataTypesInFilterAction.java index c641561add..814696cc53 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/IncludeDataTypesInFilterAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/IncludeDataTypesInFilterAction.java @@ -43,6 +43,9 @@ public class IncludeDataTypesInFilterAction extends ToggleDockingAction { @Override public void setSelected(boolean newValue) { + if (isSelected() == newValue) { + return; + } super.setSelected(newValue); provider.setIncludeDataTypeMembersInFilterCallback(newValue); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java index 8fe7703330..11ef7a7b08 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/tree/DataTypeArchiveGTree.java @@ -158,9 +158,21 @@ public class DataTypeArchiveGTree extends GTree { reloadTree(); } - public void setIncludeDataTypeMembersInSearch(boolean includeDataTypes) { - setDataTransformer( - includeDataTypes ? new DataTypeTransformer() : new DefaultGTreeDataTransformer()); + public void updateDataTransformer(DataTypesProvider provider) { + + boolean includeMembers = provider.isIncludeDataMembersInSearch(); + boolean filterOnNameOnly = provider.isFilterOnNameOnly(); + + DefaultDtTreeDataTransformer transformer; + if (includeMembers) { + transformer = new DataTypeTransformer(filterOnNameOnly); + } + else { + transformer = new DefaultDtTreeDataTransformer(filterOnNameOnly); + } + + setDataTransformer(transformer); + reloadTree(); } @@ -249,7 +261,28 @@ public class DataTypeArchiveGTree extends GTree { // Inner Classes //================================================================================================== - private class DataTypeTransformer extends DefaultGTreeDataTransformer { + private class DefaultDtTreeDataTransformer extends DefaultGTreeDataTransformer { + + private boolean filterOnNameOnly; + + DefaultDtTreeDataTransformer(boolean filterOnNameOnly) { + this.filterOnNameOnly = filterOnNameOnly; + } + + @Override + protected String toString(GTreeNode node) { + if (filterOnNameOnly) { + return node.getName(); // the node name is the type name + } + return super.toString(node); + } + } + + private class DataTypeTransformer extends DefaultDtTreeDataTransformer { + + DataTypeTransformer(boolean filterOnNameOnly) { + super(filterOnNameOnly); + } @Override public List transform(GTreeNode node) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/internal/DefaultGTreeDataTransformer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/internal/DefaultGTreeDataTransformer.java index 019647b5b6..8234b59a98 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/internal/DefaultGTreeDataTransformer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/internal/DefaultGTreeDataTransformer.java @@ -24,7 +24,7 @@ import ghidra.util.FilterTransformer; public class DefaultGTreeDataTransformer implements FilterTransformer { private ThreadLocal> localizedResults = new ThreadLocal>() { @Override - protected java.util.List initialValue() { + protected List initialValue() { return new ArrayList(); } }; @@ -33,7 +33,11 @@ public class DefaultGTreeDataTransformer implements FilterTransformer public List transform(GTreeNode node) { List results = localizedResults.get(); results.clear(); - results.add(node.getDisplayText()); + results.add(toString(node)); return results; } + + protected String toString(GTreeNode node) { + return node.getDisplayText(); + } }