diff --git a/CHANGELOG.md b/CHANGELOG.md index 99ec9356cb0..debdc670ae4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added +- We added a per-library journal abbreviation preference to Library Properties, allowing automatic LTWA abbreviation on save. [#15495](https://github.com/JabRef/jabref/issues/15495) - We fixed a glitch with the sidepane divider position on startup. [#15394](https://github.com/JabRef/jabref/issues/15394) - We added a label to the Group dropdown in the Import Dialog. [#15567](https://github.com/JabRef/jabref/issues/15567) - We added a related work text extractor, which finds and inserts the related work text into bib entries from references in the texts. [#9840](https://github.com/JabRef/jabref/issues/9840) diff --git a/jabgui/src/main/java/org/jabref/gui/LibraryTab.java b/jabgui/src/main/java/org/jabref/gui/LibraryTab.java index c27188a498f..8d68a2927bb 100644 --- a/jabgui/src/main/java/org/jabref/gui/LibraryTab.java +++ b/jabgui/src/main/java/org/jabref/gui/LibraryTab.java @@ -675,7 +675,7 @@ private boolean confirmClose() { if (buttonType.equals(saveChanges)) { try { - SaveDatabaseAction saveAction = new SaveDatabaseAction(this, dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class), stateManager); + SaveDatabaseAction saveAction = new SaveDatabaseAction(this, dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class), stateManager, Injector.instantiateModelOrService(JournalAbbreviationRepository.class)); if (saveAction.save()) { return true; } diff --git a/jabgui/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java b/jabgui/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java index 7ec0504198e..a7818920d4e 100644 --- a/jabgui/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java +++ b/jabgui/src/main/java/org/jabref/gui/dialogs/AutosaveUiManager.java @@ -5,9 +5,11 @@ import org.jabref.gui.StateManager; import org.jabref.gui.exporter.SaveDatabaseAction; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.model.database.event.AutosaveEvent; import org.jabref.model.entry.BibEntryTypesManager; +import com.airhacks.afterburner.injection.Injector; import com.google.common.eventbus.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,7 +22,7 @@ public class AutosaveUiManager { private final SaveDatabaseAction saveDatabaseAction; public AutosaveUiManager(LibraryTab libraryTab, DialogService dialogService, GuiPreferences preferences, BibEntryTypesManager entryTypesManager, StateManager stateManager) { - this.saveDatabaseAction = new SaveDatabaseAction(libraryTab, dialogService, preferences, entryTypesManager, stateManager); + this.saveDatabaseAction = new SaveDatabaseAction(libraryTab, dialogService, preferences, entryTypesManager, stateManager, Injector.instantiateModelOrService(JournalAbbreviationRepository.class)); } @Subscribe diff --git a/jabgui/src/main/java/org/jabref/gui/exporter/SaveAction.java b/jabgui/src/main/java/org/jabref/gui/exporter/SaveAction.java index fc625b35dae..75ae80acb80 100644 --- a/jabgui/src/main/java/org/jabref/gui/exporter/SaveAction.java +++ b/jabgui/src/main/java/org/jabref/gui/exporter/SaveAction.java @@ -8,6 +8,7 @@ import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.model.entry.BibEntryTypesManager; import com.airhacks.afterburner.injection.Injector; @@ -49,7 +50,8 @@ public void execute() { dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class), - stateManager); + stateManager, + Injector.instantiateModelOrService(JournalAbbreviationRepository.class)); switch (saveMethod) { case SAVE -> diff --git a/jabgui/src/main/java/org/jabref/gui/exporter/SaveAllAction.java b/jabgui/src/main/java/org/jabref/gui/exporter/SaveAllAction.java index c8b7a51700b..d8771fdd30d 100644 --- a/jabgui/src/main/java/org/jabref/gui/exporter/SaveAllAction.java +++ b/jabgui/src/main/java/org/jabref/gui/exporter/SaveAllAction.java @@ -8,6 +8,7 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntryTypesManager; @@ -35,7 +36,7 @@ public void execute() { dialogService.notify(Localization.lang("Saving all libraries...")); for (LibraryTab libraryTab : tabsSupplier.get()) { - SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction(libraryTab, dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class), stateManager); + SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction(libraryTab, dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class), stateManager, Injector.instantiateModelOrService(JournalAbbreviationRepository.class)); boolean saveResult = saveDatabaseAction.save(); if (!saveResult) { dialogService.notify(Localization.lang("Could not save file.")); diff --git a/jabgui/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/jabgui/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 64e8fdfa6df..c4a3471fd70 100644 --- a/jabgui/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/jabgui/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -10,6 +10,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; @@ -27,18 +28,22 @@ import org.jabref.gui.maintable.columns.MainTableColumn; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.FileDialogConfiguration; +import org.jabref.logic.cleanup.AbbreviateJournalCleanup; import org.jabref.logic.exporter.AtomicFileWriter; import org.jabref.logic.exporter.BibDatabaseWriter; import org.jabref.logic.exporter.BibWriter; import org.jabref.logic.exporter.SaveException; import org.jabref.logic.exporter.SelfContainedSaveConfiguration; +import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; import org.jabref.logic.os.OS; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; import org.jabref.logic.util.StandardFileType; +import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.event.ChangePropagation; +import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.metadata.SaveOrder; import org.jabref.model.metadata.SelfContainedSaveOrder; @@ -59,6 +64,7 @@ public class SaveDatabaseAction { private final GuiPreferences preferences; private final BibEntryTypesManager entryTypesManager; private final StateManager stateManager; + private final JournalAbbreviationRepository journalAbbreviationRepository; public enum SaveDatabaseMode { SILENT, NORMAL @@ -68,12 +74,14 @@ public SaveDatabaseAction(LibraryTab libraryTab, DialogService dialogService, GuiPreferences preferences, BibEntryTypesManager entryTypesManager, - StateManager stateManager) { + StateManager stateManager, + JournalAbbreviationRepository journalAbbreviationRepository) { this.libraryTab = libraryTab; this.dialogService = dialogService; this.preferences = preferences; this.entryTypesManager = entryTypesManager; this.stateManager = stateManager; + this.journalAbbreviationRepository = journalAbbreviationRepository; } public boolean save() { @@ -260,13 +268,29 @@ private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding, preferences.getCitationKeyPatternPreferences(), entryTypesManager); + List entriesToAbbreviate = selectedOnly + ? libraryTab.getSelectedEntries() + : bibDatabaseContext.getDatabase().getEntries(); + List abbreviationChanges = bibDatabaseContext.getMetaData() + .getLibraryAbbreviationType() + .map(abbreviationType -> { + boolean useFJournal = preferences.getJournalAbbreviationPreferences().shouldUseFJournalField(); + AbbreviateJournalCleanup cleanup = new AbbreviateJournalCleanup( + bibDatabaseContext.getDatabase(), journalAbbreviationRepository, abbreviationType, useFJournal); + return entriesToAbbreviate.stream() + .flatMap(entry -> cleanup.cleanup(entry).stream()) + .toList(); + }) + .orElse(List.of()); + if (selectedOnly) { databaseWriter.writePartOfDatabase(bibDatabaseContext, libraryTab.getSelectedEntries()); } else { databaseWriter.writeDatabase(bibDatabaseContext); } - libraryTab.registerUndoableChanges(databaseWriter.getSaveActionsFieldChanges()); + libraryTab.registerUndoableChanges( + Stream.concat(databaseWriter.getSaveActionsFieldChanges().stream(), abbreviationChanges.stream()).toList()); if (fileWriter.hasEncodingProblems()) { saveWithDifferentEncoding(file, selectedOnly, encoding, fileWriter.getEncodingProblems(), saveType, saveOrder); diff --git a/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesView.java b/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesView.java index c1b481662f2..dedcec10375 100644 --- a/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesView.java +++ b/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesView.java @@ -1,12 +1,16 @@ package org.jabref.gui.libraryproperties.saving; +import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.util.StringConverter; import org.jabref.gui.commonfxcontrols.FieldFormatterCleanupsPanel; import org.jabref.gui.commonfxcontrols.SaveOrderConfigPanel; import org.jabref.gui.libraryproperties.AbstractPropertiesTabView; import org.jabref.gui.libraryproperties.PropertiesTab; +import org.jabref.logic.journals.AbbreviationType; import org.jabref.logic.l10n.Localization; import org.jabref.logic.preferences.CliPreferences; import org.jabref.model.database.BibDatabaseContext; @@ -19,6 +23,7 @@ public class SavingPropertiesView extends AbstractPropertiesTabView journalAbbreviationOnSave; @Inject private CliPreferences preferences; @@ -49,5 +54,33 @@ public void initialize() { fieldFormatterCleanupsPanel.cleanupsDisableProperty().bindBidirectional(viewModel.cleanupsDisableProperty()); fieldFormatterCleanupsPanel.cleanupsProperty().bindBidirectional(viewModel.cleanupsProperty()); + + journalAbbreviationOnSave.setItems(FXCollections.observableArrayList( + null, AbbreviationType.DEFAULT, AbbreviationType.DOTLESS, + AbbreviationType.SHORTEST_UNIQUE, AbbreviationType.LTWA)); + journalAbbreviationOnSave.setConverter(new StringConverter<>() { + @Override + public String toString(AbbreviationType type) { + if (type == null) { + return Localization.lang("None (use global setting)"); + } + return switch (type) { + case DEFAULT -> + Localization.lang("Abbreviate (default)"); + case DOTLESS -> + Localization.lang("Abbreviate (dotless)"); + case SHORTEST_UNIQUE -> + Localization.lang("Abbreviate (shortest unique)"); + case LTWA -> + Localization.lang("Abbreviate (LTWA)"); + }; + } + + @Override + public AbbreviationType fromString(String string) { + return null; + } + }); + journalAbbreviationOnSave.valueProperty().bindBidirectional(viewModel.journalAbbreviationOnSaveProperty()); } } diff --git a/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesViewModel.java b/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesViewModel.java index bdc23497d9f..22d6f5232c1 100644 --- a/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/libraryproperties/saving/SavingPropertiesViewModel.java @@ -7,8 +7,10 @@ import javafx.beans.property.BooleanProperty; import javafx.beans.property.ListProperty; +import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleListProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import org.jabref.gui.commonfxcontrols.SortCriterionViewModel; @@ -16,6 +18,7 @@ import org.jabref.logic.cleanup.CleanupPreferences; import org.jabref.logic.cleanup.FieldFormatterCleanup; import org.jabref.logic.cleanup.FieldFormatterCleanupActions; +import org.jabref.logic.journals.AbbreviationType; import org.jabref.logic.preferences.CliPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.field.Field; @@ -49,6 +52,9 @@ public class SavingPropertiesViewModel implements PropertiesTabViewModel { private final BooleanProperty cleanupsDisableProperty = new SimpleBooleanProperty(); private final ListProperty cleanupsProperty = new SimpleListProperty<>(FXCollections.emptyObservableList()); + // Journal abbreviation on save + private final ObjectProperty journalAbbreviationOnSaveProperty = new SimpleObjectProperty<>(); + private final BibDatabaseContext databaseContext; private final MetaData initialMetaData; private final SaveOrder saveOrder; @@ -101,6 +107,8 @@ public void setValues() { cleanupsDisableProperty.setValue(!defaultPreset.getFieldFormatterCleanups().isEnabled()); cleanupsProperty.setValue(FXCollections.observableArrayList(defaultPreset.getFieldFormatterCleanups().getConfiguredActions())); }); + + journalAbbreviationOnSaveProperty.setValue(initialMetaData.getLibraryAbbreviationType().orElse(null)); } @Override @@ -140,6 +148,13 @@ public void storeSettings() { } } + AbbreviationType abbreviationType = journalAbbreviationOnSaveProperty.getValue(); + if (abbreviationType != null) { + newMetaData.setLibraryAbbreviationType(abbreviationType); + } else { + newMetaData.clearLibraryAbbreviationType(); + } + databaseContext.setMetaData(newMetaData); } @@ -182,4 +197,8 @@ public BooleanProperty cleanupsDisableProperty() { public ListProperty cleanupsProperty() { return cleanupsProperty; } + + public ObjectProperty journalAbbreviationOnSaveProperty() { + return journalAbbreviationOnSaveProperty; + } } diff --git a/jabgui/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java b/jabgui/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java index e4661601a5e..ac8fed787c0 100644 --- a/jabgui/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java @@ -34,6 +34,7 @@ import org.jabref.gui.util.FileFilterConverter; import org.jabref.logic.ai.AiService; import org.jabref.logic.help.HelpFile; +import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; import org.jabref.logic.shared.DBMSConnectionProperties; import org.jabref.logic.shared.DBMSConnectionPropertiesBuilder; @@ -213,7 +214,8 @@ private boolean openSharedDatabase(DBMSConnectionProperties connectionProperties dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class), - stateManager + stateManager, + Injector.instantiateModelOrService(JournalAbbreviationRepository.class) ).saveAs(Path.of(folder.getValue())); } catch (Throwable e) { LOGGER.error("Error while saving the database", e); diff --git a/jabgui/src/main/resources/org/jabref/gui/libraryproperties/saving/SavingProperties.fxml b/jabgui/src/main/resources/org/jabref/gui/libraryproperties/saving/SavingProperties.fxml index 03d828fb2ec..d925499d8a7 100644 --- a/jabgui/src/main/resources/org/jabref/gui/libraryproperties/saving/SavingProperties.fxml +++ b/jabgui/src/main/resources/org/jabref/gui/libraryproperties/saving/SavingProperties.fxml @@ -2,7 +2,9 @@ + + @@ -18,6 +20,12 @@