From 79ae7d0b992bcf01c0e11c96458f9b0255374852 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 24 Feb 2022 12:15:18 -0500 Subject: [PATCH] GP-1764 - Fixed table CSV export of boolean values --- .../widgets/table/GBooleanCellRenderer.java | 4 + .../docking/widgets/table/GTableToCSV.java | 32 ++++- .../docking/widgets/table/GTableCSVTest.java | 111 +++++++++++++----- 3 files changed, 115 insertions(+), 32 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GBooleanCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GBooleanCellRenderer.java index 9722093a52..386d5e81f9 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GBooleanCellRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GBooleanCellRenderer.java @@ -42,6 +42,10 @@ public class GBooleanCellRenderer extends GTableCellRenderer { return this; } + public boolean isSelected() { + return cb.isSelected(); + } + @Override public void invalidate() { superValidate(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableToCSV.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableToCSV.java index 4876a27d5a..31d862d09c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableToCSV.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableToCSV.java @@ -77,7 +77,7 @@ public final class GTableToCSV { private static List getVisibleColumnsInOrder(JTable table, TaskMonitor monitor) { TableColumnModel columnModel = table.getColumnModel(); - List columns = new ArrayList(); + List columns = new ArrayList<>(); for (int columnIndex = 0; columnIndex < table.getColumnCount(); ++columnIndex) { if (monitor.isCancelled()) { break; @@ -92,7 +92,7 @@ public final class GTableToCSV { List columnIndices) { TableColumnModel columnModel = table.getColumnModel(); - List columns = new ArrayList(); + List columns = new ArrayList<>(); for (Integer index : columnIndices) { TableColumn column = columnModel.getColumn(index); columns.add(column); @@ -163,7 +163,7 @@ public final class GTableToCSV { } /** - * Attempts to get the text value for the cell so that the data will match what the user sees. + * Attempts to get the text value for the cell so that the data will match what the user sees. */ private static String getTableCellValue(JTable table, TableModel model, int row, int column) { TableCellRenderer renderer = table.getCellRenderer(row, column); @@ -174,6 +174,10 @@ public final class GTableToCSV { Component component = renderer.getTableCellRendererComponent(table, value, false, false, row, column); + if (isCheckBox(component)) { + return getCheckBoxValue(component); + } + if (component instanceof JLabel) { JLabel label = (JLabel) component; return getTextForLabel(label); @@ -187,7 +191,27 @@ public final class GTableToCSV { return value == null ? "" : value.toString(); } + private static boolean isCheckBox(Component component) { + return component instanceof JCheckBox || component instanceof GBooleanCellRenderer; + } + + private static String getCheckBoxValue(Component component) { + + if (component instanceof JCheckBox) { + JCheckBox cb = (JCheckBox) component; + return Boolean.toString(cb.isSelected()); + } + + if (component instanceof GBooleanCellRenderer) { + GBooleanCellRenderer renderer = (GBooleanCellRenderer) component; + return Boolean.toString(renderer.isSelected()); + } + + return ""; + } + private static String getTextForLabel(JLabel label) { + String text = label.getText(); if (text != null) { return text; @@ -334,7 +358,7 @@ public final class GTableToCSV { private final GTable table; private File file; - private List columns = new ArrayList(); + private List columns = new ArrayList<>(); ConvertTask(File file, GTable table) { super(GTableToCSV.TITLE, true, true, true); diff --git a/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/GTableCSVTest.java b/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/GTableCSVTest.java index 6b89463670..c68a36a51f 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/GTableCSVTest.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/GTableCSVTest.java @@ -28,20 +28,17 @@ import ghidra.util.task.TaskMonitor; public class GTableCSVTest { @Test - public void testCSV_QuotesGetEscaped() { + public void testCsv_QuotesGetEscaped() { - AnyObjectTableModel model = - new AnyObjectTableModel<>("MyModel", CSVRowObject.class, + AnyObjectTableModel model = + new AnyObjectTableModel<>("MyModel", CsvRowObject.class, "getName", "getDescription", "getNumber"); - //@formatter:off - List data = Arrays.asList( - new CSVRowObject("Bob", "Bobby", 11), - new CSVRowObject("Joan", "Joan has \"quoted\" text", 0), - new CSVRowObject("Sam", "\"Sam has a single quote text", 23), - new CSVRowObject("Time", "Tim is last", 33) - ); - //@formatter:on + List data = Arrays.asList( + new CsvRowObject("Bob", "Bobby", 11), + new CsvRowObject("Joan", "Joan has \"quoted\" text", 0), + new CsvRowObject("Sam", "\"Sam has a single quote text", 23), + new CsvRowObject("Time", "Tim is last", 33)); model.setModelData(data); GTable table = new GTable(model); @@ -50,24 +47,21 @@ public class GTableCSVTest { PrintWriterSpy writer = new PrintWriterSpy(); GTableToCSV.writeCSV(writer, table, columns, TaskMonitor.DUMMY); - assertRowValues(data, writer); + assertCsvRowValues(data, writer); } @Test - public void testCSV_CommasGetEscaped() { + public void testCsv_CommasGetEscaped() { - AnyObjectTableModel model = - new AnyObjectTableModel<>("MyModel", CSVRowObject.class, + AnyObjectTableModel model = + new AnyObjectTableModel<>("MyModel", CsvRowObject.class, "getName", "getDescription", "getNumber"); - //@formatter:off - List data = Arrays.asList( - new CSVRowObject("Bob", "Bobby", 11), - new CSVRowObject("Joan", "Joan has a comma, in her text", 0), - new CSVRowObject("Sam", ",Sam has a leading comma", 23), - new CSVRowObject("Time", "Tim is last", 33) - ); - //@formatter:on + List data = Arrays.asList( + new CsvRowObject("Bob", "Bobby", 11), + new CsvRowObject("Joan", "Joan has a comma, in her text", 0), + new CsvRowObject("Sam", ",Sam has a leading comma", 23), + new CsvRowObject("Time", "Tim is last", 33)); model.setModelData(data); GTable table = new GTable(model); @@ -76,16 +70,39 @@ public class GTableCSVTest { PrintWriterSpy writer = new PrintWriterSpy(); GTableToCSV.writeCSV(writer, table, columns, TaskMonitor.DUMMY); - assertRowValues(data, writer); + assertCsvRowValues(data, writer); } - private void assertRowValues(List data, PrintWriterSpy writer) { + @Test + public void testCsv_BooleaValues() { + + AnyObjectTableModel model = + new AnyObjectTableModel<>("MyModel", BooleanCsvRowObject.class, + "getName", "isSelected"); + + List data = Arrays.asList( + new BooleanCsvRowObject("Bob", true), + new BooleanCsvRowObject("Joan", false), + new BooleanCsvRowObject("Sam", false), + new BooleanCsvRowObject("Time", true)); + model.setModelData(data); + + GTable table = new GTable(model); + List columns = new ArrayList<>(); + + PrintWriterSpy writer = new PrintWriterSpy(); + GTableToCSV.writeCSV(writer, table, columns, TaskMonitor.DUMMY); + + assertBooleanCsvRowValues(data, writer); + } + + private void assertCsvRowValues(List data, PrintWriterSpy writer) { String results = writer.toString(); String[] lines = results.split("\n"); for (int i = 1; i < lines.length; i++) { int index = i - 1; // the first line is the header - CSVRowObject row = data.get(index); + CsvRowObject row = data.get(index); String line = lines[i]; String[] columns = line.split("(? data, PrintWriterSpy writer) { + + String results = writer.toString(); + String[] lines = results.split("\n"); + for (int i = 1; i < lines.length; i++) { + int index = i - 1; // the first line is the header + BooleanCsvRowObject row = data.get(index); + String line = lines[i]; + String[] columns = line.split("(?