From 48ea841267221fe82249553bd4bb8b952f4fc5d8 Mon Sep 17 00:00:00 2001 From: Wandmalfarbe Date: Fri, 11 Aug 2023 21:22:35 +0200 Subject: [PATCH] feature: add filter and search to the validation result table - The validation results can now be searched and filtered by severity. --- .../epubcheckfx/model/Severity.java | 39 ++++++++++ .../epubcheckfx/ui/MainContentController.java | 72 ++++++++++++++++++- src/main/resources/fxml/MainContent.fxml | 18 ++++- src/main/resources/i18n/LangBundle.properties | 3 + .../resources/i18n/LangBundle_de.properties | 3 + 5 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/pascalwagler/epubcheckfx/model/Severity.java diff --git a/src/main/java/de/pascalwagler/epubcheckfx/model/Severity.java b/src/main/java/de/pascalwagler/epubcheckfx/model/Severity.java new file mode 100644 index 0000000..495459f --- /dev/null +++ b/src/main/java/de/pascalwagler/epubcheckfx/model/Severity.java @@ -0,0 +1,39 @@ +package de.pascalwagler.epubcheckfx.model; + +import atlantafx.base.theme.Styles; +import de.pascalwagler.epubcheckfx.ui.Translatable; +import lombok.Getter; +import org.kordamp.ikonli.Ikon; +import org.kordamp.ikonli.material2.Material2OutlinedAL; + +public enum Severity implements Translatable { + + + SUPPRESSED(com.adobe.epubcheck.messages.Severity.SUPPRESSED, Material2OutlinedAL.INFO, Styles.TEXT_SUBTLE, "severity.suppressed"), + + USAGE(com.adobe.epubcheck.messages.Severity.USAGE, Material2OutlinedAL.INFO, Styles.TEXT_MUTED, "severity.usage"), + + INFO(com.adobe.epubcheck.messages.Severity.INFO, Material2OutlinedAL.INFO, Styles.ACCENT, "severity.info"), + + WARNING(com.adobe.epubcheck.messages.Severity.WARNING, Material2OutlinedAL.ERROR_OUTLINE, Styles.WARNING, "severity.warning"), + + ERROR(com.adobe.epubcheck.messages.Severity.ERROR, Material2OutlinedAL.ERROR_OUTLINE, Styles.DANGER, "severity.error"), + + FATAL(com.adobe.epubcheck.messages.Severity.FATAL, Material2OutlinedAL.ERROR_OUTLINE, Styles.DANGER, "severity.fatal"); + + Severity(com.adobe.epubcheck.messages.Severity ebubcheckSeverity, Ikon icon, String colorStyleClass, String i18nKey) { + this.ebubcheckSeverity = ebubcheckSeverity; + this.icon = icon; + this.colorStyleClass = colorStyleClass; + this.i18nKey = i18nKey; + } + + @Getter + private final com.adobe.epubcheck.messages.Severity ebubcheckSeverity; + @Getter + private final Ikon icon; + @Getter + private final String colorStyleClass; + @Getter + private final String i18nKey; +} diff --git a/src/main/java/de/pascalwagler/epubcheckfx/ui/MainContentController.java b/src/main/java/de/pascalwagler/epubcheckfx/ui/MainContentController.java index 4a619df..8b69e74 100644 --- a/src/main/java/de/pascalwagler/epubcheckfx/ui/MainContentController.java +++ b/src/main/java/de/pascalwagler/epubcheckfx/ui/MainContentController.java @@ -16,6 +16,8 @@ import javafx.beans.property.Property; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.ObservableList; +import javafx.collections.transformation.FilteredList; +import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.geometry.Insets; @@ -33,6 +35,7 @@ import java.nio.file.Files; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.function.Predicate; @Slf4j public class MainContentController implements Initializable { @@ -58,6 +61,11 @@ public class MainContentController implements Initializable { @FXML private ComboBox epubProfile; + @FXML + private TextField resultTableSearchFilter; + @FXML + private ComboBox resultTableSeverityFilter; + @FXML private ComboBox exportFormat; @@ -80,6 +88,8 @@ public class MainContentController implements Initializable { @Setter private InfoPanelController infoPanelController; + private FilteredList filteredErrorList; + private static final File tempDirectory = new File(System.getProperty("java.io.tmpdir"), "EPUBCheckFX"); @Override @@ -95,14 +105,60 @@ public void initialize(URL location, ResourceBundle resourceBundle) { throw new RuntimeException(e); } initValidationResultTable(); + initSeverityFilter(); initExportFormat(); initEpubProfile(); epubcheckVersion.setText("EPUBCheck Version " + EpubCheck.version() + " - (Built " + EpubCheck.buildDate() + ")"); } + private Predicate tableFilterPredicate(String search, Severity severity) { + String searchLower = search.toLowerCase(); + return checkMessage -> { + + boolean matchesLine = checkMessage.getLine() != null && checkMessage.getLine().toString().contains(searchLower); + boolean matchesColumn = checkMessage.getColumn() != null && checkMessage.getColumn().toString().contains(searchLower); + + boolean matchesSearchString = + "".equals(search) // Special case: The empty search matches always. + || checkMessage.getMessageId().toString().toLowerCase().contains(searchLower) + || checkMessage.getMessage().toLowerCase().contains(searchLower) + || checkMessage.getSeverity().toString().contains(searchLower) + || checkMessage.getPath().contains(searchLower) + || matchesLine + || matchesColumn; + return matchesSearchString && isGreaterOrEqualSeverity(checkMessage.getSeverity(), severity); + }; + } + + private boolean isGreaterOrEqualSeverity(Severity a, Severity b) { + return a.toInt() >= b.toInt(); + } + + public void clearFilter(ActionEvent actionEvent) { + resultTableSearchFilter.setText(""); + resultTableSeverityFilter.getSelectionModel().select(de.pascalwagler.epubcheckfx.model.Severity.INFO); + } + private void initValidationResultTable() { - Property> authorListProperty = new SimpleObjectProperty<>(customReport.errorList); + resultTableSearchFilter.textProperty().addListener((observable, oldValue, newValue) -> { + log.info("search changed from " + oldValue + " to " + newValue); + if (Objects.equals(oldValue, newValue)) { + return; + } + filteredErrorList.setPredicate(tableFilterPredicate(newValue, resultTableSeverityFilter.getValue().getEbubcheckSeverity())); + }); + + resultTableSeverityFilter.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + log.info("severity changed from " + oldValue + " to " + newValue); + if (Objects.equals(oldValue, newValue)) { + return; + } + filteredErrorList.setPredicate(tableFilterPredicate(resultTableSearchFilter.getText(), newValue.getEbubcheckSeverity())); + }); + + filteredErrorList = customReport.errorList.filtered(checkMessage -> true); + Property> authorListProperty = new SimpleObjectProperty<>(filteredErrorList); validationResultTable.itemsProperty().bind(authorListProperty); messageId.setCellValueFactory(new PropertyValueFactory<>("messageId")); @@ -125,6 +181,20 @@ private TableCell createWrappingTableCell(TableColumn new TranslatableListCell<>(resourceBundle)); + resultTableSeverityFilter.getItems().addAll( + de.pascalwagler.epubcheckfx.model.Severity.SUPPRESSED, + de.pascalwagler.epubcheckfx.model.Severity.USAGE, + de.pascalwagler.epubcheckfx.model.Severity.INFO, + de.pascalwagler.epubcheckfx.model.Severity.WARNING, + de.pascalwagler.epubcheckfx.model.Severity.ERROR, + de.pascalwagler.epubcheckfx.model.Severity.FATAL + ); + resultTableSeverityFilter.setButtonCell(resultTableSeverityFilter.getCellFactory().call(null)); + resultTableSeverityFilter.getSelectionModel().select(de.pascalwagler.epubcheckfx.model.Severity.INFO); + } + private void initExportFormat() { exportFormat.setCellFactory(listView -> new TranslatableListCell<>(resourceBundle)); exportFormat.getItems().addAll( diff --git a/src/main/resources/fxml/MainContent.fxml b/src/main/resources/fxml/MainContent.fxml index 14b22db..e394e38 100644 --- a/src/main/resources/fxml/MainContent.fxml +++ b/src/main/resources/fxml/MainContent.fxml @@ -17,6 +17,21 @@ + + + + + + + + @@ -67,11 +82,12 @@ -