diff --git a/.github/failure-csl-update b/.github/failure-csl-update.md similarity index 100% rename from .github/failure-csl-update rename to .github/failure-csl-update.md diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index e380e7940166..463988566413 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -11,17 +11,17 @@ jobs: include: - os: ubuntu-latest displayName: linux - jpackageDownload: https://download.java.net/java/early_access/jpackage/1/openjdk-14-jpackage+1-70_linux-x64_bin.tar.gz + jpackageDownload: https://download.java.net/java/early_access/jdk14/27/GPL/openjdk-14-ea+27_linux-x64_bin.tar.gz jdk14Path: /jdk-14 archivePortable: tar -czf build/distribution/JabRef-portable_linux.tar.gz -C build/distribution JabRef && rm -R build/distribution/JabRef - os: windows-latest displayName: windows - jpackageDownload: https://download.java.net/java/early_access/jpackage/1/openjdk-14-jpackage+1-70_windows-x64_bin.zip + jpackageDownload: https://download.java.net/java/early_access/jdk14/27/GPL/openjdk-14-ea+27_windows-x64_bin.zip jdk14Path: /jdk-14 archivePortable: 7z a -r build/distribution/JabRef-portable_windows.zip ./build/distribution/JabRef && rm -R build/distribution/JabRef - os: macOS-latest displayName: macOS - jpackageDownload: https://download.java.net/java/early_access/jpackage/1/openjdk-14-jpackage+1-70_osx-x64_bin.tar.gz + jpackageDownload: https://download.java.net/java/early_access/jdk14/27/GPL/openjdk-14-ea+27_osx-x64_bin.tar.gz jdk14Path: /jdk-14.jdk/Contents/Home archivePortable: tar -czf build/distribution/JabRef-portable_macos.tar.gz -C build/distribution JabRef.app && rm -R build/distribution/JabRef.app diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bc6428c3026..8a2d008df700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Fixed +- We fixed an issue where the Medline fetcher was only working when JabRef was running from source [#5645](https://github.com/JabRef/jabref/issues/5645) + + ### Removed @@ -34,6 +37,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We changed the save action buttons to be easier to understand. [#5565](https://github.com/JabRef/jabref/issues/5565) - 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) - We reduced the number of write actions performed when autosave is enabled [#5679](https://github.com/JabRef/jabref/issues/5679) +- We made the column sort order in the main table persistent [#5730](https://github.com/JabRef/jabref/pull/5730) ### Fixed diff --git a/build.gradle b/build.gradle index 39a78043a13c..8ab7c0603404 100644 --- a/build.gradle +++ b/build.gradle @@ -206,15 +206,15 @@ dependencies { } - testCompile 'io.github.classgraph:classgraph:4.8.58' + testCompile 'io.github.classgraph:classgraph:4.8.59' testImplementation 'org.junit.jupiter:junit-jupiter:5.5.2' testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.5.2' testCompile 'org.junit.platform:junit-platform-launcher:1.5.2' - testCompile 'net.bytebuddy:byte-buddy-parent:1.10.4' + testCompile 'net.bytebuddy:byte-buddy-parent:1.10.5' testRuntime group: 'org.apache.logging.log4j', name: 'log4j-core', version: '3.0.0-SNAPSHOT' testRuntime group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '3.0.0-SNAPSHOT' - testCompile 'org.mockito:mockito-core:3.2.0' + testCompile 'org.mockito:mockito-core:3.2.4' //testCompile 'com.github.tomakehurst:wiremock:2.24.1' testCompile 'org.xmlunit:xmlunit-core:2.6.3' testCompile 'org.xmlunit:xmlunit-matchers:2.6.3' @@ -249,20 +249,29 @@ dependencyUpdates.resolutionStrategy = { selection.reject('Release candidate') } } - rules.withModule("com.github.tomtung:latex2unicode_2.12") { ComponentSelection selection -> - if (selection.candidate.version ==~ /0.2.*/) { - // Reject version higher than 2.0.2. see https://github.com/JabRef/jabref/pull/3781 - selection.reject("Cannot be updated to 0.2.4 until JabRef is prepared for it") + rules.withModule("org.python:jython-standalone") { ComponentSelection selection -> + if (selection.candidate.version ==~ /2.7.2b2/) { + selection.reject('Release candidate') + } + } + rules.withModule("de.jensd:fontawesomefx-materialdesignfont") { ComponentSelection selection -> + if (selection.candidate.version ==~ /2.0.26-9.1.2/) { + selection.reject('1.7.22-11 is actually newer (strange version system)') + } + } + rules.withModule("org.javamodularity.moduleplugin:org.javamodularity.moduleplugin.gradle.plugin") { ComponentSelection selection -> + if (selection.candidate.version ==~ /1.6.0/) { + selection.reject("Does not work due to bug, see https://github.com/JabRef/jabref/pull/5270") } } - rules.withModule("com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin") { ComponentSelection selection -> - if (selection.candidate.version ==~ /4.*/) { - selection.reject("Version 4.X breaks the release process.") + rules.withModule("com.microsoft.azure:applicationinsights-core") { ComponentSelection selection -> + if (selection.candidate.version ==~ /2.5.1/) { + selection.reject("Does not work due to bug, see https://github.com/JabRef/jabref/pull/5596") } } - rules.withModule("com.google.errorprone:error_prone_core") { ComponentSelection selection -> - if (selection.candidate.version ==~ /2.3.3/) { - selection.reject("Does not work due to bug https://github.com/google/error-prone/issues/1240") + rules.withModule("com.microsoft.azure:applicationinsights-logging-log4j2") { ComponentSelection selection -> + if (selection.candidate.version ==~ /2.5.1/) { + selection.reject("Does not work due to bug, see https://github.com/JabRef/jabref/pull/5596") } } } @@ -597,6 +606,7 @@ jlink { uses 'com.airhacks.afterburner.injection.PresenterFactory' uses 'org.controlsfx.glyphfont.GlyphFont' uses 'com.airhacks.afterburner.views.ResourceLocator' + uses 'javax.xml.bind.JAXBContextFactory' provides 'java.sql.Driver' with 'org.postgresql.Driver' provides 'org.controlsfx.glyphfont.GlyphFont' with 'org.controlsfx.glyphfont.FontAwesome' provides 'org.apache.commons.logging.LogFactory' with 'org.apache.logging.log4j.jcl.LogFactoryImpl' diff --git a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java index e80ed4b4bfa0..d79b3a6857b1 100644 --- a/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java +++ b/src/main/java/org/jabref/gui/maintable/ColumnPreferences.java @@ -1,32 +1,25 @@ package org.jabref.gui.maintable; import java.util.List; -import java.util.Map; - -import javafx.scene.control.TableColumn.SortType; public class ColumnPreferences { - public static final double DEFAULT_WIDTH = 100; + public static final double DEFAULT_COLUMN_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 extraFileColumnsEnabled; - private final Map columnSortType; + private final List columnSortOrder; - public ColumnPreferences(List columns, boolean extraFileColumnsEnabled, Map columnSortType) { + public ColumnPreferences(List columns, List columnSortOrder) { this.columns = columns; - this.extraFileColumnsEnabled = extraFileColumnsEnabled; - this.columnSortType = columnSortType; + this.columnSortOrder = columnSortOrder; } - public boolean getExtraFileColumnsEnabled() { return extraFileColumnsEnabled; } - public List getColumns() { return columns; } - public Map getSortTypesForColumns() { - return columnSortType; + public List getColumnSortOrder() { + return columnSortOrder; } } diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index f7b02a713a76..5eb3b3704fab 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -97,15 +97,15 @@ public MainTable(MainTableDataModel model, JabRefFrame frame, .setOnMouseDragEntered(this::handleOnDragEntered) .install(this); - /*for (Entry entries : preferences.getColumnPreferences().getSortTypesForColumns().entrySet()) { - Optional> column = this.getColumns().stream().filter(col -> entries.getKey().equals(col.getText())).findFirst(); - column.ifPresent(col -> { - col.setSortType(entries.getValue()); - this.getSortOrder().add(col); - }); - }*/ - - if (preferences.resizeColumnsToFit()) { + this.getSortOrder().clear(); + preferences.getColumnPreferences().getColumnSortOrder().forEach(columnModel -> + this.getColumns().stream() + .map(column -> (MainTableColumn) column) + .filter(column -> column.getModel().equals(columnModel)) + .findFirst() + .ifPresent(column -> this.getSortOrder().add(column))); + + if (preferences.getResizeColumnsToFit()) { this.setColumnResizePolicy(new SmartConstrainedResizePolicy()); } this.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java index efdfd28133a9..2c205a6773ca 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumn.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumn.java @@ -1,5 +1,6 @@ package org.jabref.gui.maintable; +import javafx.beans.value.ObservableValue; import javafx.scene.control.TableColumn; import org.jabref.gui.util.BindingsHelper; @@ -16,6 +17,12 @@ public MainTableColumn(MainTableColumnModel model) { model.widthProperty(), value -> this.setPrefWidth(model.widthProperty().getValue()), value -> model.widthProperty().setValue(this.getWidth())); + + BindingsHelper.bindBidirectional( + this.sortTypeProperty(), + (ObservableValue) model.sortTypeProperty(), + value -> this.setSortType(model.sortTypeProperty().getValue()), + value -> model.sortTypeProperty().setValue(this.getSortType())); } public MainTableColumnModel getModel() { return model; } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java index 4e0f3cca17ca..b4ff2ba9eba6 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnModel.java @@ -1,5 +1,6 @@ package org.jabref.gui.maintable; +import java.util.EnumSet; import java.util.Objects; import javafx.beans.property.DoubleProperty; @@ -9,6 +10,7 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import javafx.scene.control.TableColumn; import org.jabref.gui.util.FieldsUtil; import org.jabref.logic.l10n.Localization; @@ -35,6 +37,8 @@ public enum Type { NORMALFIELD("field"), SPECIALFIELD("special", Localization.lang("Special")); + public static final EnumSet ICON_COLUMNS = EnumSet.of(EXTRAFILE,FILES,GROUPS,LINKED_IDENTIFIER); + private String name; private String displayName; @@ -67,35 +71,54 @@ public static Type fromString(String text) { } } - private final ObjectProperty typeProperty; - private final StringProperty qualifierProperty; - private final DoubleProperty widthProperty; + private final ObjectProperty typeProperty = new SimpleObjectProperty<>(); + private final StringProperty qualifierProperty = new SimpleStringProperty(); + private final DoubleProperty widthProperty = new SimpleDoubleProperty(); + private final ObjectProperty sortTypeProperty = new SimpleObjectProperty<>(); /** * 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 type the {@code MainTableColumnModel.Type} of the column, e.g. "NORMALFIELD" or "EXTRAFILE" * @param qualifier the stored qualifier of the column, e.g. "author/editor" */ - public MainTableColumnModel(Type type, String qualifier, double width) { + public MainTableColumnModel(Type type, String qualifier) { Objects.requireNonNull(type); - typeProperty = new SimpleObjectProperty<>(type); - qualifierProperty = new SimpleStringProperty(qualifier); - widthProperty = new SimpleDoubleProperty(width); - } + Objects.requireNonNull(qualifier); - public MainTableColumnModel(Type type, String qualifier) { - this(type, qualifier, ColumnPreferences.DEFAULT_WIDTH); - } + this.typeProperty.setValue(type); + this.qualifierProperty.setValue(qualifier); + this.sortTypeProperty.setValue(TableColumn.SortType.ASCENDING); - public MainTableColumnModel(Type type, double width) { - this(type, "", width); + if (Type.ICON_COLUMNS.contains(type)) { + this.widthProperty.setValue(ColumnPreferences.ICON_COLUMN_WIDTH); + } else { + this.widthProperty.setValue(ColumnPreferences.DEFAULT_COLUMN_WIDTH); + } } + /** + * This is used by the preferences dialog, to initialize available basic icon columns, the user can add to the table. + * + * @param type the {@code MainTableColumnModel.Type} of the column, e.g. "GROUPS" or "LINKED_IDENTIFIER" + */ public MainTableColumnModel(Type type) { this(type, ""); } + /** + * This is used by the preference migrations. + * + * @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" + * @param width the stored width of the column + */ + public MainTableColumnModel(Type type, String qualifier, double width) { + this(type, qualifier); + + this.widthProperty.setValue(width); + } + public Type getType() { return typeProperty.getValue(); } public String getQualifier() { return qualifierProperty.getValue(); } @@ -109,10 +132,7 @@ public String getName() { } public String getDisplayName() { - if ((typeProperty.getValue() == Type.GROUPS - || typeProperty.getValue() == Type.FILES - || typeProperty.getValue() == Type.LINKED_IDENTIFIER) - && qualifierProperty.getValue().isBlank()) { + if (Type.ICON_COLUMNS.contains(typeProperty.getValue()) && qualifierProperty.getValue().isBlank()) { return typeProperty.getValue().getDisplayName(); } else { return FieldsUtil.getNameWithType(FieldFactory.parseField(qualifierProperty.getValue())); @@ -121,12 +141,14 @@ public String getDisplayName() { public StringProperty nameProperty() { return new ReadOnlyStringWrapper(getDisplayName()); } - public double getWidth() { - return widthProperty.get(); - } + public double getWidth() { return widthProperty.getValue(); } public DoubleProperty widthProperty() { return widthProperty; } + public TableColumn.SortType getSortType() { return sortTypeProperty.getValue(); } + + public ObjectProperty sortTypeProperty() { return sortTypeProperty; } + public boolean equals(Object o) { if (this == o) { return true; @@ -149,23 +171,11 @@ public int hashCode() { } /** - * This is used by JabRefPreferences, to create a new ColumnModel out ouf the stored preferences. + * This creates a new {@code MainTableColumnModel} out of a given string * - * @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 name of the column, e.g. "field:author", or "author" * - * @param rawColumnName the stored name of the column, e.g. "field:author", or "author" + * @return A new {@code MainTableColumnModel} */ public static MainTableColumnModel parse(String rawColumnName) { Objects.requireNonNull(rawColumnName); @@ -174,7 +184,9 @@ public static MainTableColumnModel parse(String rawColumnName) { Type type = Type.fromString(splittedName[0]); String qualifier = ""; - if (type == Type.NORMALFIELD || type == Type.SPECIALFIELD || type == Type.EXTRAFILE) { + 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 { diff --git a/src/main/java/org/jabref/gui/maintable/MainTablePreferences.java b/src/main/java/org/jabref/gui/maintable/MainTablePreferences.java index 8b9359c576bd..6bd58ce495b2 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTablePreferences.java +++ b/src/main/java/org/jabref/gui/maintable/MainTablePreferences.java @@ -3,17 +3,21 @@ public class MainTablePreferences { private final ColumnPreferences columnPreferences; private final boolean resizeColumnsToFit; + private final boolean extraFileColumnsEnabled; - public MainTablePreferences(ColumnPreferences columnPreferences, boolean resizeColumnsToFit) { + public MainTablePreferences(ColumnPreferences columnPreferences, boolean resizeColumnsToFit, boolean extraFileColumnsEnabled) { this.columnPreferences = columnPreferences; this.resizeColumnsToFit = resizeColumnsToFit; + this.extraFileColumnsEnabled = extraFileColumnsEnabled; } public ColumnPreferences getColumnPreferences() { return columnPreferences; } - public boolean resizeColumnsToFit() { + public boolean getResizeColumnsToFit() { return resizeColumnsToFit; } + + public boolean getExtraFileColumnsEnabled() { return extraFileColumnsEnabled; } } diff --git a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java index e9ef10fcb74b..03caa77521fd 100644 --- a/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java +++ b/src/main/java/org/jabref/gui/maintable/PersistenceVisualStateTable.java @@ -1,63 +1,45 @@ package org.jabref.gui.maintable; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.stream.Collectors; -import javafx.collections.ListChangeListener; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableColumn.SortType; +import javafx.beans.InvalidationListener; import org.jabref.preferences.JabRefPreferences; /** - * Keep track of changes made to the columns, like reordering or resizing. - * + * Keep track of changes made to the columns (reordering, resorting, resizing). */ public class PersistenceVisualStateTable { private final MainTable mainTable; private final JabRefPreferences preferences; - private final Map columnsSortOrder = new LinkedHashMap<>(); public PersistenceVisualStateTable(final MainTable mainTable, JabRefPreferences preferences) { this.mainTable = mainTable; this.preferences = preferences; - mainTable.getColumns().addListener(this::onColumnsChanged); - mainTable.getColumns().forEach(col -> { - MainTableColumn column = (MainTableColumn) col; - col.sortTypeProperty().addListener(obs -> updateColumnSortType(column.getModel().getName(), column.getSortType())); - }); - mainTable.getColumns().forEach(col -> col.widthProperty().addListener(obs -> updateColumnPreferences())); + mainTable.getColumns().addListener((InvalidationListener) obs -> updateColumnPreferences()); + mainTable.getSortOrder().addListener((InvalidationListener) obs -> updateColumnPreferences()); - } - - private void onColumnsChanged(ListChangeListener.Change> change) { - boolean changed = false; - while (change.next()) { - changed = true; - } - - if (changed) { - updateColumnPreferences(); - } - - } - - private void updateColumnSortType(String text, SortType sortType) { - columnsSortOrder.put(text, sortType); - preferences.setMainTableColumnSortType(columnsSortOrder); + // As we store the ColumnModels of the MainTable, we need to add the listener to the ColumnModel properties, + // since the value is bound to the model after the listener to the column itself is called. + mainTable.getColumns().forEach(col -> + ((MainTableColumn) col).getModel().widthProperty().addListener(obs -> updateColumnPreferences())); + mainTable.getColumns().forEach(col -> + ((MainTableColumn) col).getModel().sortTypeProperty().addListener(obs -> updateColumnPreferences())); } /** - * Store shown columns and their width in preferences. + * Store shown columns, their width and their sortType in preferences. */ private void updateColumnPreferences() { - ColumnPreferences oldColumnPreferences = preferences.getColumnPreferences(); preferences.storeColumnPreferences(new ColumnPreferences( - mainTable.getColumns().stream().map(column -> ((MainTableColumn) column).getModel()).collect(Collectors.toList()), - oldColumnPreferences.getExtraFileColumnsEnabled(), - columnsSortOrder)); + mainTable.getColumns().stream() + .map(column -> ((MainTableColumn) column).getModel()) + .collect(Collectors.toList()), + mainTable.getSortOrder().stream() + .map(column -> ((MainTableColumn) column).getModel()) + .collect(Collectors.toList()) + )); } } diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java index 256a0f9e6395..52331aba2db0 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabViewModel.java @@ -19,6 +19,7 @@ import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.maintable.ColumnPreferences; import org.jabref.gui.maintable.MainTableColumnModel; +import org.jabref.gui.maintable.MainTablePreferences; import org.jabref.gui.specialfields.SpecialFieldsPreferences; import org.jabref.gui.util.NoSelectionModel; import org.jabref.logic.l10n.Localization; @@ -59,19 +60,21 @@ public MainTableColumnModel fromString(String string) { private final BooleanProperty specialFieldsSerializeProperty = new SimpleBooleanProperty(); private final BooleanProperty extraFileColumnsEnabledProperty = new SimpleBooleanProperty(); - private FunctionBasedValidator columnsNotEmptyValidator; + private FunctionBasedValidator columnsNotEmptyValidator; private List restartWarnings = new ArrayList<>(); private final DialogService dialogService; private final JabRefPreferences preferences; + private final MainTablePreferences mainTablePreferences; 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.mainTablePreferences = preferences.getMainTablePreferences(); + this.columnPreferences = mainTablePreferences.getColumnPreferences(); this.specialFieldsPreferences = preferences.getSpecialFieldsPreferences(); specialFieldsEnabledProperty.addListener((observable, oldValue, newValue) -> { @@ -101,27 +104,25 @@ public TableColumnsTabViewModel(DialogService dialogService, JabRefPreferences p @Override public void setValues() { - ColumnPreferences columnPreferences = preferences.getColumnPreferences(); - SpecialFieldsPreferences specialFieldsPreferences = preferences.getSpecialFieldsPreferences(); - specialFieldsEnabledProperty.setValue(specialFieldsPreferences.getSpecialFieldsEnabled()); specialFieldsSyncKeywordsProperty.setValue(specialFieldsPreferences.getAutoSyncSpecialFieldsToKeyWords()); specialFieldsSerializeProperty.setValue(specialFieldsPreferences.getSerializeSpecialFields()); - extraFileColumnsEnabledProperty.setValue(columnPreferences.getExtraFileColumnsEnabled()); + extraFileColumnsEnabledProperty.setValue(mainTablePreferences.getExtraFileColumnsEnabled()); fillColumnList(); availableColumnsProperty.clear(); - 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)); + availableColumnsProperty.addAll( + new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER), + new MainTableColumnModel(MainTableColumnModel.Type.GROUPS), + new MainTableColumnModel(MainTableColumnModel.Type.FILES), + new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.TIMESTAMP.getName()), + new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.OWNER.getName()), + new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.GROUPS.getName()), + new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.KEY_FIELD.getName()), + new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, InternalField.TYPE_HEADER.getName()) + ); EnumSet.allOf(StandardField.class).stream() .map(Field::getName) @@ -207,10 +208,13 @@ public void moveColumnDown() { @Override public void storeSettings() { - preferences.storeColumnPreferences(new ColumnPreferences( - columnsListProperty.getValue(), - extraFileColumnsEnabledProperty.getValue(), - columnPreferences.getSortTypesForColumns() + MainTablePreferences newMainTablePreferences = preferences.getMainTablePreferences(); + preferences.storeMainTablePreferences(new MainTablePreferences( + new ColumnPreferences( + columnsListProperty.getValue(), + newMainTablePreferences.getColumnPreferences().getColumnSortOrder()), + newMainTablePreferences.getResizeColumnsToFit(), + extraFileColumnsEnabledProperty.getValue() )); SpecialFieldsPreferences newSpecialFieldsPreferences = new SpecialFieldsPreferences( diff --git a/src/main/java/org/jabref/gui/util/component/TagBar.java b/src/main/java/org/jabref/gui/util/component/TagBar.java index 13974238a301..3c7161ae05de 100644 --- a/src/main/java/org/jabref/gui/util/component/TagBar.java +++ b/src/main/java/org/jabref/gui/util/component/TagBar.java @@ -1,8 +1,8 @@ package org.jabref.gui.util.component; import java.util.Collection; -import java.util.function.BiConsumer; import java.util.Set; +import java.util.function.BiConsumer; import java.util.stream.Collectors; import javafx.beans.property.ListProperty; diff --git a/src/main/java/org/jabref/migrations/PreferencesMigrations.java b/src/main/java/org/jabref/migrations/PreferencesMigrations.java index cd0eaf5dabbb..d841a6c0c08e 100644 --- a/src/main/java/org/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/org/jabref/migrations/PreferencesMigrations.java @@ -11,6 +11,8 @@ import java.util.prefs.Preferences; import java.util.stream.Collectors; +import javafx.scene.control.TableColumn; + import org.jabref.Globals; import org.jabref.JabRefMain; import org.jabref.gui.maintable.ColumnPreferences; @@ -316,7 +318,7 @@ static void upgradeColumnPreferences(JabRefPreferences preferences) { try { return Double.parseDouble(string); } catch (NumberFormatException e) { - return ColumnPreferences.DEFAULT_WIDTH; + return ColumnPreferences.DEFAULT_COLUMN_WIDTH; } }) .collect(Collectors.toList()); @@ -326,30 +328,40 @@ static void upgradeColumnPreferences(JabRefPreferences preferences) { if (!columnNames.isEmpty() && columnNames.stream().noneMatch(name -> name.contains(normalFieldTypeString))) { List columns = new ArrayList<>(); - columns.add(new MainTableColumnModel(MainTableColumnModel.Type.GROUPS, 28)); - columns.add(new MainTableColumnModel(MainTableColumnModel.Type.FILES, 28)); - columns.add(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER, 28)); + columns.add(new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); + columns.add(new MainTableColumnModel(MainTableColumnModel.Type.FILES)); + columns.add(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); for (int i = 0; i < columnNames.size(); i++) { String name = columnNames.get(i); + double columnWidth = ColumnPreferences.DEFAULT_COLUMN_WIDTH; + MainTableColumnModel.Type type = SpecialField.fromName(name) .map(field -> MainTableColumnModel.Type.SPECIALFIELD) .orElse(MainTableColumnModel.Type.NORMALFIELD); + if (i < columnWidths.size()) { - columns.add(new MainTableColumnModel(type, name, columnWidths.get(i))); - } else { - columns.add(new MainTableColumnModel(type, name)); + columnWidth = columnWidths.get(i); } + + columns.add(new MainTableColumnModel(type, name, columnWidth)); } preferences.putStringList(JabRefPreferences.COLUMN_NAMES, columns.stream() - .map(MainTableColumnModel::getName) - .collect(Collectors.toList())); + .map(MainTableColumnModel::getName) + .collect(Collectors.toList())); + preferences.putStringList(JabRefPreferences.COLUMN_WIDTHS, columns.stream() - .map(MainTableColumnModel::getWidth) - .map(Double::intValue) - .map(Object::toString) - .collect(Collectors.toList())); + .map(MainTableColumnModel::getWidth) + .map(Double::intValue) + .map(Object::toString) + .collect(Collectors.toList())); + + // ASCENDING by default + preferences.putStringList(JabRefPreferences.COLUMN_SORT_TYPES, columns.stream() + .map(MainTableColumnModel::getSortType) + .map(TableColumn.SortType::toString) + .collect(Collectors.toList())); } } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index d4d40c3bf7d1..cccdea23071e 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -156,10 +155,10 @@ public class JabRefPreferences implements PreferencesService { public static final String EXPORT_TERTIARY_SORT_FIELD = "exportTerSort"; public static final String EXPORT_TERTIARY_SORT_DESCENDING = "exportTerDescending"; public static final String NEWLINE = "newline"; - public static final String COLUMN_WIDTHS = "columnWidths"; public static final String COLUMN_NAMES = "columnNames"; - public static final String COLUMN_IN_SORT_ORDER = "columnInSortOrder"; - public static final String COlUMN_IN_SORT_ORDER_TYPE = "columnInSortOrderType"; + public static final String COLUMN_WIDTHS = "columnWidths"; + public static final String COLUMN_SORT_TYPES = "columnSortTypes"; + public static final String COLUMN_SORT_ORDER = "columnSortOrder"; public static final String SIDE_PANE_COMPONENT_PREFERRED_POSITIONS = "sidePaneComponentPreferredPositions"; public static final String SIDE_PANE_COMPONENT_NAMES = "sidePaneComponentNames"; @@ -1743,12 +1742,11 @@ public void storeExportSaveOrder(SaveOrderConfig config) { private SaveOrderConfig loadTableSaveOrder() { SaveOrderConfig config = new SaveOrderConfig(); - List columns = getStringList(COLUMN_IN_SORT_ORDER); - List sortTypes = getStringList(COlUMN_IN_SORT_ORDER_TYPE).stream().map(SortType::valueOf).map(type -> type == SortType.DESCENDING).collect(Collectors.toList()); + List sortOrder = createColumnSortOrder(createMainTableColumns()); - for (int i = 0; i < columns.size(); i++) { - config.getSortCriteria().add(new SaveOrderConfig.SortCriterion(FieldFactory.parseField(columns.get(i)), sortTypes.get(i))); - } + sortOrder.forEach(column -> config.getSortCriteria().add(new SaveOrderConfig.SortCriterion( + FieldFactory.parseField(column.getQualifier()), + column.getSortType().toString()))); return config; } @@ -1853,6 +1851,7 @@ public void storeSidePanePreferredPositions(Map preferred private List createMainTableColumns() { List columnNames = getStringList(COLUMN_NAMES); + List columnWidths = getStringList(COLUMN_WIDTHS) .stream() .map(string -> { @@ -1860,27 +1859,51 @@ private List createMainTableColumns() { return Double.parseDouble(string); } catch (NumberFormatException e) { LOGGER.error("Exception while parsing column widths. Choosing default.", e); - return ColumnPreferences.DEFAULT_WIDTH; + return ColumnPreferences.DEFAULT_COLUMN_WIDTH; } }) .collect(Collectors.toList()); + List columnSortTypes = getStringList(COLUMN_SORT_TYPES) + .stream() + .map(SortType::valueOf) + .collect(Collectors.toList()); + List columns = new ArrayList<>(); for (int i = 0; i < columnNames.size(); i++) { + MainTableColumnModel columnModel = MainTableColumnModel.parse(columnNames.get(i)); + if (i < columnWidths.size()) { - columns.add(MainTableColumnModel.parse(columnNames.get(i), columnWidths.get(i))); - } else { - columns.add(MainTableColumnModel.parse(columnNames.get(i))); + columnModel.widthProperty().setValue(columnWidths.get(i)); + } + + if (i < columnSortTypes.size()) { + columnModel.sortTypeProperty().setValue(columnSortTypes.get(i)); } + + columns.add(columnModel); } + return columns; } + private List createColumnSortOrder(List columns) { + List columnsOrdered = new ArrayList<>(); + getStringList(COLUMN_SORT_ORDER).forEach(columnName -> columns.stream().filter(column -> + column.getName().equals(columnName)) + .findFirst() + .ifPresent(columnsOrdered::add) + ); + return columnsOrdered; + } + public ColumnPreferences getColumnPreferences() { + List mainTableColumns = createMainTableColumns(); + return new ColumnPreferences( - createMainTableColumns(), - getBoolean(EXTRA_FILE_COLUMNS), - getMainTableColumnSortTypes()); + mainTableColumns, + createColumnSortOrder(mainTableColumns) + ); } public void storeColumnPreferences(ColumnPreferences columnPreferences) { @@ -1888,18 +1911,29 @@ public void storeColumnPreferences(ColumnPreferences columnPreferences) { .map(MainTableColumnModel::getName) .collect(Collectors.toList())); - putBoolean(EXTRA_FILE_COLUMNS, columnPreferences.getExtraFileColumnsEnabled()); - List columnWidthsInOrder = new ArrayList<>(); columnPreferences.getColumns().forEach(column -> columnWidthsInOrder.add(column.widthProperty().getValue().toString())); putStringList(COLUMN_WIDTHS, columnWidthsInOrder); - setMainTableColumnSortType(columnPreferences.getSortTypesForColumns()); + List columnSortTypesInOrder = new ArrayList<>(); + columnPreferences.getColumns().forEach(column -> columnSortTypesInOrder.add(column.sortTypeProperty().getValue().toString())); + putStringList(COLUMN_SORT_TYPES, columnSortTypesInOrder); + + putStringList(COLUMN_SORT_ORDER, columnPreferences.getColumnSortOrder().stream() + .map(MainTableColumnModel::getName) + .collect(Collectors.toList())); } public MainTablePreferences getMainTablePreferences() { return new MainTablePreferences(getColumnPreferences(), - getBoolean(AUTO_RESIZE_MODE)); + getBoolean(AUTO_RESIZE_MODE), + getBoolean(EXTRA_FILE_COLUMNS)); + } + + public void storeMainTablePreferences(MainTablePreferences mainTablePreferences) { + storeColumnPreferences(mainTablePreferences.getColumnPreferences()); + putBoolean(AUTO_RESIZE_MODE, mainTablePreferences.getResizeColumnsToFit()); + putBoolean(EXTRA_FILE_COLUMNS, mainTablePreferences.getExtraFileColumnsEnabled()); } public SpecialFieldsPreferences getSpecialFieldsPreferences() { @@ -1987,22 +2021,6 @@ public String getIdBasedFetcherForEntryGenerator() { return get(ID_ENTRY_GENERATOR); } - public void setMainTableColumnSortType(Map sortOrder) { - putStringList(COLUMN_IN_SORT_ORDER, new ArrayList<>(sortOrder.keySet())); - List sortTypes = sortOrder.values().stream().map(SortType::name).collect(Collectors.toList()); - putStringList(COlUMN_IN_SORT_ORDER_TYPE, sortTypes); - } - - public Map getMainTableColumnSortTypes() { - List columns = getStringList(COLUMN_IN_SORT_ORDER); - List sortTypes = getStringList(COlUMN_IN_SORT_ORDER_TYPE).stream().map(SortType::valueOf).collect(Collectors.toList()); - Map map = new LinkedHashMap<>(); - for (int i = 0; i < columns.size(); i++) { - map.put(columns.get(i), sortTypes.get(i)); - } - return map; - } - @Override public List getCustomExportFormats(JournalAbbreviationLoader loader) { int i = 0; diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 4384692c1854..6f2195c6cdda 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1776,7 +1776,6 @@ BibTeX\ key\ deviates\ from\ generated\ key=BibTeX-Key weicht vom generierten Ke DOI\ %0\ is\ invalid=DOI %0 ist ungültig Select\ all\ customized\ types\ to\ be\ stored\ in\ local\ preferences\:=Wählen Sie alle angepassten Eintragstypen, die in den lokalen Einstellungen gespeichert werden sollen\: -Currently\ unknown\:=Derzeit unbekannt\: Different\ customization,\ current\ settings\ will\ be\ overwritten=Abweichende Anpassung eines Typs, bestehende Anpassungen werden überschrieben Entry\ type\ %0\ is\ only\ defined\ for\ Biblatex\ but\ not\ for\ BibTeX=Eintragstyp %0 ist nur für Biblatex, nicht aber für BibTeX definiert diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 03b3fa17549a..38088dbb972e 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1734,7 +1734,6 @@ BibTeX\ key\ deviates\ from\ generated\ key=La clave BibTeX difiere de la genera DOI\ %0\ is\ invalid=El DOI %0 no es válido Select\ all\ customized\ types\ to\ be\ stored\ in\ local\ preferences\:=Seleccione todos los tipos personalizados que se almacenarán en las preferencias locales\: -Currently\ unknown\:=Actualmente desconocido\: Different\ customization,\ current\ settings\ will\ be\ overwritten=Diferente personalización, se sobreescribirán los ajustes actuales Entry\ type\ %0\ is\ only\ defined\ for\ Biblatex\ but\ not\ for\ BibTeX=El tipo de entrada %0 está definido para BibLaTeX pero no para BibTeX diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 8453b7d8aa35..a4af4f74c17b 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -476,7 +476,7 @@ Invalid\ date\ format=Format de date invalide Invalid\ URL=URL invalide Online\ help=Aide en ligne -JabRef\ Language\ (Provides\ for\ better\ recommendations\ by\ giving\ an\ indication\ of\ user's\ preferred\ language.)=Langue de JabRef (fournit de meilleures recommandations en indiquant la langue utilisée de l'utilisateur) +JabRef\ Language\ (Provides\ for\ better\ recommendations\ by\ giving\ an\ indication\ of\ user's\ preferred\ language.)=Langue de JabRef (fournit de meilleures recommandations en indiquant la langue de l'interface utilisateur) JabRef\ preferences=Préférences pour JabRef JabRef\ requests\ recommendations\ from\ Mr.\ DLib,\ which\ is\ an\ external\ service.\ To\ enable\ Mr.\ DLib\ to\ calculate\ recommendations,\ some\ of\ your\ data\ must\ be\ shared\ with\ Mr.\ DLib.\ Generally,\ the\ more\ data\ is\ shared\ the\ better\ recommendations\ can\ be\ calculated.\ However,\ we\ understand\ that\ some\ of\ your\ data\ in\ JabRef\ is\ sensitive,\ and\ you\ may\ not\ want\ to\ share\ it.\ Therefore,\ Mr.\ DLib\ offers\ a\ choice\ of\ which\ data\ you\ would\ like\ to\ share.=JabRef demande des recommandations à Mr. DLib, qui est un service externe. Pour permettre à Mr. DLib de formuler les recommandations, certaines de vos données doivent être partagées avec Mr. DLib. Généralement, partager plus de données permet de fournir de meilleures recommandations. Cependant, nous comprenons que certaines de vos données dans JabRef puissent être sensibles, et que vous ne vouliez pas les partager. Par conséquent, Mr. DLib permet de choisir les données que vous souhaitez partager. @@ -1779,7 +1779,6 @@ BibTeX\ key\ deviates\ from\ generated\ key=La clef BibTeX diffère de la clef g DOI\ %0\ is\ invalid=Le DOI %0 est invalide Select\ all\ customized\ types\ to\ be\ stored\ in\ local\ preferences\:=Sélectionnez tous les types personnalisés à stocker dans les préférences locales \: -Currently\ unknown\:=Actuellement inconnu \: Different\ customization,\ current\ settings\ will\ be\ overwritten=Personnalisation différente, les paramètres actuels seront écrasés Entry\ type\ %0\ is\ only\ defined\ for\ Biblatex\ but\ not\ for\ BibTeX=Le type d'entrée %0 est uniquement défini pour biblatex et pas pour BibTeX diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index f166eab349bf..10eeb7a6a44b 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1779,7 +1779,6 @@ BibTeX\ key\ deviates\ from\ generated\ key=BibTeX鍵は生成された鍵と異 DOI\ %0\ is\ invalid=DOI %0は有効ではありません Select\ all\ customized\ types\ to\ be\ stored\ in\ local\ preferences\:=ローカル設定に保管されるカスタム型を全て選択: -Currently\ unknown\:=現時点では未知\: Different\ customization,\ current\ settings\ will\ be\ overwritten=異なる設定:現在の設定は上書きされます Entry\ type\ %0\ is\ only\ defined\ for\ Biblatex\ but\ not\ for\ BibTeX=項目型%0はBiblatexにのみ定義されていてBibTeXでは使えません diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 8ca0f2d65752..f2e167a7a616 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1778,7 +1778,6 @@ BibTeX\ key\ deviates\ from\ generated\ key=BibTeX anahtarı oluşturulan anahta DOI\ %0\ is\ invalid=%0 DOI geçersiz Select\ all\ customized\ types\ to\ be\ stored\ in\ local\ preferences\:=Tüm özelleştirilmiş türleri yerel tercihlerde sakla\: -Currently\ unknown\:=Halen bilinmiyor\: Different\ customization,\ current\ settings\ will\ be\ overwritten=Farklı kişiselleştirme, güncel ayarların üzerine yazılacak Entry\ type\ %0\ is\ only\ defined\ for\ Biblatex\ but\ not\ for\ BibTeX=%0 girdi türü yalnızca Biblatex için tanımlanmış BibTeX için değil diff --git a/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java b/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java index b29a4dbbe1dd..950dc132d47d 100644 --- a/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java +++ b/src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java @@ -138,6 +138,7 @@ void testUpgradeColumnPreferencesFromWithoutTypes() { List columnWidths = Arrays.asList("75", "300", "470", "60", "130", "100", "30"); List updatedNames = Arrays.asList("groups", "files", "linked_id", "field:entrytype", "field:author/editor", "field:title", "field:year", "field:journal/booktitle", "field:bibtexkey", "special:printed"); List updatedWidths = Arrays.asList("28", "28", "28", "75", "300", "470", "60", "130", "100", "30"); + List newSortTypes = Arrays.asList("ASCENDING","ASCENDING","ASCENDING","ASCENDING","ASCENDING","ASCENDING","ASCENDING","ASCENDING","ASCENDING","ASCENDING"); when(prefs.getStringList(JabRefPreferences.COLUMN_NAMES)).thenReturn(columnNames); when(prefs.getStringList(JabRefPreferences.COLUMN_WIDTHS)).thenReturn(columnWidths); @@ -146,5 +147,6 @@ void testUpgradeColumnPreferencesFromWithoutTypes() { verify(prefs).putStringList(JabRefPreferences.COLUMN_NAMES, updatedNames); verify(prefs).putStringList(JabRefPreferences.COLUMN_WIDTHS, updatedWidths); + verify(prefs).putStringList(JabRefPreferences.COLUMN_SORT_TYPES, newSortTypes); } }