Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9243759
added libraryAbbrevationtype to metadata
faneeshh Apr 8, 2026
dd2296e
add metadata seralization
faneeshh Apr 8, 2026
1133b54
wire abbreviationJournalcleanup into savadatabaseaction on save
faneeshh Apr 10, 2026
d3cb9a5
add journal abbreviation preference to library properties
faneeshh Apr 11, 2026
1163656
added tests for libraryAbbreviationtype round trip and LTWA cleanup o…
faneeshh Apr 11, 2026
753c5a3
merged two split tests into a single one
faneeshh Apr 11, 2026
8096dc9
Changelog entry
faneeshh Apr 11, 2026
a4338cf
Merge branch 'main' into fix-15495
faneeshh Apr 11, 2026
a410c82
Merge branch 'main' into fix-15495
faneeshh Apr 12, 2026
835af3f
fixed abbreviation running after write and ighnoring selectedScope only
faneeshh Apr 15, 2026
031b19d
Changelog fix
faneeshh Apr 15, 2026
fc92e0a
Merge branch 'main' into fix-15495
faneeshh Apr 15, 2026
0a9da28
Merge branch 'main' into fix-15495
faneeshh Apr 16, 2026
924366c
Merge branch 'main' into fix-15495
faneeshh Apr 25, 2026
48e3451
Merge branch 'main' into fix-15495
calixtus Jul 22, 2026
a34f44b
Update SaveDatabaseAction.java
calixtus Jul 22, 2026
480352e
Update MetaDataSerializerTest.java
calixtus Jul 22, 2026
6e12af6
fix import order in SavingPropertiesView
faneeshh Jul 24, 2026
3410f26
Merge branch 'main' into fix-15495
faneeshh Jul 24, 2026
3c02bcb
Merge branch 'main' into fix-15495
koppor Jul 25, 2026
2906fae
Merge branch 'main' into fix-15495
faneeshh Jul 25, 2026
8ab621f
switch to constructor based injection
faneeshh Jul 25, 2026
f202e99
injector cleanup and update tests
faneeshh Jul 25, 2026
3a1ffc4
Update jablib/src/main/java/org/jabref/model/metadata/MetaData.java
faneeshh Aug 6, 2026
a88b646
Update jablib/src/test/java/org/jabref/logic/cleanup/AbbreviateJourna…
faneeshh Aug 6, 2026
8e7fbda
Merge branch 'main' into fix-15495
faneeshh Aug 6, 2026
c3b61d0
fix formatting
faneeshh Aug 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- The LibreOffice integration's "Cite special" mode for JStyles can now cite author-year (without parenthesis), author-only and year-only entries. [forum#670](https://discourse.jabref.org/t/cite-special-openoffice-libreoffice-connection-tool/670). [#7861](https://github.com/JabRef/jabref/issues/7861)
- The LibreOffice/OpenOffice integration now works with Track Changes enabled in the document. [#9403](https://github.com/JabRef/jabref/issues/9403). [#14018](https://github.com/JabRef/jabref/issues/14018)
- We added configurable keyword delimiter detection for imported BibTeX, so that delimiters such as `;` are recognized and normalized to your configured keyword separator. [#12974](https://github.com/JabRef/jabref/issues/12974)
Expand Down
4 changes: 2 additions & 2 deletions jabgui/src/main/java/org/jabref/gui/LibraryTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ private void setDatabaseContext(@NonNull BibDatabaseContext bibDatabaseContext)
public void installAutosaveManagerAndBackupManager() {
if (isDatabaseReadyForAutoSave(bibDatabaseContext)) {
AutosaveManager autosaveManager = AutosaveManager.start(bibDatabaseContext, coarseChangeFilter);
autosaveManager.registerListener(new AutosaveUiManager(this, dialogService, preferences, entryTypesManager, stateManager));
autosaveManager.registerListener(new AutosaveUiManager(this, dialogService, preferences, entryTypesManager, stateManager, journalAbbreviationRepository));
}
if (isDatabaseReadyForBackup(bibDatabaseContext) && preferences.getFilePreferences().shouldCreateBackup()) {
BackupManager.start(this, bibDatabaseContext, coarseChangeFilter, Injector.instantiateModelOrService(BibEntryTypesManager.class), preferences);
Expand Down Expand Up @@ -678,7 +678,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, entryTypesManager, stateManager, journalAbbreviationRepository);
if (saveAction.save()) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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;

Expand All @@ -19,8 +20,8 @@ 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);
public AutosaveUiManager(LibraryTab libraryTab, DialogService dialogService, GuiPreferences preferences, BibEntryTypesManager entryTypesManager, StateManager stateManager, JournalAbbreviationRepository journalAbbreviationRepository) {
this.saveDatabaseAction = new SaveDatabaseAction(libraryTab, dialogService, preferences, entryTypesManager, stateManager, journalAbbreviationRepository);
}

@Subscribe
Expand Down
16 changes: 11 additions & 5 deletions jabgui/src/main/java/org/jabref/gui/exporter/SaveAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
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;

/// This class is just a simple wrapper for the soon to be refactored SaveDatabaseAction.
public class SaveAction extends SimpleCommand {

Expand All @@ -23,17 +22,23 @@ public enum SaveMethod { SAVE, SAVE_AS, SAVE_SELECTED }
private final DialogService dialogService;
private final GuiPreferences preferences;
private final StateManager stateManager;
private final BibEntryTypesManager entryTypesManager;
private final JournalAbbreviationRepository journalAbbreviationRepository;

public SaveAction(SaveMethod saveMethod,
Supplier<LibraryTab> tabSupplier,
DialogService dialogService,
GuiPreferences preferences,
StateManager stateManager) {
StateManager stateManager,
BibEntryTypesManager entryTypesManager,
JournalAbbreviationRepository journalAbbreviationRepository) {
this.saveMethod = saveMethod;
this.tabSupplier = tabSupplier;
this.dialogService = dialogService;
this.preferences = preferences;
this.stateManager = stateManager;
this.entryTypesManager = entryTypesManager;
this.journalAbbreviationRepository = journalAbbreviationRepository;

if (saveMethod == SaveMethod.SAVE_SELECTED) {
this.executable.bind(ActionHelper.needsEntriesSelected(stateManager));
Expand All @@ -48,8 +53,9 @@ public void execute() {
tabSupplier.get(),
dialogService,
preferences,
Injector.instantiateModelOrService(BibEntryTypesManager.class),
stateManager);
entryTypesManager,
stateManager,
journalAbbreviationRepository);

switch (saveMethod) {
case SAVE ->
Expand Down
11 changes: 7 additions & 4 deletions jabgui/src/main/java/org/jabref/gui/exporter/SaveAllAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
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;

import com.airhacks.afterburner.injection.Injector;

import static org.jabref.gui.actions.ActionHelper.needsDatabase;

public class SaveAllAction extends SimpleCommand {
Expand All @@ -21,21 +20,25 @@ public class SaveAllAction extends SimpleCommand {
private final DialogService dialogService;
private final GuiPreferences preferences;
private final StateManager stateManager;
private final BibEntryTypesManager entryTypesManager;
private final JournalAbbreviationRepository journalAbbreviationRepository;

public SaveAllAction(Supplier<List<LibraryTab>> tabsSupplier, GuiPreferences preferences, DialogService dialogService, StateManager stateManager) {
public SaveAllAction(Supplier<List<LibraryTab>> tabsSupplier, GuiPreferences preferences, DialogService dialogService, StateManager stateManager, BibEntryTypesManager entryTypesManager, JournalAbbreviationRepository journalAbbreviationRepository) {
this.tabsSupplier = tabsSupplier;
this.dialogService = dialogService;
this.preferences = preferences;
this.executable.bind(needsDatabase(stateManager));
this.stateManager = stateManager;
this.entryTypesManager = entryTypesManager;
this.journalAbbreviationRepository = journalAbbreviationRepository;
}

@Override
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, entryTypesManager, stateManager, journalAbbreviationRepository);
boolean saveResult = saveDatabaseAction.save();
if (!saveResult) {
dialogService.notify(Localization.lang("Could not save file."));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
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;
Expand Down Expand Up @@ -59,6 +60,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
Expand All @@ -68,12 +70,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() {
Expand Down Expand Up @@ -261,7 +265,10 @@ private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding,
saveConfiguration,
preferences.getFieldPreferences(),
preferences.getCitationKeyPatternPreferences(),
entryTypesManager);
entryTypesManager)
.withJournalAbbreviationRepository(
journalAbbreviationRepository,
preferences.getAbbreviationPreferences().shouldUseFJournalField());

if (selectedOnly) {
databaseWriter.writePartOfDatabase(bibDatabaseContext, libraryTab.getSelectedEntries());
Expand Down
8 changes: 4 additions & 4 deletions jabgui/src/main/java/org/jabref/gui/frame/MainMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ private void createMenu() {
factory.createMenuItem(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferences)),
factory.createMenuItem(StandardActions.OPEN_LIBRARY, openDatabaseActionSupplier.get()),
fileHistoryMenu,
factory.createMenuItem(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager)),
factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new SaveAction(SaveAction.SaveMethod.SAVE_AS, frame::getCurrentLibraryTab, dialogService, preferences, stateManager)),
factory.createMenuItem(StandardActions.SAVE_ALL, new SaveAllAction(frame::getLibraryTabs, preferences, dialogService, stateManager)),
factory.createMenuItem(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager, entryTypesManager, journalAbbreviationRepository)),
factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new SaveAction(SaveAction.SaveMethod.SAVE_AS, frame::getCurrentLibraryTab, dialogService, preferences, stateManager, entryTypesManager, journalAbbreviationRepository)),
factory.createMenuItem(StandardActions.SAVE_ALL, new SaveAllAction(frame::getLibraryTabs, preferences, dialogService, stateManager, entryTypesManager, journalAbbreviationRepository)),
factory.createMenuItem(StandardActions.CLOSE_LIBRARY, new JabRefFrame.CloseDatabaseAction(frame, stateManager)),

new SeparatorMenuItem(),
Expand All @@ -190,7 +190,7 @@ private void createMenu() {
factory.createSubMenu(StandardActions.EXPORT,
factory.createMenuItem(StandardActions.EXPORT_ALL, new ExportCommand(ExportCommand.ExportMethod.EXPORT_ALL, stateManager, dialogService, preferences, abbreviationRepository, taskExecutor)),
factory.createMenuItem(StandardActions.EXPORT_SELECTED, new ExportCommand(ExportCommand.ExportMethod.EXPORT_SELECTED, stateManager, dialogService, preferences, abbreviationRepository, taskExecutor)),
factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new SaveAction(SaveAction.SaveMethod.SAVE_SELECTED, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))),
factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new SaveAction(SaveAction.SaveMethod.SAVE_SELECTED, frame::getCurrentLibraryTab, dialogService, preferences, stateManager, entryTypesManager, journalAbbreviationRepository))),

new SeparatorMenuItem(),

Expand Down
2 changes: 1 addition & 1 deletion jabgui/src/main/java/org/jabref/gui/frame/MainToolBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private void createToolBar() {
new HBox(
factory.createIconButton(StandardActions.NEW_LIBRARY, new NewDatabaseAction(frame, preferences)),
factory.createIconButton(StandardActions.OPEN_LIBRARY, new OpenDatabaseAction(frame, preferences, aiService, dialogService, stateManager, fileUpdateMonitor, entryTypesManager, undoManager, clipBoardManager, taskExecutor)),
factory.createIconButton(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager))),
factory.createIconButton(StandardActions.SAVE_LIBRARY, new SaveAction(SaveAction.SaveMethod.SAVE, frame::getCurrentLibraryTab, dialogService, preferences, stateManager, entryTypesManager, journalAbbreviationRepository))),

leftSpacer,

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
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.cleanup.CleanupPreferences;
import org.jabref.logic.journals.AbbreviationType;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;

Expand All @@ -18,6 +22,7 @@ public class SavingPropertiesView extends AbstractPropertiesTabView<SavingProper
@FXML private CheckBox protect;
@FXML private SaveOrderConfigPanel saveOrderConfigPanel;
@FXML private FieldFormatterCleanupsPanel fieldFormatterCleanupsPanel;
@FXML private ComboBox<AbbreviationType> journalAbbreviationOnSave;

public SavingPropertiesView(BibDatabaseContext databaseContext) {
this.databaseContext = databaseContext;
Expand Down Expand Up @@ -46,5 +51,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)");
};
}
Comment on lines +64 to +74

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope these options sound correct.


@Override
public AbbreviationType fromString(String string) {
return null;
}
});
journalAbbreviationOnSave.valueProperty().bindBidirectional(viewModel.journalAbbreviationOnSaveProperty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@

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;
import org.jabref.gui.libraryproperties.PropertiesTabViewModel;
import org.jabref.logic.cleanup.FieldFormatterCleanup;
import org.jabref.logic.cleanup.FieldFormatterCleanupActions;
import org.jabref.logic.journals.AbbreviationType;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.FieldFactory;
Expand Down Expand Up @@ -47,6 +50,9 @@ public class SavingPropertiesViewModel implements PropertiesTabViewModel {
private final BooleanProperty cleanupsDisableProperty = new SimpleBooleanProperty();
private final ListProperty<FieldFormatterCleanup> cleanupsProperty = new SimpleListProperty<>(FXCollections.emptyObservableList());

// Journal abbreviation on save
private final ObjectProperty<AbbreviationType> journalAbbreviationOnSaveProperty = new SimpleObjectProperty<>();

private final BibDatabaseContext databaseContext;
private final MetaData initialMetaData;
private final SaveOrder saveOrder;
Expand Down Expand Up @@ -98,6 +104,8 @@ public void setValues() {
cleanupsDisableProperty.setValue(!defaultSaveActions.isEnabled());
cleanupsProperty.setValue(FXCollections.observableArrayList(defaultSaveActions.getConfiguredActions()));
});

journalAbbreviationOnSaveProperty.setValue(initialMetaData.getLibraryAbbreviationType().orElse(null));
}

@Override
Expand Down Expand Up @@ -137,6 +145,13 @@ public void storeSettings() {
}
}

AbbreviationType abbreviationType = journalAbbreviationOnSaveProperty.getValue();
if (abbreviationType != null) {
newMetaData.setLibraryAbbreviationType(abbreviationType);
} else {
newMetaData.clearLibraryAbbreviationType();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it need clearing if it's already null?
If yes, I'll post another comment to complement this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this. If for a newly loaded library with abbreviation type None, one opens the library properties and doesn't touch the drop down (stays "None), this code triggers the library to be marked dirty due to postChange

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it needs the clear

}

databaseContext.setMetaData(newMetaData);
}

Expand Down Expand Up @@ -179,4 +194,8 @@ public BooleanProperty cleanupsDisableProperty() {
public ListProperty<FieldFormatterCleanup> cleanupsProperty() {
return cleanupsProperty;
}

public ObjectProperty<AbbreviationType> journalAbbreviationOnSaveProperty() {
return journalAbbreviationOnSaveProperty;
}
}
Loading
Loading