From 213636245de64032eef6108631643b9af8cc9b8b Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Wed, 30 Oct 2019 00:43:17 +0100 Subject: [PATCH 01/16] Initial --- src/main/java/org/jabref/gui/GUIGlobals.java | 2 +- .../gui/maintable/ColumnPreferences.java | 2 + .../gui/maintable/ExtraFileTableColumn.java | 42 ++++ .../jabref/gui/maintable/MainTableColumn.java | 12 +- .../gui/maintable/MainTableColumnFactory.java | 226 +++++------------- .../gui/maintable/MainTableColumnType.java | 42 ++++ .../gui/maintable/NormalTableColumn.java | 12 +- .../gui/maintable/SpecialTableColumn.java | 114 +++++++++ .../org/jabref/gui/util/MainTableUtils.java | 37 +++ .../jabref/preferences/JabRefPreferences.java | 4 +- 10 files changed, 313 insertions(+), 180 deletions(-) create mode 100644 src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java create mode 100644 src/main/java/org/jabref/gui/maintable/MainTableColumnType.java create mode 100644 src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java create mode 100644 src/main/java/org/jabref/gui/util/MainTableUtils.java diff --git a/src/main/java/org/jabref/gui/GUIGlobals.java b/src/main/java/org/jabref/gui/GUIGlobals.java index 909465a1e43..b3e38c50de9 100644 --- a/src/main/java/org/jabref/gui/GUIGlobals.java +++ b/src/main/java/org/jabref/gui/GUIGlobals.java @@ -22,7 +22,7 @@ public class GUIGlobals { public static CustomLocalDragboard localDragboard = new CustomLocalDragboard(); - public static final int WIDTH_ICON_COL = 16 + 12; // add some additional space to improve appearance + public static final int WIDTH_ICON_COLUMN = 16 + 12; // add some additional space to improve appearance public static final int WIDTH_ICON_COL_RANKING = 5 * 16; // Width of Ranking Icon Column diff --git a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java index f2a8364f7c7..5d71589caaa 100644 --- a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java +++ b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java @@ -7,7 +7,9 @@ public class ColumnPreferences { + public static final String QUALIFIER_SEPARATOR = ":"; public static final double DEFAULT_FIELD_LENGTH = 100; + private final boolean showFileColumn; private final boolean showUrlColumn; private final boolean preferDoiOverUrl; diff --git a/src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java b/src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java new file mode 100644 index 00000000000..aee073796a5 --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java @@ -0,0 +1,42 @@ +package org.jabref.gui.maintable; + +import java.util.List; +import java.util.stream.Collectors; + +import javafx.scene.control.TableColumn; + +import org.jabref.gui.GUIGlobals; +import org.jabref.gui.externalfiletype.ExternalFileType; +import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.gui.icon.IconTheme; +import org.jabref.gui.util.MainTableUtils; +import org.jabref.gui.util.ValueTableCellFactory; +import org.jabref.model.entry.LinkedFile; + +/** + * A column for specific file types. Shows the icon for the given type (or the FILE_MULTIPLE icon) + */ +public class ExtraFileTableColumn extends MainTableColumn> { + + /** + * Creates the column. + * + * @param externalFileTypes a list of available external file types + * @param externalFileTypeName the name of the externalFileType + */ + ExtraFileTableColumn(ExternalFileTypes externalFileTypes, String externalFileTypeName) { + super(MainTableColumnType.EXTRAFILE); + + TableColumn> column = new MainTableColumn<>(MainTableColumnType.EXTRAFILE); + column.setGraphic(externalFileTypes + .getExternalFileTypeByName(externalFileTypeName) + .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) + .getGraphicNode()); + column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); + MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); + new ValueTableCellFactory>() + .withGraphic(linkedFiles -> MainTableUtils.createFileIcon(externalFileTypes, linkedFiles.stream().filter(linkedFile -> linkedFile.getFileType().equalsIgnoreCase(externalFileTypeName)).collect(Collectors.toList()))) + .install(column); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java index 815f623f3a0..55c9d5327cd 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java @@ -1,15 +1,15 @@ package org.jabref.gui.maintable; -import javafx.beans.value.ObservableValue; import javafx.scene.control.TableColumn; -abstract class MainTableColumn extends TableColumn { +class MainTableColumn extends TableColumn { - MainTableColumn(String text) { - super(text); + MainTableColumnType columnType; - setCellValueFactory(param -> getColumnValue(param.getValue())); + MainTableColumn(MainTableColumnType columnType) { + this.columnType = columnType; } - abstract ObservableValue getColumnValue(BibEntryTableViewModel entry); + public MainTableColumnType getColumnType() { return columnType; } + } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index 0ed9b632c2a..551c7e31ca7 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -27,40 +27,28 @@ import org.jabref.gui.DialogService; import org.jabref.gui.GUIGlobals; import org.jabref.gui.desktop.JabRefDesktop; -import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.icon.JabRefIcon; -import org.jabref.gui.specialfields.SpecialFieldValueViewModel; -import org.jabref.gui.specialfields.SpecialFieldViewModel; -import org.jabref.gui.util.FieldsUtil; -import org.jabref.gui.util.OptionalValueTableCellFactory; +import org.jabref.gui.util.MainTableUtils; import org.jabref.gui.util.ValueTableCellFactory; -import org.jabref.gui.util.comparator.RankingFieldComparator; -import org.jabref.gui.util.comparator.ReadStatusFieldComparator; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.SpecialFieldValue; import org.jabref.model.entry.field.StandardField; import org.jabref.model.groups.AbstractGroup; import org.jabref.model.util.OptionalUtil; -import org.controlsfx.control.Rating; import org.fxmisc.easybind.EasyBind; import org.slf4j.Logger; import org.slf4j.LoggerFactory; class MainTableColumnFactory { - private static final String ICON_COLUMN = "column-icon"; - private static final String GROUP_COLUMN = "column-groups"; - private static final Logger LOGGER = LoggerFactory.getLogger(MainTableColumnFactory.class); private final ColumnPreferences preferences; @@ -70,7 +58,6 @@ class MainTableColumnFactory { private final UndoManager undoManager; private final DialogService dialogService; - public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences preferences, ExternalFileTypes externalFileTypes, UndoManager undoManager, DialogService dialogService) { this.database = Objects.requireNonNull(database); this.preferences = Objects.requireNonNull(preferences); @@ -82,44 +69,64 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre public List> createColumns() { List> columns = new ArrayList<>(); - columns.add(createGroupColumn()); - - if (preferences.showFileColumn()) { - columns.add(createFileColumn()); - } - if (preferences.showUrlColumn()) { - if (preferences.preferDoiOverUrl()) { - columns.add(createUrlOrDoiColumn(IconTheme.JabRefIcons.DOI, StandardField.DOI, StandardField.URL)); - } else { - columns.add(createUrlOrDoiColumn(IconTheme.JabRefIcons.WWW, StandardField.URL, StandardField.DOI)); - } - } - - if (preferences.showEprintColumn()) { - columns.add(createEprintColumn(IconTheme.JabRefIcons.WWW, StandardField.EPRINT)); - } - - preferences.getColumnNames().stream().map(FieldFactory::parseField).forEach(field -> { - if (field instanceof FieldsUtil.ExtraFilePseudoField) { - columns.add(createExtraFileColumn(field.getName())); - } else if (field instanceof SpecialField) { - columns.add(createSpecialFieldColumn((SpecialField) field)); + preferences.getColumnNames().forEach(columnName -> { + String[] columnTokens = columnName.split(ColumnPreferences.QUALIFIER_SEPARATOR); + MainTableColumnType type = MainTableColumnType.parse(columnTokens[0]); + Field field; + + switch (type) { + case GROUPS: + columns.add(createGroupColumn()); + break; + case FILE: + columns.add(createFileColumn()); + break; + case LINKED_IDENTIFIER: + if (preferences.preferDoiOverUrl()) { + columns.add(createUrlOrDoiColumn(IconTheme.JabRefIcons.DOI, StandardField.DOI, StandardField.URL)); } else { - columns.add(createNormalColumn(field)); + columns.add(createUrlOrDoiColumn(IconTheme.JabRefIcons.WWW, StandardField.URL, StandardField.DOI)); + } + columns.add(createEprintColumn(IconTheme.JabRefIcons.WWW, StandardField.EPRINT)); + break; + case EXTRAFILE: + if (columnTokens.length != 2) { + break; + } + columns.add(new ExtraFileTableColumn(externalFileTypes, columnTokens[1])); + break; + case SPECIALFIELD: + if (columnTokens.length != 2) { + break; + } + field = FieldFactory.parseField(columnTokens[1]); + if (field instanceof SpecialField) { + columns.add(new SpecialTableColumn(undoManager, (SpecialField) field)); } - }); + break; + case NORMALFIELD: + if (columnTokens.length != 2) { + break; + } + field = FieldFactory.parseField(columnTokens[1]); + columns.add(createNormalColumn(field)); + break; + default: + LOGGER.warn(Localization.lang("Column type %0 is unknown.", columnName)); + } + }); return columns; } private TableColumn createGroupColumn() { - TableColumn> column = new TableColumn<>(); + TableColumn> column = new MainTableColumn<>(MainTableColumnType.GROUPS); Node headerGraphic = IconTheme.JabRefIcons.DEFAULT_GROUP_ICON.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Group color"))); column.setGraphic(headerGraphic); - column.getStyleClass().add(ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL); + column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); + MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); column.setCellValueFactory(cellData -> cellData.getValue().getMatchedGroups(database)); new ValueTableCellFactory>() .withGraphic(this::createGroupColorRegion) @@ -173,100 +180,16 @@ private Node createGroupColorRegion(BibEntryTableViewModel entry, List> createSpecialFieldColumn(SpecialField specialField) { - TableColumn> column = new TableColumn<>(); - SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); - Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); - Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); - column.setGraphic(headerGraphic); - column.getStyleClass().add(ICON_COLUMN); - if (specialField == SpecialField.RANKING) { - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL_RANKING); - new OptionalValueTableCellFactory() - .withGraphicIfPresent(this::createRating) - .install(column); - } else { - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL); - - if (specialField.isSingleValueField()) { - new OptionalValueTableCellFactory() - .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) - .withOnMouseClickedEvent((entry, value) -> event -> { - if (event.getButton() == MouseButton.PRIMARY) { - specialFieldViewModel.toggle(entry.getEntry()); - } - }) - .install(column); - } else { - new OptionalValueTableCellFactory() - .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) - .withMenu((entry, value) -> createSpecialFieldMenu(entry.getEntry(), specialFieldViewModel)) - .install(column); - } - } - column.setCellValueFactory(cellData -> cellData.getValue().getSpecialField(specialField)); - - if (specialField == SpecialField.RANKING) { - column.setComparator(new RankingFieldComparator()); - } - - // Added comparator for Read Status - if (specialField == SpecialField.READ_STATUS) { - column.setComparator(new ReadStatusFieldComparator()); - } - - column.setSortable(true); - return column; - } - - private Rating createRating(BibEntryTableViewModel entry, SpecialFieldValueViewModel value) { - Rating ranking = new Rating(); - ranking.setRating(value.getValue().toRating()); - EasyBind.subscribe(ranking.ratingProperty(), rating -> - new SpecialFieldViewModel(SpecialField.RANKING, undoManager).setSpecialFieldValue(entry.getEntry(), SpecialFieldValue.getRating(rating.intValue())) - ); - return ranking; - } - - private ContextMenu createSpecialFieldMenu(BibEntry entry, SpecialFieldViewModel specialField) { - ContextMenu contextMenu = new ContextMenu(); - - for (SpecialFieldValueViewModel value : specialField.getValues()) { - MenuItem menuItem = new MenuItem(value.getMenuString(), value.getIcon().map(JabRefIcon::getGraphicNode).orElse(null)); - menuItem.setOnAction(event -> specialField.setSpecialFieldValue(entry, value.getValue())); - contextMenu.getItems().add(menuItem); - } - - return contextMenu; - } - - private Node createSpecialFieldIcon(Optional fieldValue, SpecialFieldViewModel specialField) { - return fieldValue - .flatMap(SpecialFieldValueViewModel::getIcon) - .map(JabRefIcon::getGraphicNode) - .orElseGet(() -> { - Node node = specialField.getEmptyIcon().getGraphicNode(); - node.getStyleClass().add("empty-special-field"); - return node; - }); - } - - private void setExactWidth(TableColumn column, int width) { - column.setMinWidth(width); - column.setPrefWidth(width); - column.setMaxWidth(width); - } - private TableColumn> createFileColumn() { - TableColumn> column = new TableColumn<>(); + TableColumn> column = new MainTableColumn<>(MainTableColumnType.FILE); Node headerGraphic = IconTheme.JabRefIcons.FILE.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked files"))); column.setGraphic(headerGraphic); - column.getStyleClass().add(ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL); + column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); + MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); new ValueTableCellFactory>() - .withGraphic(this::createFileIcon) + .withGraphic(filetype -> MainTableUtils.createFileIcon(externalFileTypes, filetype)) .withTooltip(this::createFileTooltip) .withMenu(this::createFileMenu) .withOnMouseClickedEvent((entry, linkedFiles) -> event -> { @@ -310,12 +233,12 @@ private ContextMenu createFileMenu(BibEntryTableViewModel entry, List createUrlOrDoiColumn(JabRefIcon icon, Field firstField, Field secondField) { - TableColumn column = new TableColumn<>(); + TableColumn column = new MainTableColumn<>(MainTableColumnType.LINKED_IDENTIFIER); Node headerGraphic = icon.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(firstField.getDisplayName() + " / " + secondField.getDisplayName())); column.setGraphic(headerGraphic); - column.getStyleClass().add(ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL); + column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); + MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); // icon is chosen based on field name in cell, so map fields to its names column.setCellValueFactory(cellData -> EasyBind.monadic(cellData.getValue().getField(firstField)).map(x -> firstField).orElse(EasyBind.monadic(cellData.getValue().getField(secondField)).map(x -> secondField))); new ValueTableCellFactory() @@ -361,10 +284,10 @@ private String createIdentifierTooltip(BibEntryTableViewModel entry, Field field } private TableColumn createEprintColumn(JabRefIcon icon, Field field) { - TableColumn column = new TableColumn<>(); + TableColumn column = new MainTableColumn<>(MainTableColumnType.LINKED_IDENTIFIER); column.setGraphic(icon.getGraphicNode()); - column.getStyleClass().add(ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL); + column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); + MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); column.setCellValueFactory(cellData -> EasyBind.monadic(cellData.getValue().getField(field)).map(x -> field)); new ValueTableCellFactory() .withGraphic(cellFactory::getTableIcon) @@ -373,37 +296,4 @@ private TableColumn createEprintColumn(JabRefIcon .install(column); return column; } - - /** - * Creates a column for specific file types. Shows the icon for the given type (or the FILE_MULTIPLE icon) - * - * @param externalFileTypeName the name of the externalFileType - */ - private TableColumn> createExtraFileColumn(String externalFileTypeName) { - TableColumn> column = new TableColumn<>(); - column.setGraphic( - externalFileTypes.getExternalFileTypeByName(externalFileTypeName) - .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) - .getGraphicNode()); - column.getStyleClass().add(ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL); - column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); - new ValueTableCellFactory>() - .withGraphic(linkedFiles -> createFileIcon(linkedFiles.stream().filter(linkedFile -> linkedFile.getFileType().equalsIgnoreCase(externalFileTypeName)).collect(Collectors.toList()))) - .install(column); - return column; - } - - private Node createFileIcon(List linkedFiles) { - if (linkedFiles.size() > 1) { - return IconTheme.JabRefIcons.FILE_MULTIPLE.getGraphicNode(); - } else if (linkedFiles.size() == 1) { - return externalFileTypes.fromLinkedFile(linkedFiles.get(0), false) - .map(ExternalFileType::getIcon) - .orElse(IconTheme.JabRefIcons.FILE) - .getGraphicNode(); - } else { - return null; - } - } } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnType.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnType.java new file mode 100644 index 00000000000..a9fa22d9a0d --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnType.java @@ -0,0 +1,42 @@ +package org.jabref.gui.maintable; + +import org.jabref.logic.l10n.Localization; + +public enum MainTableColumnType { + + GROUPS("groups"), + FILE("file"), + EXTRAFILE("extrafile", Localization.lang("File type")), + LINKED_IDENTIFIER("linked_id"), + SPECIALFIELD("special", Localization.lang("Special")), + NORMALFIELD("field"); + + private String qualifier; + private String displayName; + + MainTableColumnType(String qualifier) { + this.qualifier = qualifier; + } + + MainTableColumnType(String qualifier, String displayName) { + this(qualifier); + this.displayName = displayName; + } + + public String getQualifier() { return qualifier; } + + public String getDisplayName() { return displayName; } + + public static MainTableColumnType parse(String text) { + switch (text) { + case "groups": return GROUPS; + case "file": return FILE; + case "extrafile": return EXTRAFILE; + case "linked_id": return LINKED_IDENTIFIER; + case "special": return SPECIALFIELD; + + case "field": + default: return NORMALFIELD; + } + } +} diff --git a/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java b/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java index 11a8bc7861a..0e6bfb4a12b 100644 --- a/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java +++ b/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java @@ -18,6 +18,9 @@ import org.jabref.model.entry.field.InternalField; import org.jabref.model.entry.field.OrFields; +/** + * A column that displays the text-value of the field + */ public class NormalTableColumn extends MainTableColumn { private final OrFields bibtexFields; @@ -32,12 +35,16 @@ public class NormalTableColumn extends MainTableColumn { private final String columnName; public NormalTableColumn(String columnName, OrFields bibtexFields, BibDatabase database) { - super(columnName); + super(MainTableColumnType.NORMALFIELD); + this.columnName = columnName; this.bibtexFields = bibtexFields; this.isIconColumn = false; this.iconLabel = Optional.empty(); this.database = Optional.of(database); + + setText(columnName); + setCellValueFactory(param -> getColumnValue(param.getValue())); } /** @@ -49,7 +56,6 @@ public String getDisplayName() { return bibtexFields.getDisplayName(); } - @Override public ObservableValue getColumnValue(BibEntryTableViewModel entry) { if (bibtexFields.isEmpty()) { return null; @@ -96,7 +102,7 @@ public Node getHeaderLabel() { * The reasons for being different are (combinations may also happen): - The entry has a crossref where the field * content is obtained from - The field has a string in it (which getColumnValue() resolves) - There are some alias * fields. For example, if the entry has a date field but no year field, {@link - * BibEntry#getResolvedFieldOrAlias(String, BibDatabase)} will return the year value from the date field when + * BibEntry#getResolvedFieldOrAlias(Field, BibDatabase)} will return the year value from the date field when * queried for year * * @param entry the BibEntry diff --git a/src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java b/src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java new file mode 100644 index 00000000000..83ff8f5be4f --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java @@ -0,0 +1,114 @@ +package org.jabref.gui.maintable; + +import java.util.Optional; + +import javax.swing.undo.UndoManager; + +import javafx.scene.Node; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.control.Tooltip; +import javafx.scene.input.MouseButton; + +import org.jabref.gui.GUIGlobals; +import org.jabref.gui.icon.JabRefIcon; +import org.jabref.gui.specialfields.SpecialFieldValueViewModel; +import org.jabref.gui.specialfields.SpecialFieldViewModel; +import org.jabref.gui.util.MainTableUtils; +import org.jabref.gui.util.OptionalValueTableCellFactory; +import org.jabref.gui.util.comparator.RankingFieldComparator; +import org.jabref.gui.util.comparator.ReadStatusFieldComparator; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.SpecialField; +import org.jabref.model.entry.field.SpecialFieldValue; + +import org.controlsfx.control.Rating; +import org.fxmisc.easybind.EasyBind; + +/** + * A column that displays a specialField + */ +public class SpecialTableColumn extends MainTableColumn> { + + private final UndoManager undoManager; + + public SpecialTableColumn(UndoManager undoManager, SpecialField specialField) { + super(MainTableColumnType.SPECIALFIELD); + + this.undoManager = undoManager; + + SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); + Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); + Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); + setGraphic(headerGraphic); + getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); + if (specialField == SpecialField.RANKING) { + MainTableUtils.setExactWidth(this, GUIGlobals.WIDTH_ICON_COL_RANKING); + new OptionalValueTableCellFactory() + .withGraphicIfPresent(this::createRating) + .install(this); + } else { + MainTableUtils.setExactWidth(this, GUIGlobals.WIDTH_ICON_COLUMN); + + if (specialField.isSingleValueField()) { + new OptionalValueTableCellFactory() + .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) + .withOnMouseClickedEvent((entry, value) -> event -> { + if (event.getButton() == MouseButton.PRIMARY) { + specialFieldViewModel.toggle(entry.getEntry()); + } + }) + .install(this); + } else { + new OptionalValueTableCellFactory() + .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) + .withMenu((entry, value) -> createSpecialFieldMenu(entry.getEntry(), specialFieldViewModel)) + .install(this); + } + } + this.setCellValueFactory(cellData -> cellData.getValue().getSpecialField(specialField)); + + if (specialField == SpecialField.RANKING) { + this.setComparator(new RankingFieldComparator()); + } + + // Added comparator for Read Status + if (specialField == SpecialField.READ_STATUS) { + this.setComparator(new ReadStatusFieldComparator()); + } + + this.setSortable(true); + } + + private Rating createRating(BibEntryTableViewModel entry, SpecialFieldValueViewModel value) { + Rating ranking = new Rating(); + ranking.setRating(value.getValue().toRating()); + EasyBind.subscribe(ranking.ratingProperty(), rating -> + new SpecialFieldViewModel(SpecialField.RANKING, undoManager).setSpecialFieldValue(entry.getEntry(), SpecialFieldValue.getRating(rating.intValue())) + ); + return ranking; + } + + private ContextMenu createSpecialFieldMenu(BibEntry entry, SpecialFieldViewModel specialField) { + ContextMenu contextMenu = new ContextMenu(); + + for (SpecialFieldValueViewModel value : specialField.getValues()) { + MenuItem menuItem = new MenuItem(value.getMenuString(), value.getIcon().map(JabRefIcon::getGraphicNode).orElse(null)); + menuItem.setOnAction(event -> specialField.setSpecialFieldValue(entry, value.getValue())); + contextMenu.getItems().add(menuItem); + } + + return contextMenu; + } + + private Node createSpecialFieldIcon(Optional fieldValue, SpecialFieldViewModel specialField) { + return fieldValue + .flatMap(SpecialFieldValueViewModel::getIcon) + .map(JabRefIcon::getGraphicNode) + .orElseGet(() -> { + Node node = specialField.getEmptyIcon().getGraphicNode(); + node.getStyleClass().add("empty-special-field"); + return node; + }); + } +} diff --git a/src/main/java/org/jabref/gui/util/MainTableUtils.java b/src/main/java/org/jabref/gui/util/MainTableUtils.java new file mode 100644 index 00000000000..c301e81fa30 --- /dev/null +++ b/src/main/java/org/jabref/gui/util/MainTableUtils.java @@ -0,0 +1,37 @@ +package org.jabref.gui.util; + +import java.util.List; + +import javafx.scene.Node; +import javafx.scene.control.TableColumn; + +import org.jabref.gui.externalfiletype.ExternalFileType; +import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.gui.icon.IconTheme; +import org.jabref.model.entry.LinkedFile; + +public class MainTableUtils { + + public static final String STYLE_ICON_COLUMN = "column-icon"; + + private MainTableUtils() { } + + public static void setExactWidth(TableColumn column, int width) { + column.setMinWidth(width); + column.setPrefWidth(width); + column.setMaxWidth(width); + } + + public static Node createFileIcon(ExternalFileTypes externalFileTypes, List linkedFiles) { + if (linkedFiles.size() > 1) { + return IconTheme.JabRefIcons.FILE_MULTIPLE.getGraphicNode(); + } else if (linkedFiles.size() == 1) { + return externalFileTypes.fromLinkedFile(linkedFiles.get(0), false) + .map(ExternalFileType::getIcon) + .orElse(IconTheme.JabRefIcons.FILE) + .getGraphicNode(); + } else { + return null; + } + } +} diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 3d59d2ecbd9..3a90fdbefaa 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -525,8 +525,8 @@ private JabRefPreferences() { defaults.put(SIDE_PANE_COMPONENT_NAMES, ""); defaults.put(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS, ""); - defaults.put(COLUMN_NAMES, "entrytype;author/editor;title;year;journal/booktitle;bibtexkey"); - defaults.put(COLUMN_WIDTHS, "75;300;470;60;130;100"); + defaults.put(COLUMN_NAMES, "groups;linked_id;field:entrytype;field:author/editor;field:title;field:year;field:journal/booktitle;field:bibtexkey"); + defaults.put(COLUMN_WIDTHS, "28;28;75;300;470;60;130;100"); defaults.put(XMP_PRIVACY_FILTERS, "pdf;timestamp;keywords;owner;note;review"); defaults.put(USE_XMP_PRIVACY_FILTER, Boolean.FALSE); From 9759a5a662954e9b14dbce3f57f86a6419b4b2e3 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Wed, 30 Oct 2019 15:10:54 +0100 Subject: [PATCH 02/16] Added combined identifier column --- .../gui/maintable/BibEntryTableViewModel.java | 13 + .../gui/maintable/ExtraFileTableColumn.java | 42 --- .../gui/maintable/MainTableColumnFactory.java | 299 ++++++++++++------ .../gui/maintable/SpecialTableColumn.java | 114 ------- .../org/jabref/gui/util/MainTableUtils.java | 37 --- src/main/resources/l10n/JabRef_en.properties | 6 +- 6 files changed, 225 insertions(+), 286 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java delete mode 100644 src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java delete mode 100644 src/main/java/org/jabref/gui/util/MainTableUtils.java diff --git a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java index af7358b450b..d7391790d7a 100644 --- a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java +++ b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java @@ -1,7 +1,9 @@ package org.jabref.gui.maintable; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -50,6 +52,17 @@ public ObservableValue> getLinkedFiles() { return EasyBind.map(getField(StandardField.FILE), FileFieldParser::parse); } + public ObservableValue> getLinkedIdentifiers() { + SimpleObjectProperty> linkedIdentifiers = new SimpleObjectProperty<>(new HashMap<>()); + + entry.getField(StandardField.URL).ifPresent(value -> linkedIdentifiers.getValue().put(StandardField.URL, value)); + entry.getField(StandardField.DOI).ifPresent(value -> linkedIdentifiers.getValue().put(StandardField.DOI, value)); + entry.getField(StandardField.URI).ifPresent(value -> linkedIdentifiers.getValue().put(StandardField.URI, value)); + entry.getField(StandardField.EPRINT).ifPresent(value -> linkedIdentifiers.getValue().put(StandardField.EPRINT, value)); + + return linkedIdentifiers; + } + public ObservableValue> getMatchedGroups(BibDatabaseContext database) { SimpleObjectProperty> matchedGroups = new SimpleObjectProperty<>(Collections.emptyList()); diff --git a/src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java b/src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java deleted file mode 100644 index aee073796a5..00000000000 --- a/src/main/java/org/jabref/gui/maintable/ExtraFileTableColumn.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jabref.gui.maintable; - -import java.util.List; -import java.util.stream.Collectors; - -import javafx.scene.control.TableColumn; - -import org.jabref.gui.GUIGlobals; -import org.jabref.gui.externalfiletype.ExternalFileType; -import org.jabref.gui.externalfiletype.ExternalFileTypes; -import org.jabref.gui.icon.IconTheme; -import org.jabref.gui.util.MainTableUtils; -import org.jabref.gui.util.ValueTableCellFactory; -import org.jabref.model.entry.LinkedFile; - -/** - * A column for specific file types. Shows the icon for the given type (or the FILE_MULTIPLE icon) - */ -public class ExtraFileTableColumn extends MainTableColumn> { - - /** - * Creates the column. - * - * @param externalFileTypes a list of available external file types - * @param externalFileTypeName the name of the externalFileType - */ - ExtraFileTableColumn(ExternalFileTypes externalFileTypes, String externalFileTypeName) { - super(MainTableColumnType.EXTRAFILE); - - TableColumn> column = new MainTableColumn<>(MainTableColumnType.EXTRAFILE); - column.setGraphic(externalFileTypes - .getExternalFileTypeByName(externalFileTypeName) - .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) - .getGraphicNode()); - column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); - MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); - column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); - new ValueTableCellFactory>() - .withGraphic(linkedFiles -> MainTableUtils.createFileIcon(externalFileTypes, linkedFiles.stream().filter(linkedFile -> linkedFile.getFileType().equalsIgnoreCase(externalFileTypeName)).collect(Collectors.toList()))) - .install(column); - } -} diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index 551c7e31ca7..affa78727d6 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -17,7 +18,6 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.Tooltip; import javafx.scene.input.MouseButton; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; @@ -27,28 +27,37 @@ import org.jabref.gui.DialogService; import org.jabref.gui.GUIGlobals; import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.icon.JabRefIcon; -import org.jabref.gui.util.MainTableUtils; +import org.jabref.gui.specialfields.SpecialFieldValueViewModel; +import org.jabref.gui.specialfields.SpecialFieldViewModel; +import org.jabref.gui.util.OptionalValueTableCellFactory; import org.jabref.gui.util.ValueTableCellFactory; +import org.jabref.gui.util.comparator.RankingFieldComparator; +import org.jabref.gui.util.comparator.ReadStatusFieldComparator; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.field.SpecialField; +import org.jabref.model.entry.field.SpecialFieldValue; import org.jabref.model.entry.field.StandardField; import org.jabref.model.groups.AbstractGroup; import org.jabref.model.util.OptionalUtil; +import org.controlsfx.control.Rating; import org.fxmisc.easybind.EasyBind; import org.slf4j.Logger; import org.slf4j.LoggerFactory; class MainTableColumnFactory { + private static final String STYLE_ICON_COLUMN = "column-icon"; private static final Logger LOGGER = LoggerFactory.getLogger(MainTableColumnFactory.class); private final ColumnPreferences preferences; @@ -83,34 +92,29 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre columns.add(createFileColumn()); break; case LINKED_IDENTIFIER: - if (preferences.preferDoiOverUrl()) { - columns.add(createUrlOrDoiColumn(IconTheme.JabRefIcons.DOI, StandardField.DOI, StandardField.URL)); - } else { - columns.add(createUrlOrDoiColumn(IconTheme.JabRefIcons.WWW, StandardField.URL, StandardField.DOI)); - } - columns.add(createEprintColumn(IconTheme.JabRefIcons.WWW, StandardField.EPRINT)); + columns.add(createIdentifierColumn()); break; case EXTRAFILE: - if (columnTokens.length != 2) { - break; + if (columnTokens.length == 2) { + columns.add(createExtraFileColumn(columnTokens[1])); } - columns.add(new ExtraFileTableColumn(externalFileTypes, columnTokens[1])); break; case SPECIALFIELD: - if (columnTokens.length != 2) { - break; - } - field = FieldFactory.parseField(columnTokens[1]); - if (field instanceof SpecialField) { - columns.add(new SpecialTableColumn(undoManager, (SpecialField) field)); + if (columnTokens.length == 2) { + field = FieldFactory.parseField(columnTokens[1]); + if (field instanceof SpecialField) { + columns.add(createSpecialFieldColumn((SpecialField) field)); + } else { + LOGGER.warn(Localization.lang("Special field type %0 is unknown. Using normal column type.", columnTokens[1])); + columns.add(createNormalColumn(field)); + } } break; case NORMALFIELD: - if (columnTokens.length != 2) { - break; + if (columnTokens.length == 2) { + field = FieldFactory.parseField(columnTokens[1]); + columns.add(createNormalColumn(field)); } - field = FieldFactory.parseField(columnTokens[1]); - columns.add(createNormalColumn(field)); break; default: LOGGER.warn(Localization.lang("Column type %0 is unknown.", columnName)); @@ -120,13 +124,22 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre return columns; } + private void setExactWidth(TableColumn column, int width) { + column.setMinWidth(width); + column.setPrefWidth(width); + column.setMaxWidth(width); + } + + /** + * Creates a column for group color bars. + */ private TableColumn createGroupColumn() { TableColumn> column = new MainTableColumn<>(MainTableColumnType.GROUPS); Node headerGraphic = IconTheme.JabRefIcons.DEFAULT_GROUP_ICON.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Group color"))); column.setGraphic(headerGraphic); - column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); - MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + column.getStyleClass().add(STYLE_ICON_COLUMN); + setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); column.setCellValueFactory(cellData -> cellData.getValue().getMatchedGroups(database)); new ValueTableCellFactory>() .withGraphic(this::createGroupColorRegion) @@ -169,37 +182,44 @@ private Node createGroupColorRegion(BibEntryTableViewModel entry, List createNormalColumn(Field field) { String columnName = field.getName(); NormalTableColumn column = new NormalTableColumn(columnName, FieldFactory.parseOrFields(columnName), database.getDatabase()); - new ValueTableCellFactory() - .withText(text -> text) - .install(column); - column.setSortable(true); - column.setPrefWidth(preferences.getColumnWidth(columnName)); + new ValueTableCellFactory() + .withText(text -> text) + .install(column); + column.setSortable(true); + column.setPrefWidth(preferences.getColumnWidth(columnName)); return column; } + /** + * Creates a column for all the linked files. Instead of creating a column for a single file type, like + * {@code createExtraFileColumn} does, this creates one single column collecting all file links. + */ private TableColumn> createFileColumn() { TableColumn> column = new MainTableColumn<>(MainTableColumnType.FILE); Node headerGraphic = IconTheme.JabRefIcons.FILE.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked files"))); column.setGraphic(headerGraphic); - column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); - MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + column.getStyleClass().add(STYLE_ICON_COLUMN); + setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); - new ValueTableCellFactory>() - .withGraphic(filetype -> MainTableUtils.createFileIcon(externalFileTypes, filetype)) - .withTooltip(this::createFileTooltip) - .withMenu(this::createFileMenu) - .withOnMouseClickedEvent((entry, linkedFiles) -> event -> { - if ((event.getButton() == MouseButton.PRIMARY) && (linkedFiles.size() == 1)) { - // Only one linked file -> open directly - LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFiles.get(0), entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs.getXMPPreferences(), Globals.prefs.getFilePreferences(), externalFileTypes); - linkedFileViewModel.open(); - } - }) - .install(column); + new ValueTableCellFactory>() + .withGraphic(this::createFileIcon) + .withTooltip(this::createFileTooltip) + .withMenu(this::createFileMenu) + .withOnMouseClickedEvent((entry, linkedFiles) -> event -> { + if ((event.getButton() == MouseButton.PRIMARY) && (linkedFiles.size() == 1)) { + // Only one linked file -> open directly + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFiles.get(0), entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs.getXMPPreferences(), Globals.prefs.getFilePreferences(), externalFileTypes); + linkedFileViewModel.open(); + } + }) + .install(column); return column; } @@ -228,72 +248,169 @@ private ContextMenu createFileMenu(BibEntryTableViewModel entry, List linkedFiles) { + if (linkedFiles.size() > 1) { + return IconTheme.JabRefIcons.FILE_MULTIPLE.getGraphicNode(); + } else if (linkedFiles.size() == 1) { + return externalFileTypes.fromLinkedFile(linkedFiles.get(0), false) + .map(ExternalFileType::getIcon) + .orElse(IconTheme.JabRefIcons.FILE) + .getGraphicNode(); + } else { + return null; + } + } + /** - * Creates a column for DOIs or URLs. - * The {@code firstField} is preferred to be shown over {@code secondField}. + * Creates a column for all the linked files of a single file type. */ - private TableColumn createUrlOrDoiColumn(JabRefIcon icon, Field firstField, Field secondField) { - TableColumn column = new MainTableColumn<>(MainTableColumnType.LINKED_IDENTIFIER); - Node headerGraphic = icon.getGraphicNode(); - Tooltip.install(headerGraphic, new Tooltip(firstField.getDisplayName() + " / " + secondField.getDisplayName())); + private TableColumn> createExtraFileColumn(String externalFileTypeName) { + TableColumn> column = new MainTableColumn<>(MainTableColumnType.EXTRAFILE); + column.setGraphic(externalFileTypes + .getExternalFileTypeByName(externalFileTypeName) + .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) + .getGraphicNode()); + column.getStyleClass().add(STYLE_ICON_COLUMN); + setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); + new ValueTableCellFactory>() + .withGraphic(linkedFiles -> createFileIcon(linkedFiles.stream().filter(linkedFile -> linkedFile.getFileType().equalsIgnoreCase(externalFileTypeName)).collect(Collectors.toList()))) + .install(column); + + return column; + } + + /** + * Creates a clickable icons column for DOIs, URLs, URIs and EPrints. + */ + private TableColumn> createIdentifierColumn() { + TableColumn> column = new MainTableColumn<>(MainTableColumnType.LINKED_IDENTIFIER); + Node headerGraphic = IconTheme.JabRefIcons.WWW.getGraphicNode(); + Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked identifiers"))); column.setGraphic(headerGraphic); - column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); - MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); - // icon is chosen based on field name in cell, so map fields to its names - column.setCellValueFactory(cellData -> EasyBind.monadic(cellData.getValue().getField(firstField)).map(x -> firstField).orElse(EasyBind.monadic(cellData.getValue().getField(secondField)).map(x -> secondField))); - new ValueTableCellFactory() - .withGraphic(cellFactory::getTableIcon) + column.getStyleClass().add(STYLE_ICON_COLUMN); + setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + column.setCellValueFactory(cellData -> cellData.getValue().getLinkedIdentifiers()); + new ValueTableCellFactory>() + .withGraphic(this::createIdentifierGraphic) .withTooltip(this::createIdentifierTooltip) - .withOnMouseClickedEvent((BibEntryTableViewModel entry, Field content) -> (MouseEvent event) -> openUrlOrDoi(event, entry, content)) + .withMenu(this::createIdentifierMenu) .install(column); return column; } - private void openUrlOrDoi(MouseEvent event, BibEntryTableViewModel entry, Field field) { - if (event.getButton() != MouseButton.PRIMARY) { - return; + private Node createIdentifierGraphic(Map values) { + if (values.isEmpty()) { + return null; + } else { + return cellFactory.getTableIcon(StandardField.URL); } + } - if (!entry.getEntry().hasField(field)) { - LOGGER.error("Requested opening viewer for {} of entry '{}', but field is not present.", field, entry.getEntry().getId()); - return; - } + private String createIdentifierTooltip(Map values) { + StringBuilder identifiers = new StringBuilder(); + values.keySet().forEach(field -> identifiers.append(field.getDisplayName()).append(": ").append(values.get(field)).append("\n")); + return identifiers.toString(); + } - entry.getEntry().getField(field).ifPresent(identifier -> { - try { - JabRefDesktop.openExternalViewer(database, identifier, field); - } catch (IOException e) { - dialogService.showErrorDialogAndWait(Localization.lang("Unable to open link."), e); - } + private ContextMenu createIdentifierMenu(BibEntryTableViewModel entry, Map values) { + ContextMenu contextMenu = new ContextMenu(); + + values.keySet().forEach(field -> { + MenuItem menuItem = new MenuItem(field.getDisplayName() + ": " + values.get(field), cellFactory.getTableIcon(field)); + menuItem.setOnAction(event -> { + try { + JabRefDesktop.openExternalViewer(database, values.get(field), field); + } catch (IOException e) { + dialogService.showErrorDialogAndWait(Localization.lang("Unable to open link."), e); + } + event.consume(); + }); + contextMenu.getItems().add(menuItem); }); - event.consume(); + + return contextMenu; } - private String createIdentifierTooltip(BibEntryTableViewModel entry, Field field) { - Optional value = entry.getEntry().getField(field); - if (value.isPresent()) { - if (StandardField.DOI.equals(field)) { - return Localization.lang("Open %0 URL (%1)", "DOI", value.get()); - } else if (StandardField.URL.equals(field)) { - return Localization.lang("Open URL (%0)", value.get()); - } else if (StandardField.EPRINT.equals(field)) { - return Localization.lang("Open %0 URL (%1)", "ArXiv", value.get()); + /** + * A column that displays a specialField + */ + private TableColumn> createSpecialFieldColumn(SpecialField specialField) { + TableColumn> column = new MainTableColumn<>(MainTableColumnType.SPECIALFIELD); + SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); + Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); + Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); + column.setGraphic(headerGraphic); + column.getStyleClass().add(STYLE_ICON_COLUMN); + if (specialField == SpecialField.RANKING) { + setExactWidth(column, GUIGlobals.WIDTH_ICON_COL_RANKING); + new OptionalValueTableCellFactory() + .withGraphicIfPresent(this::createSpecialRating) + .install(column); + } else { + setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + + if (specialField.isSingleValueField()) { + new OptionalValueTableCellFactory() + .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) + .withOnMouseClickedEvent((entry, value) -> event -> { + if (event.getButton() == MouseButton.PRIMARY) { + specialFieldViewModel.toggle(entry.getEntry()); + } + }) + .install(column); + } else { + new OptionalValueTableCellFactory() + .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) + .withMenu((entry, value) -> createSpecialFieldMenu(entry.getEntry(), specialFieldViewModel)) + .install(column); } } - return null; - } + column.setCellValueFactory(cellData -> cellData.getValue().getSpecialField(specialField)); + + if (specialField == SpecialField.RANKING) { + column.setComparator(new RankingFieldComparator()); + } + + // Added comparator for Read Status + if (specialField == SpecialField.READ_STATUS) { + column.setComparator(new ReadStatusFieldComparator()); + } + + column.setSortable(true); - private TableColumn createEprintColumn(JabRefIcon icon, Field field) { - TableColumn column = new MainTableColumn<>(MainTableColumnType.LINKED_IDENTIFIER); - column.setGraphic(icon.getGraphicNode()); - column.getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); - MainTableUtils.setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); - column.setCellValueFactory(cellData -> EasyBind.monadic(cellData.getValue().getField(field)).map(x -> field)); - new ValueTableCellFactory() - .withGraphic(cellFactory::getTableIcon) - .withTooltip(this::createIdentifierTooltip) - .withOnMouseClickedEvent((BibEntryTableViewModel entry, Field content) -> (MouseEvent event) -> openUrlOrDoi(event, entry, field)) - .install(column); return column; } + + private Rating createSpecialRating(BibEntryTableViewModel entry, SpecialFieldValueViewModel value) { + Rating ranking = new Rating(); + ranking.setRating(value.getValue().toRating()); + EasyBind.subscribe(ranking.ratingProperty(), rating -> + new SpecialFieldViewModel(SpecialField.RANKING, undoManager).setSpecialFieldValue(entry.getEntry(), SpecialFieldValue.getRating(rating.intValue())) + ); + return ranking; + } + + private ContextMenu createSpecialFieldMenu(BibEntry entry, SpecialFieldViewModel specialField) { + ContextMenu contextMenu = new ContextMenu(); + + for (SpecialFieldValueViewModel value : specialField.getValues()) { + MenuItem menuItem = new MenuItem(value.getMenuString(), value.getIcon().map(JabRefIcon::getGraphicNode).orElse(null)); + menuItem.setOnAction(event -> specialField.setSpecialFieldValue(entry, value.getValue())); + contextMenu.getItems().add(menuItem); + } + + return contextMenu; + } + + private Node createSpecialFieldIcon(Optional fieldValue, SpecialFieldViewModel specialField) { + return fieldValue + .flatMap(SpecialFieldValueViewModel::getIcon) + .map(JabRefIcon::getGraphicNode) + .orElseGet(() -> { + Node node = specialField.getEmptyIcon().getGraphicNode(); + node.getStyleClass().add("empty-special-field"); + return node; + }); + } } diff --git a/src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java b/src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java deleted file mode 100644 index 83ff8f5be4f..00000000000 --- a/src/main/java/org/jabref/gui/maintable/SpecialTableColumn.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.jabref.gui.maintable; - -import java.util.Optional; - -import javax.swing.undo.UndoManager; - -import javafx.scene.Node; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; -import javafx.scene.control.Tooltip; -import javafx.scene.input.MouseButton; - -import org.jabref.gui.GUIGlobals; -import org.jabref.gui.icon.JabRefIcon; -import org.jabref.gui.specialfields.SpecialFieldValueViewModel; -import org.jabref.gui.specialfields.SpecialFieldViewModel; -import org.jabref.gui.util.MainTableUtils; -import org.jabref.gui.util.OptionalValueTableCellFactory; -import org.jabref.gui.util.comparator.RankingFieldComparator; -import org.jabref.gui.util.comparator.ReadStatusFieldComparator; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.SpecialFieldValue; - -import org.controlsfx.control.Rating; -import org.fxmisc.easybind.EasyBind; - -/** - * A column that displays a specialField - */ -public class SpecialTableColumn extends MainTableColumn> { - - private final UndoManager undoManager; - - public SpecialTableColumn(UndoManager undoManager, SpecialField specialField) { - super(MainTableColumnType.SPECIALFIELD); - - this.undoManager = undoManager; - - SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); - Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); - Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); - setGraphic(headerGraphic); - getStyleClass().add(MainTableUtils.STYLE_ICON_COLUMN); - if (specialField == SpecialField.RANKING) { - MainTableUtils.setExactWidth(this, GUIGlobals.WIDTH_ICON_COL_RANKING); - new OptionalValueTableCellFactory() - .withGraphicIfPresent(this::createRating) - .install(this); - } else { - MainTableUtils.setExactWidth(this, GUIGlobals.WIDTH_ICON_COLUMN); - - if (specialField.isSingleValueField()) { - new OptionalValueTableCellFactory() - .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) - .withOnMouseClickedEvent((entry, value) -> event -> { - if (event.getButton() == MouseButton.PRIMARY) { - specialFieldViewModel.toggle(entry.getEntry()); - } - }) - .install(this); - } else { - new OptionalValueTableCellFactory() - .withGraphic((entry, value) -> createSpecialFieldIcon(value, specialFieldViewModel)) - .withMenu((entry, value) -> createSpecialFieldMenu(entry.getEntry(), specialFieldViewModel)) - .install(this); - } - } - this.setCellValueFactory(cellData -> cellData.getValue().getSpecialField(specialField)); - - if (specialField == SpecialField.RANKING) { - this.setComparator(new RankingFieldComparator()); - } - - // Added comparator for Read Status - if (specialField == SpecialField.READ_STATUS) { - this.setComparator(new ReadStatusFieldComparator()); - } - - this.setSortable(true); - } - - private Rating createRating(BibEntryTableViewModel entry, SpecialFieldValueViewModel value) { - Rating ranking = new Rating(); - ranking.setRating(value.getValue().toRating()); - EasyBind.subscribe(ranking.ratingProperty(), rating -> - new SpecialFieldViewModel(SpecialField.RANKING, undoManager).setSpecialFieldValue(entry.getEntry(), SpecialFieldValue.getRating(rating.intValue())) - ); - return ranking; - } - - private ContextMenu createSpecialFieldMenu(BibEntry entry, SpecialFieldViewModel specialField) { - ContextMenu contextMenu = new ContextMenu(); - - for (SpecialFieldValueViewModel value : specialField.getValues()) { - MenuItem menuItem = new MenuItem(value.getMenuString(), value.getIcon().map(JabRefIcon::getGraphicNode).orElse(null)); - menuItem.setOnAction(event -> specialField.setSpecialFieldValue(entry, value.getValue())); - contextMenu.getItems().add(menuItem); - } - - return contextMenu; - } - - private Node createSpecialFieldIcon(Optional fieldValue, SpecialFieldViewModel specialField) { - return fieldValue - .flatMap(SpecialFieldValueViewModel::getIcon) - .map(JabRefIcon::getGraphicNode) - .orElseGet(() -> { - Node node = specialField.getEmptyIcon().getGraphicNode(); - node.getStyleClass().add("empty-special-field"); - return node; - }); - } -} diff --git a/src/main/java/org/jabref/gui/util/MainTableUtils.java b/src/main/java/org/jabref/gui/util/MainTableUtils.java deleted file mode 100644 index c301e81fa30..00000000000 --- a/src/main/java/org/jabref/gui/util/MainTableUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.jabref.gui.util; - -import java.util.List; - -import javafx.scene.Node; -import javafx.scene.control.TableColumn; - -import org.jabref.gui.externalfiletype.ExternalFileType; -import org.jabref.gui.externalfiletype.ExternalFileTypes; -import org.jabref.gui.icon.IconTheme; -import org.jabref.model.entry.LinkedFile; - -public class MainTableUtils { - - public static final String STYLE_ICON_COLUMN = "column-icon"; - - private MainTableUtils() { } - - public static void setExactWidth(TableColumn column, int width) { - column.setMinWidth(width); - column.setPrefWidth(width); - column.setMaxWidth(width); - } - - public static Node createFileIcon(ExternalFileTypes externalFileTypes, List linkedFiles) { - if (linkedFiles.size() > 1) { - return IconTheme.JabRefIcons.FILE_MULTIPLE.getGraphicNode(); - } else if (linkedFiles.size() == 1) { - return externalFileTypes.fromLinkedFile(linkedFiles.get(0), false) - .map(ExternalFileType::getIcon) - .orElse(IconTheme.JabRefIcons.FILE) - .getGraphicNode(); - } else { - return null; - } - } -} diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 15fc606fd34..fae9e4ffcee 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1927,8 +1927,6 @@ Move\ panel\ down=Move panel down Linked\ files=Linked files Group\ view\ mode\ set\ to\ intersection=Group view mode set to intersection Group\ view\ mode\ set\ to\ union=Group view mode set to union -Open\ %0\ URL\ (%1)=Open %0 URL (%1) -Open\ URL\ (%0)=Open URL (%0) Open\ file\ %0=Open file %0 Toggle\ intersection=Toggle intersection Toggle\ union=Toggle union @@ -2124,3 +2122,7 @@ Start\ on\ second\ duplicate\ key\ with\ letter\ B\ (b,\ c,\ ...)=Start on secon Always\ add\ letter\ (a,\ b,\ ...)\ to\ generated\ keys=Always add letter (a, b, ...) to generated keys Default\ pattern=Default pattern Reset\ %s\ to\ default\ value=Reset %s to default value + +Column\ type\ %0\ is\ unknown.=Column type %0 is unknown. +Linked\ identifiers=Linked identifiers +Special\ field\ type\ %0\ is\ unknown.=Special field type %0 is unknown. From 8fb708bf197f524a8824b4ec1a96c7671a65d225 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Wed, 30 Oct 2019 16:33:06 +0100 Subject: [PATCH 03/16] Removed superfluous properties --- .../gui/maintable/ColumnPreferences.java | 26 +------------------ .../gui/preferences/TableColumnsTab.fxml | 10 ------- .../gui/preferences/TableColumnsTabView.java | 10 ------- .../preferences/TableColumnsTabViewModel.java | 26 +------------------ .../jabref/preferences/JabRefPreferences.java | 17 ------------ src/main/resources/l10n/JabRef_en.properties | 7 ----- 6 files changed, 2 insertions(+), 94 deletions(-) diff --git a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java index 5d71589caaa..f8a7b63f661 100644 --- a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java +++ b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java @@ -10,10 +10,6 @@ public class ColumnPreferences { public static final String QUALIFIER_SEPARATOR = ":"; public static final double DEFAULT_FIELD_LENGTH = 100; - private final boolean showFileColumn; - private final boolean showUrlColumn; - private final boolean preferDoiOverUrl; - private final boolean showEPrintColumn; private final List columnNames; private final boolean specialFieldsEnabled; private final boolean autoSyncSpecialFieldsToKeyWords; @@ -22,11 +18,7 @@ public class ColumnPreferences { private final Map columnWidths; private final Map columnSortType; - public ColumnPreferences(boolean showFileColumn, boolean showUrlColumn, boolean preferDoiOverUrl, boolean showEPrintColumn, List columnNames, boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields, boolean extraFileColumnsEnabled, Map columnWidths, Map columnSortType) { - this.showFileColumn = showFileColumn; - this.showUrlColumn = showUrlColumn; - this.preferDoiOverUrl = preferDoiOverUrl; - this.showEPrintColumn = showEPrintColumn; + public ColumnPreferences(List columnNames, boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields, boolean extraFileColumnsEnabled, Map columnWidths, Map columnSortType) { this.columnNames = columnNames; this.specialFieldsEnabled = specialFieldsEnabled; this.autoSyncSpecialFieldsToKeyWords = autoSyncSpecialFieldsToKeyWords; @@ -36,22 +28,6 @@ public ColumnPreferences(boolean showFileColumn, boolean showUrlColumn, boolean this.columnSortType = columnSortType; } - public boolean showFileColumn() { - return showFileColumn; - } - - public boolean showUrlColumn() { - return showUrlColumn; - } - - public boolean preferDoiOverUrl() { - return preferDoiOverUrl; - } - - public boolean showEprintColumn() { - return showEPrintColumn; - } - public boolean getSpecialFieldsEnabled() { return specialFieldsEnabled; } public boolean getAutoSyncSpecialFieldsToKeyWords() { diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTab.fxml b/src/main/java/org/jabref/gui/preferences/TableColumnsTab.fxml index 1bd8fb9c59a..c2c1dd444e6 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTab.fxml @@ -79,16 +79,6 @@ - - - - - - - - - - diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java index fcf310daeef..07d05081dad 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java @@ -32,11 +32,6 @@ public class TableColumnsTabView extends AbstractPreferenceTabView nameColumn; @FXML private TableColumn actionsColumn; @FXML private ComboBox addColumnName; - @FXML private CheckBox showFileColumn; - @FXML private CheckBox showUrlColumn; - @FXML private RadioButton urlFirst; - @FXML private RadioButton doiFirst; - @FXML private CheckBox showEPrintColumn; @FXML private CheckBox specialFieldsEnable; @FXML private Button specialFieldsHelp; @FXML private RadioButton specialFieldsSyncKeywords; @@ -107,11 +102,6 @@ private void setupTable() { } private void setupBindings() { - showFileColumn.selectedProperty().bindBidirectional(viewModel.showFileColumnProperty()); - showUrlColumn.selectedProperty().bindBidirectional(viewModel.showUrlColumnProperty()); - urlFirst.selectedProperty().bindBidirectional(viewModel.preferUrlProperty()); - doiFirst.selectedProperty().bindBidirectional(viewModel.preferDoiProperty()); - showEPrintColumn.selectedProperty().bindBidirectional(viewModel.showEPrintColumnProperty()); specialFieldsEnable.selectedProperty().bindBidirectional(viewModel.specialFieldsEnabledProperty()); specialFieldsSyncKeywords.selectedProperty().bindBidirectional(viewModel.specialFieldsSyncKeywordsProperty()); specialFieldsSerialize.selectedProperty().bindBidirectional(viewModel.specialFieldsSerializeProperty()); diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index cce80e1cd14..88d64f7b73a 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -43,11 +43,6 @@ public class TableColumnsTabViewModel implements PreferenceTabViewModel { private final BooleanProperty specialFieldsEnabledProperty = new SimpleBooleanProperty(); private final BooleanProperty specialFieldsSyncKeywordsProperty = new SimpleBooleanProperty(); private final BooleanProperty specialFieldsSerializeProperty = new SimpleBooleanProperty(); - private final BooleanProperty showFileColumnProperty = new SimpleBooleanProperty(); - private final BooleanProperty showUrlColumnProperty = new SimpleBooleanProperty(); - private final BooleanProperty preferUrlProperty = new SimpleBooleanProperty(); - private final BooleanProperty preferDoiProperty = new SimpleBooleanProperty(); - private final BooleanProperty showEPrintColumnProperty = new SimpleBooleanProperty(); private final BooleanProperty extraFileColumnsEnabledProperty = new SimpleBooleanProperty(); private FunctionBasedValidator columnsNotEmptyValidator; @@ -90,11 +85,6 @@ public TableColumnsTabViewModel(DialogService dialogService, JabRefPreferences p @Override public void setValues() { - showFileColumnProperty.setValue(columnPreferences.showFileColumn()); - showUrlColumnProperty.setValue(columnPreferences.showUrlColumn()); - preferUrlProperty.setValue(!columnPreferences.preferDoiOverUrl()); - preferDoiProperty.setValue(columnPreferences.preferDoiOverUrl()); - showEPrintColumnProperty.setValue(columnPreferences.showEprintColumn()); specialFieldsEnabledProperty.setValue(columnPreferences.getSpecialFieldsEnabled()); specialFieldsSyncKeywordsProperty.setValue(columnPreferences.getAutoSyncSpecialFieldsToKeyWords()); specialFieldsSerializeProperty.setValue(columnPreferences.getSerializeSpecialFields()); @@ -193,17 +183,13 @@ public void moveColumnDown() { @Override public void storeSettings() { List columnNames = columnsListProperty.stream() - .map(item -> item.getField().getName()).collect(Collectors.toList()); + .map(item -> item.getField().getName()).collect(Collectors.toList()); // for each column get either actual width or - if it does not exist - default value Map columnWidths = new HashMap<>(); columnNames.forEach(field -> columnWidths.put(field,columnPreferences.getColumnWidth(field))); ColumnPreferences newColumnPreferences = new ColumnPreferences( - showFileColumnProperty.getValue(), - showUrlColumnProperty.getValue(), - preferDoiProperty.getValue(), - showEPrintColumnProperty.getValue(), columnNames, specialFieldsEnabledProperty.getValue(), specialFieldsSyncKeywordsProperty.getValue(), @@ -251,22 +237,12 @@ public List getRestartWarnings() { public ObjectProperty addColumnProperty() { return this.addColumnProperty; } - public BooleanProperty showFileColumnProperty() { return this.showFileColumnProperty; } - - public BooleanProperty showUrlColumnProperty() { return this.showUrlColumnProperty; } - - public BooleanProperty preferUrlProperty() { return this.preferUrlProperty; } - - public BooleanProperty preferDoiProperty() { return this.preferDoiProperty; } - public BooleanProperty specialFieldsEnabledProperty() { return this.specialFieldsEnabledProperty; } public BooleanProperty specialFieldsSyncKeywordsProperty() { return this.specialFieldsSyncKeywordsProperty; } public BooleanProperty specialFieldsSerializeProperty() { return this.specialFieldsSerializeProperty; } - public BooleanProperty showEPrintColumnProperty() { return this.showEPrintColumnProperty; } - public BooleanProperty extraFileColumnsEnabledProperty() { return this.extraFileColumnsEnabledProperty; } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 3a90fdbefaa..2937f721b65 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -206,10 +206,6 @@ public class JabRefPreferences implements PreferencesService { public static final String KEYWORD_SEPARATOR = "groupKeywordSeparator"; public static final String AUTO_ASSIGN_GROUP = "autoAssignGroup"; public static final String EXTRA_FILE_COLUMNS = "extraFileColumns"; - public static final String ARXIV_COLUMN = "arxivColumn"; - public static final String FILE_COLUMN = "fileColumn"; - public static final String PREFER_URL_DOI = "preferUrlDoi"; - public static final String URL_COLUMN = "urlColumn"; // Colors public static final String FIELD_EDITOR_TEXT_COLOR = "fieldEditorTextColor"; public static final String ACTIVE_FIELD_EDITOR_BACKGROUND_COLOR = "activeFieldEditorBackgroundColor"; @@ -599,11 +595,6 @@ private JabRefPreferences() { // default icon colors defaults.put(ICON_DISABLED_COLOR, "200:200:200"); - defaults.put(URL_COLUMN, Boolean.TRUE); - defaults.put(PREFER_URL_DOI, Boolean.FALSE); - defaults.put(FILE_COLUMN, Boolean.TRUE); - defaults.put(ARXIV_COLUMN, Boolean.FALSE); - defaults.put(EXTRA_FILE_COLUMNS, Boolean.FALSE); defaults.put(PROTECTED_TERMS_ENABLED_INTERNAL, convertListToString(ProtectedTermsLoader.getInternalLists())); @@ -1879,10 +1870,6 @@ private Map createColumnWidths() { public ColumnPreferences getColumnPreferences() { return new ColumnPreferences( - getBoolean(FILE_COLUMN), - getBoolean(URL_COLUMN), - getBoolean(PREFER_URL_DOI), - getBoolean(ARXIV_COLUMN), getStringList(COLUMN_NAMES), getBoolean(SPECIALFIELDSENABLED), getBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS), @@ -1893,10 +1880,6 @@ public ColumnPreferences getColumnPreferences() { } public void storeColumnPreferences(ColumnPreferences columnPreferences) { - putBoolean(FILE_COLUMN, columnPreferences.showFileColumn()); - putBoolean(URL_COLUMN, columnPreferences.showUrlColumn()); - putBoolean(PREFER_URL_DOI, columnPreferences.preferDoiOverUrl()); - putBoolean(ARXIV_COLUMN, columnPreferences.showEprintColumn()); putStringList(COLUMN_NAMES, columnPreferences.getColumnNames()); putBoolean(SPECIALFIELDSENABLED, columnPreferences.getSpecialFieldsEnabled()); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index fae9e4ffcee..0f6b43d8b43 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -843,8 +843,6 @@ Show\ BibTeX\ source\ by\ default=Show BibTeX source by default Show\ confirmation\ dialog\ when\ deleting\ entries=Show confirmation dialog when deleting entries -Show\ file\ column=Show file column - Show\ last\ names\ only=Show last names only Show\ names\ unchanged=Show names unchanged @@ -853,8 +851,6 @@ Show\ optional\ fields=Show optional fields Show\ required\ fields=Show required fields -Show\ URL/DOI\ column=Show URL/DOI column - Show\ validation\ messages=Show validation messages Simple\ HTML=Simple HTML @@ -1082,7 +1078,6 @@ General\ file\ directory=General file directory User-specific\ file\ directory=User-specific file directory LaTex\ file\ directory=LaTex file directory Search\ failed\:\ illegal\ search\ expression=Search failed: illegal search expression -Show\ ArXiv\ column=Show ArXiv column You\ must\ enter\ an\ integer\ value\ in\ the\ interval\ 1025-65535=You must enter an integer value in the interval 1025-65535 Automatically\ open\ browse\ dialog\ when\ creating\ new\ file\ link=Automatically open browse dialog when creating new file link @@ -1271,8 +1266,6 @@ Merged\ entries=Merged entries None=None Parse=Parse Result=Result -Show\ DOI\ first=Show DOI first -Show\ URL\ first=Show URL first You\ have\ to\ choose\ exactly\ two\ entries\ to\ merge.=You have to choose exactly two entries to merge. Update\ timestamp\ on\ modification=Update timestamp on modification From 090fe51119205970a2364cf25f952a87c1e952e5 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Fri, 1 Nov 2019 10:30:01 +0100 Subject: [PATCH 04/16] Added display names and refactored --- .../jabref/gui/maintable/MainTableColumn.java | 15 --- .../gui/maintable/MainTableColumnFactory.java | 34 ++--- .../gui/maintable/MainTableColumnModel.java | 119 ++++++++++++++++++ .../gui/maintable/MainTableColumnType.java | 42 ------- .../gui/maintable/NormalTableColumn.java | 5 +- .../preferences/TableColumnsItemModel.java | 67 ++-------- .../gui/preferences/TableColumnsTabView.java | 44 +++++-- .../preferences/TableColumnsTabViewModel.java | 52 ++++---- .../java/org/jabref/gui/util/FieldsUtil.java | 31 ----- src/main/resources/l10n/JabRef_en.properties | 3 +- 10 files changed, 210 insertions(+), 202 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/maintable/MainTableColumn.java create mode 100644 src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java delete mode 100644 src/main/java/org/jabref/gui/maintable/MainTableColumnType.java diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java deleted file mode 100644 index 55c9d5327cd..00000000000 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.jabref.gui.maintable; - -import javafx.scene.control.TableColumn; - -class MainTableColumn extends TableColumn { - - MainTableColumnType columnType; - - MainTableColumn(MainTableColumnType columnType) { - this.columnType = columnType; - } - - public MainTableColumnType getColumnType() { return columnType; } - -} diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index affa78727d6..7c83036c780 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -79,12 +79,12 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre public List> createColumns() { List> columns = new ArrayList<>(); - preferences.getColumnNames().forEach(columnName -> { - String[] columnTokens = columnName.split(ColumnPreferences.QUALIFIER_SEPARATOR); - MainTableColumnType type = MainTableColumnType.parse(columnTokens[0]); + preferences.getColumnNames().forEach(rawColumnName -> { + MainTableColumnModel column = new MainTableColumnModel(rawColumnName); + Field field; - switch (type) { + switch (column.getType()) { case GROUPS: columns.add(createGroupColumn()); break; @@ -95,29 +95,29 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre columns.add(createIdentifierColumn()); break; case EXTRAFILE: - if (columnTokens.length == 2) { - columns.add(createExtraFileColumn(columnTokens[1])); + if (!column.getName().equals("")) { + columns.add(createExtraFileColumn(column.getName())); } break; case SPECIALFIELD: - if (columnTokens.length == 2) { - field = FieldFactory.parseField(columnTokens[1]); + if (!column.getName().equals("")) { + field = FieldFactory.parseField(column.getName()); if (field instanceof SpecialField) { columns.add(createSpecialFieldColumn((SpecialField) field)); } else { - LOGGER.warn(Localization.lang("Special field type %0 is unknown. Using normal column type.", columnTokens[1])); + LOGGER.warn(Localization.lang("Special field type %0 is unknown. Using normal column type.", column.getName())); columns.add(createNormalColumn(field)); } } break; case NORMALFIELD: - if (columnTokens.length == 2) { - field = FieldFactory.parseField(columnTokens[1]); + if (!column.getName().equals("")) { + field = FieldFactory.parseField(column.getName()); columns.add(createNormalColumn(field)); } break; default: - LOGGER.warn(Localization.lang("Column type %0 is unknown.", columnName)); + LOGGER.warn(Localization.lang("Column type %0 is unknown.", rawColumnName)); } }); @@ -134,7 +134,7 @@ private void setExactWidth(TableColumn column, int width) { * Creates a column for group color bars. */ private TableColumn createGroupColumn() { - TableColumn> column = new MainTableColumn<>(MainTableColumnType.GROUPS); + TableColumn> column = new TableColumn<>(); Node headerGraphic = IconTheme.JabRefIcons.DEFAULT_GROUP_ICON.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Group color"))); column.setGraphic(headerGraphic); @@ -201,7 +201,7 @@ private Node createGroupColorRegion(BibEntryTableViewModel entry, List> createFileColumn() { - TableColumn> column = new MainTableColumn<>(MainTableColumnType.FILE); + TableColumn> column = new TableColumn<>(); Node headerGraphic = IconTheme.JabRefIcons.FILE.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked files"))); column.setGraphic(headerGraphic); @@ -265,7 +265,7 @@ private Node createFileIcon(List linkedFiles) { * Creates a column for all the linked files of a single file type. */ private TableColumn> createExtraFileColumn(String externalFileTypeName) { - TableColumn> column = new MainTableColumn<>(MainTableColumnType.EXTRAFILE); + TableColumn> column = new TableColumn<>(); column.setGraphic(externalFileTypes .getExternalFileTypeByName(externalFileTypeName) .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) @@ -284,7 +284,7 @@ private TableColumn> createExtraFileCol * Creates a clickable icons column for DOIs, URLs, URIs and EPrints. */ private TableColumn> createIdentifierColumn() { - TableColumn> column = new MainTableColumn<>(MainTableColumnType.LINKED_IDENTIFIER); + TableColumn> column = new TableColumn<>(); Node headerGraphic = IconTheme.JabRefIcons.WWW.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked identifiers"))); column.setGraphic(headerGraphic); @@ -336,7 +336,7 @@ private ContextMenu createIdentifierMenu(BibEntryTableViewModel entry, Map> createSpecialFieldColumn(SpecialField specialField) { - TableColumn> column = new MainTableColumn<>(MainTableColumnType.SPECIALFIELD); + TableColumn> column = new TableColumn<>(); SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java new file mode 100644 index 00000000000..7b5391a678f --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -0,0 +1,119 @@ +package org.jabref.gui.maintable; + +import java.util.Objects; + +import org.jabref.gui.util.FieldsUtil; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.entry.field.FieldFactory; + +public class MainTableColumnModel { + + public enum Type { + EXTRAFILE("extrafile", Localization.lang("File type")), + FILE("files", Localization.lang("Linked files")), + GROUPS("groups", Localization.lang("Groups")), + LINKED_IDENTIFIER("linked_id", Localization.lang("Linked identifiers")), + NORMALFIELD("field"), + SPECIALFIELD("special", Localization.lang("Special")); + + private String name; + private String displayName; + + Type(String name) { + this.name = name; + this.displayName = name; + } + + Type(String name, String displayName) { + this.name = name; + this.displayName = displayName; + } + + public String getName() { + return name; + } + + public String getDisplayName() { + return displayName; + } + + public static Type parse(String text) { + switch (text) { + case "groups": return GROUPS; + case "files": return FILE; + case "extrafile": return EXTRAFILE; + case "linked_id": return LINKED_IDENTIFIER; + case "special": return SPECIALFIELD; + case "field": + default: return NORMALFIELD; + } + } + } + + private final Type type; + private final String name; + + public MainTableColumnModel(String rawColumnName) { + Objects.requireNonNull(rawColumnName); + + String[] splitname = rawColumnName.split(ColumnPreferences.QUALIFIER_SEPARATOR); + type = Type.parse(splitname[0]); + if (type == Type.GROUPS || type == Type.FILE || type == Type.LINKED_IDENTIFIER) { + name = ""; + } else { + if (splitname.length == 1) { + name = splitname[0]; // If default type is parsed as NORMALFIELD + } else { + name = splitname[1]; + } + } + } + + public MainTableColumnModel(Type type, String name) { + Objects.requireNonNull(type); + Objects.requireNonNull(name); + this.type = type; + this.name = name; + } + + public Type getType() { return type; } + + public String getName() { return name; } + + public String getDisplayName() { + if ((type == Type.GROUPS || type == Type.FILE || type == Type.LINKED_IDENTIFIER) && name.isBlank()) { + return type.getDisplayName(); + } else { + return FieldsUtil.getNameWithType(FieldFactory.parseField(name)); + } + } + + public String toString() { + if (name.isBlank()) { + return type.getName(); + } else { + return type.getName() + ":" + name; + } + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + MainTableColumnModel that = (MainTableColumnModel) o; + + if (type != that.type) { + return false; + } + return Objects.equals(name, that.name); + } + + public int hashCode() { + return Objects.hash(type, name); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnType.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnType.java deleted file mode 100644 index a9fa22d9a0d..00000000000 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnType.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jabref.gui.maintable; - -import org.jabref.logic.l10n.Localization; - -public enum MainTableColumnType { - - GROUPS("groups"), - FILE("file"), - EXTRAFILE("extrafile", Localization.lang("File type")), - LINKED_IDENTIFIER("linked_id"), - SPECIALFIELD("special", Localization.lang("Special")), - NORMALFIELD("field"); - - private String qualifier; - private String displayName; - - MainTableColumnType(String qualifier) { - this.qualifier = qualifier; - } - - MainTableColumnType(String qualifier, String displayName) { - this(qualifier); - this.displayName = displayName; - } - - public String getQualifier() { return qualifier; } - - public String getDisplayName() { return displayName; } - - public static MainTableColumnType parse(String text) { - switch (text) { - case "groups": return GROUPS; - case "file": return FILE; - case "extrafile": return EXTRAFILE; - case "linked_id": return LINKED_IDENTIFIER; - case "special": return SPECIALFIELD; - - case "field": - default: return NORMALFIELD; - } - } -} diff --git a/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java b/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java index 0e6bfb4a12b..e1459225395 100644 --- a/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java +++ b/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java @@ -7,6 +7,7 @@ import javafx.beans.value.ObservableValue; import javafx.scene.Node; import javafx.scene.control.Label; +import javafx.scene.control.TableColumn; import org.jabref.gui.icon.JabRefIcon; import org.jabref.logic.layout.LayoutFormatter; @@ -21,7 +22,7 @@ /** * A column that displays the text-value of the field */ -public class NormalTableColumn extends MainTableColumn { +public class NormalTableColumn extends TableColumn { private final OrFields bibtexFields; @@ -35,8 +36,6 @@ public class NormalTableColumn extends MainTableColumn { private final String columnName; public NormalTableColumn(String columnName, OrFields bibtexFields, BibDatabase database) { - super(MainTableColumnType.NORMALFIELD); - this.columnName = columnName; this.bibtexFields = bibtexFields; this.isIconColumn = false; diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java index 9ac5faa8fb7..3d92dcbdaf4 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java @@ -2,87 +2,44 @@ import java.util.Objects; -import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.ObjectProperty; -import javafx.beans.property.ReadOnlyBooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import org.jabref.gui.maintable.ColumnPreferences; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.entry.field.Field; -import org.jabref.model.entry.field.UnknownField; +import org.jabref.gui.maintable.MainTableColumnModel; public class TableColumnsItemModel { - private final ObjectProperty field; - private final StringProperty name = new SimpleStringProperty(""); + private final ObjectProperty columnName; private final DoubleProperty length = new SimpleDoubleProperty(ColumnPreferences.DEFAULT_FIELD_LENGTH); - private final BooleanProperty editableProperty = new SimpleBooleanProperty(true); - public TableColumnsItemModel() { - this.field = new SimpleObjectProperty<>(new UnknownField(Localization.lang("New column"))); + public TableColumnsItemModel(MainTableColumnModel columnName) { + this.columnName = new SimpleObjectProperty<>(columnName); } - public TableColumnsItemModel(Field field) { - this.field = new SimpleObjectProperty<>(field); - this.editableProperty.setValue(this.field.get() instanceof UnknownField); - } - - public TableColumnsItemModel(Field field, double length) { - this.field = new SimpleObjectProperty<>(field); + public TableColumnsItemModel(MainTableColumnModel columnName, double length) { + this(columnName); this.length.setValue(length); - this.editableProperty.setValue(this.field.get() instanceof UnknownField); - } - - public void setField(Field field) { - this.field.set(field); - } - - public Field getField() { - return field.get(); - } - - public ObservableValue fieldProperty() { return this.field; } - - public void setName(String name) { - if (editableProperty.get()) { - field.setValue(new UnknownField(name)); - } - } - - public String getName() { - return field.get().getName(); } - public StringProperty nameProperty() { return this.name; } + public MainTableColumnModel getColumnName() { return columnName.get(); } - public void setLength(double length) { - this.length.set(length); - } - - public double getLength() { - return length.get(); - } + public ObservableValue columnNameProperty() { return this.columnName; } - public DoubleProperty lengthProperty() { return this.length; } + public void setLength(double length) { this.length.set(length); } - public ReadOnlyBooleanProperty editableProperty() { return editableProperty; } + public double getLength() { return length.get(); } @Override - public int hashCode() { - return Objects.hash(field); - } + public int hashCode() { return Objects.hash(columnName); } @Override public boolean equals(Object obj) { if (obj instanceof TableColumnsItemModel) { - return Objects.equals(this.field, ((TableColumnsItemModel) obj).field); + return Objects.equals(this.columnName, ((TableColumnsItemModel) obj).columnName); } else { return false; } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java index 07d05081dad..c9c73d0ae22 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java @@ -9,18 +9,18 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.input.KeyCode; +import javafx.util.StringConverter; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.StandardActions; import org.jabref.gui.help.HelpAction; import org.jabref.gui.icon.IconTheme; -import org.jabref.gui.util.FieldsUtil; +import org.jabref.gui.maintable.MainTableColumnModel; import org.jabref.gui.util.IconValidationDecorator; import org.jabref.gui.util.ValueTableCellFactory; import org.jabref.gui.util.ViewModelListCellFactory; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; -import org.jabref.model.entry.field.Field; import org.jabref.preferences.JabRefPreferences; import com.airhacks.afterburner.views.ViewLoader; @@ -28,10 +28,26 @@ public class TableColumnsTabView extends AbstractPreferenceTabView implements PreferencesTab { + private static StringConverter columnNameStringConverter = new StringConverter<>() { + @Override + public String toString(MainTableColumnModel object) { + if (object != null) { + return object.toString(); + } else { + return ""; + } + } + + @Override + public MainTableColumnModel fromString(String string) { + return new MainTableColumnModel(string); + } + }; + @FXML private TableView columnsList; - @FXML private TableColumn nameColumn; - @FXML private TableColumn actionsColumn; - @FXML private ComboBox addColumnName; + @FXML private TableColumn nameColumn; + @FXML private TableColumn actionsColumn; + @FXML private ComboBox addColumnName; @FXML private CheckBox specialFieldsEnable; @FXML private Button specialFieldsHelp; @FXML private RadioButton specialFieldsSyncKeywords; @@ -68,15 +84,17 @@ public void initialize() { private void setupTable() { nameColumn.setSortable(false); nameColumn.setReorderable(false); - nameColumn.setCellValueFactory(cellData -> cellData.getValue().fieldProperty()); - new ValueTableCellFactory().withText(FieldsUtil::getNameWithType).install(nameColumn); + nameColumn.setCellValueFactory(cellData -> cellData.getValue().columnNameProperty()); + new ValueTableCellFactory() + .withText(MainTableColumnModel::getDisplayName) + .install(nameColumn); actionsColumn.setSortable(false); actionsColumn.setReorderable(false); - actionsColumn.setCellValueFactory(cellData -> cellData.getValue().fieldProperty()); - new ValueTableCellFactory() + actionsColumn.setCellValueFactory(cellData -> cellData.getValue().columnNameProperty()); + new ValueTableCellFactory() .withGraphic(item -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) - .withTooltip(name -> Localization.lang("Remove column") + " " + name.getDisplayName()) + .withTooltip(name -> Localization.lang("Remove column") + " " + name.getName()) .withOnMouseClickedEvent(item -> evt -> viewModel.removeColumn(columnsList.getFocusModel().getFocusedItem())) .install(actionsColumn); @@ -90,12 +108,12 @@ private void setupTable() { columnsList.itemsProperty().bind(viewModel.columnsListProperty()); - new ViewModelListCellFactory() - .withText(FieldsUtil::getNameWithType) + new ViewModelListCellFactory() + .withText(MainTableColumnModel::getDisplayName) .install(addColumnName); addColumnName.itemsProperty().bind(viewModel.availableColumnsProperty()); addColumnName.valueProperty().bindBidirectional(viewModel.addColumnProperty()); - addColumnName.setConverter(FieldsUtil.fieldStringConverter); + addColumnName.setConverter(columnNameStringConverter); validationVisualizer.setDecoration(new IconValidationDecorator()); Platform.runLater(() -> validationVisualizer.initVisualization(viewModel.columnsListValidationStatus(), columnsList)); diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index 88d64f7b73a..d54eae6888f 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -20,11 +20,10 @@ import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.maintable.ColumnPreferences; -import org.jabref.gui.util.FieldsUtil; +import org.jabref.gui.maintable.MainTableColumnModel; import org.jabref.gui.util.NoSelectionModel; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.Field; -import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.field.InternalField; import org.jabref.model.entry.field.SpecialField; import org.jabref.model.entry.field.StandardField; @@ -38,8 +37,8 @@ public class TableColumnsTabViewModel implements PreferenceTabViewModel { private final ListProperty columnsListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); private final ObjectProperty> selectedColumnModelProperty = new SimpleObjectProperty<>(new NoSelectionModel<>()); - private final ListProperty availableColumnsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); - private final ObjectProperty addColumnProperty = new SimpleObjectProperty<>(); + private final ListProperty availableColumnsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); + private final ObjectProperty addColumnProperty = new SimpleObjectProperty<>(); private final BooleanProperty specialFieldsEnabledProperty = new SimpleBooleanProperty(); private final BooleanProperty specialFieldsSyncKeywordsProperty = new SimpleBooleanProperty(); private final BooleanProperty specialFieldsSerializeProperty = new SimpleBooleanProperty(); @@ -94,13 +93,16 @@ public void setValues() { availableColumnsProperty.clear(); - availableColumnsProperty.add(InternalField.TIMESTAMP); - availableColumnsProperty.add(InternalField.OWNER); - availableColumnsProperty.add(InternalField.GROUPS); - availableColumnsProperty.add(InternalField.KEY_FIELD); - availableColumnsProperty.add(InternalField.TYPE_HEADER); + availableColumnsProperty.add(new MainTableColumnModel(InternalField.TIMESTAMP.getName())); + availableColumnsProperty.add(new MainTableColumnModel(InternalField.OWNER.getName())); + availableColumnsProperty.add(new MainTableColumnModel(InternalField.GROUPS.getName())); + availableColumnsProperty.add(new MainTableColumnModel(InternalField.KEY_FIELD.getName())); + availableColumnsProperty.add(new MainTableColumnModel(InternalField.TYPE_HEADER.getName())); - EnumSet.allOf(StandardField.class).forEach(item -> availableColumnsProperty.getValue().add(item)); + EnumSet.allOf(StandardField.class).stream() + .map(Field::getName) + .map(name -> new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, name)) + .forEach(item -> availableColumnsProperty.getValue().add(item)); if (specialFieldsEnabledProperty.getValue()) { insertSpecialFieldColumns(); @@ -115,30 +117,31 @@ public void fillColumnList() { columnsListProperty.getValue().clear(); columnPreferences.getColumnNames().stream() - .map(FieldFactory::parseField) - .map(field -> new TableColumnsItemModel(field, columnPreferences.getColumnWidth(field.getName()))) + .map(columnName -> new TableColumnsItemModel(new MainTableColumnModel(columnName), columnPreferences.getColumnWidth(columnName))) .forEach(columnsListProperty.getValue()::add); } private void insertSpecialFieldColumns() { - EnumSet.allOf(SpecialField.class).forEach(item -> availableColumnsProperty.getValue().add(0, item)); + EnumSet.allOf(SpecialField.class).stream() + .map(Field::getName).map(name -> new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, name)) + .forEach(item -> availableColumnsProperty.getValue().add(0, item)); } private void removeSpecialFieldColumns() { - columnsListProperty.getValue().removeIf(column -> column.getField() instanceof SpecialField); - availableColumnsProperty.getValue().removeIf(field -> field instanceof SpecialField); + columnsListProperty.getValue().removeIf(column -> column.getColumnName().getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); + availableColumnsProperty.getValue().removeIf(columnName -> columnName.getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); } private void insertExtraFileColumns() { ExternalFileTypes.getInstance().getExternalFileTypeSelection().stream() - .map(ExternalFileType::getName) - .map(FieldsUtil.ExtraFilePseudoField::new) - .forEach(availableColumnsProperty::add); + .map(ExternalFileType::getName) + .map(name -> new MainTableColumnModel(MainTableColumnModel.Type.EXTRAFILE, name)) + .forEach(item -> availableColumnsProperty.getValue().add(item)); } private void removeExtraFileColumns() { - columnsListProperty.getValue().removeIf(column -> column.getField() instanceof FieldsUtil.ExtraFilePseudoField); - availableColumnsProperty.getValue().removeIf(field -> field instanceof FieldsUtil.ExtraFilePseudoField); + columnsListProperty.getValue().removeIf(column -> column.getColumnName().getType() == MainTableColumnModel.Type.EXTRAFILE); + availableColumnsProperty.getValue().removeIf(columnName -> columnName.getType().equals(MainTableColumnModel.Type.EXTRAFILE)); } public void insertColumnInList() { @@ -146,7 +149,7 @@ public void insertColumnInList() { return; } - if (columnsListProperty.getValue().stream().filter(item -> item.getField().equals(addColumnProperty.getValue())).findAny().isEmpty()) { + if (columnsListProperty.getValue().stream().map(TableColumnsItemModel::getColumnName).filter(item -> item.equals(addColumnProperty.getValue())).findAny().isEmpty()) { columnsListProperty.add(new TableColumnsItemModel(addColumnProperty.getValue())); addColumnProperty.setValue(null); } @@ -183,7 +186,8 @@ public void moveColumnDown() { @Override public void storeSettings() { List columnNames = columnsListProperty.stream() - .map(item -> item.getField().getName()).collect(Collectors.toList()); + .map(item -> item.getColumnName().toString()) + .collect(Collectors.toList()); // for each column get either actual width or - if it does not exist - default value Map columnWidths = new HashMap<>(); @@ -233,9 +237,9 @@ public List getRestartWarnings() { public ObjectProperty> selectedColumnModelProperty() { return selectedColumnModelProperty; } - public ListProperty availableColumnsProperty() { return this.availableColumnsProperty; } + public ListProperty availableColumnsProperty() { return this.availableColumnsProperty; } - public ObjectProperty addColumnProperty() { return this.addColumnProperty; } + public ObjectProperty addColumnProperty() { return this.addColumnProperty; } public BooleanProperty specialFieldsEnabledProperty() { return this.specialFieldsEnabledProperty; } diff --git a/src/main/java/org/jabref/gui/util/FieldsUtil.java b/src/main/java/org/jabref/gui/util/FieldsUtil.java index 69c2158c156..7a72b944c91 100644 --- a/src/main/java/org/jabref/gui/util/FieldsUtil.java +++ b/src/main/java/org/jabref/gui/util/FieldsUtil.java @@ -1,14 +1,10 @@ package org.jabref.gui.util; -import java.util.Collections; -import java.util.Set; - import javafx.util.StringConverter; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; -import org.jabref.model.entry.field.FieldProperty; import org.jabref.model.entry.field.IEEEField; import org.jabref.model.entry.field.InternalField; import org.jabref.model.entry.field.SpecialField; @@ -41,35 +37,8 @@ public static String getNameWithType(Field field) { return field.getDisplayName() + " (" + Localization.lang("Internal") + ")"; } else if (field instanceof UnknownField) { return field.getDisplayName() + " (" + Localization.lang("Custom") + ")"; - } else if (field instanceof ExtraFilePseudoField) { - return field.getDisplayName() + " (" + Localization.lang("File type") + ")"; } else { return field.getDisplayName(); } } - - public static class ExtraFilePseudoField implements Field { - - String name; - - public ExtraFilePseudoField(String name) { - this.name = name; - } - - @Override - public Set getProperties() { - return Collections.emptySet(); - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean isStandardField() { - return false; - } - - } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 0f6b43d8b43..083a913d686 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2092,7 +2092,6 @@ List\ must\ not\ be\ empty.=List must not be empty. Add\ field\ to\ filter\ list=Add field to filter list Add\ formatter\ to\ list=Add formatter to list Filter\ List=Filter List -New\ column=New column Open\ files...=Open files... Affected\ fields\:=Affected fields: @@ -2118,4 +2117,4 @@ Reset\ %s\ to\ default\ value=Reset %s to default value Column\ type\ %0\ is\ unknown.=Column type %0 is unknown. Linked\ identifiers=Linked identifiers -Special\ field\ type\ %0\ is\ unknown.=Special field type %0 is unknown. +Special\ field\ type\ %0\ is\ unknown.\ Using\ normal\ column\ type.=Special field type %0 is unknown. Using normal column type. From bf4b02e128043080f3cedb062030ea016e758602 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Fri, 1 Nov 2019 11:46:07 +0100 Subject: [PATCH 05/16] Fixed persistent state --- ...ormalTableColumn.java => FieldColumn.java} | 37 ++++--------------- .../jabref/gui/maintable/MainTableColumn.java | 35 ++++++++++++++++++ .../gui/maintable/MainTableColumnFactory.java | 29 ++++++++------- .../gui/maintable/MainTableColumnModel.java | 14 +++++-- .../PersistenceVisualStateTable.java | 8 +--- 5 files changed, 70 insertions(+), 53 deletions(-) rename src/main/java/org/jabref/gui/maintable/{NormalTableColumn.java => FieldColumn.java} (77%) create mode 100644 src/main/java/org/jabref/gui/maintable/MainTableColumn.java diff --git a/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java b/src/main/java/org/jabref/gui/maintable/FieldColumn.java similarity index 77% rename from src/main/java/org/jabref/gui/maintable/NormalTableColumn.java rename to src/main/java/org/jabref/gui/maintable/FieldColumn.java index e1459225395..b288e5f2511 100644 --- a/src/main/java/org/jabref/gui/maintable/NormalTableColumn.java +++ b/src/main/java/org/jabref/gui/maintable/FieldColumn.java @@ -5,11 +5,7 @@ import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.value.ObservableValue; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.control.TableColumn; -import org.jabref.gui.icon.JabRefIcon; import org.jabref.logic.layout.LayoutFormatter; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; import org.jabref.model.database.BibDatabase; @@ -22,27 +18,20 @@ /** * A column that displays the text-value of the field */ -public class NormalTableColumn extends TableColumn { +public class FieldColumn extends MainTableColumn { private final OrFields bibtexFields; - private final boolean isIconColumn; - - private final Optional iconLabel; - private final Optional database; private final LayoutFormatter toUnicode = new LatexToUnicodeFormatter(); - private final String columnName; - public NormalTableColumn(String columnName, OrFields bibtexFields, BibDatabase database) { - this.columnName = columnName; + public FieldColumn(MainTableColumnModel model, OrFields bibtexFields, BibDatabase database) { + super(model); this.bibtexFields = bibtexFields; - this.isIconColumn = false; - this.iconLabel = Optional.empty(); this.database = Optional.of(database); - setText(columnName); + setText(getDisplayName()); setCellValueFactory(param -> getColumnValue(param.getValue())); } @@ -51,16 +40,15 @@ public NormalTableColumn(String columnName, OrFields bibtexFields, BibDatabase d * * @return name to be displayed. null if field is empty. */ - public String getDisplayName() { - return bibtexFields.getDisplayName(); - } + @Override + public String getDisplayName() { return bibtexFields.getDisplayName(); } public ObservableValue getColumnValue(BibEntryTableViewModel entry) { if (bibtexFields.isEmpty()) { return null; } - ObjectBinding[] dependencies = bibtexFields.stream().map(entry::getField).toArray(ObjectBinding[]::new); + ObjectBinding[] dependencies = bibtexFields.stream().map(entry::getField).toArray(ObjectBinding[]::new); return Bindings.createStringBinding(() -> computeText(entry), dependencies); } @@ -88,14 +76,6 @@ private String computeText(BibEntryTableViewModel entry) { return result; } - public Node getHeaderLabel() { - if (isIconColumn) { - return iconLabel.map(JabRefIcon::getGraphicNode).get(); - } else { - return new Label(getDisplayName()); - } - } - /** * Check if the value returned by getColumnValue() is the same as a simple check of the entry's field(s) would give * The reasons for being different are (combinations may also happen): - The entry has a crossref where the field @@ -131,7 +111,4 @@ public boolean isResolved(BibEntry entry) { return (!resolvedFieldContent.equals(plainFieldContent)); } - public String getColumnName() { - return columnName; - } } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java new file mode 100644 index 00000000000..f4443913cc5 --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java @@ -0,0 +1,35 @@ +package org.jabref.gui.maintable; + +import java.util.Optional; + +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.TableColumn; + +import org.jabref.gui.icon.JabRefIcon; + +public class MainTableColumn extends TableColumn { + + private MainTableColumnModel model; + + private final Optional iconLabel; + + public MainTableColumn(MainTableColumnModel model) { + this.model = model; + this.iconLabel = Optional.empty(); + } + + public MainTableColumnModel getModel() { return model; } + + public Node getHeaderLabel() { + if (model.getType() == MainTableColumnModel.Type.GROUPS || model.getType() == MainTableColumnModel.Type.FILES) { + return iconLabel.map(JabRefIcon::getGraphicNode).get(); + } else { + return new Label(model.getDisplayName()); + } + } + + public String getDisplayName() { + return model.getDisplayName(); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index 7c83036c780..dfd3e4b54c0 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -88,8 +88,8 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre case GROUPS: columns.add(createGroupColumn()); break; - case FILE: - columns.add(createFileColumn()); + case FILES: + columns.add(createFilesColumn()); break; case LINKED_IDENTIFIER: columns.add(createIdentifierColumn()); @@ -106,14 +106,14 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre columns.add(createSpecialFieldColumn((SpecialField) field)); } else { LOGGER.warn(Localization.lang("Special field type %0 is unknown. Using normal column type.", column.getName())); - columns.add(createNormalColumn(field)); + columns.add(createFieldColumn(field)); } } break; case NORMALFIELD: if (!column.getName().equals("")) { field = FieldFactory.parseField(column.getName()); - columns.add(createNormalColumn(field)); + columns.add(createFieldColumn(field)); } break; default: @@ -134,7 +134,7 @@ private void setExactWidth(TableColumn column, int width) { * Creates a column for group color bars. */ private TableColumn createGroupColumn() { - TableColumn> column = new TableColumn<>(); + TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); Node headerGraphic = IconTheme.JabRefIcons.DEFAULT_GROUP_ICON.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Group color"))); column.setGraphic(headerGraphic); @@ -185,9 +185,12 @@ private Node createGroupColorRegion(BibEntryTableViewModel entry, List createNormalColumn(Field field) { + private TableColumn createFieldColumn(Field field) { String columnName = field.getName(); - NormalTableColumn column = new NormalTableColumn(columnName, FieldFactory.parseOrFields(columnName), database.getDatabase()); + FieldColumn column = new FieldColumn(new MainTableColumnModel( + MainTableColumnModel.Type.NORMALFIELD, columnName), + FieldFactory.parseOrFields(columnName), + database.getDatabase()); new ValueTableCellFactory() .withText(text -> text) .install(column); @@ -200,8 +203,8 @@ private Node createGroupColorRegion(BibEntryTableViewModel entry, List> createFileColumn() { - TableColumn> column = new TableColumn<>(); + private TableColumn> createFilesColumn() { + TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.FILES)); Node headerGraphic = IconTheme.JabRefIcons.FILE.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked files"))); column.setGraphic(headerGraphic); @@ -265,7 +268,7 @@ private Node createFileIcon(List linkedFiles) { * Creates a column for all the linked files of a single file type. */ private TableColumn> createExtraFileColumn(String externalFileTypeName) { - TableColumn> column = new TableColumn<>(); + TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.EXTRAFILE, externalFileTypeName)); column.setGraphic(externalFileTypes .getExternalFileTypeByName(externalFileTypeName) .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) @@ -284,7 +287,7 @@ private TableColumn> createExtraFileCol * Creates a clickable icons column for DOIs, URLs, URIs and EPrints. */ private TableColumn> createIdentifierColumn() { - TableColumn> column = new TableColumn<>(); + TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); Node headerGraphic = IconTheme.JabRefIcons.WWW.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked identifiers"))); column.setGraphic(headerGraphic); @@ -333,10 +336,10 @@ private ContextMenu createIdentifierMenu(BibEntryTableViewModel entry, Map> createSpecialFieldColumn(SpecialField specialField) { - TableColumn> column = new TableColumn<>(); + TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, specialField.getName())); SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index 7b5391a678f..6b45b94b5fd 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -10,7 +10,7 @@ public class MainTableColumnModel { public enum Type { EXTRAFILE("extrafile", Localization.lang("File type")), - FILE("files", Localization.lang("Linked files")), + FILES("files", Localization.lang("Linked files")), GROUPS("groups", Localization.lang("Groups")), LINKED_IDENTIFIER("linked_id", Localization.lang("Linked identifiers")), NORMALFIELD("field"), @@ -40,7 +40,7 @@ public String getDisplayName() { public static Type parse(String text) { switch (text) { case "groups": return GROUPS; - case "files": return FILE; + case "files": return FILES; case "extrafile": return EXTRAFILE; case "linked_id": return LINKED_IDENTIFIER; case "special": return SPECIALFIELD; @@ -58,7 +58,7 @@ public MainTableColumnModel(String rawColumnName) { String[] splitname = rawColumnName.split(ColumnPreferences.QUALIFIER_SEPARATOR); type = Type.parse(splitname[0]); - if (type == Type.GROUPS || type == Type.FILE || type == Type.LINKED_IDENTIFIER) { + if (type == Type.GROUPS || type == Type.FILES || type == Type.LINKED_IDENTIFIER) { name = ""; } else { if (splitname.length == 1) { @@ -76,12 +76,18 @@ public MainTableColumnModel(Type type, String name) { this.name = name; } + public MainTableColumnModel(Type type) { + Objects.requireNonNull(type); + this.type = type; + this.name = ""; + } + public Type getType() { return type; } public String getName() { return name; } public String getDisplayName() { - if ((type == Type.GROUPS || type == Type.FILE || type == Type.LINKED_IDENTIFIER) && name.isBlank()) { + if ((type == Type.GROUPS || type == Type.FILES || type == Type.LINKED_IDENTIFIER) && name.isBlank()) { return type.getDisplayName(); } else { return FieldsUtil.getNameWithType(FieldFactory.parseField(name)); diff --git a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java index 0b7d7b1dbb4..af2885b807d 100644 --- a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java +++ b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java @@ -57,12 +57,8 @@ private void updateColumnPreferences() { List columnsWidths = new ArrayList<>(); for (TableColumn column : mainTable.getColumns()) { - if (column instanceof NormalTableColumn) { - NormalTableColumn normalColumn = (NormalTableColumn) column; - - columnNames.add(normalColumn.getColumnName()); - columnsWidths.add(String.valueOf(Double.valueOf(normalColumn.getWidth()).intValue())); - } + columnNames.add(((MainTableColumn) column).getModel().toString()); + columnsWidths.add(String.valueOf(Double.valueOf(column.getWidth()).intValue())); } if ((columnNames.size() == columnsWidths.size()) && From 7a5a09f47e92d069eae132f8a4acc7049220fd68 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Fri, 1 Nov 2019 12:01:23 +0100 Subject: [PATCH 06/16] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac70ed8452b..e3f06c1b83e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - The entry editor is now open by default when JabRef starts up. [#5460](https://github.com/JabRef/jabref/issues/5460) - We added a new ADS fetcher to use the new ADS API [#4949](https://github.com/JabRef/jabref/issues/4949) - We added support of the [X11 primary selection](https://unix.stackexchange.com/a/139193/18033) [#2389](https://github.com/JabRef/jabref/issues/2389) +- We made the columns for groups, files and uri in the main table reorderable and merged the clickable icon columns for uri, url, doi and eprint. [#5544](https://github.com/JabRef/jabref/pull/5544) ### Fixed From 8edfbe06cd18671a4f23c2bb50399ab4ed67261b Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Fri, 1 Nov 2019 12:18:21 +0100 Subject: [PATCH 07/16] Added columns to available set --- .../preferences/TableColumnsTabViewModel.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index d54eae6888f..e87dca489be 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -93,11 +93,16 @@ public void setValues() { availableColumnsProperty.clear(); - availableColumnsProperty.add(new MainTableColumnModel(InternalField.TIMESTAMP.getName())); - availableColumnsProperty.add(new MainTableColumnModel(InternalField.OWNER.getName())); - availableColumnsProperty.add(new MainTableColumnModel(InternalField.GROUPS.getName())); - availableColumnsProperty.add(new MainTableColumnModel(InternalField.KEY_FIELD.getName())); - availableColumnsProperty.add(new MainTableColumnModel(InternalField.TYPE_HEADER.getName())); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.FILES)); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.TIMESTAMP.getName())); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.OWNER.getName())); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.GROUPS.getName())); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.KEY_FIELD.getName())); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.TYPE_HEADER.getName())); + availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); + EnumSet.allOf(StandardField.class).stream() .map(Field::getName) @@ -124,7 +129,7 @@ public void fillColumnList() { private void insertSpecialFieldColumns() { EnumSet.allOf(SpecialField.class).stream() .map(Field::getName).map(name -> new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, name)) - .forEach(item -> availableColumnsProperty.getValue().add(0, item)); + .forEach(item -> availableColumnsProperty.getValue().add(3, item)); } private void removeSpecialFieldColumns() { From 59551c09226de3631541d3f4d166ef12c66d5c85 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Fri, 1 Nov 2019 12:57:50 +0100 Subject: [PATCH 08/16] checkstyle --- .../org/jabref/gui/preferences/TableColumnsTabViewModel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index e87dca489be..53dd6f8908e 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -103,7 +103,6 @@ public void setValues() { availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.TYPE_HEADER.getName())); availableColumnsProperty.add(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); - EnumSet.allOf(StandardField.class).stream() .map(Field::getName) .map(name -> new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, name)) From 18af53512f10a1dbd24206f7ba349523da73fb35 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Fri, 1 Nov 2019 22:03:53 +0100 Subject: [PATCH 09/16] Fixed bug in persistent view --- .../java/org/jabref/gui/maintable/MainTableColumnModel.java | 5 +++++ .../jabref/gui/maintable/PersistenceVisualStateTable.java | 6 ++++-- .../jabref/gui/preferences/TableColumnsTabViewModel.java | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index 6b45b94b5fd..dedf540ff82 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -47,6 +47,11 @@ public static Type parse(String text) { case "field": default: return NORMALFIELD; } + /* try { + return Type.valueOf(text); + } catch (IllegalArgumentException iae) { + return NORMALFIELD; + } */ } } diff --git a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java index af2885b807d..8b16a6d154f 100644 --- a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java +++ b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java @@ -26,8 +26,10 @@ public PersistenceVisualStateTable(final MainTable mainTable, JabRefPreferences this.preferences = preferences; mainTable.getColumns().addListener(this::onColumnsChanged); - mainTable.getColumns().forEach(col -> col.sortTypeProperty().addListener(obs -> - updateColumnSortType(col.getText(), col.getSortType()))); + mainTable.getColumns().forEach(col -> { + MainTableColumn column = (MainTableColumn) col; + col.sortTypeProperty().addListener(obs -> updateColumnSortType(column.getModel().toString(), column.getSortType())); + }); mainTable.getColumns().forEach(col -> col.widthProperty().addListener(obs -> updateColumnPreferences())); } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index 53dd6f8908e..eddf3c1d3d9 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -128,7 +128,7 @@ public void fillColumnList() { private void insertSpecialFieldColumns() { EnumSet.allOf(SpecialField.class).stream() .map(Field::getName).map(name -> new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, name)) - .forEach(item -> availableColumnsProperty.getValue().add(3, item)); + .forEach(item -> availableColumnsProperty.getValue().add(0, item)); } private void removeSpecialFieldColumns() { From f94f87ea1296f4aaf2d6362012cda349fe139efb Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Sat, 2 Nov 2019 22:53:47 +0100 Subject: [PATCH 10/16] Refactored parse, rewording, cleanups --- .../gui/maintable/ColumnPreferences.java | 11 ++- .../gui/maintable/MainTableColumnFactory.java | 23 +++--- .../gui/maintable/MainTableColumnModel.java | 73 ++++++++++--------- .../preferences/TableColumnsItemModel.java | 18 ++--- .../gui/preferences/TableColumnsTabView.java | 6 +- .../preferences/TableColumnsTabViewModel.java | 26 ++++--- .../jabref/preferences/JabRefPreferences.java | 39 +++++++--- 7 files changed, 106 insertions(+), 90 deletions(-) diff --git a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java index f8a7b63f661..292b00542e5 100644 --- a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java +++ b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java @@ -7,10 +7,9 @@ public class ColumnPreferences { - public static final String QUALIFIER_SEPARATOR = ":"; public static final double DEFAULT_FIELD_LENGTH = 100; - private final List columnNames; + private final List columns; private final boolean specialFieldsEnabled; private final boolean autoSyncSpecialFieldsToKeyWords; private final boolean serializeSpecialFields; @@ -18,8 +17,8 @@ public class ColumnPreferences { private final Map columnWidths; private final Map columnSortType; - public ColumnPreferences(List columnNames, boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields, boolean extraFileColumnsEnabled, Map columnWidths, Map columnSortType) { - this.columnNames = columnNames; + public ColumnPreferences(List columns, boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields, boolean extraFileColumnsEnabled, Map columnWidths, Map columnSortType) { + this.columns = columns; this.specialFieldsEnabled = specialFieldsEnabled; this.autoSyncSpecialFieldsToKeyWords = autoSyncSpecialFieldsToKeyWords; this.serializeSpecialFields = serializeSpecialFields; @@ -40,8 +39,8 @@ public boolean getSerializeSpecialFields() { public boolean getExtraFileColumnsEnabled() { return extraFileColumnsEnabled; } - public List getColumnNames() { - return columnNames; + public List getColumns() { + return columns; } public Map getColumnWidths() { diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index dfd3e4b54c0..ba97d096683 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -79,10 +79,7 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre public List> createColumns() { List> columns = new ArrayList<>(); - preferences.getColumnNames().forEach(rawColumnName -> { - MainTableColumnModel column = new MainTableColumnModel(rawColumnName); - - Field field; + preferences.getColumns().forEach(column -> { switch (column.getType()) { case GROUPS: @@ -95,29 +92,27 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre columns.add(createIdentifierColumn()); break; case EXTRAFILE: - if (!column.getName().equals("")) { - columns.add(createExtraFileColumn(column.getName())); + if (!column.getQualifier().equals("")) { + columns.add(createExtraFileColumn(column.getQualifier())); } break; case SPECIALFIELD: - if (!column.getName().equals("")) { - field = FieldFactory.parseField(column.getName()); + if (!column.getQualifier().equals("")) { + Field field = FieldFactory.parseField(column.getQualifier()); if (field instanceof SpecialField) { columns.add(createSpecialFieldColumn((SpecialField) field)); } else { - LOGGER.warn(Localization.lang("Special field type %0 is unknown. Using normal column type.", column.getName())); + LOGGER.warn(Localization.lang("Special field type %0 is unknown. Using normal column type.", column.getQualifier())); columns.add(createFieldColumn(field)); } } break; + default: case NORMALFIELD: - if (!column.getName().equals("")) { - field = FieldFactory.parseField(column.getName()); - columns.add(createFieldColumn(field)); + if (!column.getQualifier().equals("")) { + columns.add(createFieldColumn(FieldFactory.parseField(column.getQualifier()))); } break; - default: - LOGGER.warn(Localization.lang("Column type %0 is unknown.", rawColumnName)); } }); diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index dedf540ff82..2716f401337 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -5,9 +5,19 @@ import org.jabref.gui.util.FieldsUtil; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.FieldFactory; +import org.jabref.preferences.JabRefPreferences; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Represents the full internal name of a column in the main table. Consists of two parts: + * The type of the column and a qualifier, like the field name to be displayed in the column. + */ public class MainTableColumnModel { + private static final Logger LOGGER = LoggerFactory.getLogger(MainTableColumnModel.class); + public enum Type { EXTRAFILE("extrafile", Localization.lang("File type")), FILES("files", Localization.lang("Linked files")), @@ -37,73 +47,68 @@ public String getDisplayName() { return displayName; } - public static Type parse(String text) { - switch (text) { - case "groups": return GROUPS; - case "files": return FILES; - case "extrafile": return EXTRAFILE; - case "linked_id": return LINKED_IDENTIFIER; - case "special": return SPECIALFIELD; - case "field": - default: return NORMALFIELD; + public static Type fromString(String text) { + for (Type type : Type.values()) { + if (type.getName().equals(text)) { + return type; + } } - /* try { - return Type.valueOf(text); - } catch (IllegalArgumentException iae) { - return NORMALFIELD; - } */ + LOGGER.warn(Localization.lang("Column type %0 is unknown.", text)); + return NORMALFIELD; } } private final Type type; - private final String name; + private final String qualifier; public MainTableColumnModel(String rawColumnName) { Objects.requireNonNull(rawColumnName); - String[] splitname = rawColumnName.split(ColumnPreferences.QUALIFIER_SEPARATOR); - type = Type.parse(splitname[0]); - if (type == Type.GROUPS || type == Type.FILES || type == Type.LINKED_IDENTIFIER) { - name = ""; - } else { - if (splitname.length == 1) { - name = splitname[0]; // If default type is parsed as NORMALFIELD + String[] splittedName = rawColumnName.split(JabRefPreferences.COLUMNS_QUALIFIER_DELIMITER.toString()); + + type = Type.fromString(splittedName[0]); + + if (type == Type.NORMALFIELD || type == Type.SPECIALFIELD || type == Type.EXTRAFILE) { + if (splittedName.length == 1) { + qualifier = splittedName[0]; // On default the rawColumnName is parsed as NORMALFIELD } else { - name = splitname[1]; + qualifier = splittedName[1]; } + } else { + qualifier = ""; } } - public MainTableColumnModel(Type type, String name) { + public MainTableColumnModel(Type type, String qualifier) { Objects.requireNonNull(type); - Objects.requireNonNull(name); + Objects.requireNonNull(qualifier); this.type = type; - this.name = name; + this.qualifier = qualifier; } public MainTableColumnModel(Type type) { Objects.requireNonNull(type); this.type = type; - this.name = ""; + this.qualifier = ""; } public Type getType() { return type; } - public String getName() { return name; } + public String getQualifier() { return qualifier; } public String getDisplayName() { - if ((type == Type.GROUPS || type == Type.FILES || type == Type.LINKED_IDENTIFIER) && name.isBlank()) { + if ((type == Type.GROUPS || type == Type.FILES || type == Type.LINKED_IDENTIFIER) && qualifier.isBlank()) { return type.getDisplayName(); } else { - return FieldsUtil.getNameWithType(FieldFactory.parseField(name)); + return FieldsUtil.getNameWithType(FieldFactory.parseField(qualifier)); } } public String toString() { - if (name.isBlank()) { + if (qualifier.isBlank()) { return type.getName(); } else { - return type.getName() + ":" + name; + return type.getName() + ":" + qualifier; } } @@ -121,10 +126,10 @@ public boolean equals(Object o) { if (type != that.type) { return false; } - return Objects.equals(name, that.name); + return Objects.equals(qualifier, that.qualifier); } public int hashCode() { - return Objects.hash(type, name); + return Objects.hash(type, qualifier); } } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java index 3d92dcbdaf4..02ac162444a 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java @@ -13,33 +13,33 @@ public class TableColumnsItemModel { - private final ObjectProperty columnName; + private final ObjectProperty columnModel; private final DoubleProperty length = new SimpleDoubleProperty(ColumnPreferences.DEFAULT_FIELD_LENGTH); - public TableColumnsItemModel(MainTableColumnModel columnName) { - this.columnName = new SimpleObjectProperty<>(columnName); + public TableColumnsItemModel(MainTableColumnModel columnModel) { + this.columnModel = new SimpleObjectProperty<>(columnModel); } - public TableColumnsItemModel(MainTableColumnModel columnName, double length) { - this(columnName); + public TableColumnsItemModel(MainTableColumnModel columnModel, double length) { + this(columnModel); this.length.setValue(length); } - public MainTableColumnModel getColumnName() { return columnName.get(); } + public MainTableColumnModel getColumnModel() { return columnModel.get(); } - public ObservableValue columnNameProperty() { return this.columnName; } + public ObservableValue columnModelProperty() { return this.columnModel; } public void setLength(double length) { this.length.set(length); } public double getLength() { return length.get(); } @Override - public int hashCode() { return Objects.hash(columnName); } + public int hashCode() { return Objects.hash(columnModel); } @Override public boolean equals(Object obj) { if (obj instanceof TableColumnsItemModel) { - return Objects.equals(this.columnName, ((TableColumnsItemModel) obj).columnName); + return Objects.equals(this.columnModel, ((TableColumnsItemModel) obj).columnModel); } else { return false; } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java index c9c73d0ae22..16a176b2c75 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java @@ -84,17 +84,17 @@ public void initialize() { private void setupTable() { nameColumn.setSortable(false); nameColumn.setReorderable(false); - nameColumn.setCellValueFactory(cellData -> cellData.getValue().columnNameProperty()); + nameColumn.setCellValueFactory(cellData -> cellData.getValue().columnModelProperty()); new ValueTableCellFactory() .withText(MainTableColumnModel::getDisplayName) .install(nameColumn); actionsColumn.setSortable(false); actionsColumn.setReorderable(false); - actionsColumn.setCellValueFactory(cellData -> cellData.getValue().columnNameProperty()); + actionsColumn.setCellValueFactory(cellData -> cellData.getValue().columnModelProperty()); new ValueTableCellFactory() .withGraphic(item -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) - .withTooltip(name -> Localization.lang("Remove column") + " " + name.getName()) + .withTooltip(name -> Localization.lang("Remove column") + " " + name.getQualifier()) .withOnMouseClickedEvent(item -> evt -> viewModel.removeColumn(columnsList.getFocusModel().getFocusedItem())) .install(actionsColumn); diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index eddf3c1d3d9..7b04b301d29 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -120,9 +120,11 @@ public void setValues() { public void fillColumnList() { columnsListProperty.getValue().clear(); - columnPreferences.getColumnNames().stream() - .map(columnName -> new TableColumnsItemModel(new MainTableColumnModel(columnName), columnPreferences.getColumnWidth(columnName))) - .forEach(columnsListProperty.getValue()::add); + columnPreferences.getColumns().stream() + .map(column -> new TableColumnsItemModel( + column, + columnPreferences.getColumnWidth(column.toString()))) + .forEach(columnsListProperty.getValue()::add); } private void insertSpecialFieldColumns() { @@ -132,7 +134,7 @@ private void insertSpecialFieldColumns() { } private void removeSpecialFieldColumns() { - columnsListProperty.getValue().removeIf(column -> column.getColumnName().getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); + columnsListProperty.getValue().removeIf(column -> column.getColumnModel().getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); availableColumnsProperty.getValue().removeIf(columnName -> columnName.getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); } @@ -144,7 +146,7 @@ private void insertExtraFileColumns() { } private void removeExtraFileColumns() { - columnsListProperty.getValue().removeIf(column -> column.getColumnName().getType() == MainTableColumnModel.Type.EXTRAFILE); + columnsListProperty.getValue().removeIf(column -> column.getColumnModel().getType() == MainTableColumnModel.Type.EXTRAFILE); availableColumnsProperty.getValue().removeIf(columnName -> columnName.getType().equals(MainTableColumnModel.Type.EXTRAFILE)); } @@ -153,7 +155,7 @@ public void insertColumnInList() { return; } - if (columnsListProperty.getValue().stream().map(TableColumnsItemModel::getColumnName).filter(item -> item.equals(addColumnProperty.getValue())).findAny().isEmpty()) { + if (columnsListProperty.getValue().stream().map(TableColumnsItemModel::getColumnModel).filter(item -> item.equals(addColumnProperty.getValue())).findAny().isEmpty()) { columnsListProperty.add(new TableColumnsItemModel(addColumnProperty.getValue())); addColumnProperty.setValue(null); } @@ -189,16 +191,16 @@ public void moveColumnDown() { @Override public void storeSettings() { - List columnNames = columnsListProperty.stream() - .map(item -> item.getColumnName().toString()) - .collect(Collectors.toList()); + List columns = columnsListProperty.stream() + .map(TableColumnsItemModel::getColumnModel) + .collect(Collectors.toList()); // for each column get either actual width or - if it does not exist - default value - Map columnWidths = new HashMap<>(); - columnNames.forEach(field -> columnWidths.put(field,columnPreferences.getColumnWidth(field))); + Map columnWidths = new HashMap<>(); + columns.forEach(column -> columnWidths.put(column.toString(),columnPreferences.getColumnWidth(column.toString()))); ColumnPreferences newColumnPreferences = new ColumnPreferences( - columnNames, + columns, specialFieldsEnabledProperty.getValue(), specialFieldsSyncKeywordsProperty.getValue(), specialFieldsSerializeProperty.getValue(), diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 2937f721b65..23bfa5649f8 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -49,6 +49,7 @@ import org.jabref.gui.groups.GroupViewMode; import org.jabref.gui.keyboard.KeyBindingRepository; import org.jabref.gui.maintable.ColumnPreferences; +import org.jabref.gui.maintable.MainTableColumnModel; import org.jabref.gui.maintable.MainTablePreferences; import org.jabref.gui.mergeentries.MergeEntries; import org.jabref.gui.preferences.ImportTabViewModel; @@ -353,9 +354,13 @@ public class JabRefPreferences implements PreferencesService { // Id Entry Generator Preferences public static final String ID_ENTRY_GENERATOR = "idEntryGenerator"; - //File linking Options for entry editor + // File linking Options for entry editor public static final String ENTRY_EDITOR_DRAG_DROP_PREFERENCE_TYPE = "DragDropPreferenceType"; + // String delimiters + public static final Character STRINGLIST_DELIMITER = ';'; + public static final Character COLUMNS_QUALIFIER_DELIMITER = ':'; + // Preview private static final String PREVIEW_STYLE = "previewStyle"; private static final String CYCLE_PREVIEW_POS = "cyclePreviewPos"; @@ -773,7 +778,7 @@ public static JabRefPreferences getInstance() { } private static String convertListToString(List value) { - return value.stream().map(val -> StringUtil.quote(val, ";", '\\')).collect(Collectors.joining(";")); + return value.stream().map(val -> StringUtil.quote(val, STRINGLIST_DELIMITER.toString(), '\\')).collect(Collectors.joining(STRINGLIST_DELIMITER.toString())); } /** @@ -818,7 +823,7 @@ private static Optional getNextUnit(Reader data) throws IOException { // last character was escape symbol boolean escape = false; - // true if a ";" is found + // true if a STRINGLIST_DELIMITER is found boolean done = false; StringBuilder res = new StringBuilder(); @@ -831,9 +836,9 @@ private static Optional getNextUnit(Reader data) throws IOException { escape = true; } } else { - if (c == ';') { + if (c == STRINGLIST_DELIMITER) { if (escape) { - res.append(';'); + res.append(STRINGLIST_DELIMITER); } else { done = true; } @@ -959,7 +964,7 @@ private List getCustomTabFieldNames() { break; } - customFields.addAll(Arrays.stream(fields.split(";")).map(FieldFactory::parseField).collect(Collectors.toList())); + customFields.addAll(Arrays.stream(fields.split(STRINGLIST_DELIMITER.toString())).map(FieldFactory::parseField).collect(Collectors.toList())); defNumber++; } return customFields; @@ -968,7 +973,7 @@ private List getCustomTabFieldNames() { public void setLanguageDependentDefaultValues() { // Entry editor tab 0: defaults.put(CUSTOM_TAB_NAME + "_def0", Localization.lang("General")); - String fieldNames = FieldFactory.getDefaultGeneralFields().stream().map(Field::getName).collect(Collectors.joining(";")); + String fieldNames = FieldFactory.getDefaultGeneralFields().stream().map(Field::getName).collect(Collectors.joining(STRINGLIST_DELIMITER.toString())); defaults.put(CUSTOM_TAB_FIELDS + "_def0", fieldNames); // Entry editor tab 1: @@ -1057,8 +1062,8 @@ public void remove(String key) { } /** - * Puts a list of strings into the Preferences, by linking its elements with ';' into a single string. Escape - * characters make the process transparent even if strings contain ';'. + * Puts a list of strings into the Preferences, by linking its elements with a STRINGLIST_DELIMITER into a single + * string. Escape characters make the process transparent even if strings contains a STRINGLIST_DELIMITER. */ public void putStringList(String key, List value) { if (value == null) { @@ -1847,6 +1852,12 @@ public void storeSidePanePreferredPositions(Map preferred putStringList(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS, positions); } + private List createMainTableColumns() { + return getStringList(COLUMN_NAMES).stream() + .map(MainTableColumnModel::new) + .collect(Collectors.toList()); + } + private Map createColumnWidths() { List columns = getStringList(COLUMN_NAMES); List widths = getStringList(COLUMN_WIDTHS) @@ -1870,7 +1881,7 @@ private Map createColumnWidths() { public ColumnPreferences getColumnPreferences() { return new ColumnPreferences( - getStringList(COLUMN_NAMES), + createMainTableColumns(), getBoolean(SPECIALFIELDSENABLED), getBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS), getBoolean(SERIALIZESPECIALFIELDS), @@ -1880,7 +1891,10 @@ public ColumnPreferences getColumnPreferences() { } public void storeColumnPreferences(ColumnPreferences columnPreferences) { - putStringList(COLUMN_NAMES, columnPreferences.getColumnNames()); + + putStringList(COLUMN_NAMES, columnPreferences.getColumns().stream() + .map(MainTableColumnModel::toString) + .collect(Collectors.toList())); putBoolean(SPECIALFIELDSENABLED, columnPreferences.getSpecialFieldsEnabled()); putBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS, columnPreferences.getAutoSyncSpecialFieldsToKeyWords()); @@ -1888,7 +1902,8 @@ public void storeColumnPreferences(ColumnPreferences columnPreferences) { putBoolean(EXTRA_FILE_COLUMNS, columnPreferences.getExtraFileColumnsEnabled()); List columnWidthsInOrder = new ArrayList<>(); - columnPreferences.getColumnNames().forEach(name -> columnWidthsInOrder.add(columnPreferences.getColumnWidths().get(name).toString())); + columnPreferences.getColumns().forEach(column -> + columnWidthsInOrder.add(columnPreferences.getColumnWidths().get(column.toString()).toString())); putStringList(COLUMN_WIDTHS, columnWidthsInOrder); setMainTableColumnSortType(columnPreferences.getSortTypesForColumns()); From 0a4e3f74b63977b37d87159220bec42050922a77 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Sun, 3 Nov 2019 01:56:48 +0100 Subject: [PATCH 11/16] Removed TableColumnsItemModel, cleanups --- .../gui/maintable/ColumnPreferences.java | 12 +- .../gui/maintable/MainTableColumnFactory.java | 198 +++++++++--------- .../gui/maintable/MainTableColumnModel.java | 81 ++++--- .../PersistenceVisualStateTable.java | 28 +-- .../preferences/TableColumnsItemModel.java | 47 ----- .../gui/preferences/TableColumnsTabView.java | 20 +- .../preferences/TableColumnsTabViewModel.java | 47 ++--- .../jabref/preferences/JabRefPreferences.java | 43 ++-- 8 files changed, 211 insertions(+), 265 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java diff --git a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java index 292b00542e5..bdced5d255e 100644 --- a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java +++ b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java @@ -14,16 +14,14 @@ public class ColumnPreferences { private final boolean autoSyncSpecialFieldsToKeyWords; private final boolean serializeSpecialFields; private final boolean extraFileColumnsEnabled; - private final Map columnWidths; private final Map columnSortType; - public ColumnPreferences(List columns, boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields, boolean extraFileColumnsEnabled, Map columnWidths, Map columnSortType) { + public ColumnPreferences(List columns, boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields, boolean extraFileColumnsEnabled, Map columnSortType) { this.columns = columns; this.specialFieldsEnabled = specialFieldsEnabled; this.autoSyncSpecialFieldsToKeyWords = autoSyncSpecialFieldsToKeyWords; this.serializeSpecialFields = serializeSpecialFields; this.extraFileColumnsEnabled = extraFileColumnsEnabled; - this.columnWidths = columnWidths; this.columnSortType = columnSortType; } @@ -43,14 +41,6 @@ public List getColumns() { return columns; } - public Map getColumnWidths() { - return columnWidths; - } - - public double getColumnWidth(String columnName) { - return columnWidths.getOrDefault(columnName, DEFAULT_FIELD_LENGTH); - } - public Map getSortTypesForColumns() { return columnSortType; } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index ba97d096683..317571d628d 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -93,24 +93,24 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre break; case EXTRAFILE: if (!column.getQualifier().equals("")) { - columns.add(createExtraFileColumn(column.getQualifier())); + columns.add(createExtraFileColumn(column)); } break; case SPECIALFIELD: if (!column.getQualifier().equals("")) { Field field = FieldFactory.parseField(column.getQualifier()); if (field instanceof SpecialField) { - columns.add(createSpecialFieldColumn((SpecialField) field)); + columns.add(createSpecialFieldColumn(column)); } else { LOGGER.warn(Localization.lang("Special field type %0 is unknown. Using normal column type.", column.getQualifier())); - columns.add(createFieldColumn(field)); + columns.add(createFieldColumn(column)); } } break; default: case NORMALFIELD: if (!column.getQualifier().equals("")) { - columns.add(createFieldColumn(FieldFactory.parseField(column.getQualifier()))); + columns.add(createFieldColumn(column)); } break; } @@ -168,8 +168,8 @@ private Node createGroupColorRegion(BibEntryTableViewModel entry, List createFieldColumn(Field field) { - String columnName = field.getName(); - FieldColumn column = new FieldColumn(new MainTableColumnModel( - MainTableColumnModel.Type.NORMALFIELD, columnName), - FieldFactory.parseOrFields(columnName), + private TableColumn createFieldColumn(MainTableColumnModel columnModel) { + FieldColumn column = new FieldColumn(columnModel, + FieldFactory.parseOrFields(columnModel.getQualifier()), database.getDatabase()); new ValueTableCellFactory() .withText(text -> text) .install(column); column.setSortable(true); - column.setPrefWidth(preferences.getColumnWidth(columnName)); - return column; - } - - /** - * Creates a column for all the linked files. Instead of creating a column for a single file type, like - * {@code createExtraFileColumn} does, this creates one single column collecting all file links. - */ - private TableColumn> createFilesColumn() { - TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.FILES)); - Node headerGraphic = IconTheme.JabRefIcons.FILE.getGraphicNode(); - Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked files"))); - column.setGraphic(headerGraphic); - column.getStyleClass().add(STYLE_ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); - column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); - new ValueTableCellFactory>() - .withGraphic(this::createFileIcon) - .withTooltip(this::createFileTooltip) - .withMenu(this::createFileMenu) - .withOnMouseClickedEvent((entry, linkedFiles) -> event -> { - if ((event.getButton() == MouseButton.PRIMARY) && (linkedFiles.size() == 1)) { - // Only one linked file -> open directly - LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFiles.get(0), entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs.getXMPPreferences(), Globals.prefs.getFilePreferences(), externalFileTypes); - linkedFileViewModel.open(); - } - }) - .install(column); - return column; - } - - private String createFileTooltip(List linkedFiles) { - if (linkedFiles.size() > 0) { - return Localization.lang("Open file %0", linkedFiles.get(0).getLink()); - } - return null; - } - - private ContextMenu createFileMenu(BibEntryTableViewModel entry, List linkedFiles) { - if (linkedFiles.size() <= 1) { - return null; - } - - ContextMenu contextMenu = new ContextMenu(); - - for (LinkedFile linkedFile : linkedFiles) { - LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFile, entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs.getXMPPreferences(), Globals.prefs.getFilePreferences(), externalFileTypes); - - MenuItem menuItem = new MenuItem(linkedFileViewModel.getDescriptionAndLink(), linkedFileViewModel.getTypeIcon().getGraphicNode()); - menuItem.setOnAction(event -> linkedFileViewModel.open()); - contextMenu.getItems().add(menuItem); - } - - return contextMenu; - } - - private Node createFileIcon(List linkedFiles) { - if (linkedFiles.size() > 1) { - return IconTheme.JabRefIcons.FILE_MULTIPLE.getGraphicNode(); - } else if (linkedFiles.size() == 1) { - return externalFileTypes.fromLinkedFile(linkedFiles.get(0), false) - .map(ExternalFileType::getIcon) - .orElse(IconTheme.JabRefIcons.FILE) - .getGraphicNode(); - } else { - return null; - } - } - - /** - * Creates a column for all the linked files of a single file type. - */ - private TableColumn> createExtraFileColumn(String externalFileTypeName) { - TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.EXTRAFILE, externalFileTypeName)); - column.setGraphic(externalFileTypes - .getExternalFileTypeByName(externalFileTypeName) - .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) - .getGraphicNode()); - column.getStyleClass().add(STYLE_ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); - column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); - new ValueTableCellFactory>() - .withGraphic(linkedFiles -> createFileIcon(linkedFiles.stream().filter(linkedFile -> linkedFile.getFileType().equalsIgnoreCase(externalFileTypeName)).collect(Collectors.toList()))) - .install(column); - + column.setPrefWidth(columnModel.getWidth()); return column; } @@ -333,8 +247,10 @@ private ContextMenu createIdentifierMenu(BibEntryTableViewModel entry, Map> createSpecialFieldColumn(SpecialField specialField) { - TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, specialField.getName())); + private TableColumn> createSpecialFieldColumn(MainTableColumnModel columnModel) { + SpecialField specialField = (SpecialField) FieldFactory.parseField(columnModel.getQualifier()); + TableColumn> column = + new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, specialField.getName())); SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); @@ -411,4 +327,90 @@ private Node createSpecialFieldIcon(Optional fieldVa return node; }); } + + /** + * Creates a column for all the linked files. Instead of creating a column for a single file type, like {@code + * createExtraFileColumn} does, this creates one single column collecting all file links. + */ + private TableColumn> createFilesColumn() { + TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.FILES)); + Node headerGraphic = IconTheme.JabRefIcons.FILE.getGraphicNode(); + Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked files"))); + column.setGraphic(headerGraphic); + column.getStyleClass().add(STYLE_ICON_COLUMN); + setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); + new ValueTableCellFactory>() + .withGraphic(this::createFileIcon) + .withTooltip(this::createFileTooltip) + .withMenu(this::createFileMenu) + .withOnMouseClickedEvent((entry, linkedFiles) -> event -> { + if ((event.getButton() == MouseButton.PRIMARY) && (linkedFiles.size() == 1)) { + // Only one linked file -> open directly + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFiles.get(0), entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs.getXMPPreferences(), Globals.prefs.getFilePreferences(), externalFileTypes); + linkedFileViewModel.open(); + } + }) + .install(column); + return column; + } + + private String createFileTooltip(List linkedFiles) { + if (linkedFiles.size() > 0) { + return Localization.lang("Open file %0", linkedFiles.get(0).getLink()); + } + return null; + } + + private ContextMenu createFileMenu(BibEntryTableViewModel entry, List linkedFiles) { + if (linkedFiles.size() <= 1) { + return null; + } + + ContextMenu contextMenu = new ContextMenu(); + + for (LinkedFile linkedFile : linkedFiles) { + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFile, entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs.getXMPPreferences(), Globals.prefs.getFilePreferences(), externalFileTypes); + + MenuItem menuItem = new MenuItem(linkedFileViewModel.getDescriptionAndLink(), linkedFileViewModel.getTypeIcon().getGraphicNode()); + menuItem.setOnAction(event -> linkedFileViewModel.open()); + contextMenu.getItems().add(menuItem); + } + + return contextMenu; + } + + private Node createFileIcon(List linkedFiles) { + if (linkedFiles.size() > 1) { + return IconTheme.JabRefIcons.FILE_MULTIPLE.getGraphicNode(); + } else if (linkedFiles.size() == 1) { + return externalFileTypes.fromLinkedFile(linkedFiles.get(0), false) + .map(ExternalFileType::getIcon) + .orElse(IconTheme.JabRefIcons.FILE) + .getGraphicNode(); + } else { + return null; + } + } + + /** + * Creates a column for all the linked files of a single file type. + */ + private TableColumn> createExtraFileColumn(MainTableColumnModel columnModel) { + TableColumn> column = new MainTableColumn<>( + new MainTableColumnModel(MainTableColumnModel.Type.EXTRAFILE, columnModel.getQualifier())); + column.setGraphic(externalFileTypes + .getExternalFileTypeByName(columnModel.getQualifier()) + .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) + .getGraphicNode()); + column.getStyleClass().add(STYLE_ICON_COLUMN); + setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); + new ValueTableCellFactory>() + .withGraphic(linkedFiles -> createFileIcon(linkedFiles.stream().filter(linkedFile -> + linkedFile.getFileType().equalsIgnoreCase(columnModel.getQualifier())).collect(Collectors.toList()))) + .install(column); + + return column; + } } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index 2716f401337..54b9cf1f108 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -2,6 +2,14 @@ import java.util.Objects; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyStringWrapper; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + import org.jabref.gui.util.FieldsUtil; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.FieldFactory; @@ -58,60 +66,75 @@ public static Type fromString(String text) { } } - private final Type type; - private final String qualifier; + private final ObjectProperty typeProperty = new SimpleObjectProperty<>(); + private final StringProperty qualifierProperty = new SimpleStringProperty(""); + private final DoubleProperty widthProperty = new SimpleDoubleProperty(ColumnPreferences.DEFAULT_FIELD_LENGTH); public MainTableColumnModel(String rawColumnName) { Objects.requireNonNull(rawColumnName); String[] splittedName = rawColumnName.split(JabRefPreferences.COLUMNS_QUALIFIER_DELIMITER.toString()); + Type type = Type.fromString(splittedName[0]); - type = Type.fromString(splittedName[0]); + typeProperty.setValue(type); if (type == Type.NORMALFIELD || type == Type.SPECIALFIELD || type == Type.EXTRAFILE) { if (splittedName.length == 1) { - qualifier = splittedName[0]; // On default the rawColumnName is parsed as NORMALFIELD + qualifierProperty.setValue(splittedName[0]); // On default the rawColumnName is parsed as NORMALFIELD } else { - qualifier = splittedName[1]; + qualifierProperty.setValue(splittedName[1]); } - } else { - qualifier = ""; } } - public MainTableColumnModel(Type type, String qualifier) { - Objects.requireNonNull(type); - Objects.requireNonNull(qualifier); - this.type = type; - this.qualifier = qualifier; + public MainTableColumnModel(String rawColumnName, Double width) { + this(rawColumnName); + + Objects.requireNonNull(width); + this.widthProperty.setValue(width); } - public MainTableColumnModel(Type type) { - Objects.requireNonNull(type); - this.type = type; - this.qualifier = ""; + public MainTableColumnModel(Type typeProperty, String qualifierProperty) { + Objects.requireNonNull(typeProperty); + Objects.requireNonNull(qualifierProperty); + this.typeProperty.setValue(typeProperty); + this.qualifierProperty.setValue(qualifierProperty); } - public Type getType() { return type; } + public MainTableColumnModel(Type typeProperty) { + Objects.requireNonNull(typeProperty); + this.typeProperty.setValue(typeProperty); + } - public String getQualifier() { return qualifier; } + public Type getType() { return typeProperty.getValue(); } - public String getDisplayName() { - if ((type == Type.GROUPS || type == Type.FILES || type == Type.LINKED_IDENTIFIER) && qualifier.isBlank()) { - return type.getDisplayName(); + public String getQualifier() { return qualifierProperty.getValue(); } + + public String getName() { + if (qualifierProperty.getValue().isBlank()) { + return typeProperty.getValue().getName(); } else { - return FieldsUtil.getNameWithType(FieldFactory.parseField(qualifier)); + return typeProperty.getValue().getName() + ":" + qualifierProperty.getValue(); } } - public String toString() { - if (qualifier.isBlank()) { - return type.getName(); + public String getDisplayName() { + if ((typeProperty.getValue() == Type.GROUPS + || typeProperty.getValue() == Type.FILES + || typeProperty.getValue() == Type.LINKED_IDENTIFIER) + && qualifierProperty.getValue().isBlank()) { + return typeProperty.getValue().getDisplayName(); } else { - return type.getName() + ":" + qualifier; + return FieldsUtil.getNameWithType(FieldFactory.parseField(qualifierProperty.getValue())); } } + public void setWidth(double length) { this.widthProperty.setValue(length); } + + public Double getWidth() { return widthProperty.getValue(); } + + public StringProperty nameProperty() { return new ReadOnlyStringWrapper(getDisplayName()); } + public boolean equals(Object o) { if (this == o) { return true; @@ -123,13 +146,13 @@ public boolean equals(Object o) { MainTableColumnModel that = (MainTableColumnModel) o; - if (type != that.type) { + if (typeProperty != that.typeProperty) { return false; } - return Objects.equals(qualifier, that.qualifier); + return Objects.equals(qualifierProperty, that.qualifierProperty); } public int hashCode() { - return Objects.hash(type, qualifier); + return Objects.hash(typeProperty.getValue(), qualifierProperty.getValue()); } } diff --git a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java index 8b16a6d154f..cb0a5db3a5e 100644 --- a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java +++ b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java @@ -28,7 +28,7 @@ public PersistenceVisualStateTable(final MainTable mainTable, JabRefPreferences mainTable.getColumns().addListener(this::onColumnsChanged); mainTable.getColumns().forEach(col -> { MainTableColumn column = (MainTableColumn) col; - col.sortTypeProperty().addListener(obs -> updateColumnSortType(column.getModel().toString(), column.getSortType())); + col.sortTypeProperty().addListener(obs -> updateColumnSortType(column.getModel().getName(), column.getSortType())); }); mainTable.getColumns().forEach(col -> col.widthProperty().addListener(obs -> updateColumnPreferences())); @@ -55,18 +55,22 @@ private void updateColumnSortType(String text, SortType sortType) { * Store shown columns and their width in preferences. */ private void updateColumnPreferences() { - List columnNames = new ArrayList<>(); - List columnsWidths = new ArrayList<>(); + List columns = new ArrayList<>(); - for (TableColumn column : mainTable.getColumns()) { - columnNames.add(((MainTableColumn) column).getModel().toString()); - columnsWidths.add(String.valueOf(Double.valueOf(column.getWidth()).intValue())); - } + mainTable.getColumns().forEach(column -> { + MainTableColumnModel columnModel = ((MainTableColumn) column).getModel(); + columnModel.setWidth(column.getWidth()); + columns.add(columnModel); + }); - if ((columnNames.size() == columnsWidths.size()) && - (columnNames.size() == preferences.getStringList(JabRefPreferences.COLUMN_NAMES).size())) { - preferences.putStringList(JabRefPreferences.COLUMN_NAMES, columnNames); - preferences.putStringList(JabRefPreferences.COLUMN_WIDTHS, columnsWidths); - } + ColumnPreferences oldColumnPreferences = preferences.getColumnPreferences(); + + preferences.storeColumnPreferences(new ColumnPreferences( + columns, + oldColumnPreferences.getSpecialFieldsEnabled(), + oldColumnPreferences.getAutoSyncSpecialFieldsToKeyWords(), + oldColumnPreferences.getSerializeSpecialFields(), + oldColumnPreferences.getExtraFileColumnsEnabled(), + oldColumnPreferences.getSortTypesForColumns())); } } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java deleted file mode 100644 index 02ac162444a..00000000000 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsItemModel.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.jabref.gui.preferences; - -import java.util.Objects; - -import javafx.beans.property.DoubleProperty; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleDoubleProperty; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ObservableValue; - -import org.jabref.gui.maintable.ColumnPreferences; -import org.jabref.gui.maintable.MainTableColumnModel; - -public class TableColumnsItemModel { - - private final ObjectProperty columnModel; - private final DoubleProperty length = new SimpleDoubleProperty(ColumnPreferences.DEFAULT_FIELD_LENGTH); - - public TableColumnsItemModel(MainTableColumnModel columnModel) { - this.columnModel = new SimpleObjectProperty<>(columnModel); - } - - public TableColumnsItemModel(MainTableColumnModel columnModel, double length) { - this(columnModel); - this.length.setValue(length); - } - - public MainTableColumnModel getColumnModel() { return columnModel.get(); } - - public ObservableValue columnModelProperty() { return this.columnModel; } - - public void setLength(double length) { this.length.set(length); } - - public double getLength() { return length.get(); } - - @Override - public int hashCode() { return Objects.hash(columnModel); } - - @Override - public boolean equals(Object obj) { - if (obj instanceof TableColumnsItemModel) { - return Objects.equals(this.columnModel, ((TableColumnsItemModel) obj).columnModel); - } else { - return false; - } - } -} diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java index 16a176b2c75..c750dd256d4 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java @@ -32,7 +32,7 @@ public class TableColumnsTabView extends AbstractPreferenceTabView columnsList; - @FXML private TableColumn nameColumn; - @FXML private TableColumn actionsColumn; + @FXML private TableView columnsList; + @FXML private TableColumn nameColumn; + @FXML private TableColumn actionsColumn; @FXML private ComboBox addColumnName; @FXML private CheckBox specialFieldsEnable; @FXML private Button specialFieldsHelp; @@ -84,17 +84,17 @@ public void initialize() { private void setupTable() { nameColumn.setSortable(false); nameColumn.setReorderable(false); - nameColumn.setCellValueFactory(cellData -> cellData.getValue().columnModelProperty()); - new ValueTableCellFactory() - .withText(MainTableColumnModel::getDisplayName) + nameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty()); + new ValueTableCellFactory() + .withText(name -> name) .install(nameColumn); actionsColumn.setSortable(false); actionsColumn.setReorderable(false); - actionsColumn.setCellValueFactory(cellData -> cellData.getValue().columnModelProperty()); - new ValueTableCellFactory() + actionsColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty()); + new ValueTableCellFactory() .withGraphic(item -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) - .withTooltip(name -> Localization.lang("Remove column") + " " + name.getQualifier()) + .withTooltip(name -> Localization.lang("Remove column") + " " + name) .withOnMouseClickedEvent(item -> evt -> viewModel.removeColumn(columnsList.getFocusModel().getFocusedItem())) .install(actionsColumn); diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index 7b04b301d29..b8dc56a686d 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -2,10 +2,7 @@ import java.util.ArrayList; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ListProperty; @@ -35,8 +32,8 @@ public class TableColumnsTabViewModel implements PreferenceTabViewModel { - private final ListProperty columnsListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); - private final ObjectProperty> selectedColumnModelProperty = new SimpleObjectProperty<>(new NoSelectionModel<>()); + private final ListProperty columnsListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); + private final ObjectProperty> selectedColumnModelProperty = new SimpleObjectProperty<>(new NoSelectionModel<>()); private final ListProperty availableColumnsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); private final ObjectProperty addColumnProperty = new SimpleObjectProperty<>(); private final BooleanProperty specialFieldsEnabledProperty = new SimpleBooleanProperty(); @@ -119,12 +116,7 @@ public void setValues() { public void fillColumnList() { columnsListProperty.getValue().clear(); - - columnPreferences.getColumns().stream() - .map(column -> new TableColumnsItemModel( - column, - columnPreferences.getColumnWidth(column.toString()))) - .forEach(columnsListProperty.getValue()::add); + columnPreferences.getColumns().forEach(columnsListProperty.getValue()::add); } private void insertSpecialFieldColumns() { @@ -134,8 +126,8 @@ private void insertSpecialFieldColumns() { } private void removeSpecialFieldColumns() { - columnsListProperty.getValue().removeIf(column -> column.getColumnModel().getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); - availableColumnsProperty.getValue().removeIf(columnName -> columnName.getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); + columnsListProperty.getValue().removeIf(column -> column.getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); + availableColumnsProperty.getValue().removeIf(column -> column.getType().equals(MainTableColumnModel.Type.SPECIALFIELD)); } private void insertExtraFileColumns() { @@ -146,8 +138,8 @@ private void insertExtraFileColumns() { } private void removeExtraFileColumns() { - columnsListProperty.getValue().removeIf(column -> column.getColumnModel().getType() == MainTableColumnModel.Type.EXTRAFILE); - availableColumnsProperty.getValue().removeIf(columnName -> columnName.getType().equals(MainTableColumnModel.Type.EXTRAFILE)); + columnsListProperty.getValue().removeIf(column -> column.getType().equals(MainTableColumnModel.Type.EXTRAFILE)); + availableColumnsProperty.getValue().removeIf(column -> column.getType().equals(MainTableColumnModel.Type.EXTRAFILE)); } public void insertColumnInList() { @@ -155,18 +147,18 @@ public void insertColumnInList() { return; } - if (columnsListProperty.getValue().stream().map(TableColumnsItemModel::getColumnModel).filter(item -> item.equals(addColumnProperty.getValue())).findAny().isEmpty()) { - columnsListProperty.add(new TableColumnsItemModel(addColumnProperty.getValue())); + if (columnsListProperty.getValue().stream().filter(item -> item.equals(addColumnProperty.getValue())).findAny().isEmpty()) { + columnsListProperty.add(addColumnProperty.getValue()); addColumnProperty.setValue(null); } } - public void removeColumn(TableColumnsItemModel column) { + public void removeColumn(MainTableColumnModel column) { columnsListProperty.remove(column); } public void moveColumnUp() { - TableColumnsItemModel selectedColumn = selectedColumnModelProperty.getValue().getSelectedItem(); + MainTableColumnModel selectedColumn = selectedColumnModelProperty.getValue().getSelectedItem(); int row = columnsListProperty.getValue().indexOf(selectedColumn); if (selectedColumn == null || row < 1) { return; @@ -178,7 +170,7 @@ public void moveColumnUp() { } public void moveColumnDown() { - TableColumnsItemModel selectedColumn = selectedColumnModelProperty.getValue().getSelectedItem(); + MainTableColumnModel selectedColumn = selectedColumnModelProperty.getValue().getSelectedItem(); int row = columnsListProperty.getValue().indexOf(selectedColumn); if (selectedColumn == null || row > columnsListProperty.getValue().size() - 2) { return; @@ -191,21 +183,12 @@ public void moveColumnDown() { @Override public void storeSettings() { - List columns = columnsListProperty.stream() - .map(TableColumnsItemModel::getColumnModel) - .collect(Collectors.toList()); - - // for each column get either actual width or - if it does not exist - default value - Map columnWidths = new HashMap<>(); - columns.forEach(column -> columnWidths.put(column.toString(),columnPreferences.getColumnWidth(column.toString()))); - ColumnPreferences newColumnPreferences = new ColumnPreferences( - columns, + columnsListProperty.getValue(), specialFieldsEnabledProperty.getValue(), specialFieldsSyncKeywordsProperty.getValue(), specialFieldsSerializeProperty.getValue(), extraFileColumnsEnabledProperty.getValue(), - columnWidths, columnPreferences.getSortTypesForColumns() ); @@ -239,9 +222,9 @@ public List getRestartWarnings() { return restartWarnings; } - public ListProperty columnsListProperty() { return this.columnsListProperty; } + public ListProperty columnsListProperty() { return this.columnsListProperty; } - public ObjectProperty> selectedColumnModelProperty() { return selectedColumnModelProperty; } + public ObjectProperty> selectedColumnModelProperty() { return selectedColumnModelProperty; } public ListProperty availableColumnsProperty() { return this.availableColumnsProperty; } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 23bfa5649f8..9415f5923b2 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -25,7 +25,6 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.TreeMap; import java.util.UUID; import java.util.prefs.BackingStoreException; import java.util.prefs.InvalidPreferencesFormatException; @@ -1853,30 +1852,24 @@ public void storeSidePanePreferredPositions(Map preferred } private List createMainTableColumns() { - return getStringList(COLUMN_NAMES).stream() - .map(MainTableColumnModel::new) + List columnNames = getStringList(COLUMN_NAMES); + List columnWidths = getStringList(COLUMN_WIDTHS) + .stream() + .map(string -> { + try { + return Double.parseDouble(string); + } catch (NumberFormatException e) { + LOGGER.error("Exception while parsing column widths. Choosing default.", e); + return ColumnPreferences.DEFAULT_FIELD_LENGTH; + } + }) .collect(Collectors.toList()); - } - private Map createColumnWidths() { - List columns = getStringList(COLUMN_NAMES); - List widths = getStringList(COLUMN_WIDTHS) - .stream() - .map(string -> { - try { - return Double.parseDouble(string); - } catch (NumberFormatException e) { - LOGGER.error("Exception while parsing column widths. Choosing default.", e); - return ColumnPreferences.DEFAULT_FIELD_LENGTH; - } - }) - .collect(Collectors.toList()); - - Map map = new TreeMap<>(); - for (int i = 0; i < columns.size(); i++) { - map.put(columns.get(i), widths.get(i)); + List columns = new ArrayList<>(); + for (int i = 0; i < columnNames.size(); i++) { + columns.add(new MainTableColumnModel(columnNames.get(i), columnWidths.get(i))); } - return map; + return columns; } public ColumnPreferences getColumnPreferences() { @@ -1886,14 +1879,13 @@ public ColumnPreferences getColumnPreferences() { getBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS), getBoolean(SERIALIZESPECIALFIELDS), getBoolean(EXTRA_FILE_COLUMNS), - createColumnWidths(), getMainTableColumnSortTypes()); } public void storeColumnPreferences(ColumnPreferences columnPreferences) { putStringList(COLUMN_NAMES, columnPreferences.getColumns().stream() - .map(MainTableColumnModel::toString) + .map(MainTableColumnModel::getName) .collect(Collectors.toList())); putBoolean(SPECIALFIELDSENABLED, columnPreferences.getSpecialFieldsEnabled()); @@ -1902,8 +1894,7 @@ public void storeColumnPreferences(ColumnPreferences columnPreferences) { putBoolean(EXTRA_FILE_COLUMNS, columnPreferences.getExtraFileColumnsEnabled()); List columnWidthsInOrder = new ArrayList<>(); - columnPreferences.getColumns().forEach(column -> - columnWidthsInOrder.add(columnPreferences.getColumnWidths().get(column.toString()).toString())); + columnPreferences.getColumns().forEach(column -> columnWidthsInOrder.add(column.getWidth().toString())); putStringList(COLUMN_WIDTHS, columnWidthsInOrder); setMainTableColumnSortType(columnPreferences.getSortTypesForColumns()); From ae0821b5e36c78acdfb31828610484de04b7b51a Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Sun, 3 Nov 2019 11:45:56 +0100 Subject: [PATCH 12/16] Added migration and some minor tweaks --- .../gui/maintable/MainTableColumnModel.java | 7 ++-- .../preferences/TableColumnsTabViewModel.java | 3 +- .../migrations/PreferencesMigrations.java | 32 +++++++++++++++++++ .../jabref/preferences/JabRefPreferences.java | 3 +- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index 54b9cf1f108..2ef05399455 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -13,7 +13,6 @@ import org.jabref.gui.util.FieldsUtil; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.FieldFactory; -import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +23,8 @@ */ public class MainTableColumnModel { + public static final Character COLUMNS_QUALIFIER_DELIMITER = ':'; + private static final Logger LOGGER = LoggerFactory.getLogger(MainTableColumnModel.class); public enum Type { @@ -73,7 +74,7 @@ public static Type fromString(String text) { public MainTableColumnModel(String rawColumnName) { Objects.requireNonNull(rawColumnName); - String[] splittedName = rawColumnName.split(JabRefPreferences.COLUMNS_QUALIFIER_DELIMITER.toString()); + String[] splittedName = rawColumnName.split(COLUMNS_QUALIFIER_DELIMITER.toString()); Type type = Type.fromString(splittedName[0]); typeProperty.setValue(type); @@ -114,7 +115,7 @@ public String getName() { if (qualifierProperty.getValue().isBlank()) { return typeProperty.getValue().getName(); } else { - return typeProperty.getValue().getName() + ":" + qualifierProperty.getValue(); + return typeProperty.getValue().getName() + COLUMNS_QUALIFIER_DELIMITER + qualifierProperty.getValue(); } } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index b8dc56a686d..8c9768fb611 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -121,7 +121,8 @@ public void fillColumnList() { private void insertSpecialFieldColumns() { EnumSet.allOf(SpecialField.class).stream() - .map(Field::getName).map(name -> new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, name)) + .map(Field::getName) + .map(name -> new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, name)) .forEach(item -> availableColumnsProperty.getValue().add(0, item)); } diff --git a/src/main/java/org/jabref/migrations/PreferencesMigrations.java b/src/main/java/org/jabref/migrations/PreferencesMigrations.java index a5386c8b1d4..5fb4dd9aed7 100644 --- a/src/main/java/org/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/org/jabref/migrations/PreferencesMigrations.java @@ -12,6 +12,8 @@ import org.jabref.Globals; import org.jabref.JabRefMain; +import org.jabref.gui.maintable.ColumnPreferences; +import org.jabref.gui.maintable.MainTableColumnModel; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.EntryTypeFactory; @@ -43,6 +45,7 @@ public static void runMigrations() { upgradeKeyBindingsToJavaFX(Globals.prefs); addCrossRefRelatedFieldsForAutoComplete(Globals.prefs); upgradePreviewStyleFromReviewToComment(Globals.prefs); + upgradeColumnPreferences(Globals.prefs); } /** @@ -294,4 +297,33 @@ static void upgradePreviewStyleFromReviewToComment(JabRefPreferences prefs) { String migratedStyle = currentPreviewStyle.replace("\\begin{review}

Review: \\format[HTMLChars]{\\review} \\end{review}", "\\begin{comment}

Comment: \\format[HTMLChars]{\\comment} \\end{comment}"); prefs.setPreviewStyle(migratedStyle); } + + /** + * The former preferences default of columns was a simple list of strings ("author;title;year;..."). Since 5.0 + * the preferences store the type of the column too, so that the formerly hardwired columns like the graphic groups + * column or the other icon columns can be reordered in the main table and behave like any other field column + * ("groups;linked_id;field:author;special:readstatus;extrafile:pdf;..."). + * + * Simple strings are by default parsed as a FieldColumn, so there is nothing to do there, but the formerly hard + * wired columns need to be added. + */ + static void upgradeColumnPreferences(JabRefPreferences preferences) { + String rawColumnsList = preferences.get(JabRefPreferences.COLUMN_NAMES); + + if (!rawColumnsList.contains(MainTableColumnModel.Type.NORMALFIELD.getName() + + MainTableColumnModel.COLUMNS_QUALIFIER_DELIMITER)) { + ColumnPreferences oldColumnPreferences = preferences.getColumnPreferences(); + List columns = oldColumnPreferences.getColumns(); + columns.add(0, new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); + columns.add(1, new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); + preferences.storeColumnPreferences(new ColumnPreferences( + columns, + oldColumnPreferences.getSpecialFieldsEnabled(), + oldColumnPreferences.getAutoSyncSpecialFieldsToKeyWords(), + oldColumnPreferences.getSerializeSpecialFields(), + oldColumnPreferences.getExtraFileColumnsEnabled(), + oldColumnPreferences.getSortTypesForColumns() + )); + } + } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 9415f5923b2..939345e1a5c 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -356,9 +356,8 @@ public class JabRefPreferences implements PreferencesService { // File linking Options for entry editor public static final String ENTRY_EDITOR_DRAG_DROP_PREFERENCE_TYPE = "DragDropPreferenceType"; - // String delimiters + // String delimiter public static final Character STRINGLIST_DELIMITER = ';'; - public static final Character COLUMNS_QUALIFIER_DELIMITER = ':'; // Preview private static final String PREVIEW_STYLE = "previewStyle"; From e9caf51c63fad92a56d1cbb62ecc309d169fbe84 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Sun, 3 Nov 2019 12:04:01 +0100 Subject: [PATCH 13/16] Removed superfluous method getHeaderLabel --- .../jabref/gui/maintable/MainTableColumn.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java index f4443913cc5..85399eb483c 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java @@ -1,35 +1,16 @@ package org.jabref.gui.maintable; -import java.util.Optional; - -import javafx.scene.Node; -import javafx.scene.control.Label; import javafx.scene.control.TableColumn; -import org.jabref.gui.icon.JabRefIcon; - public class MainTableColumn extends TableColumn { private MainTableColumnModel model; - private final Optional iconLabel; - public MainTableColumn(MainTableColumnModel model) { this.model = model; - this.iconLabel = Optional.empty(); } public MainTableColumnModel getModel() { return model; } - public Node getHeaderLabel() { - if (model.getType() == MainTableColumnModel.Type.GROUPS || model.getType() == MainTableColumnModel.Type.FILES) { - return iconLabel.map(JabRefIcon::getGraphicNode).get(); - } else { - return new Label(model.getDisplayName()); - } - } - - public String getDisplayName() { - return model.getDisplayName(); - } + public String getDisplayName() { return model.getDisplayName(); } } From dd01025288504b4fc7db805b69b0177eadbcc802 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Mon, 4 Nov 2019 13:33:08 +0100 Subject: [PATCH 14/16] Cleanups, seperating specialFieldsPreferences, added width-binding --- src/main/java/org/jabref/gui/GUIGlobals.java | 4 -- .../gui/maintable/ColumnPreferences.java | 21 ++------- .../jabref/gui/maintable/MainTableColumn.java | 8 ++++ .../gui/maintable/MainTableColumnFactory.java | 47 ++++++++++--------- .../gui/maintable/MainTableColumnModel.java | 43 +++++++++++------ .../PersistenceVisualStateTable.java | 19 ++------ .../gui/preferences/TableColumnsTabView.java | 6 +++ .../preferences/TableColumnsTabViewModel.java | 30 +++++++----- .../SpecialFieldsPreferences.java | 22 +++++++++ .../migrations/PreferencesMigrations.java | 8 ++-- .../jabref/preferences/JabRefPreferences.java | 33 ++++++++----- 11 files changed, 139 insertions(+), 102 deletions(-) create mode 100644 src/main/java/org/jabref/gui/specialfields/SpecialFieldsPreferences.java diff --git a/src/main/java/org/jabref/gui/GUIGlobals.java b/src/main/java/org/jabref/gui/GUIGlobals.java index b3e38c50de9..21c19c98081 100644 --- a/src/main/java/org/jabref/gui/GUIGlobals.java +++ b/src/main/java/org/jabref/gui/GUIGlobals.java @@ -22,10 +22,6 @@ public class GUIGlobals { public static CustomLocalDragboard localDragboard = new CustomLocalDragboard(); - public static final int WIDTH_ICON_COLUMN = 16 + 12; // add some additional space to improve appearance - - public static final int WIDTH_ICON_COL_RANKING = 5 * 16; // Width of Ranking Icon Column - public static final String UNTITLED_TITLE = Localization.lang("untitled"); private GUIGlobals() { diff --git a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java index bdced5d255e..e80ed4b4bfa 100644 --- a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java +++ b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java @@ -7,34 +7,19 @@ public class ColumnPreferences { - public static final double DEFAULT_FIELD_LENGTH = 100; + public static final double DEFAULT_WIDTH = 100; + public static final double ICON_COLUMN_WIDTH = 16 + 12; // add some additional space to improve appearance private final List columns; - private final boolean specialFieldsEnabled; - private final boolean autoSyncSpecialFieldsToKeyWords; - private final boolean serializeSpecialFields; private final boolean extraFileColumnsEnabled; private final Map columnSortType; - public ColumnPreferences(List columns, boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields, boolean extraFileColumnsEnabled, Map columnSortType) { + public ColumnPreferences(List columns, boolean extraFileColumnsEnabled, Map columnSortType) { this.columns = columns; - this.specialFieldsEnabled = specialFieldsEnabled; - this.autoSyncSpecialFieldsToKeyWords = autoSyncSpecialFieldsToKeyWords; - this.serializeSpecialFields = serializeSpecialFields; this.extraFileColumnsEnabled = extraFileColumnsEnabled; this.columnSortType = columnSortType; } - public boolean getSpecialFieldsEnabled() { return specialFieldsEnabled; } - - public boolean getAutoSyncSpecialFieldsToKeyWords() { - return autoSyncSpecialFieldsToKeyWords; - } - - public boolean getSerializeSpecialFields() { - return serializeSpecialFields; - } - public boolean getExtraFileColumnsEnabled() { return extraFileColumnsEnabled; } public List getColumns() { diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java index 85399eb483c..efdfd28133a 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java @@ -2,12 +2,20 @@ import javafx.scene.control.TableColumn; +import org.jabref.gui.util.BindingsHelper; + public class MainTableColumn extends TableColumn { private MainTableColumnModel model; public MainTableColumn(MainTableColumnModel model) { this.model = model; + + BindingsHelper.bindBidirectional( + this.widthProperty(), + model.widthProperty(), + value -> this.setPrefWidth(model.widthProperty().getValue()), + value -> model.widthProperty().setValue(this.getWidth())); } public MainTableColumnModel getModel() { return model; } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index 317571d628d..dcce768923e 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -25,7 +25,6 @@ import org.jabref.Globals; import org.jabref.gui.DialogService; -import org.jabref.gui.GUIGlobals; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; @@ -34,6 +33,7 @@ import org.jabref.gui.icon.JabRefIcon; import org.jabref.gui.specialfields.SpecialFieldValueViewModel; import org.jabref.gui.specialfields.SpecialFieldViewModel; +import org.jabref.gui.specialfields.SpecialFieldsPreferences; import org.jabref.gui.util.OptionalValueTableCellFactory; import org.jabref.gui.util.ValueTableCellFactory; import org.jabref.gui.util.comparator.RankingFieldComparator; @@ -83,13 +83,13 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre switch (column.getType()) { case GROUPS: - columns.add(createGroupColumn()); + columns.add(createGroupColumn(column)); break; case FILES: - columns.add(createFilesColumn()); + columns.add(createFilesColumn(column)); break; case LINKED_IDENTIFIER: - columns.add(createIdentifierColumn()); + columns.add(createIdentifierColumn(column)); break; case EXTRAFILE: if (!column.getQualifier().equals("")) { @@ -119,7 +119,7 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre return columns; } - private void setExactWidth(TableColumn column, int width) { + private void setExactWidth(TableColumn column, double width) { column.setMinWidth(width); column.setPrefWidth(width); column.setMaxWidth(width); @@ -128,13 +128,14 @@ private void setExactWidth(TableColumn column, int width) { /** * Creates a column for group color bars. */ - private TableColumn createGroupColumn() { - TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); + private TableColumn createGroupColumn(MainTableColumnModel columnModel) { + TableColumn> column = new MainTableColumn<>(columnModel); Node headerGraphic = IconTheme.JabRefIcons.DEFAULT_GROUP_ICON.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Group color"))); column.setGraphic(headerGraphic); column.getStyleClass().add(STYLE_ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + setExactWidth(column, ColumnPreferences.ICON_COLUMN_WIDTH); + column.setResizable(false); column.setCellValueFactory(cellData -> cellData.getValue().getMatchedGroups(database)); new ValueTableCellFactory>() .withGraphic(this::createGroupColorRegion) @@ -188,20 +189,20 @@ private Node createGroupColorRegion(BibEntryTableViewModel entry, List text) .install(column); column.setSortable(true); - column.setPrefWidth(columnModel.getWidth()); return column; } /** * Creates a clickable icons column for DOIs, URLs, URIs and EPrints. */ - private TableColumn> createIdentifierColumn() { - TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); + private TableColumn> createIdentifierColumn(MainTableColumnModel columnModel) { + TableColumn> column = new MainTableColumn<>(columnModel); Node headerGraphic = IconTheme.JabRefIcons.WWW.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked identifiers"))); column.setGraphic(headerGraphic); column.getStyleClass().add(STYLE_ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + setExactWidth(column, ColumnPreferences.ICON_COLUMN_WIDTH); + column.setResizable(false); column.setCellValueFactory(cellData -> cellData.getValue().getLinkedIdentifiers()); new ValueTableCellFactory>() .withGraphic(this::createIdentifierGraphic) @@ -249,20 +250,21 @@ private ContextMenu createIdentifierMenu(BibEntryTableViewModel entry, Map> createSpecialFieldColumn(MainTableColumnModel columnModel) { SpecialField specialField = (SpecialField) FieldFactory.parseField(columnModel.getQualifier()); - TableColumn> column = - new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, specialField.getName())); + TableColumn> column = new MainTableColumn<>(columnModel); SpecialFieldViewModel specialFieldViewModel = new SpecialFieldViewModel(specialField, undoManager); Node headerGraphic = specialFieldViewModel.getIcon().getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(specialFieldViewModel.getLocalization())); column.setGraphic(headerGraphic); column.getStyleClass().add(STYLE_ICON_COLUMN); if (specialField == SpecialField.RANKING) { - setExactWidth(column, GUIGlobals.WIDTH_ICON_COL_RANKING); + setExactWidth(column, SpecialFieldsPreferences.COLUMN_RANKING_WIDTH); + column.setResizable(false); new OptionalValueTableCellFactory() .withGraphicIfPresent(this::createSpecialRating) .install(column); } else { - setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + setExactWidth(column, ColumnPreferences.ICON_COLUMN_WIDTH); + column.setResizable(false); if (specialField.isSingleValueField()) { new OptionalValueTableCellFactory() @@ -332,13 +334,14 @@ private Node createSpecialFieldIcon(Optional fieldVa * Creates a column for all the linked files. Instead of creating a column for a single file type, like {@code * createExtraFileColumn} does, this creates one single column collecting all file links. */ - private TableColumn> createFilesColumn() { - TableColumn> column = new MainTableColumn<>(new MainTableColumnModel(MainTableColumnModel.Type.FILES)); + private TableColumn> createFilesColumn(MainTableColumnModel columnModel) { + TableColumn> column = new MainTableColumn<>(columnModel); Node headerGraphic = IconTheme.JabRefIcons.FILE.getGraphicNode(); Tooltip.install(headerGraphic, new Tooltip(Localization.lang("Linked files"))); column.setGraphic(headerGraphic); column.getStyleClass().add(STYLE_ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + setExactWidth(column, ColumnPreferences.ICON_COLUMN_WIDTH); + column.setResizable(false); column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); new ValueTableCellFactory>() .withGraphic(this::createFileIcon) @@ -397,14 +400,14 @@ private Node createFileIcon(List linkedFiles) { * Creates a column for all the linked files of a single file type. */ private TableColumn> createExtraFileColumn(MainTableColumnModel columnModel) { - TableColumn> column = new MainTableColumn<>( - new MainTableColumnModel(MainTableColumnModel.Type.EXTRAFILE, columnModel.getQualifier())); + TableColumn> column = new MainTableColumn<>(columnModel); column.setGraphic(externalFileTypes .getExternalFileTypeByName(columnModel.getQualifier()) .map(ExternalFileType::getIcon).orElse(IconTheme.JabRefIcons.FILE) .getGraphicNode()); column.getStyleClass().add(STYLE_ICON_COLUMN); - setExactWidth(column, GUIGlobals.WIDTH_ICON_COLUMN); + setExactWidth(column, ColumnPreferences.ICON_COLUMN_WIDTH); + column.setResizable(false); column.setCellValueFactory(cellData -> cellData.getValue().getLinkedFiles()); new ValueTableCellFactory>() .withGraphic(linkedFiles -> createFileIcon(linkedFiles.stream().filter(linkedFile -> diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index 2ef05399455..3991fa1dcaa 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -69,8 +69,13 @@ public static Type fromString(String text) { private final ObjectProperty typeProperty = new SimpleObjectProperty<>(); private final StringProperty qualifierProperty = new SimpleStringProperty(""); - private final DoubleProperty widthProperty = new SimpleDoubleProperty(ColumnPreferences.DEFAULT_FIELD_LENGTH); + private final DoubleProperty widthProperty = new SimpleDoubleProperty(ColumnPreferences.DEFAULT_WIDTH); + /** + * This is used by the preferences dialog, to allow the user to type in a field he wants to add to the table. + * + * @param rawColumnName the stored name of the column, e.g. "field:author", or "author" + */ public MainTableColumnModel(String rawColumnName) { Objects.requireNonNull(rawColumnName); @@ -88,6 +93,24 @@ public MainTableColumnModel(String rawColumnName) { } } + /** + * This is used by the preferences dialog, to initialize available columns the user can add to the table. + * + * @param type the {@code MainTableColumnModel.Type} of the column, e.g. "NORMALFIELD" or "GROUPS" + * @param qualifier the stored qualifier of the column, e.g. "author/editor" + */ + public MainTableColumnModel(Type type, String qualifier) { + Objects.requireNonNull(type); + this.typeProperty.setValue(type); + this.qualifierProperty.setValue(qualifier); + } + + /** + * This is used by JabRefPreferences, to create a new ColumnModel out ouf the stored preferences. + * + * @param rawColumnName the stored name of the column, e.g. "field:author" + * @param width the stored width of the column + */ public MainTableColumnModel(String rawColumnName, Double width) { this(rawColumnName); @@ -95,16 +118,8 @@ public MainTableColumnModel(String rawColumnName, Double width) { this.widthProperty.setValue(width); } - public MainTableColumnModel(Type typeProperty, String qualifierProperty) { - Objects.requireNonNull(typeProperty); - Objects.requireNonNull(qualifierProperty); - this.typeProperty.setValue(typeProperty); - this.qualifierProperty.setValue(qualifierProperty); - } - - public MainTableColumnModel(Type typeProperty) { - Objects.requireNonNull(typeProperty); - this.typeProperty.setValue(typeProperty); + public MainTableColumnModel(Type type) { + this(type, ""); } public Type getType() { return typeProperty.getValue(); } @@ -130,12 +145,10 @@ public String getDisplayName() { } } - public void setWidth(double length) { this.widthProperty.setValue(length); } - - public Double getWidth() { return widthProperty.getValue(); } - public StringProperty nameProperty() { return new ReadOnlyStringWrapper(getDisplayName()); } + public DoubleProperty widthProperty() { return widthProperty; } + public boolean equals(Object o) { if (this == o) { return true; diff --git a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java index cb0a5db3a5e..e9ef10fcb74 100644 --- a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java +++ b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java @@ -1,9 +1,8 @@ package org.jabref.gui.maintable; -import java.util.ArrayList; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javafx.collections.ListChangeListener; import javafx.scene.control.TableColumn; @@ -55,22 +54,10 @@ private void updateColumnSortType(String text, SortType sortType) { * Store shown columns and their width in preferences. */ private void updateColumnPreferences() { - List columns = new ArrayList<>(); - - mainTable.getColumns().forEach(column -> { - MainTableColumnModel columnModel = ((MainTableColumn) column).getModel(); - columnModel.setWidth(column.getWidth()); - columns.add(columnModel); - }); - ColumnPreferences oldColumnPreferences = preferences.getColumnPreferences(); - preferences.storeColumnPreferences(new ColumnPreferences( - columns, - oldColumnPreferences.getSpecialFieldsEnabled(), - oldColumnPreferences.getAutoSyncSpecialFieldsToKeyWords(), - oldColumnPreferences.getSerializeSpecialFields(), + mainTable.getColumns().stream().map(column -> ((MainTableColumn) column).getModel()).collect(Collectors.toList()), oldColumnPreferences.getExtraFileColumnsEnabled(), - oldColumnPreferences.getSortTypesForColumns())); + columnsSortOrder)); } } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java index c750dd256d4..90126fa3794 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java @@ -114,6 +114,12 @@ private void setupTable() { addColumnName.itemsProperty().bind(viewModel.availableColumnsProperty()); addColumnName.valueProperty().bindBidirectional(viewModel.addColumnProperty()); addColumnName.setConverter(columnNameStringConverter); + addColumnName.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.ENTER) { + viewModel.insertColumnInList(); + event.consume(); + } + }); validationVisualizer.setDecoration(new IconValidationDecorator()); Platform.runLater(() -> validationVisualizer.initVisualization(viewModel.columnsListValidationStatus(), columnsList)); diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index 8c9768fb611..c0130083f01 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -18,6 +18,7 @@ import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.maintable.ColumnPreferences; import org.jabref.gui.maintable.MainTableColumnModel; +import org.jabref.gui.specialfields.SpecialFieldsPreferences; import org.jabref.gui.util.NoSelectionModel; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.Field; @@ -48,11 +49,13 @@ public class TableColumnsTabViewModel implements PreferenceTabViewModel { private final DialogService dialogService; private final JabRefPreferences preferences; private final ColumnPreferences columnPreferences; + private final SpecialFieldsPreferences specialFieldsPreferences; public TableColumnsTabViewModel(DialogService dialogService, JabRefPreferences preferences) { this.dialogService = dialogService; this.preferences = preferences; this.columnPreferences = preferences.getColumnPreferences(); + this.specialFieldsPreferences = preferences.getSpecialFieldsPreferences(); specialFieldsEnabledProperty.addListener((observable, oldValue, newValue) -> { if (newValue) { @@ -81,9 +84,12 @@ public TableColumnsTabViewModel(DialogService dialogService, JabRefPreferences p @Override public void setValues() { - specialFieldsEnabledProperty.setValue(columnPreferences.getSpecialFieldsEnabled()); - specialFieldsSyncKeywordsProperty.setValue(columnPreferences.getAutoSyncSpecialFieldsToKeyWords()); - specialFieldsSerializeProperty.setValue(columnPreferences.getSerializeSpecialFields()); + ColumnPreferences columnPreferences = preferences.getColumnPreferences(); + SpecialFieldsPreferences specialFieldsPreferences = preferences.getSpecialFieldsPreferences(); + + specialFieldsEnabledProperty.setValue(specialFieldsPreferences.getSpecialFieldsEnabled()); + specialFieldsSyncKeywordsProperty.setValue(specialFieldsPreferences.getAutoSyncSpecialFieldsToKeyWords()); + specialFieldsSerializeProperty.setValue(specialFieldsPreferences.getSerializeSpecialFields()); extraFileColumnsEnabledProperty.setValue(columnPreferences.getExtraFileColumnsEnabled()); fillColumnList(); @@ -184,24 +190,26 @@ public void moveColumnDown() { @Override public void storeSettings() { - ColumnPreferences newColumnPreferences = new ColumnPreferences( + preferences.storeColumnPreferences(new ColumnPreferences( columnsListProperty.getValue(), - specialFieldsEnabledProperty.getValue(), - specialFieldsSyncKeywordsProperty.getValue(), - specialFieldsSerializeProperty.getValue(), extraFileColumnsEnabledProperty.getValue(), columnPreferences.getSortTypesForColumns() - ); + )); + + SpecialFieldsPreferences newSpecialFieldsPreferences = new SpecialFieldsPreferences( + specialFieldsEnabledProperty.getValue(), + specialFieldsSyncKeywordsProperty.getValue(), + specialFieldsSerializeProperty.getValue()); - if (columnPreferences.getAutoSyncSpecialFieldsToKeyWords() != newColumnPreferences.getAutoSyncSpecialFieldsToKeyWords()) { + if (specialFieldsPreferences.getAutoSyncSpecialFieldsToKeyWords() != newSpecialFieldsPreferences.getAutoSyncSpecialFieldsToKeyWords()) { restartWarnings.add(Localization.lang("Synchronize special fields to keywords")); } - if (columnPreferences.getSerializeSpecialFields() != newColumnPreferences.getSerializeSpecialFields()) { + if (specialFieldsPreferences.getSerializeSpecialFields() != newSpecialFieldsPreferences.getSerializeSpecialFields()) { restartWarnings.add(Localization.lang("Serialize special fields")); } - preferences.storeColumnPreferences(newColumnPreferences); + preferences.storeSpecialFieldsPreferences(newSpecialFieldsPreferences); } ValidationStatus columnsListValidationStatus() { diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldsPreferences.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldsPreferences.java new file mode 100644 index 00000000000..b584e28024e --- /dev/null +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldsPreferences.java @@ -0,0 +1,22 @@ +package org.jabref.gui.specialfields; + +public class SpecialFieldsPreferences { + + public static final int COLUMN_RANKING_WIDTH = 5 * 16; // Width of Ranking Icon Column + + private final boolean specialFieldsEnabled; + private final boolean autoSyncSpecialFieldsToKeyWords; + private final boolean serializeSpecialFields; + + public SpecialFieldsPreferences(boolean specialFieldsEnabled, boolean autoSyncSpecialFieldsToKeyWords, boolean serializeSpecialFields) { + this.specialFieldsEnabled = specialFieldsEnabled; + this.autoSyncSpecialFieldsToKeyWords = autoSyncSpecialFieldsToKeyWords; + this.serializeSpecialFields = serializeSpecialFields; + } + + public boolean getSpecialFieldsEnabled() { return specialFieldsEnabled; } + + public boolean getAutoSyncSpecialFieldsToKeyWords() { return autoSyncSpecialFieldsToKeyWords; } + + public boolean getSerializeSpecialFields() { return serializeSpecialFields; } +} diff --git a/src/main/java/org/jabref/migrations/PreferencesMigrations.java b/src/main/java/org/jabref/migrations/PreferencesMigrations.java index 5fb4dd9aed7..cb7c1ff0f58 100644 --- a/src/main/java/org/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/org/jabref/migrations/PreferencesMigrations.java @@ -310,17 +310,15 @@ static void upgradePreviewStyleFromReviewToComment(JabRefPreferences prefs) { static void upgradeColumnPreferences(JabRefPreferences preferences) { String rawColumnsList = preferences.get(JabRefPreferences.COLUMN_NAMES); - if (!rawColumnsList.contains(MainTableColumnModel.Type.NORMALFIELD.getName() - + MainTableColumnModel.COLUMNS_QUALIFIER_DELIMITER)) { + if (!rawColumnsList.isEmpty() && + !rawColumnsList.contains(MainTableColumnModel.Type.NORMALFIELD.getName() + + MainTableColumnModel.COLUMNS_QUALIFIER_DELIMITER)) { ColumnPreferences oldColumnPreferences = preferences.getColumnPreferences(); List columns = oldColumnPreferences.getColumns(); columns.add(0, new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); columns.add(1, new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); preferences.storeColumnPreferences(new ColumnPreferences( columns, - oldColumnPreferences.getSpecialFieldsEnabled(), - oldColumnPreferences.getAutoSyncSpecialFieldsToKeyWords(), - oldColumnPreferences.getSerializeSpecialFields(), oldColumnPreferences.getExtraFileColumnsEnabled(), oldColumnPreferences.getSortTypesForColumns() )); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 939345e1a5c..d51220b0589 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -54,6 +54,7 @@ import org.jabref.gui.preferences.ImportTabViewModel; import org.jabref.gui.push.PushToApplication; import org.jabref.gui.push.PushToApplicationsManager; +import org.jabref.gui.specialfields.SpecialFieldsPreferences; import org.jabref.gui.util.ThemeLoader; import org.jabref.logic.bibtex.FieldContentParserPreferences; import org.jabref.logic.bibtex.LatexFieldFormatterPreferences; @@ -1859,14 +1860,18 @@ private List createMainTableColumns() { return Double.parseDouble(string); } catch (NumberFormatException e) { LOGGER.error("Exception while parsing column widths. Choosing default.", e); - return ColumnPreferences.DEFAULT_FIELD_LENGTH; + return ColumnPreferences.DEFAULT_WIDTH; } }) .collect(Collectors.toList()); List columns = new ArrayList<>(); for (int i = 0; i < columnNames.size(); i++) { - columns.add(new MainTableColumnModel(columnNames.get(i), columnWidths.get(i))); + if (i < columnWidths.size()) { + columns.add(new MainTableColumnModel(columnNames.get(i), columnWidths.get(i))); + } else { + columns.add(new MainTableColumnModel(columnNames.get(i))); + } } return columns; } @@ -1874,9 +1879,6 @@ private List createMainTableColumns() { public ColumnPreferences getColumnPreferences() { return new ColumnPreferences( createMainTableColumns(), - getBoolean(SPECIALFIELDSENABLED), - getBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS), - getBoolean(SERIALIZESPECIALFIELDS), getBoolean(EXTRA_FILE_COLUMNS), getMainTableColumnSortTypes()); } @@ -1887,24 +1889,33 @@ public void storeColumnPreferences(ColumnPreferences columnPreferences) { .map(MainTableColumnModel::getName) .collect(Collectors.toList())); - putBoolean(SPECIALFIELDSENABLED, columnPreferences.getSpecialFieldsEnabled()); - putBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS, columnPreferences.getAutoSyncSpecialFieldsToKeyWords()); - putBoolean(SERIALIZESPECIALFIELDS, columnPreferences.getSerializeSpecialFields()); putBoolean(EXTRA_FILE_COLUMNS, columnPreferences.getExtraFileColumnsEnabled()); List columnWidthsInOrder = new ArrayList<>(); - columnPreferences.getColumns().forEach(column -> columnWidthsInOrder.add(column.getWidth().toString())); + columnPreferences.getColumns().forEach(column -> columnWidthsInOrder.add(column.widthProperty().getValue().toString())); putStringList(COLUMN_WIDTHS, columnWidthsInOrder); setMainTableColumnSortType(columnPreferences.getSortTypesForColumns()); } public MainTablePreferences getMainTablePreferences() { - return new MainTablePreferences( - getColumnPreferences(), + return new MainTablePreferences(getColumnPreferences(), getBoolean(AUTO_RESIZE_MODE)); } + public SpecialFieldsPreferences getSpecialFieldsPreferences() { + return new SpecialFieldsPreferences( + getBoolean(SPECIALFIELDSENABLED), + getBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS), + getBoolean(SERIALIZESPECIALFIELDS)); + } + + public void storeSpecialFieldsPreferences(SpecialFieldsPreferences specialFieldsPreferences) { + putBoolean(SPECIALFIELDSENABLED, specialFieldsPreferences.getSpecialFieldsEnabled()); + putBoolean(AUTOSYNCSPECIALFIELDSTOKEYWORDS, specialFieldsPreferences.getAutoSyncSpecialFieldsToKeyWords()); + putBoolean(SERIALIZESPECIALFIELDS, specialFieldsPreferences.getSerializeSpecialFields()); + } + @Override public Path getWorkingDir() { return Paths.get(get(WORKING_DIRECTORY)); From 68119ecdea4b9b99b9482deb289666bb8bc6de1e Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Mon, 4 Nov 2019 21:19:43 +0100 Subject: [PATCH 15/16] Refactored according to remarks --- .../gui/maintable/MainTableColumnFactory.java | 6 +- .../gui/maintable/MainTableColumnModel.java | 72 ++++++++++--------- .../gui/preferences/TableColumnsTabView.java | 19 +---- .../preferences/TableColumnsTabViewModel.java | 17 +++++ .../jabref/preferences/JabRefPreferences.java | 4 +- 5 files changed, 60 insertions(+), 58 deletions(-) diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index dcce768923e..1448a7d68e7 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -92,12 +92,12 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre columns.add(createIdentifierColumn(column)); break; case EXTRAFILE: - if (!column.getQualifier().equals("")) { + if (!column.getQualifier().isBlank()) { columns.add(createExtraFileColumn(column)); } break; case SPECIALFIELD: - if (!column.getQualifier().equals("")) { + if (!column.getQualifier().isBlank()) { Field field = FieldFactory.parseField(column.getQualifier()); if (field instanceof SpecialField) { columns.add(createSpecialFieldColumn(column)); @@ -109,7 +109,7 @@ public MainTableColumnFactory(BibDatabaseContext database, ColumnPreferences pre break; default: case NORMALFIELD: - if (!column.getQualifier().equals("")) { + if (!column.getQualifier().isBlank()) { columns.add(createFieldColumn(column)); } break; diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index 3991fa1dcaa..99ce8bd9ce8 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -71,28 +71,6 @@ public static Type fromString(String text) { private final StringProperty qualifierProperty = new SimpleStringProperty(""); private final DoubleProperty widthProperty = new SimpleDoubleProperty(ColumnPreferences.DEFAULT_WIDTH); - /** - * This is used by the preferences dialog, to allow the user to type in a field he wants to add to the table. - * - * @param rawColumnName the stored name of the column, e.g. "field:author", or "author" - */ - public MainTableColumnModel(String rawColumnName) { - Objects.requireNonNull(rawColumnName); - - String[] splittedName = rawColumnName.split(COLUMNS_QUALIFIER_DELIMITER.toString()); - Type type = Type.fromString(splittedName[0]); - - typeProperty.setValue(type); - - if (type == Type.NORMALFIELD || type == Type.SPECIALFIELD || type == Type.EXTRAFILE) { - if (splittedName.length == 1) { - qualifierProperty.setValue(splittedName[0]); // On default the rawColumnName is parsed as NORMALFIELD - } else { - qualifierProperty.setValue(splittedName[1]); - } - } - } - /** * This is used by the preferences dialog, to initialize available columns the user can add to the table. * @@ -105,19 +83,6 @@ public MainTableColumnModel(Type type, String qualifier) { this.qualifierProperty.setValue(qualifier); } - /** - * This is used by JabRefPreferences, to create a new ColumnModel out ouf the stored preferences. - * - * @param rawColumnName the stored name of the column, e.g. "field:author" - * @param width the stored width of the column - */ - public MainTableColumnModel(String rawColumnName, Double width) { - this(rawColumnName); - - Objects.requireNonNull(width); - this.widthProperty.setValue(width); - } - public MainTableColumnModel(Type type) { this(type, ""); } @@ -169,4 +134,41 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(typeProperty.getValue(), qualifierProperty.getValue()); } + + /** + * This is used by JabRefPreferences, to create a new ColumnModel out ouf the stored preferences. + * + * @param rawColumnName the stored name of the column, e.g. "field:author" + * @param width the stored width of the column + */ + public static MainTableColumnModel parse(String rawColumnName, Double width) { + MainTableColumnModel columnModel = parse(rawColumnName); + + Objects.requireNonNull(width); + columnModel.widthProperty().setValue(width); + return columnModel; + } + + /** + * This is used by the preferences dialog, to allow the user to type in a field he wants to add to the table. + * + * @param rawColumnName the stored name of the column, e.g. "field:author", or "author" + */ + public static MainTableColumnModel parse(String rawColumnName) { + Objects.requireNonNull(rawColumnName); + String[] splittedName = rawColumnName.split(COLUMNS_QUALIFIER_DELIMITER.toString()); + + Type type = Type.fromString(splittedName[0]); + String qualifier = ""; + + if (type == Type.NORMALFIELD || type == Type.SPECIALFIELD || type == Type.EXTRAFILE) { + if (splittedName.length == 1) { + qualifier = splittedName[0]; // By default the rawColumnName is parsed as NORMALFIELD + } else { + qualifier = splittedName[1]; + } + } + + return new MainTableColumnModel(type, qualifier); + } } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java index 90126fa3794..2bf146a50b5 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java @@ -9,7 +9,6 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.input.KeyCode; -import javafx.util.StringConverter; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.StandardActions; @@ -28,22 +27,6 @@ public class TableColumnsTabView extends AbstractPreferenceTabView implements PreferencesTab { - private static StringConverter columnNameStringConverter = new StringConverter<>() { - @Override - public String toString(MainTableColumnModel object) { - if (object != null) { - return object.getName(); - } else { - return ""; - } - } - - @Override - public MainTableColumnModel fromString(String string) { - return new MainTableColumnModel(string); - } - }; - @FXML private TableView columnsList; @FXML private TableColumn nameColumn; @FXML private TableColumn actionsColumn; @@ -113,7 +96,7 @@ private void setupTable() { .install(addColumnName); addColumnName.itemsProperty().bind(viewModel.availableColumnsProperty()); addColumnName.valueProperty().bindBidirectional(viewModel.addColumnProperty()); - addColumnName.setConverter(columnNameStringConverter); + addColumnName.setConverter(TableColumnsTabViewModel.columnNameStringConverter); addColumnName.setOnKeyPressed(event -> { if (event.getCode() == KeyCode.ENTER) { viewModel.insertColumnInList(); diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index c0130083f01..256a0f9e639 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -12,6 +12,7 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.scene.control.SelectionModel; +import javafx.util.StringConverter; import org.jabref.gui.DialogService; import org.jabref.gui.externalfiletype.ExternalFileType; @@ -33,6 +34,22 @@ public class TableColumnsTabViewModel implements PreferenceTabViewModel { + static StringConverter columnNameStringConverter = new StringConverter<>() { + @Override + public String toString(MainTableColumnModel object) { + if (object != null) { + return object.getName(); + } else { + return ""; + } + } + + @Override + public MainTableColumnModel fromString(String string) { + return MainTableColumnModel.parse(string); + } + }; + private final ListProperty columnsListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); private final ObjectProperty> selectedColumnModelProperty = new SimpleObjectProperty<>(new NoSelectionModel<>()); private final ListProperty availableColumnsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index d51220b0589..76e0c962e8b 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -1868,9 +1868,9 @@ private List createMainTableColumns() { List columns = new ArrayList<>(); for (int i = 0; i < columnNames.size(); i++) { if (i < columnWidths.size()) { - columns.add(new MainTableColumnModel(columnNames.get(i), columnWidths.get(i))); + columns.add(MainTableColumnModel.parse(columnNames.get(i), columnWidths.get(i))); } else { - columns.add(new MainTableColumnModel(columnNames.get(i))); + columns.add(MainTableColumnModel.parse(columnNames.get(i))); } } return columns; From e34cbee3c450d5cd54a683fb37bbe1a7278c88eb Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Tue, 5 Nov 2019 00:28:40 +0100 Subject: [PATCH 16/16] Added Tests --- .../migrations/PreferencesMigrations.java | 24 ++++++------ .../maintable/MainTableColumnModelTest.java | 39 +++++++++++++++++++ .../migrations/PreferencesMigrationsTest.java | 30 ++++++++++++++ 3 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 src/test/java/org/jabref/gui/maintable/MainTableColumnModelTest.java diff --git a/src/main/java/org/jabref/migrations/PreferencesMigrations.java b/src/main/java/org/jabref/migrations/PreferencesMigrations.java index cb7c1ff0f58..8401e0b6165 100644 --- a/src/main/java/org/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/org/jabref/migrations/PreferencesMigrations.java @@ -12,7 +12,6 @@ import org.jabref.Globals; import org.jabref.JabRefMain; -import org.jabref.gui.maintable.ColumnPreferences; import org.jabref.gui.maintable.MainTableColumnModel; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; import org.jabref.model.entry.field.StandardField; @@ -308,20 +307,19 @@ static void upgradePreviewStyleFromReviewToComment(JabRefPreferences prefs) { * wired columns need to be added. */ static void upgradeColumnPreferences(JabRefPreferences preferences) { - String rawColumnsList = preferences.get(JabRefPreferences.COLUMN_NAMES); + String columnNames = preferences.get(JabRefPreferences.COLUMN_NAMES); - if (!rawColumnsList.isEmpty() && - !rawColumnsList.contains(MainTableColumnModel.Type.NORMALFIELD.getName() + if (!columnNames.isEmpty() && + !columnNames.contains(MainTableColumnModel.Type.NORMALFIELD.getName() // "field:" + MainTableColumnModel.COLUMNS_QUALIFIER_DELIMITER)) { - ColumnPreferences oldColumnPreferences = preferences.getColumnPreferences(); - List columns = oldColumnPreferences.getColumns(); - columns.add(0, new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); - columns.add(1, new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); - preferences.storeColumnPreferences(new ColumnPreferences( - columns, - oldColumnPreferences.getExtraFileColumnsEnabled(), - oldColumnPreferences.getSortTypesForColumns() - )); + + String columnWidths = preferences.get(JabRefPreferences.COLUMN_WIDTHS); + + columnNames = "groups;linked_id;" + columnNames; + columnWidths = "28;28;" + columnWidths; + + preferences.put(JabRefPreferences.COLUMN_NAMES, columnNames); + preferences.put(JabRefPreferences.COLUMN_WIDTHS,columnWidths); } } } diff --git a/src/test/java/org/jabref/gui/maintable/MainTableColumnModelTest.java b/src/test/java/org/jabref/gui/maintable/MainTableColumnModelTest.java new file mode 100644 index 00000000000..253039bd340 --- /dev/null +++ b/src/test/java/org/jabref/gui/maintable/MainTableColumnModelTest.java @@ -0,0 +1,39 @@ +package org.jabref.gui.maintable; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MainTableColumnModelTest { + + private static String testName = "field:author"; + private static MainTableColumnModel.Type testType = MainTableColumnModel.Type.NORMALFIELD; + private static String testQualifier = "author"; + + private static String testTypeOnlyName = "linked_id"; + private static MainTableColumnModel.Type testTypeOnlyType = MainTableColumnModel.Type.LINKED_IDENTIFIER; + + @Test + public void testMainTableColumnModelParser() { + MainTableColumnModel testColumnModel = MainTableColumnModel.parse(testQualifier); + + assertEquals(testColumnModel.getType(),testType); + assertEquals(testColumnModel.getQualifier(), testQualifier); + } + + @Test + public void testMainTableColumnModelParserFull() { + MainTableColumnModel testColumnModel = MainTableColumnModel.parse(testName); + + assertEquals(testColumnModel.getType(),testType); + assertEquals(testColumnModel.getQualifier(), testQualifier); + } + + @Test + public void testMainTableColumnModelParserTypeOnly() { + MainTableColumnModel testColumnModel = MainTableColumnModel.parse(testTypeOnlyName); + + assertEquals(testColumnModel.getType(), testTypeOnlyType); + assertEquals(testColumnModel.getQualifier(), ""); + } +} diff --git a/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java b/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java index 6a2ee9bc5e8..537b91be4a2 100644 --- a/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java +++ b/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java @@ -115,4 +115,34 @@ void testPreviewStyle() { verify(prefs).setPreviewStyle(newPreviewStyle); } + + @Test + void testUpgradeColumnPreferencesAlreadyMigrated() { + String columnNames = "groups;linked_id;field:entrytype;field:author/editor;field:title;field:year;field:journal/booktitle;field:bibtexkey"; + String columnWidths = "28;28;75;300;470;60;130;100"; + + when(prefs.get(JabRefPreferences.COLUMN_NAMES)).thenReturn(columnNames); + when(prefs.get(JabRefPreferences.COLUMN_WIDTHS)).thenReturn(columnWidths); + + PreferencesMigrations.upgradeColumnPreferences(prefs); + + verify(prefs, never()).put(JabRefPreferences.COLUMN_NAMES, "anyString"); + verify(prefs, never()).put(JabRefPreferences.COLUMN_WIDTHS, "anyString"); + } + + @Test + void testUpgradeColumnPreferencesFromWithoutTypes() { + String columnNames = "entrytype;author/editor;title;year;journal/booktitle;bibtexkey"; + String columnWidths = "75;300;470;60;130;100"; + String updatedNames = "groups;linked_id;entrytype;author/editor;title;year;journal/booktitle;bibtexkey"; + String updatedWidths = "28;28;75;300;470;60;130;100"; + + when(prefs.get(JabRefPreferences.COLUMN_NAMES)).thenReturn(columnNames); + when(prefs.get(JabRefPreferences.COLUMN_WIDTHS)).thenReturn(columnWidths); + + PreferencesMigrations.upgradeColumnPreferences(prefs); + + verify(prefs).put(JabRefPreferences.COLUMN_NAMES, updatedNames); + verify(prefs).put(JabRefPreferences.COLUMN_WIDTHS, updatedWidths); + } }