From 0d2efc46c9a595786f46ce170e1bdd239b7827d8 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Mon, 17 Feb 2020 20:45:10 +0100 Subject: [PATCH 001/287] Preview and XMPWriter --- src/main/java/org/jabref/gui/BasePanel.java | 7 ++-- src/main/java/org/jabref/gui/JabRefFrame.java | 8 +++-- .../EntryEditorPreviewChangeAction.java | 31 +++++++++++++++++ .../jabref/gui/exporter/WriteXMPAction.java | 33 +++++++++++-------- 4 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/jabref/gui/entryeditor/EntryEditorPreviewChangeAction.java diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index efec6542ab0..767e6199dfa 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -40,7 +40,6 @@ import org.jabref.gui.edit.ReplaceStringAction; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; -import org.jabref.gui.exporter.WriteXMPAction; import org.jabref.gui.externalfiles.DownloadFullTextAction; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; @@ -355,16 +354,16 @@ private void setupActions() { new SpecialFieldViewModel(SpecialField.READ_STATUS, undoManager).getSpecialFieldAction(status, this.frame)); } - actions.put(Actions.NEXT_PREVIEW_STYLE, () -> { + /* actions.put(Actions.NEXT_PREVIEW_STYLE, () -> { entryEditor.nextPreviewStyle(); }); actions.put(Actions.PREVIOUS_PREVIEW_STYLE, () -> { entryEditor.previousPreviewStyle(); - }); + }); */ actions.put(Actions.SEND_AS_EMAIL, new SendAsEMailAction(frame)); - actions.put(Actions.WRITE_XMP, new WriteXMPAction(this)::execute); + // actions.put(Actions.WRITE_XMP, new WriteXMPAction(this)::execute); actions.put(Actions.ABBREVIATE_DEFAULT, new AbbreviateAction(this, AbbreviationType.DEFAULT)); actions.put(Actions.ABBREVIATE_MEDLINE, new AbbreviateAction(this, AbbreviationType.MEDLINE)); diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 7fd1df234f9..6712bfd9777 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -62,11 +62,13 @@ import org.jabref.gui.edit.ManageKeywordsAction; import org.jabref.gui.edit.MassSetFieldsAction; import org.jabref.gui.edit.OpenBrowserAction; +import org.jabref.gui.entryeditor.EntryEditorPreviewChangeAction; import org.jabref.gui.exporter.ExportCommand; import org.jabref.gui.exporter.ExportToClipboardAction; import org.jabref.gui.exporter.ManageCustomExportsAction; import org.jabref.gui.exporter.SaveAllAction; import org.jabref.gui.exporter.SaveDatabaseAction; +import org.jabref.gui.exporter.WriteXMPAction; import org.jabref.gui.externalfiles.AutoLinkFilesAction; import org.jabref.gui.externalfiles.FindUnlinkedFilesAction; import org.jabref.gui.externalfiletype.EditExternalFileTypesAction; @@ -765,7 +767,7 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.PARSE_TEX, new ParseTexAction(stateManager)), factory.createMenuItem(StandardActions.NEW_SUB_LIBRARY_FROM_AUX, new NewSubLibraryAction(this, stateManager)), factory.createMenuItem(StandardActions.FIND_UNLINKED_FILES, new FindUnlinkedFilesAction(this, stateManager)), - factory.createMenuItem(StandardActions.WRITE_XMP, new OldDatabaseCommandWrapper(Actions.WRITE_XMP, this, stateManager)), + factory.createMenuItem(StandardActions.WRITE_XMP, new WriteXMPAction(stateManager, dialogService)), factory.createMenuItem(StandardActions.COPY_LINKED_FILES, new CopyFilesAction(stateManager, this.getDialogService())), factory.createMenuItem(StandardActions.EXTRACT_BIBTEX, new ExtractBibtexAction(stateManager)), @@ -803,8 +805,8 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new OldDatabaseCommandWrapper(Actions.NEXT_PREVIEW_STYLE, this, stateManager)), - factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new OldDatabaseCommandWrapper(Actions.PREVIOUS_PREVIEW_STYLE, this, stateManager)), + factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new EntryEditorPreviewChangeAction(EntryEditorPreviewChangeAction.Direction.NEXT, this, stateManager)), + factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new EntryEditorPreviewChangeAction(EntryEditorPreviewChangeAction.Direction.PREVIOUS, this, stateManager)), new SeparatorMenuItem(), diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreviewChangeAction.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreviewChangeAction.java new file mode 100644 index 00000000000..d6f0ce47ea7 --- /dev/null +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreviewChangeAction.java @@ -0,0 +1,31 @@ +package org.jabref.gui.entryeditor; + +import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + +public class EntryEditorPreviewChangeAction extends SimpleCommand { + + public enum Direction { PREVIOUS, NEXT } + + private final JabRefFrame frame; + private final Direction direction; + + public EntryEditorPreviewChangeAction(Direction direction, JabRefFrame frame, StateManager stateManager) { + this.frame = frame; + this.direction = direction; + + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + if (direction == Direction.NEXT) { + frame.getCurrentBasePanel().getEntryEditor().nextPreviewStyle(); + } else { + frame.getCurrentBasePanel().getEntryEditor().previousPreviewStyle(); + } + } +} diff --git a/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java b/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java index 043ceac725d..f275740f5a1 100644 --- a/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java +++ b/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java @@ -21,9 +21,9 @@ import javafx.stage.Stage; import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.FXDialog; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.BackgroundTask; import org.jabref.logic.l10n.Localization; @@ -31,25 +31,28 @@ import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + public class WriteXMPAction extends SimpleCommand { - private final BasePanel basePanel; - private OptionsDialog optionsDialog; + private final StateManager stateManager; + private final DialogService dialogService; - private Collection entries; + private OptionsDialog optionsDialog; private BibDatabase database; + private Collection entries; private boolean shouldContinue = true; - private int skipped; private int entriesChanged; private int errors; - private final DialogService dialogService; - public WriteXMPAction(BasePanel basePanel) { - this.basePanel = basePanel; - dialogService = basePanel.frame().getDialogService(); + public WriteXMPAction(StateManager stateManager, DialogService dialogService) { + this.stateManager = stateManager; + this.dialogService = dialogService; + + this.executable.bind(needsDatabase(stateManager)); } @Override @@ -60,9 +63,13 @@ public void execute() { } public void init() { - database = basePanel.getDatabase(); + if (stateManager.getActiveDatabase().isEmpty()) { + return; + } + + database = stateManager.getActiveDatabase().get().getDatabase(); // Get entries and check if it makes sense to perform this operation - entries = basePanel.getSelectedEntries(); + entries = stateManager.getSelectedEntries(); if (entries.isEmpty()) { @@ -97,7 +104,7 @@ public void init() { } private void writeXMP() { - if (!shouldContinue) { + if (!shouldContinue || stateManager.getActiveDatabase().isEmpty()) { return; } @@ -105,7 +112,7 @@ private void writeXMP() { // Make a list of all PDFs linked from this entry: List files = entry.getFiles().stream() .filter(file -> file.getFileType().equalsIgnoreCase("pdf")) - .map(file -> file.findIn(basePanel.getBibDatabaseContext(), Globals.prefs.getFilePreferences())) + .map(file -> file.findIn(stateManager.getActiveDatabase().get(), Globals.prefs.getFilePreferences())) .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toList()); From d1d74c7d4d12c81b1b324fc4f973f2f437b2bb83 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Mon, 17 Feb 2020 23:14:23 +0100 Subject: [PATCH 002/287] OpenConsole, OpenFolder, OpenExternalFile --- src/main/java/org/jabref/gui/BasePanel.java | 87 ------------------- src/main/java/org/jabref/gui/JabRefFrame.java | 2 +- .../org/jabref/gui/OpenConsoleAction.java | 35 ++++++++ .../jabref/gui/OpenExternalFileAction.java | 53 +++++++++++ .../java/org/jabref/gui/OpenFolderAction.java | 45 ++++++++++ .../org/jabref/gui/maintable/MainTable.java | 2 +- .../jabref/gui/maintable/RightClickMenu.java | 22 ++--- 7 files changed, 142 insertions(+), 104 deletions(-) create mode 100644 src/main/java/org/jabref/gui/OpenConsoleAction.java create mode 100644 src/main/java/org/jabref/gui/OpenExternalFileAction.java create mode 100644 src/main/java/org/jabref/gui/OpenFolderAction.java diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 767e6199dfa..f45506934ff 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -306,21 +306,6 @@ private void setupActions() { actions.put(Actions.MERGE_DATABASE, new AppendDatabaseAction(frame, this)); - actions.put(Actions.OPEN_EXTERNAL_FILE, this::openExternalFile); - - actions.put(Actions.OPEN_FOLDER, () -> JabRefExecutorService.INSTANCE.execute(() -> { - final List files = FileUtil.getListOfLinkedFiles(mainTable.getSelectedEntries(), bibDatabaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); - for (final Path f : files) { - try { - JabRefDesktop.openFolderAndSelectFile(f.toAbsolutePath()); - } catch (IOException e) { - LOGGER.info("Could not open folder", e); - } - } - })); - - actions.put(Actions.OPEN_CONSOLE, () -> JabRefDesktop.openConsole(frame.getCurrentBasePanel().getBibDatabaseContext().getDatabaseFile().orElse(null))); - actions.put(Actions.PULL_CHANGES_FROM_SHARED_DATABASE, () -> { DatabaseSynchronizer dbmsSynchronizer = frame.getCurrentBasePanel().getBibDatabaseContext().getDBMSSynchronizer(); dbmsSynchronizer.pullChanges(); @@ -542,37 +527,6 @@ private void copyKeyAndTitle() { } } - private void openExternalFile() { - final List selectedEntries = mainTable.getSelectedEntries(); - if (selectedEntries.size() != 1) { - output(Localization.lang("This operation requires exactly one item to be selected.")); - return; - } - JabRefExecutorService.INSTANCE.execute(() -> { - final BibEntry entry = selectedEntries.get(0); - if (!entry.hasField(StandardField.FILE)) { - // no bibtex field - new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); - return; - } - - List files = new ArrayList<>(); - entry.getField(StandardField.FILE).map(FileFieldParser::parse).ifPresent(files::addAll); - - if (files.isEmpty()) { - // content in BibTeX field is not readable - new SearchAndOpenFile(entry, BasePanel.this).searchAndOpen(); - return; - } - LinkedFile flEntry = files.get(0); - try { - JabRefDesktop.openExternalFileAnyFormat(this.getBibDatabaseContext(), flEntry.getLink(), ExternalFileTypes.getInstance().fromLinkedFile(flEntry, true)); - } catch (IOException ex) { - dialogService.showErrorDialogAndWait(ex); - } - }); - } - /** * This method is called from JabRefFrame if a database specific action is requested by the user. Runs the command * if it is defined, or prints an error message to the standard error stream. @@ -1076,47 +1030,6 @@ public void cut() { mainTable.cut(); } - private static class SearchAndOpenFile { - - private final BibEntry entry; - private final BasePanel basePanel; - - public SearchAndOpenFile(final BibEntry entry, final BasePanel basePanel) { - this.entry = entry; - this.basePanel = basePanel; - } - - public void searchAndOpen() { - if (!Globals.prefs.getBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH)) { - /* The search can lead to an unexpected 100% CPU usage which is perceived - as a bug, if the search incidentally starts at a directory with lots - of stuff below. It is now disabled by default. */ - return; - } - - final Set types = ExternalFileTypes.getInstance().getExternalFileTypeSelection(); - final List dirs = basePanel.getBibDatabaseContext().getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences()); - final List extensions = types.stream().map(ExternalFileType::getExtension).collect(Collectors.toList()); - - // Run the search operation: - FileFinder fileFinder = FileFinders.constructFromConfiguration(Globals.prefs.getAutoLinkPreferences()); - try { - List files = fileFinder.findAssociatedFiles(entry, dirs, extensions); - if (!files.isEmpty()) { - Path file = files.get(0); - Optional type = ExternalFileTypes.getInstance().getExternalFileTypeByFile(file); - if (type.isPresent()) { - JabRefDesktop.openExternalFileAnyFormat(file, basePanel.getBibDatabaseContext(), type); - basePanel.output(Localization.lang("External viewer called") + '.'); - } - } - } catch (IOException ex) { - LOGGER.error("Problems with finding/or opening files ", ex); - basePanel.output(Localization.lang("Error") + ": " + ex.getMessage()); - } - } - } - private class GroupTreeListener { @Subscribe diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 6712bfd9777..e93c8c8896a 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -812,7 +812,7 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.SHOW_PDF_VIEWER, new ShowDocumentViewerAction()), factory.createMenuItem(StandardActions.EDIT_ENTRY, new OldDatabaseCommandWrapper(Actions.EDIT, this, stateManager)), - factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OldDatabaseCommandWrapper(Actions.OPEN_CONSOLE, this, stateManager)) + factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OpenConsoleAction(stateManager)) ); }); diff --git a/src/main/java/org/jabref/gui/OpenConsoleAction.java b/src/main/java/org/jabref/gui/OpenConsoleAction.java new file mode 100644 index 00000000000..34cf38b261c --- /dev/null +++ b/src/main/java/org/jabref/gui/OpenConsoleAction.java @@ -0,0 +1,35 @@ +package org.jabref.gui; + +import java.io.IOException; + +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.model.database.BibDatabaseContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + +public class OpenConsoleAction extends SimpleCommand { + + private static final Logger LOGGER = LoggerFactory.getLogger(OpenConsoleAction.class); + private final StateManager stateManager; + + public OpenConsoleAction(StateManager stateManager) { + this.stateManager = stateManager; + + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().flatMap(BibDatabaseContext::getDatabasePath).ifPresent(path -> { + try { + JabRefDesktop.openConsole(path.toFile()); + } catch (IOException e) { + LOGGER.info("Could not open console", e); + } + }); + } +} diff --git a/src/main/java/org/jabref/gui/OpenExternalFileAction.java b/src/main/java/org/jabref/gui/OpenExternalFileAction.java new file mode 100644 index 00000000000..4fd2b376f76 --- /dev/null +++ b/src/main/java/org/jabref/gui/OpenExternalFileAction.java @@ -0,0 +1,53 @@ +package org.jabref.gui; + +import java.util.List; + +import org.jabref.Globals; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.gui.fieldeditors.LinkedFileViewModel; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.entry.BibEntry; +import org.jabref.preferences.PreferencesService; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + +public class OpenExternalFileAction extends SimpleCommand { + + private final DialogService dialogService; + private final StateManager stateManager; + private final PreferencesService preferencesService; + + public OpenExternalFileAction(DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { + this.dialogService = dialogService; + this.stateManager = stateManager; + this.preferencesService = preferencesService; + + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().ifPresent(databaseContext -> { + final List selectedEntries = stateManager.getSelectedEntries(); + + if (selectedEntries.size() != 1) { + dialogService.notify(Localization.lang("This operation requires exactly one item to be selected.")); + return; + } + + final BibEntry entry = selectedEntries.get(0); + + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel( + entry.getFiles().get(0), + entry, + databaseContext, + Globals.TASK_EXECUTOR, + dialogService, + preferencesService.getXMPPreferences(), + preferencesService.getFilePreferences(), + ExternalFileTypes.getInstance()); + linkedFileViewModel.open(); + }); + } +} diff --git a/src/main/java/org/jabref/gui/OpenFolderAction.java b/src/main/java/org/jabref/gui/OpenFolderAction.java new file mode 100644 index 00000000000..d0512071b41 --- /dev/null +++ b/src/main/java/org/jabref/gui/OpenFolderAction.java @@ -0,0 +1,45 @@ +package org.jabref.gui; + +import org.jabref.Globals; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.externalfiletype.ExternalFileTypes; +import org.jabref.gui.fieldeditors.LinkedFileViewModel; +import org.jabref.preferences.PreferencesService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + +public class OpenFolderAction extends SimpleCommand { + + private static final Logger LOGGER = LoggerFactory.getLogger(OpenFolderAction.class); + private final DialogService dialogService; + private final StateManager stateManager; + private final PreferencesService preferencesService; + + public OpenFolderAction(DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { + this.dialogService = dialogService; + this.stateManager = stateManager; + this.preferencesService = preferencesService; + + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().ifPresent(databaseContext -> + stateManager.getSelectedEntries().forEach(entry -> { + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel( + entry.getFiles().get(0), + entry, + databaseContext, + Globals.TASK_EXECUTOR, + dialogService, + preferencesService.getXMPPreferences(), + preferencesService.getFilePreferences(), + ExternalFileTypes.getInstance()); + linkedFileViewModel.openFolder(); + })); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index 935470b1599..2293be5e914 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -85,7 +85,7 @@ public MainTable(MainTableDataModel model, JabRefFrame frame, panel.showAndEdit(entry.getEntry()); } }) - .withContextMenu(entry -> RightClickMenu.create(entry, keyBindingRepository, panel, frame.getDialogService())) + .withContextMenu(entry -> RightClickMenu.create(entry, keyBindingRepository, panel, frame.getDialogService(), Globals.stateManager, Globals.prefs)) .setOnDragDetected(this::handleOnDragDetected) .setOnDragDropped(this::handleOnDragDropped) .setOnDragOver(this::handleOnDragOver) diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index 7029810a2fa..1204706c66e 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -10,6 +10,9 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; +import org.jabref.gui.OpenExternalFileAction; +import org.jabref.gui.OpenFolderAction; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.Actions; import org.jabref.gui.actions.OldCommandWrapper; @@ -27,11 +30,12 @@ import org.jabref.model.entry.field.SpecialField; import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.JabRefPreferences; +import org.jabref.preferences.PreferencesService; import org.jabref.preferences.PreviewPreferences; public class RightClickMenu { - public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingRepository keyBindingRepository, BasePanel panel, DialogService dialogService) { + public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingRepository keyBindingRepository, BasePanel panel, DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { ContextMenu contextMenu = new ContextMenu(); ActionFactory factory = new ActionFactory(keyBindingRepository); @@ -58,8 +62,8 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit contextMenu.getItems().add(new SeparatorMenuItem()); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_FOLDER, getOpenFolderCommand(panel))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_EXTERNAL_FILE, getOpenExternalFileCommand(panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_FOLDER, new OpenFolderAction(dialogService, stateManager, preferencesService))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_EXTERNAL_FILE, new OpenExternalFileAction(dialogService, stateManager, preferencesService))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_URL, getOpenUrlCommand(panel))); contextMenu.getItems().add(new SeparatorMenuItem()); @@ -90,18 +94,6 @@ private static OldCommandWrapper getOpenUrlCommand(BasePanel panel) { return command; } - private static OldCommandWrapper getOpenExternalFileCommand(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.OPEN_EXTERNAL_FILE, panel); - command.setExecutable(isFieldSetForSelectedEntry(StandardField.FILE, panel)); - return command; - } - - private static OldCommandWrapper getOpenFolderCommand(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.OPEN_FOLDER, panel); - command.setExecutable(isFieldSetForSelectedEntry(StandardField.FILE, panel)); - return command; - } - private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService) { Menu copySpecialMenu = factory.createMenu(StandardActions.COPY_MORE); copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_TITLE, new OldCommandWrapper(Actions.COPY_TITLE, panel))); From f664d10470572e00e1f5c91bbc3eec83853abb92 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Tue, 18 Feb 2020 18:41:18 +0100 Subject: [PATCH 003/287] Added OpenUrlAction, Refactored MergeEntriesAction, MergeWitchFetchedEntryAction, AttachFileAction --- src/main/java/org/jabref/gui/BasePanel.java | 71 +----------------- src/main/java/org/jabref/gui/JabRefFrame.java | 2 +- .../org/jabref/gui/OpenConsoleAction.java | 6 +- .../org/jabref/gui/actions/ActionHelper.java | 23 ++++++ .../jabref/gui/filelist/AttachFileAction.java | 57 ++++++++------- .../OpenExternalFileAction.java | 11 ++- .../gui/{ => maintable}/OpenFolderAction.java | 14 ++-- .../jabref/gui/maintable/OpenUrlAction.java | 73 +++++++++++++++++++ .../jabref/gui/maintable/RightClickMenu.java | 49 ++----------- .../gui/mergeentries/MergeEntriesAction.java | 15 ++-- .../MergeWithFetchedEntryAction.java | 24 +++--- 11 files changed, 175 insertions(+), 170 deletions(-) rename src/main/java/org/jabref/gui/{ => maintable}/OpenExternalFileAction.java (82%) rename src/main/java/org/jabref/gui/{ => maintable}/OpenFolderAction.java (82%) create mode 100644 src/main/java/org/jabref/gui/maintable/OpenUrlAction.java diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index f45506934ff..e12ba0a5622 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -10,7 +10,6 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import javax.swing.undo.CannotRedoException; @@ -35,13 +34,11 @@ import org.jabref.gui.cleanup.CleanupAction; import org.jabref.gui.collab.DatabaseChangeMonitor; import org.jabref.gui.collab.DatabaseChangePane; -import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.edit.CopyBibTeXKeyAndLinkAction; import org.jabref.gui.edit.ReplaceStringAction; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; import org.jabref.gui.externalfiles.DownloadFullTextAction; -import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.importer.actions.AppendDatabaseAction; import org.jabref.gui.journals.AbbreviateAction; @@ -49,8 +46,6 @@ import org.jabref.gui.journals.UnabbreviateAction; import org.jabref.gui.maintable.MainTable; import org.jabref.gui.maintable.MainTableDataModel; -import org.jabref.gui.mergeentries.MergeEntriesAction; -import org.jabref.gui.mergeentries.MergeWithFetchedEntryAction; import org.jabref.gui.preview.CitationStyleToClipboardWorker; import org.jabref.gui.specialfields.SpecialFieldDatabaseChangeListener; import org.jabref.gui.specialfields.SpecialFieldValueViewModel; @@ -70,9 +65,6 @@ import org.jabref.logic.pdf.FileAnnotationCache; import org.jabref.logic.search.SearchQuery; import org.jabref.logic.util.UpdateField; -import org.jabref.logic.util.io.FileFinder; -import org.jabref.logic.util.io.FileFinders; -import org.jabref.logic.util.io.FileUtil; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; @@ -84,15 +76,12 @@ import org.jabref.model.database.shared.DatabaseLocation; import org.jabref.model.database.shared.DatabaseSynchronizer; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.FileFieldParser; -import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.EntryChangedEvent; 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.preferences.JabRefPreferences; import com.google.common.eventbus.Subscribe; @@ -281,7 +270,7 @@ private void setupActions() { // The action for cleaning up entry. actions.put(Actions.CLEANUP, cleanUpAction); - actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame, Globals.stateManager).execute()); + // actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame, Globals.stateManager).execute()); // The action for copying the selected entry's key. actions.put(Actions.COPY_KEY, this::copyKey); @@ -311,9 +300,9 @@ private void setupActions() { dbmsSynchronizer.pullChanges(); }); - actions.put(Actions.OPEN_URL, new OpenURLAction()); + // actions.put(Actions.OPEN_URL, new OpenURLAction()); - actions.put(Actions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(this, frame.getDialogService())); + // actions.put(Actions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(this, frame.getDialogService())); actions.put(Actions.REPLACE_ALL, () -> (new ReplaceStringAction(this)).execute()); @@ -1112,60 +1101,6 @@ public void action() { } } - private class OpenURLAction implements BaseAction { - - @Override - public void action() { - final List bes = mainTable.getSelectedEntries(); - if (bes.size() == 1) { - Field field = StandardField.DOI; - Optional link = bes.get(0).getField(StandardField.DOI); - if (bes.get(0).hasField(StandardField.URL)) { - link = bes.get(0).getField(StandardField.URL); - field = StandardField.URL; - } - if (link.isPresent()) { - try { - JabRefDesktop.openExternalViewer(bibDatabaseContext, link.get(), field); - output(Localization.lang("External viewer called") + '.'); - } catch (IOException ex) { - output(Localization.lang("Error") + ": " + ex.getMessage()); - } - } else { - // No URL or DOI found in the "url" and "doi" fields. - // Look for web links in the "file" field as a fallback: - - List files = bes.get(0).getFiles(); - - Optional linkedFile = files.stream() - .filter(file -> (StandardField.URL.getName().equalsIgnoreCase(file.getFileType()) - || StandardField.PS.getName().equalsIgnoreCase(file.getFileType()) - || StandardField.PDF.getName().equalsIgnoreCase(file.getFileType()))) - .findFirst(); - - if (linkedFile.isPresent()) { - - try { - - JabRefDesktop.openExternalFileAnyFormat(bibDatabaseContext, - linkedFile.get().getLink(), - ExternalFileTypes.getInstance().fromLinkedFile(linkedFile.get(), true)); - - output(Localization.lang("External viewer called") + '.'); - } catch (IOException e) { - output(Localization.lang("Could not open link")); - LOGGER.info("Could not open link", e); - } - } else { - output(Localization.lang("No URL defined") + '.'); - } - } - } else { - output(Localization.lang("This operation requires exactly one item to be selected.")); - } - } - } - private class RedoAction implements BaseAction { @Override diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index e93c8c8896a..179855815df 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -749,7 +749,7 @@ private MenuBar createMenu() { quality.getItems().addAll( factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this, dialogService, stateManager)), - factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this, stateManager)), + factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this.getCurrentBasePanel(), dialogService, stateManager)), factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(this, stateManager, Globals.TASK_EXECUTOR)), factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, stateManager)), diff --git a/src/main/java/org/jabref/gui/OpenConsoleAction.java b/src/main/java/org/jabref/gui/OpenConsoleAction.java index 34cf38b261c..2dbfbbc992f 100644 --- a/src/main/java/org/jabref/gui/OpenConsoleAction.java +++ b/src/main/java/org/jabref/gui/OpenConsoleAction.java @@ -2,15 +2,15 @@ import java.io.IOException; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.field.StandardField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.jabref.gui.actions.ActionHelper.needsDatabase; - public class OpenConsoleAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(OpenConsoleAction.class); @@ -19,7 +19,7 @@ public class OpenConsoleAction extends SimpleCommand { public OpenConsoleAction(StateManager stateManager) { this.stateManager = stateManager; - this.executable.bind(needsDatabase(stateManager)); + this.executable.bind(ActionHelper.isFieldSetForSelectedEntry(StandardField.FILE, stateManager)); } @Override diff --git a/src/main/java/org/jabref/gui/actions/ActionHelper.java b/src/main/java/org/jabref/gui/actions/ActionHelper.java index dfd66772a3a..199d959c1f9 100644 --- a/src/main/java/org/jabref/gui/actions/ActionHelper.java +++ b/src/main/java/org/jabref/gui/actions/ActionHelper.java @@ -1,9 +1,14 @@ package org.jabref.gui.actions; +import java.util.Collections; +import java.util.List; + import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanExpression; import org.jabref.gui.StateManager; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.Field; public class ActionHelper { public static BooleanExpression needsDatabase(StateManager stateManager) { @@ -13,4 +18,22 @@ public static BooleanExpression needsDatabase(StateManager stateManager) { public static BooleanExpression needsEntriesSelected(StateManager stateManager) { return Bindings.isNotEmpty(stateManager.getSelectedEntries()); } + + public static BooleanExpression needsEntriesSelected(int numberOfEntries, StateManager stateManager) { + return Bindings.createBooleanBinding( + () -> stateManager.getSelectedEntries().size() == numberOfEntries, + stateManager.getSelectedEntries()); + } + + public static BooleanExpression isFieldSetForSelectedEntry(Field field, StateManager stateManager) { + return isAnyFieldSetForSelectedEntry(Collections.singletonList(field), stateManager); + } + + public static BooleanExpression isAnyFieldSetForSelectedEntry(List fields, StateManager stateManager) { + BibEntry entry = stateManager.getSelectedEntries().get(0); + return Bindings.createBooleanBinding( + () -> !Collections.disjoint(fields, entry.getFields()), + entry.getFieldsObservable(), + stateManager.getSelectedEntries()); + } } diff --git a/src/main/java/org/jabref/gui/filelist/AttachFileAction.java b/src/main/java/org/jabref/gui/filelist/AttachFileAction.java index 51fa192c115..ff9a1ae3bf7 100644 --- a/src/main/java/org/jabref/gui/filelist/AttachFileAction.java +++ b/src/main/java/org/jabref/gui/filelist/AttachFileAction.java @@ -1,12 +1,12 @@ package org.jabref.gui.filelist; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Optional; -import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFilesEditorViewModel; @@ -16,51 +16,58 @@ import org.jabref.model.FieldChange; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; -import org.jabref.preferences.JabRefPreferences; +import org.jabref.preferences.PreferencesService; public class AttachFileAction extends SimpleCommand { private final BasePanel panel; + private final StateManager stateManager; private final DialogService dialogService; + private final PreferencesService preferencesService; - public AttachFileAction(BasePanel panel, DialogService dialogService) { + public AttachFileAction(BasePanel panel, DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { this.panel = panel; + this.stateManager = stateManager; this.dialogService = dialogService; + this.preferencesService = preferencesService; + + this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager)); } @Override public void execute() { - if (panel.getSelectedEntries().size() != 1) { + if (stateManager.getSelectedEntries().size() != 1) { dialogService.notify(Localization.lang("This operation requires exactly one item to be selected.")); return; } - BibEntry entry = panel.getSelectedEntries().get(0); + stateManager.getActiveDatabase().ifPresent(databaseContext -> { + BibEntry entry = stateManager.getSelectedEntries().get(0); - Path workingDirectory = panel.getBibDatabaseContext() - .getFirstExistingFileDir(Globals.prefs.getFilePreferences()) - .orElse(Paths.get(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY))); + Path workingDirectory = databaseContext.getFirstExistingFileDir(preferencesService.getFilePreferences()) + .orElse(preferencesService.getWorkingDir()); - FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() - .withInitialDirectory(workingDirectory) - .build(); + FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() + .withInitialDirectory(workingDirectory) + .build(); - dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(newFile -> { - LinkedFile linkedFile = LinkedFilesEditorViewModel.fromFile(newFile, - panel.getBibDatabaseContext().getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences()), - ExternalFileTypes.getInstance()); + dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(newFile -> { + LinkedFile linkedFile = LinkedFilesEditorViewModel.fromFile(newFile, + databaseContext.getFileDirectoriesAsPaths(preferencesService.getFilePreferences()), + ExternalFileTypes.getInstance()); - LinkedFileEditDialogView dialog = new LinkedFileEditDialogView(linkedFile); + LinkedFileEditDialogView dialog = new LinkedFileEditDialogView(linkedFile); - dialog.showAndWait() - .ifPresent(editedLinkedFile -> { - Optional fieldChange = entry.addFile(editedLinkedFile); - fieldChange.ifPresent(change -> { - UndoableFieldChange ce = new UndoableFieldChange(change); - panel.getUndoManager().addEdit(ce); - panel.markBaseChanged(); + dialog.showAndWait() + .ifPresent(editedLinkedFile -> { + Optional fieldChange = entry.addFile(editedLinkedFile); + fieldChange.ifPresent(change -> { + UndoableFieldChange ce = new UndoableFieldChange(change); + panel.getUndoManager().addEdit(ce); + panel.markBaseChanged(); + }); }); - }); + }); }); } } diff --git a/src/main/java/org/jabref/gui/OpenExternalFileAction.java b/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java similarity index 82% rename from src/main/java/org/jabref/gui/OpenExternalFileAction.java rename to src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java index 4fd2b376f76..6579eed3102 100644 --- a/src/main/java/org/jabref/gui/OpenExternalFileAction.java +++ b/src/main/java/org/jabref/gui/maintable/OpenExternalFileAction.java @@ -1,17 +1,19 @@ -package org.jabref.gui; +package org.jabref.gui.maintable; import java.util.List; import org.jabref.Globals; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.PreferencesService; -import static org.jabref.gui.actions.ActionHelper.needsDatabase; - public class OpenExternalFileAction extends SimpleCommand { private final DialogService dialogService; @@ -23,7 +25,8 @@ public OpenExternalFileAction(DialogService dialogService, StateManager stateMan this.stateManager = stateManager; this.preferencesService = preferencesService; - this.executable.bind(needsDatabase(stateManager)); + this.executable.bind(ActionHelper.isFieldSetForSelectedEntry(StandardField.FILE, stateManager) + .and(ActionHelper.needsEntriesSelected(1, stateManager))); } @Override diff --git a/src/main/java/org/jabref/gui/OpenFolderAction.java b/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java similarity index 82% rename from src/main/java/org/jabref/gui/OpenFolderAction.java rename to src/main/java/org/jabref/gui/maintable/OpenFolderAction.java index d0512071b41..a2c3c211785 100644 --- a/src/main/java/org/jabref/gui/OpenFolderAction.java +++ b/src/main/java/org/jabref/gui/maintable/OpenFolderAction.java @@ -1,19 +1,17 @@ -package org.jabref.gui; +package org.jabref.gui.maintable; import org.jabref.Globals; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.fieldeditors.LinkedFileViewModel; +import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.PreferencesService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.jabref.gui.actions.ActionHelper.needsDatabase; - public class OpenFolderAction extends SimpleCommand { - private static final Logger LOGGER = LoggerFactory.getLogger(OpenFolderAction.class); private final DialogService dialogService; private final StateManager stateManager; private final PreferencesService preferencesService; @@ -23,7 +21,7 @@ public OpenFolderAction(DialogService dialogService, StateManager stateManager, this.stateManager = stateManager; this.preferencesService = preferencesService; - this.executable.bind(needsDatabase(stateManager)); + this.executable.bind(ActionHelper.isFieldSetForSelectedEntry(StandardField.FILE, stateManager)); } @Override diff --git a/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java new file mode 100644 index 00000000000..2e42ec30d41 --- /dev/null +++ b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java @@ -0,0 +1,73 @@ +package org.jabref.gui.maintable; + +import java.io.IOException; +import java.util.List; +import java.util.Optional; + +import javafx.beans.binding.BooleanBinding; + +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.Field; +import org.jabref.model.entry.field.StandardField; + +public class OpenUrlAction extends SimpleCommand { + + private final DialogService dialogService; + private final StateManager stateManager; + + public OpenUrlAction(DialogService dialogService, StateManager stateManager) { + this.dialogService = dialogService; + this.stateManager = stateManager; + + BooleanBinding fieldIsSet = ActionHelper.isFieldSetForSelectedEntry(StandardField.URL, stateManager) + .or(ActionHelper.isFieldSetForSelectedEntry(StandardField.DOI, stateManager) + .or(ActionHelper.isFieldSetForSelectedEntry(StandardField.URI, stateManager) + .or(ActionHelper.isFieldSetForSelectedEntry(StandardField.EPRINT, stateManager)))); + this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager).and(fieldIsSet)); + } + + @Override + public void execute() { + stateManager.getActiveDatabase().ifPresent(databaseContext -> { + final List entries = stateManager.getSelectedEntries(); + + if (entries.size() != 1) { + dialogService.notify(Localization.lang("This operation requires exactly one item to be selected.")); + return; + } + + BibEntry entry = entries.get(0); + + // ToDo: Create dialog or menu to chose which one to open + // URL - DOI - DOI - EPRINT + Optional link = entry.getField(StandardField.EPRINT); + Field field = StandardField.EPRINT; + if (entry.hasField(StandardField.URI)) { + link = entry.getField(StandardField.URI); + field = StandardField.URI; + } + if (entry.hasField(StandardField.DOI)) { + link = entry.getField(StandardField.DOI); + field = StandardField.DOI; + } + if (entry.hasField(StandardField.URL)) { + link = entry.getField(StandardField.URL); + field = StandardField.URL; + } + + if (link.isPresent()) { + try { + JabRefDesktop.openExternalViewer(databaseContext, link.get(), field); + } catch (IOException e) { + dialogService.showErrorDialogAndWait(Localization.lang("Unable to open link."), e); + } + } + }); + } +} diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index 1204706c66e..cabe83d8ab5 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -1,8 +1,5 @@ package org.jabref.gui.maintable; -import java.util.Collections; -import java.util.List; - import javafx.scene.control.ContextMenu; import javafx.scene.control.Menu; import javafx.scene.control.SeparatorMenuItem; @@ -10,8 +7,6 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; -import org.jabref.gui.OpenExternalFileAction; -import org.jabref.gui.OpenFolderAction; import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.Actions; @@ -21,14 +16,12 @@ import org.jabref.gui.filelist.AttachFileAction; import org.jabref.gui.keyboard.KeyBindingRepository; import org.jabref.gui.menus.ChangeEntryTypeMenu; -import org.jabref.gui.mergeentries.FetchAndMergeEntry; +import org.jabref.gui.mergeentries.MergeEntriesAction; +import org.jabref.gui.mergeentries.MergeWithFetchedEntryAction; import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory; import org.jabref.logic.citationstyle.CitationStylePreviewLayout; import org.jabref.logic.citationstyle.PreviewLayout; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.SpecialField; -import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.JabRefPreferences; import org.jabref.preferences.PreferencesService; import org.jabref.preferences.PreviewPreferences; @@ -64,36 +57,18 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_FOLDER, new OpenFolderAction(dialogService, stateManager, preferencesService))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_EXTERNAL_FILE, new OpenExternalFileAction(dialogService, stateManager, preferencesService))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_URL, getOpenUrlCommand(panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_URL, new OpenUrlAction(dialogService, stateManager))); contextMenu.getItems().add(new SeparatorMenuItem()); contextMenu.getItems().add(new ChangeEntryTypeMenu().getChangeEntryTypeMenu(entry.getEntry(), panel.getBibDatabaseContext(), panel.getUndoManager())); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_WITH_FETCHED_ENTRY, getFetchEntryData(panel))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.ATTACH_FILE, new AttachFileAction(panel, dialogService))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, mergeEntries(panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(panel, dialogService, stateManager))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.ATTACH_FILE, new AttachFileAction(panel, dialogService, stateManager, preferencesService))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(panel, dialogService, stateManager))); return contextMenu; } - private static OldCommandWrapper mergeEntries(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.MERGE_ENTRIES, panel); - command.setExecutable(panel.getMainTable().getSelectedEntries().size() == 2); - return command; - } - - private static OldCommandWrapper getFetchEntryData(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.MERGE_WITH_FETCHED_ENTRY, panel); - command.setExecutable(isAnyFieldSetForSelectedEntry(FetchAndMergeEntry.SUPPORTED_FIELDS, panel)); - return command; - } - - private static OldCommandWrapper getOpenUrlCommand(BasePanel panel) { - OldCommandWrapper command = new OldCommandWrapper(Actions.OPEN_URL, panel); - command.setExecutable(isFieldSetForSelectedEntry(StandardField.URL, panel) || isFieldSetForSelectedEntry(StandardField.DOI, panel)); - return command; - } - private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService) { Menu copySpecialMenu = factory.createMenu(StandardActions.COPY_MORE); copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_TITLE, new OldCommandWrapper(Actions.COPY_TITLE, panel))); @@ -120,16 +95,4 @@ private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, Di copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.EXPORT_TO_CLIPBOARD, new ExportToClipboardAction(panel, dialogService))); return copySpecialMenu; } - - private static boolean isFieldSetForSelectedEntry(Field field, BasePanel panel) { - return isAnyFieldSetForSelectedEntry(Collections.singletonList(field), panel); - } - - private static boolean isAnyFieldSetForSelectedEntry(List fields, BasePanel panel) { - if (panel.getMainTable().getSelectedEntries().size() == 1) { - BibEntry entry = panel.getMainTable().getSelectedEntries().get(0); - return !Collections.disjoint(fields, entry.getFields()); - } - return false; - } } diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java index baca427159e..173523860e6 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java @@ -6,8 +6,8 @@ import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; -import org.jabref.gui.JabRefFrame; import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertEntries; @@ -15,23 +15,20 @@ import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; -import static org.jabref.gui.actions.ActionHelper.needsDatabase; - public class MergeEntriesAction extends SimpleCommand { - private final JabRefFrame jabRefFrame; + private final BasePanel basePanel; private final DialogService dialogService; - public MergeEntriesAction(JabRefFrame jabRefFrame, StateManager stateManager) { - this.jabRefFrame = jabRefFrame; - this.dialogService = jabRefFrame.getDialogService(); + public MergeEntriesAction(BasePanel panel, DialogService dialogService, StateManager stateManager) { + this.basePanel = panel; + this.dialogService = dialogService; - this.executable.bind(needsDatabase(stateManager)); + this.executable.bind(ActionHelper.needsEntriesSelected(2, stateManager)); } @Override public void execute() { - BasePanel basePanel = jabRefFrame.getCurrentBasePanel(); // Check if there are two entries selected List selectedEntries = basePanel.getSelectedEntries(); diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java index 2b2edf17017..e67c42b0df2 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeWithFetchedEntryAction.java @@ -3,32 +3,38 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; -import org.jabref.gui.actions.BaseAction; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.OrFields; import org.jabref.model.entry.field.StandardField; -public class MergeWithFetchedEntryAction implements BaseAction { +public class MergeWithFetchedEntryAction extends SimpleCommand { private final BasePanel basePanel; private final DialogService dialogService; + private final StateManager stateManager; - public MergeWithFetchedEntryAction(BasePanel basePanel, DialogService dialogService) { + public MergeWithFetchedEntryAction(BasePanel basePanel, DialogService dialogService, StateManager stateManager) { this.basePanel = basePanel; this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager) + .and(ActionHelper.isAnyFieldSetForSelectedEntry(FetchAndMergeEntry.SUPPORTED_FIELDS, stateManager))); } @Override - public void action() { - if (basePanel.getMainTable().getSelectedEntries().size() == 1) { - BibEntry originalEntry = basePanel.getMainTable().getSelectedEntries().get(0); - new FetchAndMergeEntry(basePanel, Globals.TASK_EXECUTOR).fetchAndMerge(originalEntry); - } else { + public void execute() { + if (stateManager.getSelectedEntries().size() != 1) { dialogService.showInformationDialogAndWait( Localization.lang("Merge entry with %0 information", new OrFields(StandardField.DOI, StandardField.ISBN, StandardField.EPRINT).getDisplayName()), Localization.lang("This operation requires exactly one item to be selected.")); - } + + BibEntry originalEntry = stateManager.getSelectedEntries().get(0); + new FetchAndMergeEntry(basePanel, Globals.TASK_EXECUTOR).fetchAndMerge(originalEntry); } } From b71360bd16ad307ac15b86bee828d0338eee49fd Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Tue, 18 Feb 2020 20:32:52 +0100 Subject: [PATCH 004/287] Refactored SendAsEMailAction --- src/main/java/org/jabref/gui/BasePanel.java | 3 +- src/main/java/org/jabref/gui/JabRefFrame.java | 3 +- .../jabref/gui/maintable/RightClickMenu.java | 3 +- .../jabref/gui/worker/SendAsEMailAction.java | 42 ++++++++++--------- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index e12ba0a5622..528ecc321c8 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -56,7 +56,6 @@ import org.jabref.gui.undo.UndoableInsertEntries; import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.gui.util.DefaultTaskExecutor; -import org.jabref.gui.worker.SendAsEMailAction; import org.jabref.logic.citationstyle.CitationStyleCache; import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.l10n.Localization; @@ -335,7 +334,7 @@ private void setupActions() { entryEditor.previousPreviewStyle(); }); */ - actions.put(Actions.SEND_AS_EMAIL, new SendAsEMailAction(frame)); + // actions.put(Actions.SEND_AS_EMAIL, new SendAsEMailAction(frame)); // actions.put(Actions.WRITE_XMP, new WriteXMPAction(this)::execute); diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 179855815df..2516f2af529 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -104,6 +104,7 @@ import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.DefaultTaskExecutor; +import org.jabref.gui.worker.SendAsEMailAction; import org.jabref.logic.autosaveandbackup.AutosaveManager; import org.jabref.logic.autosaveandbackup.BackupManager; import org.jabref.logic.importer.IdFetcher; @@ -780,7 +781,7 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new OldDatabaseCommandWrapper(Actions.MAKE_KEY, this, stateManager)), factory.createMenuItem(StandardActions.REPLACE_ALL, new OldDatabaseCommandWrapper(Actions.REPLACE_ALL, this, stateManager)), - factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new OldDatabaseCommandWrapper(Actions.SEND_AS_EMAIL, this, stateManager)), + factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new SendAsEMailAction(dialogService, stateManager)), pushToApplicationMenuItem, factory.createSubMenu(StandardActions.ABBREVIATE, diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index cabe83d8ab5..64536acced7 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -19,6 +19,7 @@ import org.jabref.gui.mergeentries.MergeEntriesAction; import org.jabref.gui.mergeentries.MergeWithFetchedEntryAction; import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory; +import org.jabref.gui.worker.SendAsEMailAction; import org.jabref.logic.citationstyle.CitationStylePreviewLayout; import org.jabref.logic.citationstyle.PreviewLayout; import org.jabref.model.entry.field.SpecialField; @@ -40,7 +41,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit contextMenu.getItems().add(new SeparatorMenuItem()); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new OldCommandWrapper(Actions.SEND_AS_EMAIL, panel))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new SendAsEMailAction(dialogService, stateManager))); contextMenu.getItems().add(new SeparatorMenuItem()); diff --git a/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java b/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java index 24877673394..401d64a2420 100644 --- a/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java +++ b/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java @@ -9,15 +9,17 @@ import java.util.List; import org.jabref.Globals; -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.actions.BaseAction; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.util.BackgroundTask; import org.jabref.logic.bibtex.BibEntryWriter; import org.jabref.logic.bibtex.FieldWriter; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.io.FileUtil; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.preferences.JabRefPreferences; @@ -34,49 +36,50 @@ * are opened. This feature is disabled by default and can be switched on at * preferences/external programs */ -public class SendAsEMailAction implements BaseAction { +public class SendAsEMailAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(SendAsEMailAction.class); - private final JabRefFrame frame; + private DialogService dialogService; + private StateManager stateManager; - public SendAsEMailAction(JabRefFrame frame) { - this.frame = frame; + public SendAsEMailAction(DialogService dialogService, StateManager stateManager) { + this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); } @Override - public void action() { + public void execute() { BackgroundTask.wrap(this::sendEmail) - .onSuccess(frame.getDialogService()::notify) + .onSuccess(dialogService::notify) .onFailure(e -> { String message = Localization.lang("Error creating email"); LOGGER.warn(message, e); - frame.getDialogService().notify(message); + dialogService.notify(message); }) .executeWith(Globals.TASK_EXECUTOR); } private String sendEmail() throws Exception { - if (!Desktop.isDesktopSupported()) { + if (!Desktop.isDesktopSupported() || stateManager.getActiveDatabase().isEmpty()) { return Localization.lang("Error creating email"); } - BasePanel panel = frame.getCurrentBasePanel(); - if (panel == null) { - throw new IllegalStateException("Base panel is not available."); - } - if (panel.getSelectedEntries().isEmpty()) { + if (stateManager.getSelectedEntries().isEmpty()) { return Localization.lang("This operation requires one or more entries to be selected."); } StringWriter sw = new StringWriter(); - List bes = panel.getSelectedEntries(); + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); + List bes = stateManager.getSelectedEntries(); // write the entries using sw, which is used later to form the email content BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new FieldWriter(Globals.prefs.getFieldWriterPreferences()), Globals.entryTypesManager); for (BibEntry entry : bes) { try { - bibtexEntryWriter.write(entry, sw, panel.getBibDatabaseContext().getMode()); + bibtexEntryWriter.write(entry, sw, databaseContext.getMode()); } catch (IOException e) { LOGGER.warn("Problem creating BibTeX file for mailing.", e); } @@ -88,8 +91,7 @@ private String sendEmail() throws Exception { // the unofficial "mailto:attachment" property boolean openFolders = JabRefPreferences.getInstance().getBoolean(JabRefPreferences.OPEN_FOLDERS_OF_ATTACHED_FILES); - List fileList = FileUtil.getListOfLinkedFiles(bes, frame.getCurrentBasePanel().getBibDatabaseContext() - .getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); + List fileList = FileUtil.getListOfLinkedFiles(bes, databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); for (Path f : fileList) { attachments.add(f.toAbsolutePath().toString()); if (openFolders) { From 18a3439bad26f09acc39b0594776e1ae6c54bb57 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Tue, 18 Feb 2020 20:41:42 +0100 Subject: [PATCH 005/287] Refactored AttachFileAction --- .../jabref/gui/filelist/AttachFileAction.java | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/jabref/gui/filelist/AttachFileAction.java b/src/main/java/org/jabref/gui/filelist/AttachFileAction.java index ff9a1ae3bf7..fc186923784 100644 --- a/src/main/java/org/jabref/gui/filelist/AttachFileAction.java +++ b/src/main/java/org/jabref/gui/filelist/AttachFileAction.java @@ -14,6 +14,7 @@ import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.l10n.Localization; import org.jabref.model.FieldChange; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.jabref.preferences.PreferencesService; @@ -36,38 +37,43 @@ public AttachFileAction(BasePanel panel, DialogService dialogService, StateManag @Override public void execute() { + if (stateManager.getActiveDatabase().isEmpty()) { + dialogService.notify(Localization.lang("This operation requires exactly an open library.")); + return; + } + if (stateManager.getSelectedEntries().size() != 1) { dialogService.notify(Localization.lang("This operation requires exactly one item to be selected.")); return; } - stateManager.getActiveDatabase().ifPresent(databaseContext -> { - BibEntry entry = stateManager.getSelectedEntries().get(0); + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); + + BibEntry entry = stateManager.getSelectedEntries().get(0); - Path workingDirectory = databaseContext.getFirstExistingFileDir(preferencesService.getFilePreferences()) - .orElse(preferencesService.getWorkingDir()); + Path workingDirectory = databaseContext.getFirstExistingFileDir(preferencesService.getFilePreferences()) + .orElse(preferencesService.getWorkingDir()); - FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() - .withInitialDirectory(workingDirectory) - .build(); + FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() + .withInitialDirectory(workingDirectory) + .build(); - dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(newFile -> { - LinkedFile linkedFile = LinkedFilesEditorViewModel.fromFile(newFile, - databaseContext.getFileDirectoriesAsPaths(preferencesService.getFilePreferences()), - ExternalFileTypes.getInstance()); + dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(newFile -> { + LinkedFile linkedFile = LinkedFilesEditorViewModel.fromFile(newFile, + databaseContext.getFileDirectoriesAsPaths(preferencesService.getFilePreferences()), + ExternalFileTypes.getInstance()); - LinkedFileEditDialogView dialog = new LinkedFileEditDialogView(linkedFile); + LinkedFileEditDialogView dialog = new LinkedFileEditDialogView(linkedFile); - dialog.showAndWait() - .ifPresent(editedLinkedFile -> { - Optional fieldChange = entry.addFile(editedLinkedFile); - fieldChange.ifPresent(change -> { - UndoableFieldChange ce = new UndoableFieldChange(change); - panel.getUndoManager().addEdit(ce); - panel.markBaseChanged(); - }); + dialog.showAndWait() + .ifPresent(editedLinkedFile -> { + Optional fieldChange = entry.addFile(editedLinkedFile); + fieldChange.ifPresent(change -> { + UndoableFieldChange ce = new UndoableFieldChange(change); + panel.getUndoManager().addEdit(ce); + panel.markBaseChanged(); }); - }); + }); }); } } From e1a6e78eaed85d953ea191cefd261dbcdf12bfce Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Tue, 18 Feb 2020 21:41:58 +0100 Subject: [PATCH 006/287] Refactored CitationStyleToClipboardWorkerTest to CopyCitationAction --- src/main/java/org/jabref/gui/BasePanel.java | 14 ++------- src/main/java/org/jabref/gui/JabRefFrame.java | 5 ++-- .../gui/{worker => }/SendAsEMailAction.java | 4 +-- .../jabref/gui/maintable/RightClickMenu.java | 20 +++++++------ ...ardWorker.java => CopyCitationAction.java} | 30 ++++++++++++------- ...rTest.java => CopyCitationActionTest.java} | 14 ++++----- 6 files changed, 43 insertions(+), 44 deletions(-) rename src/main/java/org/jabref/gui/{worker => }/SendAsEMailAction.java (97%) rename src/main/java/org/jabref/gui/preview/{CitationStyleToClipboardWorker.java => CopyCitationAction.java} (89%) rename src/test/java/org/jabref/gui/preview/{CitationStyleToClipboardWorkerTest.java => CopyCitationActionTest.java} (94%) diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 528ecc321c8..0546c35f67c 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -46,7 +46,6 @@ import org.jabref.gui.journals.UnabbreviateAction; import org.jabref.gui.maintable.MainTable; import org.jabref.gui.maintable.MainTableDataModel; -import org.jabref.gui.preview.CitationStyleToClipboardWorker; import org.jabref.gui.specialfields.SpecialFieldDatabaseChangeListener; import org.jabref.gui.specialfields.SpecialFieldValueViewModel; import org.jabref.gui.specialfields.SpecialFieldViewModel; @@ -57,7 +56,6 @@ import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.logic.citationstyle.CitationStyleCache; -import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.l10n.Localization; import org.jabref.logic.layout.Layout; import org.jabref.logic.layout.LayoutHelper; @@ -283,11 +281,13 @@ private void setupActions() { // The action for copying the BibTeX key and the title for the first selected entry actions.put(Actions.COPY_KEY_AND_TITLE, this::copyKeyAndTitle); + /* actions.put(Actions.COPY_CITATION_ASCII_DOC, () -> copyCitationToClipboard(CitationStyleOutputFormat.ASCII_DOC)); actions.put(Actions.COPY_CITATION_XSLFO, () -> copyCitationToClipboard(CitationStyleOutputFormat.XSL_FO)); actions.put(Actions.COPY_CITATION_HTML, () -> copyCitationToClipboard(CitationStyleOutputFormat.HTML)); actions.put(Actions.COPY_CITATION_RTF, () -> copyCitationToClipboard(CitationStyleOutputFormat.RTF)); actions.put(Actions.COPY_CITATION_TEXT, () -> copyCitationToClipboard(CitationStyleOutputFormat.TEXT)); + */ // The action for copying the BibTeX keys as hyperlinks to the urls of the selected entries actions.put(Actions.COPY_KEY_AND_LINK, new CopyBibTeXKeyAndLinkAction(mainTable, Globals.clipboardManager)); @@ -346,16 +346,6 @@ private void setupActions() { actions.put(Actions.DOWNLOAD_FULL_TEXT, new DownloadFullTextAction(this)::execute); } - /** - * Generates and copies citations based on the selected entries to the clipboard - * - * @param outputFormat the desired {@link CitationStyleOutputFormat} - */ - private void copyCitationToClipboard(CitationStyleOutputFormat outputFormat) { - CitationStyleToClipboardWorker worker = new CitationStyleToClipboardWorker(this, outputFormat, dialogService, Globals.clipboardManager, Globals.prefs.getPreviewPreferences()); - worker.copyCitationStyleToClipboard(Globals.TASK_EXECUTOR); - } - /** * Removes the selected entries from the database * diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 2516f2af529..8a325a92b91 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -94,6 +94,7 @@ import org.jabref.gui.metadata.BibtexStringEditorAction; import org.jabref.gui.metadata.PreambleEditor; import org.jabref.gui.preferences.ShowPreferencesAction; +import org.jabref.gui.preview.CopyCitationAction; import org.jabref.gui.protectedterms.ManageProtectedTermsAction; import org.jabref.gui.push.PushToApplicationAction; import org.jabref.gui.push.PushToApplicationsManager; @@ -104,9 +105,9 @@ import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.DefaultTaskExecutor; -import org.jabref.gui.worker.SendAsEMailAction; import org.jabref.logic.autosaveandbackup.AutosaveManager; import org.jabref.logic.autosaveandbackup.BackupManager; +import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.importer.IdFetcher; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.importer.WebFetchers; @@ -706,7 +707,7 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.COPY_CITE_KEY, new OldDatabaseCommandWrapper(Actions.COPY_CITE_KEY, this, stateManager)), factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_TITLE, this, stateManager)), factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_LINK, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new OldDatabaseCommandWrapper(Actions.COPY_CITATION_HTML, this, stateManager)), + factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.clipboardManager, prefs.getPreviewPreferences())), factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(this, dialogService))), factory.createMenuItem(StandardActions.PASTE, new EditAction(Actions.PASTE)), diff --git a/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java b/src/main/java/org/jabref/gui/SendAsEMailAction.java similarity index 97% rename from src/main/java/org/jabref/gui/worker/SendAsEMailAction.java rename to src/main/java/org/jabref/gui/SendAsEMailAction.java index 401d64a2420..06031631dde 100644 --- a/src/main/java/org/jabref/gui/worker/SendAsEMailAction.java +++ b/src/main/java/org/jabref/gui/SendAsEMailAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.worker; +package org.jabref.gui; import java.awt.Desktop; import java.io.IOException; @@ -9,8 +9,6 @@ import java.util.List; import org.jabref.Globals; -import org.jabref.gui.DialogService; -import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.desktop.JabRefDesktop; diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index 64536acced7..bd3d6f3245b 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -7,6 +7,7 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; +import org.jabref.gui.SendAsEMailAction; import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.Actions; @@ -18,8 +19,9 @@ import org.jabref.gui.menus.ChangeEntryTypeMenu; import org.jabref.gui.mergeentries.MergeEntriesAction; import org.jabref.gui.mergeentries.MergeWithFetchedEntryAction; +import org.jabref.gui.preview.CopyCitationAction; import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory; -import org.jabref.gui.worker.SendAsEMailAction; +import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.citationstyle.CitationStylePreviewLayout; import org.jabref.logic.citationstyle.PreviewLayout; import org.jabref.model.entry.field.SpecialField; @@ -34,7 +36,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit ActionFactory factory = new ActionFactory(keyBindingRepository); contextMenu.getItems().add(factory.createMenuItem(StandardActions.COPY, new OldCommandWrapper(Actions.COPY, panel))); - contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService)); + contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService, stateManager)); contextMenu.getItems().add(factory.createMenuItem(StandardActions.PASTE, new OldCommandWrapper(Actions.PASTE, panel))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.CUT, new OldCommandWrapper(Actions.CUT, panel))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.DELETE, new OldCommandWrapper(Actions.DELETE, panel))); @@ -70,7 +72,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit return contextMenu; } - private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService) { + private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService, StateManager stateManager) { Menu copySpecialMenu = factory.createMenu(StandardActions.COPY_MORE); copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_TITLE, new OldCommandWrapper(Actions.COPY_TITLE, panel))); copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY, new OldCommandWrapper(Actions.COPY_KEY, panel))); @@ -82,15 +84,15 @@ private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, Di PreviewPreferences previewPreferences = Globals.prefs.getPreviewPreferences(); PreviewLayout style = previewPreferences.getCurrentPreviewStyle(); if (style instanceof CitationStylePreviewLayout) { - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_HTML, new OldCommandWrapper(Actions.COPY_CITATION_HTML, panel))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_HTML, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); Menu copyCitationMenu = factory.createMenu(StandardActions.COPY_CITATION_MORE); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_TEXT, new OldCommandWrapper(Actions.COPY_CITATION_TEXT, panel))); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_RTF, new OldCommandWrapper(Actions.COPY_CITATION_RTF, panel))); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_ASCII_DOC, new OldCommandWrapper(Actions.COPY_CITATION_ASCII_DOC, panel))); - copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_XSLFO, new OldCommandWrapper(Actions.COPY_CITATION_XSLFO, panel))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_TEXT, new CopyCitationAction(CitationStyleOutputFormat.TEXT, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_RTF, new CopyCitationAction(CitationStyleOutputFormat.RTF, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_ASCII_DOC, new CopyCitationAction(CitationStyleOutputFormat.ASCII_DOC, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); + copyCitationMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_XSLFO, new CopyCitationAction(CitationStyleOutputFormat.XSL_FO, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); copySpecialMenu.getItems().add(copyCitationMenu); } else { - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new OldCommandWrapper(Actions.COPY_CITATION_HTML, panel))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.clipboardManager, previewPreferences))); } copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.EXPORT_TO_CLIPBOARD, new ExportToClipboardAction(panel, dialogService))); diff --git a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java similarity index 89% rename from src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java rename to src/main/java/org/jabref/gui/preview/CopyCitationAction.java index 23a4f056d36..a882225c09b 100644 --- a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java +++ b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java @@ -3,16 +3,18 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javafx.scene.input.ClipboardContent; import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.ClipBoardManager; import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.BackgroundTask; -import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.citationstyle.CitationStyleGenerator; import org.jabref.logic.citationstyle.CitationStyleOutputFormat; import org.jabref.logic.citationstyle.CitationStylePreviewLayout; @@ -32,33 +34,35 @@ * Copies the selected entries and formats them with the selected citation style (or preview), then it is copied to the clipboard. * This worker cannot be reused. */ -public class CitationStyleToClipboardWorker { +public class CopyCitationAction extends SimpleCommand { - private static final Logger LOGGER = LoggerFactory.getLogger(CitationStyleToClipboardWorker.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CopyCitationAction.class); - private final BasePanel basePanel; private final List selectedEntries; + private StateManager stateManager; private final PreviewLayout style; private final String previewStyle; private final CitationStyleOutputFormat outputFormat; private final DialogService dialogService; private final ClipBoardManager clipBoardManager; - public CitationStyleToClipboardWorker(BasePanel basePanel, CitationStyleOutputFormat outputFormat, DialogService dialogService, ClipBoardManager clipBoardManager, PreviewPreferences previewPreferences) { - this.basePanel = basePanel; - this.selectedEntries = basePanel.getSelectedEntries(); + public CopyCitationAction(CitationStyleOutputFormat outputFormat, DialogService dialogService, StateManager stateManager, ClipBoardManager clipBoardManager, PreviewPreferences previewPreferences) { + this.selectedEntries = stateManager.getSelectedEntries(); this.style = previewPreferences.getCurrentPreviewStyle(); this.previewStyle = previewPreferences.getPreviewStyle(); this.outputFormat = outputFormat; this.clipBoardManager = clipBoardManager; this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); } - public void copyCitationStyleToClipboard(TaskExecutor taskExecutor) { + public void execute() { BackgroundTask.wrap(this::generateCitations) .onFailure(ex -> LOGGER.error("Error while copying citations to the clipboard", ex)) .onSuccess(this::setClipBoardContent) - .executeWith(taskExecutor); + .executeWith(Globals.TASK_EXECUTOR); } private List generateCitations() throws IOException { @@ -71,13 +75,17 @@ private List generateCitations() throws IOException { if (styleSource != null) { return CitationStyleGenerator.generateCitations(selectedEntries, styleSource, outputFormat); } else { + if (stateManager.getActiveDatabase().isEmpty()) { + return Collections.emptyList(); + } + StringReader sr = new StringReader(previewStyle.replace("__NEWLINE__", "\n")); LayoutFormatterPreferences layoutFormatterPreferences = Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader); Layout layout = new LayoutHelper(sr, layoutFormatterPreferences).getLayoutFromText(); List citations = new ArrayList<>(selectedEntries.size()); for (BibEntry entry : selectedEntries) { - citations.add(layout.doLayout(entry, basePanel.getDatabase())); + citations.add(layout.doLayout(entry, stateManager.getActiveDatabase().get().getDatabase())); } return citations; } diff --git a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java b/src/test/java/org/jabref/gui/preview/CopyCitationActionTest.java similarity index 94% rename from src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java rename to src/test/java/org/jabref/gui/preview/CopyCitationActionTest.java index 82501d0e182..7dec89193c5 100644 --- a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java +++ b/src/test/java/org/jabref/gui/preview/CopyCitationActionTest.java @@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class CitationStyleToClipboardWorkerTest { +class CopyCitationActionTest { @Test void processPreviewText() throws Exception { @@ -39,7 +39,7 @@ void processPreviewText() throws Exception { OS.NEWLINE + "Abstract: This entry describes a test scenario which may be useful in JabRef. By providing a test entry it is possible to see how certain things will look in this graphical BIB-file mananger. "; - ClipboardContent clipboardContent = CitationStyleToClipboardWorker.processPreview(Arrays.asList(citation, citation)); + ClipboardContent clipboardContent = CopyCitationAction.processPreview(Arrays.asList(citation, citation)); String actual = clipboardContent.getString(); assertEquals(expected, actual); @@ -92,7 +92,7 @@ void processPreviewHtml() throws Exception { "" + OS.NEWLINE + "

"; - ClipboardContent clipboardContent = CitationStyleToClipboardWorker.processPreview(Arrays.asList(citation, citation)); + ClipboardContent clipboardContent = CopyCitationAction.processPreview(Arrays.asList(citation, citation)); String actual = clipboardContent.getString(); assertEquals(expected, actual); } @@ -103,7 +103,7 @@ void processText() throws Exception { "[1]B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016." + OS.NEWLINE; String citation = "[1]B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016." + OS.NEWLINE; - ClipboardContent textTransferable = CitationStyleToClipboardWorker.processText(Arrays.asList(citation, citation)); + ClipboardContent textTransferable = CopyCitationAction.processText(Arrays.asList(citation, citation)); String actual = textTransferable.getString(); assertEquals(expected, actual); @@ -118,7 +118,7 @@ void processRtf() throws Exception { "}"; String citation = "[1]\\tab B. Smith, B. Jones, and J. Williams, \\uc0\\u8220{}Title of the test entry,\\uc0\\u8221{} {\\i{}BibTeX Journal}, vol. 34, no. 3, pp. 45\\uc0\\u8211{}67, Jul. 2016." + OS.NEWLINE; - ClipboardContent content = CitationStyleToClipboardWorker.processRtf(Arrays.asList(citation, citation)); + ClipboardContent content = CopyCitationAction.processRtf(Arrays.asList(citation, citation)); Object actual = content.getRtf(); assertEquals(expected, actual); @@ -191,7 +191,7 @@ void processXslFo() throws Exception { " " + OS.NEWLINE + "" + OS.NEWLINE; - ClipboardContent xmlTransferable = CitationStyleToClipboardWorker.processXslFo(Arrays.asList(citation, citation)); + ClipboardContent xmlTransferable = CopyCitationAction.processXslFo(Arrays.asList(citation, citation)); Object actual = xmlTransferable.get(ClipBoardManager.XML); assertEquals(expected, actual); @@ -221,7 +221,7 @@ void processHtmlAsHtml() throws Exception { String citation = "
" + OS.NEWLINE + "
[1]
B. Smith, B. Jones, and J. Williams, “Title of the test entry,” BibTeX Journal, vol. 34, no. 3, pp. 45–67, Jul. 2016.
" + OS.NEWLINE + "
" + OS.NEWLINE; - ClipboardContent htmlTransferable = CitationStyleToClipboardWorker.processHtml(Arrays.asList(citation, citation)); + ClipboardContent htmlTransferable = CopyCitationAction.processHtml(Arrays.asList(citation, citation)); Object actual = htmlTransferable.getHtml(); assertEquals(expected, actual); From b83d547af4ac0db3a4df350301c2a45487f81054 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Wed, 19 Feb 2020 00:34:41 +0100 Subject: [PATCH 007/287] Refactored CopyBibTeXKeyAndLinkAction, copyTitle, copyCiteKey, copyKey, copyKeyAndTitle to CopyMoreActions --- src/main/java/org/jabref/gui/BasePanel.java | 137 +---------- .../gui/edit/CopyBibTeXKeyAndLinkAction.java | 65 ----- .../org/jabref/gui/edit/CopyMoreAction.java | 228 ++++++++++++++++++ .../jabref/gui/maintable/RightClickMenu.java | 15 +- 4 files changed, 241 insertions(+), 204 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java create mode 100644 src/main/java/org/jabref/gui/edit/CopyMoreAction.java diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 0546c35f67c..9ec4eddf7de 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -1,16 +1,12 @@ package org.jabref.gui; -import java.io.IOException; -import java.io.StringReader; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.stream.Collectors; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; @@ -34,7 +30,6 @@ import org.jabref.gui.cleanup.CleanupAction; import org.jabref.gui.collab.DatabaseChangeMonitor; import org.jabref.gui.collab.DatabaseChangePane; -import org.jabref.gui.edit.CopyBibTeXKeyAndLinkAction; import org.jabref.gui.edit.ReplaceStringAction; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; @@ -57,8 +52,6 @@ import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.logic.citationstyle.CitationStyleCache; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.Layout; -import org.jabref.logic.layout.LayoutHelper; import org.jabref.logic.pdf.FileAnnotationCache; import org.jabref.logic.search.SearchQuery; import org.jabref.logic.util.UpdateField; @@ -270,16 +263,16 @@ private void setupActions() { // actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame, Globals.stateManager).execute()); // The action for copying the selected entry's key. - actions.put(Actions.COPY_KEY, this::copyKey); + // actions.put(Actions.COPY_KEY, this::copyKey); // The action for copying the selected entry's title. - actions.put(Actions.COPY_TITLE, this::copyTitle); + // actions.put(Actions.COPY_TITLE, this::copyTitle); // The action for copying a cite for the selected entry. - actions.put(Actions.COPY_CITE_KEY, this::copyCiteKey); + // actions.put(Actions.COPY_CITE_KEY, this::copyCiteKey); // The action for copying the BibTeX key and the title for the first selected entry - actions.put(Actions.COPY_KEY_AND_TITLE, this::copyKeyAndTitle); + // actions.put(Actions.COPY_KEY_AND_TITLE, this::copyKeyAndTitle); /* actions.put(Actions.COPY_CITATION_ASCII_DOC, () -> copyCitationToClipboard(CitationStyleOutputFormat.ASCII_DOC)); @@ -290,7 +283,7 @@ private void setupActions() { */ // The action for copying the BibTeX keys as hyperlinks to the urls of the selected entries - actions.put(Actions.COPY_KEY_AND_LINK, new CopyBibTeXKeyAndLinkAction(mainTable, Globals.clipboardManager)); + // actions.put(Actions.COPY_KEY_AND_LINK, new CopyBibTeXKeyAndLinkAction(mainTable, Globals.clipboardManager)); actions.put(Actions.MERGE_DATABASE, new AppendDatabaseAction(frame, this)); @@ -385,126 +378,6 @@ public void delete(BibEntry entry) { delete(false, Collections.singletonList(entry)); } - private void copyTitle() { - List selectedBibEntries = mainTable.getSelectedEntries(); - if (!selectedBibEntries.isEmpty()) { - // Collect all non-null titles. - List titles = selectedBibEntries.stream() - .filter(bibEntry -> bibEntry.getTitle().isPresent()) - .map(bibEntry -> bibEntry.getTitle().get()) - .collect(Collectors.toList()); - - if (titles.isEmpty()) { - output(Localization.lang("None of the selected entries have titles.")); - return; - } - final String copiedTitles = String.join("\n", titles); - Globals.clipboardManager.setContent(copiedTitles); - - if (titles.size() == selectedBibEntries.size()) { - // All entries had titles. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedTitles) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined title.", Integer.toString(selectedBibEntries.size() - titles.size()), Integer.toString(selectedBibEntries.size()))); - } - } - } - - private void copyCiteKey() { - List bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - List keys = new ArrayList<>(bes.size()); - // Collect all non-null keys. - for (BibEntry be : bes) { - be.getCiteKeyOptional().ifPresent(keys::add); - } - if (keys.isEmpty()) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - String citeCommand = Optional.ofNullable(Globals.prefs.get(JabRefPreferences.CITE_COMMAND)) - .filter(cite -> cite.contains("\\")) // must contain \ - .orElse("\\cite"); - final String copiedCiteCommand = citeCommand + "{" + String.join(",", keys) + '}'; - Globals.clipboardManager.setContent(copiedCiteCommand); - - if (keys.size() == bes.size()) { - // All entries had keys. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedCiteCommand) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); - } - } - } - - private void copyKey() { - List bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - List keys = new ArrayList<>(bes.size()); - // Collect all non-null keys. - for (BibEntry be : bes) { - be.getCiteKeyOptional().ifPresent(keys::add); - } - if (keys.isEmpty()) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - final String copiedKeys = String.join(",", keys); - Globals.clipboardManager.setContent(copiedKeys); - - if (keys.size() == bes.size()) { - // All entries had keys. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedKeys) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(bes.size() - keys.size()), Integer.toString(bes.size()))); - } - } - } - - private void copyKeyAndTitle() { - List bes = mainTable.getSelectedEntries(); - if (!bes.isEmpty()) { - // OK: in a future version, this string should be configurable to allow arbitrary exports - StringReader sr = new StringReader("\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); - Layout layout; - try { - layout = new LayoutHelper(sr, Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader)) - .getLayoutFromText(); - } catch (IOException e) { - LOGGER.info("Could not get layout", e); - return; - } - - StringBuilder sb = new StringBuilder(); - - int copied = 0; - // Collect all non-null keys. - for (BibEntry be : bes) { - if (be.hasCiteKey()) { - copied++; - sb.append(layout.doLayout(be, bibDatabaseContext.getDatabase())); - } - } - - if (copied == 0) { - output(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - final String copiedKeysAndTitles = sb.toString(); - Globals.clipboardManager.setContent(copiedKeysAndTitles); - - if (copied == bes.size()) { - // All entries had keys. - output(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedKeysAndTitles) + "'."); - } else { - output(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(bes.size() - copied), Integer.toString(bes.size()))); - } - } - } - /** * This method is called from JabRefFrame if a database specific action is requested by the user. Runs the command * if it is defined, or prints an error message to the standard error stream. diff --git a/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java b/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java deleted file mode 100644 index 86e0912400a..00000000000 --- a/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.jabref.gui.edit; - -import java.util.List; -import java.util.stream.Collectors; - -import org.jabref.JabRefGUI; -import org.jabref.gui.ClipBoardManager; -import org.jabref.gui.JabRefDialogService; -import org.jabref.gui.actions.BaseAction; -import org.jabref.gui.maintable.MainTable; -import org.jabref.gui.util.DefaultTaskExecutor; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.OS; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.StandardField; - -/** - * This class will copy each selected entry's BibTeX key as a hyperlink to its url to the clipboard. - * In case an entry doesn't have a BibTeX key it will not be copied. - * In case an entry doesn't have an url this will only copy the BibTeX key. - */ -public class CopyBibTeXKeyAndLinkAction implements BaseAction { - - private final MainTable mainTable; - private final ClipBoardManager clipboardManager; - - public CopyBibTeXKeyAndLinkAction(MainTable mainTable, ClipBoardManager clipboardManager) { - this.mainTable = mainTable; - this.clipboardManager = clipboardManager; - } - - @Override - public void action() throws Exception { - List entries = mainTable.getSelectedEntries(); - if (!entries.isEmpty()) { - StringBuilder sb = new StringBuilder(); - - List entriesWithKey = entries.stream().filter(BibEntry::hasCiteKey).collect(Collectors.toList()); - - if (entriesWithKey.isEmpty()) { - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } - - for (BibEntry entry : entriesWithKey) { - String key = entry.getCiteKeyOptional().get(); - String url = entry.getField(StandardField.URL).orElse(""); - sb.append(url.isEmpty() ? key : String.format("%s", url, key)); - sb.append(OS.NEWLINE); - } - final String keyAndLink = sb.toString(); - DefaultTaskExecutor.runInJavaFXThread(() -> clipboardManager.setHtmlContent(keyAndLink)); - - int copied = entriesWithKey.size(); - int toCopy = entries.size(); - if (copied == toCopy) { - // All entries had keys. - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(keyAndLink) + "'."); - } else { - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", - Long.toString(toCopy - copied), Integer.toString(toCopy))); - } - } - } -} diff --git a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java new file mode 100644 index 00000000000..b40353bc365 --- /dev/null +++ b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java @@ -0,0 +1,228 @@ +package org.jabref.gui.edit; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.jabref.Globals; +import org.jabref.JabRefGUI; +import org.jabref.gui.ClipBoardManager; +import org.jabref.gui.DialogService; +import org.jabref.gui.JabRefDialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.ActionHelper; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.actions.StandardActions; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.layout.Layout; +import org.jabref.logic.layout.LayoutHelper; +import org.jabref.logic.util.OS; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.preferences.JabRefPreferences; +import org.jabref.preferences.PreferencesService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CopyMoreAction extends SimpleCommand { + + private static final Logger LOGGER = LoggerFactory.getLogger(CopyMoreAction.class); + private StandardActions action; + private DialogService dialogService; + private StateManager stateManager; + private final ClipBoardManager clipBoardManager; + private PreferencesService preferencesService; + + public CopyMoreAction(StandardActions action, DialogService dialogService, StateManager stateManager, ClipBoardManager clipBoardManager, PreferencesService preferencesService) { + this.action = action; + this.dialogService = dialogService; + this.stateManager = stateManager; + this.clipBoardManager = clipBoardManager; + this.preferencesService = preferencesService; + + this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); + } + + @Override + public void execute() { + if (stateManager.getActiveDatabase().isEmpty() || stateManager.getSelectedEntries().isEmpty()) { + return; + } + + if (!Arrays.asList( + StandardActions.COPY_TITLE, + StandardActions.COPY_KEY, + StandardActions.COPY_CITE_KEY, + StandardActions.COPY_KEY_AND_TITLE, + StandardActions.COPY_KEY_AND_LINK) + .contains(action)) { + return; + } + + switch (action) { + case COPY_TITLE: copyTitle(); break; + case COPY_KEY: copyKey(); break; + case COPY_CITE_KEY: copyCiteKey(); break; + case COPY_KEY_AND_TITLE: copyKeyAndTitle(); break; + case COPY_KEY_AND_LINK: copyKeyAndLink(); break; + } + } + + private void copyTitle() { + List selectedBibEntries = stateManager.getSelectedEntries(); + + List titles = selectedBibEntries.stream() + .filter(bibEntry -> bibEntry.getTitle().isPresent()) + .map(bibEntry -> bibEntry.getTitle().get()) + .collect(Collectors.toList()); + + if (titles.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have titles.")); + return; + } + + final String copiedTitles = String.join("\n", titles); + clipBoardManager.setContent(copiedTitles); + + if (titles.size() == selectedBibEntries.size()) { + // All entries had titles. + dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedTitles) + "'."); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined title.", Integer.toString(selectedBibEntries.size() - titles.size()), Integer.toString(selectedBibEntries.size()))); + } + } + + private void copyKey() { + List entries = stateManager.getSelectedEntries(); + + List keys = new ArrayList<>(entries.size()); + // Collect all non-null keys. + for (BibEntry entry : entries) { + entry.getCiteKeyOptional().ifPresent(keys::add); + } + if (keys.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + final String copiedKeys = String.join(",", keys); + clipBoardManager.setContent(copiedKeys); + + if (keys.size() == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedKeys) + "'."); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); + } + } + + private void copyCiteKey() { + List entries = stateManager.getSelectedEntries(); + List keys = new ArrayList<>(entries.size()); + + // Collect all non-null keys. + for (BibEntry entry : entries) { + entry.getCiteKeyOptional().ifPresent(keys::add); + } + if (keys.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + String citeCommand = Optional.ofNullable(Globals.prefs.get(JabRefPreferences.CITE_COMMAND)) + .filter(cite -> cite.contains("\\")) // must contain \ + .orElse("\\cite"); + + final String copiedCiteCommand = citeCommand + "{" + String.join(",", keys) + '}'; + clipBoardManager.setContent(copiedCiteCommand); + + if (keys.size() == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedCiteCommand) + "'."); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); + } + } + + private void copyKeyAndTitle() { + List entries = stateManager.getSelectedEntries(); + + // ToDo: in a future version, this string should be configurable to allow arbitrary exports + StringReader layoutString = new StringReader("\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); + Layout layout; + try { + layout = new LayoutHelper(layoutString, preferencesService.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader)) + .getLayoutFromText(); + } catch (IOException e) { + LOGGER.info("Could not get layout", e); + return; + } + + StringBuilder keyAndTitle = new StringBuilder(); + + int copied = 0; + // Collect all non-null keys. + for (BibEntry entry : entries) { + if (entry.hasCiteKey()) { + copied++; + keyAndTitle.append(layout.doLayout(entry, stateManager.getActiveDatabase().get().getDatabase())); + } + } + + if (copied == 0) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + clipBoardManager.setContent(keyAndTitle.toString()); + + if (copied == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(keyAndTitle.toString()) + "'."); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(entries.size() - copied), Integer.toString(entries.size()))); + } + } + + /** + * This method will copy each selected entry's BibTeX key as a hyperlink to its url to the clipboard. + * In case an entry doesn't have a BibTeX key it will not be copied. + * In case an entry doesn't have an url this will only copy the BibTeX key. + */ + private void copyKeyAndLink() { + List entries = stateManager.getSelectedEntries(); + + StringBuilder keyAndLink = new StringBuilder(); + + List entriesWithKey = entries.stream().filter(BibEntry::hasCiteKey).collect(Collectors.toList()); + + if (entriesWithKey.isEmpty()) { + JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } + + for (BibEntry entry : entriesWithKey) { + String key = entry.getCiteKeyOptional().get(); + String url = entry.getField(StandardField.URL).orElse(""); + keyAndLink.append(url.isEmpty() ? key : String.format("%s", url, key)); + keyAndLink.append(OS.NEWLINE); + } + + clipBoardManager.setHtmlContent(keyAndLink.toString()); + + int copied = entriesWithKey.size(); + int toCopy = entries.size(); + if (copied == toCopy) { + // All entries had keys. + JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(keyAndLink.toString()) + "'."); + } else { + JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Long.toString(toCopy - copied), Integer.toString(toCopy))); + } + } +} diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index bd3d6f3245b..e7e8b4f875f 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -13,6 +13,7 @@ import org.jabref.gui.actions.Actions; import org.jabref.gui.actions.OldCommandWrapper; import org.jabref.gui.actions.StandardActions; +import org.jabref.gui.edit.CopyMoreAction; import org.jabref.gui.exporter.ExportToClipboardAction; import org.jabref.gui.filelist.AttachFileAction; import org.jabref.gui.keyboard.KeyBindingRepository; @@ -36,7 +37,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit ActionFactory factory = new ActionFactory(keyBindingRepository); contextMenu.getItems().add(factory.createMenuItem(StandardActions.COPY, new OldCommandWrapper(Actions.COPY, panel))); - contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService, stateManager)); + contextMenu.getItems().add(createCopySubMenu(panel, factory, dialogService, stateManager, preferencesService)); contextMenu.getItems().add(factory.createMenuItem(StandardActions.PASTE, new OldCommandWrapper(Actions.PASTE, panel))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.CUT, new OldCommandWrapper(Actions.CUT, panel))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.DELETE, new OldCommandWrapper(Actions.DELETE, panel))); @@ -72,13 +73,13 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit return contextMenu; } - private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService, StateManager stateManager) { + private static Menu createCopySubMenu(BasePanel panel, ActionFactory factory, DialogService dialogService, StateManager stateManager, PreferencesService preferencesService) { Menu copySpecialMenu = factory.createMenu(StandardActions.COPY_MORE); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_TITLE, new OldCommandWrapper(Actions.COPY_TITLE, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY, new OldCommandWrapper(Actions.COPY_KEY, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITE_KEY, new OldCommandWrapper(Actions.COPY_CITE_KEY, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new OldCommandWrapper(Actions.COPY_KEY_AND_TITLE, panel))); - copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new OldCommandWrapper(Actions.COPY_KEY_AND_LINK, panel))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_TITLE, new CopyMoreAction(StandardActions.COPY_TITLE, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY, new CopyMoreAction(StandardActions.COPY_KEY, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_CITE_KEY, new CopyMoreAction(StandardActions.COPY_CITE_KEY, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new CopyMoreAction(StandardActions.COPY_KEY_AND_TITLE, dialogService, stateManager, Globals.clipboardManager, preferencesService))); + copySpecialMenu.getItems().add(factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new CopyMoreAction(StandardActions.COPY_KEY_AND_LINK, dialogService, stateManager, Globals.clipboardManager, preferencesService))); // the submenu will behave dependent on what style is currently selected (citation/preview) PreviewPreferences previewPreferences = Globals.prefs.getPreviewPreferences(); From def0e67d43a7d604479bf17ba125f0dae43e673e Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Wed, 19 Feb 2020 17:11:58 +0100 Subject: [PATCH 008/287] l10n and some minor corrections --- src/main/java/org/jabref/gui/JabRefFrame.java | 6 +- .../org/jabref/gui/SendAsEMailAction.java | 20 +-- .../org/jabref/gui/edit/CopyMoreAction.java | 137 ++++++++++-------- ...geAction.java => PreviewSwitchAction.java} | 4 +- src/main/resources/l10n/JabRef_en.properties | 7 +- 5 files changed, 91 insertions(+), 83 deletions(-) rename src/main/java/org/jabref/gui/entryeditor/{EntryEditorPreviewChangeAction.java => PreviewSwitchAction.java} (80%) diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 8a325a92b91..0643f67c6a4 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -62,7 +62,7 @@ import org.jabref.gui.edit.ManageKeywordsAction; import org.jabref.gui.edit.MassSetFieldsAction; import org.jabref.gui.edit.OpenBrowserAction; -import org.jabref.gui.entryeditor.EntryEditorPreviewChangeAction; +import org.jabref.gui.entryeditor.PreviewSwitchAction; import org.jabref.gui.exporter.ExportCommand; import org.jabref.gui.exporter.ExportToClipboardAction; import org.jabref.gui.exporter.ManageCustomExportsAction; @@ -807,8 +807,8 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new EntryEditorPreviewChangeAction(EntryEditorPreviewChangeAction.Direction.NEXT, this, stateManager)), - factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new EntryEditorPreviewChangeAction(EntryEditorPreviewChangeAction.Direction.PREVIOUS, this, stateManager)), + factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.NEXT, this, stateManager)), + factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new PreviewSwitchAction(PreviewSwitchAction.Direction.PREVIOUS, this, stateManager)), new SeparatorMenuItem(), diff --git a/src/main/java/org/jabref/gui/SendAsEMailAction.java b/src/main/java/org/jabref/gui/SendAsEMailAction.java index 06031631dde..08f412b6a28 100644 --- a/src/main/java/org/jabref/gui/SendAsEMailAction.java +++ b/src/main/java/org/jabref/gui/SendAsEMailAction.java @@ -68,16 +68,16 @@ private String sendEmail() throws Exception { return Localization.lang("This operation requires one or more entries to be selected."); } - StringWriter sw = new StringWriter(); + StringWriter rawEntries = new StringWriter(); BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); - List bes = stateManager.getSelectedEntries(); + List entries = stateManager.getSelectedEntries(); // write the entries using sw, which is used later to form the email content BibEntryWriter bibtexEntryWriter = new BibEntryWriter(new FieldWriter(Globals.prefs.getFieldWriterPreferences()), Globals.entryTypesManager); - for (BibEntry entry : bes) { + for (BibEntry entry : entries) { try { - bibtexEntryWriter.write(entry, sw, databaseContext.getMode()); + bibtexEntryWriter.write(entry, rawEntries, databaseContext.getMode()); } catch (IOException e) { LOGGER.warn("Problem creating BibTeX file for mailing.", e); } @@ -89,19 +89,19 @@ private String sendEmail() throws Exception { // the unofficial "mailto:attachment" property boolean openFolders = JabRefPreferences.getInstance().getBoolean(JabRefPreferences.OPEN_FOLDERS_OF_ATTACHED_FILES); - List fileList = FileUtil.getListOfLinkedFiles(bes, databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); - for (Path f : fileList) { - attachments.add(f.toAbsolutePath().toString()); + List fileList = FileUtil.getListOfLinkedFiles(entries, databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFilePreferences())); + for (Path path : fileList) { + attachments.add(path.toAbsolutePath().toString()); if (openFolders) { try { - JabRefDesktop.openFolderAndSelectFile(f.toAbsolutePath()); + JabRefDesktop.openFolderAndSelectFile(path.toAbsolutePath()); } catch (IOException e) { LOGGER.debug("Cannot open file", e); } } } - String mailTo = "?Body=".concat(sw.getBuffer().toString()); + String mailTo = "?Body=".concat(rawEntries.getBuffer().toString()); mailTo = mailTo.concat("&Subject="); mailTo = mailTo.concat(JabRefPreferences.getInstance().get(JabRefPreferences.EMAIL_SUBJECT)); for (String path : attachments) { @@ -114,6 +114,6 @@ private String sendEmail() throws Exception { Desktop desktop = Desktop.getDesktop(); desktop.mail(uriMailTo); - return String.format("%s: %d", Localization.lang("Entries added to an email"), bes.size()); + return String.format("%s: %d", Localization.lang("Entries added to an email"), entries.size()); } } diff --git a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java index b40353bc365..0026bfcb374 100644 --- a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java +++ b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java @@ -2,14 +2,11 @@ import java.io.IOException; import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import org.jabref.Globals; -import org.jabref.JabRefGUI; import org.jabref.gui.ClipBoardManager; import org.jabref.gui.DialogService; import org.jabref.gui.JabRefDialogService; @@ -54,22 +51,24 @@ public void execute() { return; } - if (!Arrays.asList( - StandardActions.COPY_TITLE, - StandardActions.COPY_KEY, - StandardActions.COPY_CITE_KEY, - StandardActions.COPY_KEY_AND_TITLE, - StandardActions.COPY_KEY_AND_LINK) - .contains(action)) { - return; - } - switch (action) { - case COPY_TITLE: copyTitle(); break; - case COPY_KEY: copyKey(); break; - case COPY_CITE_KEY: copyCiteKey(); break; - case COPY_KEY_AND_TITLE: copyKeyAndTitle(); break; - case COPY_KEY_AND_LINK: copyKeyAndLink(); break; + case COPY_TITLE: + copyTitle(); + break; + case COPY_KEY: + copyKey(); + break; + case COPY_CITE_KEY: + copyCiteKey(); + break; + case COPY_KEY_AND_TITLE: + copyKeyAndTitle(); + break; + case COPY_KEY_AND_LINK: + copyKeyAndLink(); + break; + default: + LOGGER.info("Unknown copy command."); } } @@ -91,44 +90,50 @@ private void copyTitle() { if (titles.size() == selectedBibEntries.size()) { // All entries had titles. - dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedTitles) + "'."); + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(copiedTitles))); } else { - dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined title.", Integer.toString(selectedBibEntries.size() - titles.size()), Integer.toString(selectedBibEntries.size()))); + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined title.", + Integer.toString(selectedBibEntries.size() - titles.size()), Integer.toString(selectedBibEntries.size()))); } } private void copyKey() { List entries = stateManager.getSelectedEntries(); - List keys = new ArrayList<>(entries.size()); - // Collect all non-null keys. - for (BibEntry entry : entries) { - entry.getCiteKeyOptional().ifPresent(keys::add); - } - if (keys.isEmpty()) { - dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); - return; - } + // Collect all non-null keys. + List keys = entries.stream() + .filter(entry -> entry.getCiteKeyOptional().isPresent()) + .map(entry -> entry.getCiteKeyOptional().get()) + .collect(Collectors.toList()); + + if (keys.isEmpty()) { + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); + return; + } - final String copiedKeys = String.join(",", keys); - clipBoardManager.setContent(copiedKeys); + final String copiedKeys = String.join(",", keys); + clipBoardManager.setContent(copiedKeys); - if (keys.size() == entries.size()) { - // All entries had keys. - dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedKeys) + "'."); - } else { - dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); - } + if (keys.size() == entries.size()) { + // All entries had keys. + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(copiedKeys))); + } else { + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); + } } private void copyCiteKey() { List entries = stateManager.getSelectedEntries(); - List keys = new ArrayList<>(entries.size()); // Collect all non-null keys. - for (BibEntry entry : entries) { - entry.getCiteKeyOptional().ifPresent(keys::add); - } + List keys = entries.stream() + .filter(entry -> entry.getCiteKeyOptional().isPresent()) + .map(entry -> entry.getCiteKeyOptional().get()) + .collect(Collectors.toList()); + if (keys.isEmpty()) { dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); return; @@ -143,66 +148,71 @@ private void copyCiteKey() { if (keys.size() == entries.size()) { // All entries had keys. - dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(copiedCiteCommand) + "'."); + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(copiedCiteCommand))); } else { - dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); } } private void copyKeyAndTitle() { List entries = stateManager.getSelectedEntries(); - // ToDo: in a future version, this string should be configurable to allow arbitrary exports + // ToDo: this string should be configurable to allow arbitrary exports StringReader layoutString = new StringReader("\\bibtexkey - \\begin{title}\\format[RemoveBrackets]{\\title}\\end{title}\n"); Layout layout; try { - layout = new LayoutHelper(layoutString, preferencesService.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader)) - .getLayoutFromText(); + layout = new LayoutHelper(layoutString, preferencesService.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader)).getLayoutFromText(); } catch (IOException e) { - LOGGER.info("Could not get layout", e); + LOGGER.info("Could not get layout.", e); return; } StringBuilder keyAndTitle = new StringBuilder(); - int copied = 0; + int entriesWithKeys = 0; // Collect all non-null keys. for (BibEntry entry : entries) { if (entry.hasCiteKey()) { - copied++; + entriesWithKeys++; keyAndTitle.append(layout.doLayout(entry, stateManager.getActiveDatabase().get().getDatabase())); } } - if (copied == 0) { + if (entriesWithKeys == 0) { dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); return; } clipBoardManager.setContent(keyAndTitle.toString()); - if (copied == entries.size()) { + if (entriesWithKeys == entries.size()) { // All entries had keys. - dialogService.notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(keyAndTitle.toString()) + "'."); + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(keyAndTitle.toString()))); } else { - dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", Integer.toString(entries.size() - copied), Integer.toString(entries.size()))); + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Integer.toString(entries.size() - entriesWithKeys), Integer.toString(entries.size()))); } } /** - * This method will copy each selected entry's BibTeX key as a hyperlink to its url to the clipboard. - * In case an entry doesn't have a BibTeX key it will not be copied. - * In case an entry doesn't have an url this will only copy the BibTeX key. + * This method will copy each selected entry's BibTeX key as a hyperlink to its url to the clipboard. In case an + * entry doesn't have a BibTeX key it will not be copied. In case an entry doesn't have an url this will only copy + * the BibTeX key. */ private void copyKeyAndLink() { List entries = stateManager.getSelectedEntries(); StringBuilder keyAndLink = new StringBuilder(); - List entriesWithKey = entries.stream().filter(BibEntry::hasCiteKey).collect(Collectors.toList()); + List entriesWithKey = entries.stream() + .filter(BibEntry::hasCiteKey) + .collect(Collectors.toList()); if (entriesWithKey.isEmpty()) { - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("None of the selected entries have BibTeX keys.")); + dialogService.notify(Localization.lang("None of the selected entries have BibTeX keys.")); return; } @@ -215,14 +225,13 @@ private void copyKeyAndLink() { clipBoardManager.setHtmlContent(keyAndLink.toString()); - int copied = entriesWithKey.size(); - int toCopy = entries.size(); - if (copied == toCopy) { + if (entriesWithKey.size() == entries.size()) { // All entries had keys. - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Copied") + " '" + JabRefDialogService.shortenDialogMessage(keyAndLink.toString()) + "'."); + dialogService.notify(Localization.lang("Copied '%0' to clipboard.", + JabRefDialogService.shortenDialogMessage(keyAndLink.toString()))); } else { - JabRefGUI.getMainFrame().getDialogService().notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", - Long.toString(toCopy - copied), Integer.toString(toCopy))); + dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined BibTeX key.", + Long.toString(entries.size() - entriesWithKey.size()), Integer.toString(entries.size()))); } } } diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreviewChangeAction.java b/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java similarity index 80% rename from src/main/java/org/jabref/gui/entryeditor/EntryEditorPreviewChangeAction.java rename to src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java index d6f0ce47ea7..03247c4fdd0 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreviewChangeAction.java +++ b/src/main/java/org/jabref/gui/entryeditor/PreviewSwitchAction.java @@ -6,14 +6,14 @@ import static org.jabref.gui.actions.ActionHelper.needsDatabase; -public class EntryEditorPreviewChangeAction extends SimpleCommand { +public class PreviewSwitchAction extends SimpleCommand { public enum Direction { PREVIOUS, NEXT } private final JabRefFrame frame; private final Direction direction; - public EntryEditorPreviewChangeAction(Direction direction, JabRefFrame frame, StateManager stateManager) { + public PreviewSwitchAction(Direction direction, JabRefFrame frame, StateManager stateManager) { this.frame = frame; this.direction = direction; diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 7b0b9e6ec57..4f93dc17e6f 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -171,7 +171,6 @@ Could\ not\ import\ preferences=Could not import preferences Could\ not\ instantiate\ %0=Could not instantiate %0 Could\ not\ instantiate\ %0\ %1=Could not instantiate %0 %1 Could\ not\ instantiate\ %0.\ Have\ you\ chosen\ the\ correct\ package\ path?=Could not instantiate %0. Have you chosen the correct package path? -Could\ not\ open\ link=Could not open link Could\ not\ print\ preview=Could not print preview @@ -334,8 +333,6 @@ External\ file\ links=External file links External\ programs=External programs -External\ viewer\ called=External viewer called - Field=Field field=field @@ -569,7 +566,6 @@ No\ journal\ names\ could\ be\ unabbreviated.=No journal names could be unabbrev Open\ PDF=Open PDF -No\ URL\ defined=No URL defined not=not not\ found=not found @@ -2098,3 +2094,6 @@ Invalid\ regular\ expression.=Invalid regular expression. Keyword\ delimiter=Keyword delimiter Hierarchical\ keyword\ delimiter=Hierarchical keyword delimiter Escape\ ampersands=Escape ampersands + +Copied\ '%0'\ to\ clipboard.=Copied '%0' to clipboard. +This\ operation\ requires\ exactly\ an\ open\ library.=This operation requires exactly an open library. From bca3a0b9f0767c5dcf79adb8ad57f63c50233372 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Thu, 20 Feb 2020 14:08:32 +0100 Subject: [PATCH 009/287] Refactored ActionHelper, removed some deprecated Actions and minor corrections --- src/main/java/org/jabref/gui/BasePanel.java | 40 ------------------- src/main/java/org/jabref/gui/JabRefFrame.java | 13 +++--- .../org/jabref/gui/OpenConsoleAction.java | 3 +- .../org/jabref/gui/actions/ActionHelper.java | 2 +- .../java/org/jabref/gui/actions/Actions.java | 20 ---------- .../org/jabref/gui/edit/CopyMoreAction.java | 8 ++-- .../jabref/gui/maintable/OpenUrlAction.java | 9 ++--- .../jabref/gui/maintable/RightClickMenu.java | 2 +- .../gui/mergeentries/MergeEntriesAction.java | 28 ++++++++----- .../gui/preview/CopyCitationAction.java | 2 +- 10 files changed, 36 insertions(+), 91 deletions(-) diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 9ec4eddf7de..952b9785c23 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -260,31 +260,6 @@ private void setupActions() { // The action for cleaning up entry. actions.put(Actions.CLEANUP, cleanUpAction); - // actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame, Globals.stateManager).execute()); - - // The action for copying the selected entry's key. - // actions.put(Actions.COPY_KEY, this::copyKey); - - // The action for copying the selected entry's title. - // actions.put(Actions.COPY_TITLE, this::copyTitle); - - // The action for copying a cite for the selected entry. - // actions.put(Actions.COPY_CITE_KEY, this::copyCiteKey); - - // The action for copying the BibTeX key and the title for the first selected entry - // actions.put(Actions.COPY_KEY_AND_TITLE, this::copyKeyAndTitle); - - /* - actions.put(Actions.COPY_CITATION_ASCII_DOC, () -> copyCitationToClipboard(CitationStyleOutputFormat.ASCII_DOC)); - actions.put(Actions.COPY_CITATION_XSLFO, () -> copyCitationToClipboard(CitationStyleOutputFormat.XSL_FO)); - actions.put(Actions.COPY_CITATION_HTML, () -> copyCitationToClipboard(CitationStyleOutputFormat.HTML)); - actions.put(Actions.COPY_CITATION_RTF, () -> copyCitationToClipboard(CitationStyleOutputFormat.RTF)); - actions.put(Actions.COPY_CITATION_TEXT, () -> copyCitationToClipboard(CitationStyleOutputFormat.TEXT)); - */ - - // The action for copying the BibTeX keys as hyperlinks to the urls of the selected entries - // actions.put(Actions.COPY_KEY_AND_LINK, new CopyBibTeXKeyAndLinkAction(mainTable, Globals.clipboardManager)); - actions.put(Actions.MERGE_DATABASE, new AppendDatabaseAction(frame, this)); actions.put(Actions.PULL_CHANGES_FROM_SHARED_DATABASE, () -> { @@ -292,10 +267,6 @@ private void setupActions() { dbmsSynchronizer.pullChanges(); }); - // actions.put(Actions.OPEN_URL, new OpenURLAction()); - - // actions.put(Actions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(this, frame.getDialogService())); - actions.put(Actions.REPLACE_ALL, () -> (new ReplaceStringAction(this)).execute()); actions.put(new SpecialFieldValueViewModel(SpecialField.RELEVANCE.getValues().get(0)).getCommand(), @@ -320,17 +291,6 @@ private void setupActions() { new SpecialFieldViewModel(SpecialField.READ_STATUS, undoManager).getSpecialFieldAction(status, this.frame)); } - /* actions.put(Actions.NEXT_PREVIEW_STYLE, () -> { - entryEditor.nextPreviewStyle(); - }); - actions.put(Actions.PREVIOUS_PREVIEW_STYLE, () -> { - entryEditor.previousPreviewStyle(); - }); */ - - // actions.put(Actions.SEND_AS_EMAIL, new SendAsEMailAction(frame)); - - // actions.put(Actions.WRITE_XMP, new WriteXMPAction(this)::execute); - actions.put(Actions.ABBREVIATE_DEFAULT, new AbbreviateAction(this, AbbreviationType.DEFAULT)); actions.put(Actions.ABBREVIATE_MEDLINE, new AbbreviateAction(this, AbbreviationType.MEDLINE)); actions.put(Actions.ABBREVIATE_SHORTEST_UNIQUE, new AbbreviateAction(this, AbbreviationType.SHORTEST_UNIQUE)); diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 771e769e7ed..f30ff15512c 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -60,6 +60,7 @@ import org.jabref.gui.dialogs.AutosaveUIManager; import org.jabref.gui.documentviewer.ShowDocumentViewerAction; import org.jabref.gui.duplicationFinder.DuplicateSearch; +import org.jabref.gui.edit.CopyMoreAction; import org.jabref.gui.edit.ManageKeywordsAction; import org.jabref.gui.edit.MassSetFieldsAction; import org.jabref.gui.edit.OpenBrowserAction; @@ -703,11 +704,11 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.COPY, new EditAction(Actions.COPY)), factory.createSubMenu(StandardActions.COPY_MORE, - factory.createMenuItem(StandardActions.COPY_TITLE, new OldDatabaseCommandWrapper(Actions.COPY_TITLE, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY, new OldDatabaseCommandWrapper(Actions.COPY_KEY, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_CITE_KEY, new OldDatabaseCommandWrapper(Actions.COPY_CITE_KEY, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_TITLE, this, stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_LINK, this, stateManager)), + factory.createMenuItem(StandardActions.COPY_TITLE, new CopyMoreAction(StandardActions.COPY_TITLE, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_KEY, new CopyMoreAction(StandardActions.COPY_KEY, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_CITE_KEY, new CopyMoreAction(StandardActions.COPY_CITE_KEY, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new CopyMoreAction(StandardActions.COPY_KEY_AND_TITLE, dialogService, stateManager, Globals.clipboardManager, prefs)), + factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new CopyMoreAction(StandardActions.COPY_KEY_AND_LINK, dialogService, stateManager, Globals.clipboardManager, prefs)), factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new CopyCitationAction(CitationStyleOutputFormat.HTML, dialogService, stateManager, Globals.clipboardManager, prefs.getPreviewPreferences())), factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(this, dialogService))), @@ -752,7 +753,7 @@ private MenuBar createMenu() { quality.getItems().addAll( factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this, dialogService, stateManager)), - factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this.getCurrentBasePanel(), dialogService, stateManager)), + factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(dialogService, stateManager)), factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(this, stateManager, Globals.TASK_EXECUTOR)), factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, stateManager)), diff --git a/src/main/java/org/jabref/gui/OpenConsoleAction.java b/src/main/java/org/jabref/gui/OpenConsoleAction.java index 2dbfbbc992f..ce634dd73e5 100644 --- a/src/main/java/org/jabref/gui/OpenConsoleAction.java +++ b/src/main/java/org/jabref/gui/OpenConsoleAction.java @@ -6,7 +6,6 @@ import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.entry.field.StandardField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,7 +18,7 @@ public class OpenConsoleAction extends SimpleCommand { public OpenConsoleAction(StateManager stateManager) { this.stateManager = stateManager; - this.executable.bind(ActionHelper.isFieldSetForSelectedEntry(StandardField.FILE, stateManager)); + this.executable.bind(ActionHelper.needsDatabase(stateManager)); } @Override diff --git a/src/main/java/org/jabref/gui/actions/ActionHelper.java b/src/main/java/org/jabref/gui/actions/ActionHelper.java index 199d959c1f9..01e23d67e22 100644 --- a/src/main/java/org/jabref/gui/actions/ActionHelper.java +++ b/src/main/java/org/jabref/gui/actions/ActionHelper.java @@ -32,7 +32,7 @@ public static BooleanExpression isFieldSetForSelectedEntry(Field field, StateMan public static BooleanExpression isAnyFieldSetForSelectedEntry(List fields, StateManager stateManager) { BibEntry entry = stateManager.getSelectedEntries().get(0); return Bindings.createBooleanBinding( - () -> !Collections.disjoint(fields, entry.getFields()), + () -> entry.getFields().stream().anyMatch(fields::contains), entry.getFieldsObservable(), stateManager.getSelectedEntries()); } diff --git a/src/main/java/org/jabref/gui/actions/Actions.java b/src/main/java/org/jabref/gui/actions/Actions.java index 49040b8e00b..a2bbb17e58f 100644 --- a/src/main/java/org/jabref/gui/actions/Actions.java +++ b/src/main/java/org/jabref/gui/actions/Actions.java @@ -11,16 +11,6 @@ public enum Actions { ADD_FILE_LINK, CLEANUP, COPY, - COPY_CITATION_ASCII_DOC, - COPY_CITATION_XSLFO, - COPY_CITATION_HTML, - COPY_CITATION_RTF, - COPY_CITATION_TEXT, - COPY_KEY, - COPY_CITE_KEY, - COPY_KEY_AND_TITLE, - COPY_KEY_AND_LINK, - COPY_TITLE, CUT, DELETE, DOWNLOAD_FULL_TEXT, @@ -31,15 +21,7 @@ public enum Actions { MAKE_KEY, MANAGE_SELECTORS, MERGE_DATABASE, - MERGE_ENTRIES, - MERGE_WITH_FETCHED_ENTRY, - NEXT_PREVIEW_STYLE, - OPEN_CONSOLE, - OPEN_EXTERNAL_FILE, - OPEN_FOLDER, - OPEN_URL, PASTE, - PREVIOUS_PREVIEW_STYLE, PULL_CHANGES_FROM_SHARED_DATABASE, REDO, REPLACE_ALL, @@ -47,11 +29,9 @@ public enum Actions { SAVE_AS, SAVE_SELECTED_AS_PLAIN, SELECT_ALL, - SEND_AS_EMAIL, TOGGLE_GROUPS, UNABBREVIATE, UNDO, - WRITE_XMP, PRINT_PREVIEW, TOGGLE_PRINTED, CLEAR_PRIORITY, diff --git a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java index 0026bfcb374..6ee6db5c95f 100644 --- a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java +++ b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java @@ -29,11 +29,11 @@ public class CopyMoreAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(CopyMoreAction.class); - private StandardActions action; - private DialogService dialogService; - private StateManager stateManager; + private final StandardActions action; + private final DialogService dialogService; + private final StateManager stateManager; private final ClipBoardManager clipBoardManager; - private PreferencesService preferencesService; + private final PreferencesService preferencesService; public CopyMoreAction(StandardActions action, DialogService dialogService, StateManager stateManager, ClipBoardManager clipBoardManager, PreferencesService preferencesService) { this.action = action; diff --git a/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java index 2e42ec30d41..cfcd40b262c 100644 --- a/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java +++ b/src/main/java/org/jabref/gui/maintable/OpenUrlAction.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.Optional; -import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.BooleanExpression; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; @@ -25,10 +25,9 @@ public OpenUrlAction(DialogService dialogService, StateManager stateManager) { this.dialogService = dialogService; this.stateManager = stateManager; - BooleanBinding fieldIsSet = ActionHelper.isFieldSetForSelectedEntry(StandardField.URL, stateManager) - .or(ActionHelper.isFieldSetForSelectedEntry(StandardField.DOI, stateManager) - .or(ActionHelper.isFieldSetForSelectedEntry(StandardField.URI, stateManager) - .or(ActionHelper.isFieldSetForSelectedEntry(StandardField.EPRINT, stateManager)))); + BooleanExpression fieldIsSet = ActionHelper.isAnyFieldSetForSelectedEntry( + List.of(StandardField.URL, StandardField.DOI, StandardField.URI, StandardField.EPRINT), + stateManager); this.executable.bind(ActionHelper.needsEntriesSelected(1, stateManager).and(fieldIsSet)); } diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index e7e8b4f875f..1aec1973d49 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -68,7 +68,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit contextMenu.getItems().add(new ChangeEntryTypeMenu().getChangeEntryTypeMenu(entry.getEntry(), panel.getBibDatabaseContext(), panel.getUndoManager())); contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(panel, dialogService, stateManager))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.ATTACH_FILE, new AttachFileAction(panel, dialogService, stateManager, preferencesService))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(panel, dialogService, stateManager))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(dialogService, stateManager))); return contextMenu; } diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java index 173523860e6..a31eb06fbcc 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.Optional; -import org.jabref.gui.BasePanel; +import org.jabref.Globals; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; @@ -13,31 +13,35 @@ import org.jabref.gui.undo.UndoableInsertEntries; import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; public class MergeEntriesAction extends SimpleCommand { - private final BasePanel basePanel; private final DialogService dialogService; + private final StateManager stateManager; - public MergeEntriesAction(BasePanel panel, DialogService dialogService, StateManager stateManager) { - this.basePanel = panel; + public MergeEntriesAction(DialogService dialogService, StateManager stateManager) { this.dialogService = dialogService; + this.stateManager = stateManager; this.executable.bind(ActionHelper.needsEntriesSelected(2, stateManager)); } @Override public void execute() { + if (stateManager.getActiveDatabase().isEmpty()) { + return; + } + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); // Check if there are two entries selected - List selectedEntries = basePanel.getSelectedEntries(); + List selectedEntries = stateManager.getSelectedEntries(); if (selectedEntries.size() != 2) { // Inform the user to select entries first. dialogService.showInformationDialogAndWait( Localization.lang("Merge entries"), Localization.lang("You have to choose exactly two entries to merge.")); - return; } @@ -49,17 +53,19 @@ public void execute() { dlg.setTitle(Localization.lang("Merge entries")); Optional mergedEntry = dlg.showAndWait(); if (mergedEntry.isPresent()) { - basePanel.insertEntry(mergedEntry.get()); + // FixMe: BibDatabase::insertEntry does not contain logic to mark the BasePanel as changed and to mark + // entries with a timestamp, only BasePanel::insertEntry does. + databaseContext.getDatabase().insertEntry(mergedEntry.get()); // Create a new entry and add it to the undo stack // Remove the other two entries and add them to the undo stack (which is not working...) NamedCompound ce = new NamedCompound(Localization.lang("Merge entries")); - ce.addEdit(new UndoableInsertEntries(basePanel.getDatabase(), mergedEntry.get())); + ce.addEdit(new UndoableInsertEntries(databaseContext.getDatabase(), mergedEntry.get())); List entriesToRemove = Arrays.asList(one, two); - ce.addEdit(new UndoableRemoveEntries(basePanel.getDatabase(), entriesToRemove)); - basePanel.getDatabase().removeEntries(entriesToRemove); + ce.addEdit(new UndoableRemoveEntries(databaseContext.getDatabase(), entriesToRemove)); + databaseContext.getDatabase().removeEntries(entriesToRemove); ce.end(); - basePanel.getUndoManager().addEdit(ce); + Globals.undoManager.addEdit(ce); // ToDo: Rework UndoManager and extract Globals dialogService.notify(Localization.lang("Merged entries")); } else { diff --git a/src/main/java/org/jabref/gui/preview/CopyCitationAction.java b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java index a882225c09b..46e671147c2 100644 --- a/src/main/java/org/jabref/gui/preview/CopyCitationAction.java +++ b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java @@ -39,7 +39,7 @@ public class CopyCitationAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(CopyCitationAction.class); private final List selectedEntries; - private StateManager stateManager; + private final StateManager stateManager; private final PreviewLayout style; private final String previewStyle; private final CitationStyleOutputFormat outputFormat; From 08fa945653e36bc705513fec9ced36e35410c3bd Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Thu, 20 Feb 2020 14:18:37 +0100 Subject: [PATCH 010/287] Fixed l10n merge errors --- src/main/resources/l10n/JabRef_en.properties | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 0e357ac8784..e86258e2e84 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1356,7 +1356,6 @@ Increase\ table\ font\ size=Increase table font size New\ article=New article New\ book=New book New\ entry=New entry -New\ from\ plain\ text=New from plain text New\ inbook=New inbook New\ mastersthesis=New mastersthesis New\ phdthesis=New phdthesis @@ -1969,11 +1968,6 @@ Accept\ changes=Accept changes Dismiss\ changes=Dismiss changes The\ library\ has\ been\ modified\ by\ another\ program.=The library has been modified by another program. -Extract=Extract -Extract\ BibTeX\ from\ plain\ text= Extract BibTeX from plain text -Input\ text\ to\ parse=Input text to parse -Starts\ the\ extraction\ of\ the\ BibTeX\ entry=Starts the extraction of the BibTeX entry - Execute\ command=Execute command Open\ File\ Browser=Open File Browser Use\ default\ file\ browser=Use default file browser From 9b8e385eb4cc13ae25116287b0750e621dba6683 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage Date: Thu, 20 Feb 2020 23:40:10 +0100 Subject: [PATCH 011/287] CHANGELOG.md --- src/main/java/org/jabref/gui/JabRefFrame.java | 2 +- .../org/jabref/gui/maintable/RightClickMenu.java | 2 +- .../jabref/gui/mergeentries/MergeEntriesAction.java | 12 ++++++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 5a4c0476b97..ce6cf9092fa 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -755,7 +755,7 @@ private MenuBar createMenu() { quality.getItems().addAll( factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this, dialogService, stateManager)), - factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(dialogService, stateManager)), + factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this, dialogService, stateManager)), factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(this, stateManager, Globals.TASK_EXECUTOR)), factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, stateManager)), diff --git a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java index 1aec1973d49..b55c525dc13 100644 --- a/src/main/java/org/jabref/gui/maintable/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/maintable/RightClickMenu.java @@ -68,7 +68,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit contextMenu.getItems().add(new ChangeEntryTypeMenu().getChangeEntryTypeMenu(entry.getEntry(), panel.getBibDatabaseContext(), panel.getUndoManager())); contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_WITH_FETCHED_ENTRY, new MergeWithFetchedEntryAction(panel, dialogService, stateManager))); contextMenu.getItems().add(factory.createMenuItem(StandardActions.ATTACH_FILE, new AttachFileAction(panel, dialogService, stateManager, preferencesService))); - contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(dialogService, stateManager))); + contextMenu.getItems().add(factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(panel.frame(), dialogService, stateManager))); return contextMenu; } diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java index a31eb06fbcc..7ccc29e2515 100644 --- a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java +++ b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java @@ -6,6 +6,7 @@ import org.jabref.Globals; import org.jabref.gui.DialogService; +import org.jabref.gui.JabRefFrame; import org.jabref.gui.StateManager; import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; @@ -18,10 +19,12 @@ public class MergeEntriesAction extends SimpleCommand { + private final JabRefFrame frame; private final DialogService dialogService; private final StateManager stateManager; - public MergeEntriesAction(DialogService dialogService, StateManager stateManager) { + public MergeEntriesAction(JabRefFrame frame, DialogService dialogService, StateManager stateManager) { + this.frame = frame; this.dialogService = dialogService; this.stateManager = stateManager; @@ -53,9 +56,10 @@ public void execute() { dlg.setTitle(Localization.lang("Merge entries")); Optional mergedEntry = dlg.showAndWait(); if (mergedEntry.isPresent()) { - // FixMe: BibDatabase::insertEntry does not contain logic to mark the BasePanel as changed and to mark - // entries with a timestamp, only BasePanel::insertEntry does. - databaseContext.getDatabase().insertEntry(mergedEntry.get()); + // ToDo: BibDatabase::insertEntry does not contain logic to mark the BasePanel as changed and to mark + // entries with a timestamp, only BasePanel::insertEntry does. Workaround for the moment is to get the + // BasePanel from the constructor injected JabRefFrame. Should be refactored and extracted! + frame.getCurrentBasePanel().insertEntry(mergedEntry.get()); // Create a new entry and add it to the undo stack // Remove the other two entries and add them to the undo stack (which is not working...) From 044ab17b9ba140377998e14184e465b42c0771b3 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 21 Feb 2020 01:10:48 +0100 Subject: [PATCH 012/287] Fix casing of "LaTeX" --> either "Latex" (code) or "LaTeX" (code comments, user-facing) Never LaTex --- .../gui/entryeditor/LatexCitationsTabViewModel.java | 6 +++--- .../org/jabref/gui/groups/GroupDialogViewModel.java | 2 +- .../gui/libraryproperties/LibraryPropertiesDialog.fxml | 4 ++-- .../libraryproperties/LibraryPropertiesDialogView.java | 8 ++++---- .../LibraryPropertiesDialogViewModel.java | 10 +++++----- .../jabref/gui/texparser/ParseTexDialogViewModel.java | 2 +- .../jabref/logic/bibtex/comparator/MetaDataDiff.java | 4 ++-- .../org/jabref/logic/exporter/MetaDataSerializer.java | 2 +- .../bibtexfields/OrdinalsToSuperscriptFormatter.java | 2 +- .../org/jabref/logic/importer/util/MetaDataParser.java | 2 +- .../org/jabref/model/entry/field/StandardField.java | 2 +- src/main/java/org/jabref/model/groups/TexGroup.java | 4 ++-- src/main/java/org/jabref/model/metadata/MetaData.java | 8 ++++---- src/main/resources/l10n/JabRef_de.properties | 2 +- src/main/resources/l10n/JabRef_en.properties | 2 +- src/main/resources/l10n/JabRef_es.properties | 2 +- src/main/resources/l10n/JabRef_fr.properties | 4 ++-- src/main/resources/l10n/JabRef_ja.properties | 2 +- src/main/resources/l10n/JabRef_pt.properties | 2 +- src/main/resources/l10n/JabRef_ru.properties | 2 +- src/main/resources/l10n/JabRef_tr.properties | 5 ++--- .../logic/exporter/BibtexDatabaseWriterTest.java | 2 +- .../logic/importer/fileformat/BibtexParserTest.java | 2 +- .../java/org/jabref/model/groups/TexGroupTest.java | 2 +- 24 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java index 9ef038f50b5..13546cbc64e 100644 --- a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java +++ b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java @@ -65,7 +65,7 @@ public LatexCitationsTabViewModel(BibDatabaseContext databaseContext, Preference this.preferencesService = preferencesService; this.taskExecutor = taskExecutor; this.dialogService = dialogService; - this.directory = new SimpleObjectProperty<>(databaseContext.getMetaData().getLaTexFileDirectory(preferencesService.getUser()) + this.directory = new SimpleObjectProperty<>(databaseContext.getMetaData().getLatexFileDirectory(preferencesService.getUser()) .orElseGet(preferencesService::getWorkingDir)); this.citationList = FXCollections.observableArrayList(); this.status = new SimpleObjectProperty<>(Status.IN_PROGRESS); @@ -126,7 +126,7 @@ private void cancelSearch() { } private Collection searchAndParse(String citeKey) throws IOException { - Path newDirectory = databaseContext.getMetaData().getLaTexFileDirectory(preferencesService.getUser()) + Path newDirectory = databaseContext.getMetaData().getLatexFileDirectory(preferencesService.getUser()) .orElseGet(preferencesService::getWorkingDir); if (texParserResult == null || !newDirectory.equals(directory.get())) { @@ -168,7 +168,7 @@ public void setLatexDirectory() { .withInitialDirectory(directory.get()).build(); dialogService.showDirectorySelectionDialog(directoryDialogConfiguration).ifPresent(selectedDirectory -> - databaseContext.getMetaData().setLaTexFileDirectory(preferencesService.getUser(), selectedDirectory.toAbsolutePath())); + databaseContext.getMetaData().setLatexFileDirectory(preferencesService.getUser(), selectedDirectory.toAbsolutePath())); init(currentEntry); } diff --git a/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java b/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java index 47a2c88f52f..2a465886d3d 100644 --- a/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java @@ -392,7 +392,7 @@ public void openHelpPage() { private List getFileDirectoriesAsPaths() { List fileDirs = new ArrayList<>(); MetaData metaData = currentDatabase.getMetaData(); - metaData.getLaTexFileDirectory(preferencesService.getFilePreferences().getUser()).ifPresent(fileDirs::add); + metaData.getLatexFileDirectory(preferencesService.getFilePreferences().getUser()).ifPresent(fileDirs::add); return fileDirs; } diff --git a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml index 7d43bd84e46..50faf887c78 100644 --- a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml +++ b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml @@ -65,9 +65,9 @@ + +
@@ -26,23 +38,4 @@
- - - - - - - - - - - From 45200d39ad24b766a4a6fb9905d011bb2188b377 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Fri, 13 Mar 2020 22:02:34 +0100 Subject: [PATCH 137/287] Increase size of expand groups icon --- src/main/java/org/jabref/gui/groups/GroupTree.css | 4 ++-- src/main/java/org/jabref/gui/groups/GroupTree.fxml | 7 ++++--- src/main/java/org/jabref/gui/groups/GroupTreeView.java | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/gui/groups/GroupTree.css b/src/main/java/org/jabref/gui/groups/GroupTree.css index 929d77c55e4..cfd75e2de0a 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTree.css +++ b/src/main/java/org/jabref/gui/groups/GroupTree.css @@ -29,7 +29,7 @@ -fx-fill: -jr-group-hits-fg; } -.disclosureNodeColumn { +.expansionNodeColumn { -fx-alignment: top-right; } @@ -73,7 +73,7 @@ -fx-padding: 0.40em 0.2em 0.40em 0em; } -.tree-table-row-cell:root > .disclosureNodeColumn { +.tree-table-row-cell:root > .expansionNodeColumn { -fx-padding: 0.45em 0.2em 0.45em 0.2em; } diff --git a/src/main/java/org/jabref/gui/groups/GroupTree.fxml b/src/main/java/org/jabref/gui/groups/GroupTree.fxml index 662090bf0b7..8990ffada01 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTree.fxml +++ b/src/main/java/org/jabref/gui/groups/GroupTree.fxml @@ -14,7 +14,8 @@ - - - + + diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java index b1f05c01d1e..1012ba68224 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTabView.java @@ -9,6 +9,7 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.StandardActions; @@ -83,9 +84,10 @@ private void setupTable() { .install(actionsColumn); viewModel.selectedColumnModelProperty().setValue(columnsList.getSelectionModel()); - columnsList.setOnKeyPressed(event -> { + columnsList.addEventFilter(KeyEvent.KEY_PRESSED, event -> { if (event.getCode() == KeyCode.DELETE) { viewModel.removeColumn(columnsList.getSelectionModel().getSelectedItem()); + event.consume(); } }); @@ -97,7 +99,7 @@ private void setupTable() { addColumnName.itemsProperty().bind(viewModel.availableColumnsProperty()); addColumnName.valueProperty().bindBidirectional(viewModel.addColumnProperty()); addColumnName.setConverter(TableColumnsTabViewModel.columnNameStringConverter); - addColumnName.setOnKeyPressed(event -> { + addColumnName.addEventFilter(KeyEvent.KEY_PRESSED, event -> { if (event.getCode() == KeyCode.ENTER) { viewModel.insertColumnInList(); event.consume(); diff --git a/src/main/java/org/jabref/gui/preferences/XmpPrivacyTabView.java b/src/main/java/org/jabref/gui/preferences/XmpPrivacyTabView.java index 3f18f58c4c6..1763b759651 100644 --- a/src/main/java/org/jabref/gui/preferences/XmpPrivacyTabView.java +++ b/src/main/java/org/jabref/gui/preferences/XmpPrivacyTabView.java @@ -8,6 +8,7 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.util.BindingsHelper; @@ -69,9 +70,10 @@ public void initialize () { item -> evt -> viewModel.removeFilter(filterList.getFocusModel().getFocusedItem())) .install(actionsColumn); - filterList.setOnKeyPressed(event -> { + filterList.addEventFilter(KeyEvent.KEY_PRESSED, event -> { if (event.getCode() == KeyCode.DELETE) { viewModel.removeFilter(filterList.getSelectionModel().getSelectedItem()); + event.consume(); } }); @@ -84,6 +86,12 @@ public void initialize () { addFieldName.itemsProperty().bind(viewModel.availableFieldsProperty()); addFieldName.valueProperty().bindBidirectional(viewModel.addFieldNameProperty()); addFieldName.setConverter(FieldsUtil.fieldStringConverter); + addFieldName.addEventFilter(KeyEvent.KEY_PRESSED, event -> { + if (event.getCode() == KeyCode.ENTER) { + viewModel.addField(); + event.consume(); + } + }); validationVisualizer.setDecoration(new IconValidationDecorator()); Platform.runLater(() -> validationVisualizer.initVisualization(viewModel.xmpFilterListValidationStatus(), filterList)); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index c426bbec82d..1ef1fa19bf3 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -205,9 +205,6 @@ public class JabRefPreferences implements PreferencesService { public static final String KEY_PATTERN_REPLACEMENT = "KeyPatternReplacement"; public static final String CONSOLE_COMMAND = "consoleCommand"; public static final String USE_DEFAULT_CONSOLE_APPLICATION = "useDefaultConsoleApplication"; - public static final String ADOBE_ACROBAT_COMMAND = "adobeAcrobatCommand"; - public static final String SUMATRA_PDF_COMMAND = "sumatraCommand"; - public static final String USE_PDF_READER = "usePDFReader"; public static final String USE_DEFAULT_FILE_BROWSER_APPLICATION = "userDefaultFileBrowserApplication"; public static final String FILE_BROWSER_COMMAND = "fileBrowserCommand"; @@ -644,15 +641,9 @@ private JabRefPreferences() { defaults.put(USE_DEFAULT_FILE_BROWSER_APPLICATION, Boolean.TRUE); if (OS.WINDOWS) { defaults.put(CONSOLE_COMMAND, "C:\\Program Files\\ConEmu\\ConEmu64.exe /single /dir \"%DIR\""); - defaults.put(ADOBE_ACROBAT_COMMAND, "C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader"); - defaults.put(SUMATRA_PDF_COMMAND, "C:\\Program Files\\SumatraPDF"); - defaults.put(USE_PDF_READER, ADOBE_ACROBAT_COMMAND); defaults.put(FILE_BROWSER_COMMAND, "explorer.exe /select, \"%DIR\""); } else { defaults.put(CONSOLE_COMMAND, ""); - defaults.put(ADOBE_ACROBAT_COMMAND, ""); - defaults.put(SUMATRA_PDF_COMMAND, ""); - defaults.put(USE_PDF_READER, ""); defaults.put(FILE_BROWSER_COMMAND, ""); } @@ -1997,7 +1988,7 @@ public PushToApplication getActivePushToApplication(PushToApplicationsManager ma } public void setActivePushToApplication(PushToApplication application, PushToApplicationsManager manager) { - if (application.getApplicationName() != get(PUSH_TO_APPLICATION)) { + if (!application.getApplicationName().equals(get(PUSH_TO_APPLICATION))) { put(PUSH_TO_APPLICATION, application.getApplicationName()); manager.updateApplicationAction(); } @@ -2008,7 +1999,7 @@ public NewLineSeparator getNewLineSeparator() { } public void setNewLineSeparator(NewLineSeparator newLineSeparator) { - String escapeChars = newLineSeparator.getEscapeChars(); + String escapeChars = newLineSeparator.toString(); put(JabRefPreferences.NEWLINE, escapeChars); // we also have to change Globals variable as globals is not a getter, but a constant diff --git a/src/main/java/org/jabref/preferences/NewLineSeparator.java b/src/main/java/org/jabref/preferences/NewLineSeparator.java index 975bdcd88fc..6870cfc50b9 100644 --- a/src/main/java/org/jabref/preferences/NewLineSeparator.java +++ b/src/main/java/org/jabref/preferences/NewLineSeparator.java @@ -1,16 +1,15 @@ package org.jabref.preferences; +/** + * An enum which contains the possible NewLineSeperators + * Possible are CR ("\n"), LF ("\r") and the windows standard CR/LF. + */ public enum NewLineSeparator { CR, LF, CRLF; - /** - * An enum which contains the possible NewLineSeperators - * Possible are CR ("\n"), LF ("\r") and the windows standard CR/LF. - */ - - public String toString() { + public String getDisplayName() { switch (this) { case CR: return "CR (\"\\r\")"; @@ -24,7 +23,7 @@ public String toString() { /** * @return the name of the current mode as String */ - public String getEscapeChars() { + public String toString() { switch (this) { case CR: return "\r"; diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index d01aea778bc..3915f9ca525 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -561,8 +561,6 @@ No\ journal\ names\ could\ be\ abbreviated.=No journal names could be abbreviate No\ journal\ names\ could\ be\ unabbreviated.=No journal names could be unabbreviated. -Open\ PDF=Open PDF - not=not not\ found=not found @@ -1698,8 +1696,6 @@ Author=Author Date=Date File\ annotations=File annotations Show\ file\ annotations=Show file annotations -Adobe\ Acrobat\ Reader=Adobe Acrobat Reader -Sumatra\ Reader=Sumatra Reader shared=shared should\ contain\ an\ integer\ or\ a\ literal=should contain an integer or a literal should\ have\ the\ first\ letter\ capitalized=should have the first letter capitalized @@ -1777,7 +1773,7 @@ Show\ this\ document\ until\ unlocked.=Show this document until unlocked. Set\ current\ user\ name\ as\ owner.=Set current user name as owner. Sort\ all\ subgroups\ (recursively)=Sort all subgroups (recursively) -Collect\ and\ share\ telemetry\ data\ to\ help\ improve\ JabRef.=Collect and share telemetry data to help improve JabRef. +Collect\ and\ share\ telemetry\ data\ to\ help\ improve\ JabRef=Collect and share telemetry data to help improve JabRef Don't\ share=Don't share Share\ anonymous\ statistics=Share anonymous statistics Telemetry\:\ Help\ make\ JabRef\ better=Telemetry: Help make JabRef better @@ -2035,7 +2031,6 @@ Light\ theme=Light theme Dark\ theme=Dark theme Overwrite\ existing\ keys=Overwrite existing keys Key\ patterns=Key patterns -Size\:=Size: Font\ settings=Font settings Override\ font\ settings=Override font settings Override\ font\ size=Override font size @@ -2116,3 +2111,5 @@ Unable\ to\ open\ ShortScience.=Unable to open ShortScience. Shared\ database=Shared database Lookup=Lookup + +Remove\ formatter\ %0=Remove formatter %0 From deb8ae87893eefcac95fbde679b517db9d24b108 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2020 20:35:19 +0100 Subject: [PATCH 163/287] Bump org.beryx.jlink from 2.17.2 to 2.17.3 (#6133) Bumps org.beryx.jlink from 2.17.2 to 2.17.3. Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e2b07c91978..e5df4972274 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ plugins { id 'com.github.ben-manes.versions' version '0.28.0' id 'org.javamodularity.moduleplugin' version '1.5.0' id 'org.openjfx.javafxplugin' version '0.0.8' - id 'org.beryx.jlink' version '2.17.2' + id 'org.beryx.jlink' version '2.17.3' // nicer test outputs during running and completion id 'com.adarshr.test-logger' version '2.0.0' From 663815dd686f96d1936f08f318b2b088c965ebac Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2020 20:35:34 +0100 Subject: [PATCH 164/287] Bump mockito-core from 3.3.1 to 3.3.3 (#6132) Bumps [mockito-core](https://github.com/mockito/mockito) from 3.3.1 to 3.3.3. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v3.3.1...v3.3.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e5df4972274..995fec00881 100644 --- a/build.gradle +++ b/build.gradle @@ -204,7 +204,7 @@ dependencies { testImplementation 'net.bytebuddy:byte-buddy-parent:1.10.8' 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' - testImplementation 'org.mockito:mockito-core:3.3.1' + testImplementation 'org.mockito:mockito-core:3.3.3' testImplementation 'org.xmlunit:xmlunit-core:2.6.4' testImplementation 'org.xmlunit:xmlunit-matchers:2.6.4' testImplementation 'com.tngtech.archunit:archunit-junit5-api:0.13.1' From fd2ac2499938c2253f0165fec8b83654fe486938 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2020 20:36:19 +0100 Subject: [PATCH 165/287] Bump postgresql from 42.2.10 to 42.2.11 (#6131) Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.2.10 to 42.2.11. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.2.10...REL42.2.11) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 995fec00881..9ede77b7f44 100644 --- a/build.gradle +++ b/build.gradle @@ -143,7 +143,7 @@ dependencies { implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.5.4' - implementation 'org.postgresql:postgresql:42.2.10' + implementation 'org.postgresql:postgresql:42.2.11' implementation ('com.oracle.ojdbc:ojdbc10:19.3.0.0') { // causing module issues From 98d0fa926029335e61ecfbb828332c70e30eef89 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 16 Mar 2020 22:58:12 +0100 Subject: [PATCH 166/287] Fix typos --- docs/development-strategy.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/development-strategy.md b/docs/development-strategy.md index 00a205c476f..f5923afae7a 100644 --- a/docs/development-strategy.md +++ b/docs/development-strategy.md @@ -1,4 +1,4 @@ -# JabRef's development strategy +# JabRef's Development Strategy We aim to keep up to high-quality code standards and use code quality tools wherever possible. @@ -10,9 +10,9 @@ To ensure high code-quality, * we document our design decisions using the lightweight architectural decision records [MADR](https://adr.github.io/madr/). * we review each external pull request by at least two [JabRef Core Developers](https://github.com/JabRef/jabref/blob/master/DEVELOPERS). -Read on on our automated quality checks at [Code Quality](code-quality.md). +Read on about our automated quality checks at [Code Quality](code-quality.md). -## Continuos integration +## Continuous integration Since end of 2019, we just use GitHub actions to execute our tests and to creates binaries. The binaries are create using [gradle](https://gradle.org/) and are uploaded to to [https://builds.jabref.org](https://builds.jabref.org). These binaries are created without any checks to have them available as quickly as possible, even if the localization or some fetchers are broken. Deep link: [https://github.com/JabRef/jabref/actions?workflow=Deployment](https://github.com/JabRef/jabref/actions?workflow=Deployment). From 2339e958599109cf92f4d69168e8fddff2007da0 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 16 Mar 2020 22:59:12 +0100 Subject: [PATCH 167/287] Fix typo --- docs/development-strategy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/development-strategy.md b/docs/development-strategy.md index f5923afae7a..8571ae2f406 100644 --- a/docs/development-strategy.md +++ b/docs/development-strategy.md @@ -6,7 +6,7 @@ To ensure high code-quality, * we follow the principles of [Java by Comparison](https://java.by-comparison.com/). * we follow the principles of [Effective Java](https://www.oreilly.com/library/view/effective-java-3rd/9780134686097/). -* we use [Design Pattners](https://java-design-patterns.com/patterns/) when applicable. +* we use [Design Patterns](https://java-design-patterns.com/patterns/) when applicable. * we document our design decisions using the lightweight architectural decision records [MADR](https://adr.github.io/madr/). * we review each external pull request by at least two [JabRef Core Developers](https://github.com/JabRef/jabref/blob/master/DEVELOPERS). @@ -22,7 +22,7 @@ The branch [master](https://builds.jabref.org/master/) is the main development l Other branches are used for discussing improvements with the help of [pull requests](https://github.com/JabRef/jabref/pulls). One can see the binaries of each branch at [https://builds.jabref.org/](https://builds.jabref.org/). Releases mark milestones and are based on the master at a point in time. -## How JabRef aquires contributors +## How JabRef acquires contributors * We participate in [Hacktoberfest](https://hacktoberfest.digitalocean.com/). See [https://www.jabref.org/hacktoberfest/](https://www.jabref.org/hacktoberfest/) for details. * We participate in [Google Summer of Code](https://developers.google.com/open-source/gsoc/). From f4fe97b93cb166da459d1301f4d11f0a99d6635c Mon Sep 17 00:00:00 2001 From: eetian <57387212+eetian@users.noreply.github.com> Date: Mon, 16 Mar 2020 22:27:36 -0700 Subject: [PATCH 168/287] Fix warning display issue for entering a title made of two words (#6054) --- CHANGELOG.md | 1 + .../jabref/logic/integrity/TitleChecker.java | 28 ++++--- .../logic/integrity/IntegrityCheckTest.java | 22 ++++++ .../logic/integrity/TitleCheckerTest.java | 79 +++++++++++++++++++ 4 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 89470a03de6..86642cc2bf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We fixed an issue where the group and the link column were not updated after changing the entry in the main table. [#5985](https://github.com/JabRef/jabref/issues/5985) - We fixed an issue where reordering the groups was not possible after inserting an article. [#6008](https://github.com/JabRef/jabref/issues/6008) - We fixed an issue where citation styles except the default "Preview" could not be used. [#56220](https://github.com/JabRef/jabref/issues/5622) +- We fixed an issue where a warning was displayed when the title content is made up of two sentences. [#5832](https://github.com/JabRef/jabref/issues/5832) - We fixed an issue where an exception was thrown when adding a save action without a selected formatter in the library properties [#6069](https://github.com/JabRef/jabref/issues/6069) ### Removed diff --git a/src/main/java/org/jabref/logic/integrity/TitleChecker.java b/src/main/java/org/jabref/logic/integrity/TitleChecker.java index c2725949d24..43c77df59bc 100644 --- a/src/main/java/org/jabref/logic/integrity/TitleChecker.java +++ b/src/main/java/org/jabref/logic/integrity/TitleChecker.java @@ -12,6 +12,7 @@ public class TitleChecker implements ValueChecker { private static final Pattern INSIDE_CURLY_BRAKETS = Pattern.compile("\\{[^}\\{]*\\}"); + private static final Pattern DELIMITERS = Pattern.compile("\\.|\\!|\\?|\\;|\\:"); private static final Predicate HAS_CAPITAL_LETTERS = Pattern.compile("[\\p{Lu}\\p{Lt}]").asPredicate(); private final BibDatabaseContext databaseContext; @@ -22,10 +23,13 @@ public TitleChecker(BibDatabaseContext databaseContext) { /** * Algorithm: - * - remove trailing whitespaces - * - ignore first letter as this can always be written in caps * - remove everything that is in brackets - * - check if at least one capital letter is in the title + * - split the title into sub titles based on the delimiters + * (defined in the local variable DELIMITERS, currently . ! ? ; :) + * - for each sub title: + * - remove trailing whitespaces + * - ignore first letter as this can always be written in caps + * - check if at least one capital letter is in the sub title */ @Override public Optional checkValue(String value) { @@ -37,9 +41,7 @@ public Optional checkValue(String value) { return Optional.empty(); } - String valueTrimmed = value.trim(); - String valueIgnoringFirstLetter = valueTrimmed.startsWith("{") ? valueTrimmed : valueTrimmed.substring(1); - String valueOnlySpacesWithinCurlyBraces = valueIgnoringFirstLetter; + String valueOnlySpacesWithinCurlyBraces = value; while (true) { Matcher matcher = INSIDE_CURLY_BRAKETS.matcher(valueOnlySpacesWithinCurlyBraces); if (!matcher.find()) { @@ -48,11 +50,15 @@ public Optional checkValue(String value) { valueOnlySpacesWithinCurlyBraces = matcher.replaceAll(""); } - boolean hasCapitalLettersThatBibtexWillConvertToSmallerOnes = HAS_CAPITAL_LETTERS - .test(valueOnlySpacesWithinCurlyBraces); - - if (hasCapitalLettersThatBibtexWillConvertToSmallerOnes) { - return Optional.of(Localization.lang("capital letters are not masked using curly brackets {}")); + String[] splitTitle = DELIMITERS.split(valueOnlySpacesWithinCurlyBraces); + for (String subTitle : splitTitle) { + subTitle = subTitle.trim(); + if (!subTitle.isEmpty()) { + subTitle = subTitle.substring(1); + if (HAS_CAPITAL_LETTERS.test(subTitle)) { + return Optional.of(Localization.lang("capital letters are not masked using curly brackets {}")); + } + } } return Optional.empty(); diff --git a/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java index 2e096753fed..6f5639e9c13 100644 --- a/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java @@ -186,6 +186,17 @@ void testTitleChecks() { assertCorrect(withMode(createContext(StandardField.TITLE, "This is a {Title}"), BibDatabaseMode.BIBTEX)); assertCorrect(withMode(createContext(StandardField.TITLE, "{C}urrent {C}hronicle"), BibDatabaseMode.BIBTEX)); assertCorrect(withMode(createContext(StandardField.TITLE, "{A Model-Driven Approach for Monitoring {ebBP} BusinessTransactions}"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: This is a sub title 2"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: this is a sub title 2"), BibDatabaseMode.BIBTEX)); + assertWrong(withMode(createContext(StandardField.TITLE, "This is a sub title 1: This is A sub title 2"), BibDatabaseMode.BIBTEX)); + assertWrong(withMode(createContext(StandardField.TITLE, "This is a sub title 1: this is A sub title 2"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: This is {A} sub title 2"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: this is {A} sub title 2"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1...This is a sub title 2"), BibDatabaseMode.BIBTEX)); + assertWrong(withMode(createContext(StandardField.TITLE, "This is a sub title 1... this is a sub Title 2"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is; A sub title 1.... This is a sub title 2"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This!is!!A!Title??"), BibDatabaseMode.BIBTEX)); + assertWrong(withMode(createContext(StandardField.TITLE, "This!is!!A!TitlE??"), BibDatabaseMode.BIBTEX)); assertCorrect(withMode(createContext(StandardField.TITLE, "This is a title"), BibDatabaseMode.BIBLATEX)); assertCorrect(withMode(createContext(StandardField.TITLE, "This is a Title"), BibDatabaseMode.BIBLATEX)); @@ -194,6 +205,17 @@ void testTitleChecks() { assertCorrect(withMode(createContext(StandardField.TITLE, "This is a {Title}"), BibDatabaseMode.BIBLATEX)); assertCorrect(withMode(createContext(StandardField.TITLE, "{C}urrent {C}hronicle"), BibDatabaseMode.BIBLATEX)); assertCorrect(withMode(createContext(StandardField.TITLE, "{A Model-Driven Approach for Monitoring {ebBP} BusinessTransactions}"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: This is a sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: this is a sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: This is A sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: this is A sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: This is {A} sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1: this is {A} sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1...This is a sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is a sub title 1... this is a sub Title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This is; A sub title 1.... This is a sub title 2"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This!is!!A!Title??"), BibDatabaseMode.BIBLATEX)); + assertCorrect(withMode(createContext(StandardField.TITLE, "This!is!!A!TitlE??"), BibDatabaseMode.BIBLATEX)); } @Test diff --git a/src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java b/src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java new file mode 100644 index 00000000000..930f1598129 --- /dev/null +++ b/src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java @@ -0,0 +1,79 @@ +package org.jabref.logic.integrity; + +import java.util.Optional; + +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.database.BibDatabaseMode; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class TitleCheckerTest { + + private TitleChecker checker; + + @BeforeEach + public void setUp() { + BibDatabaseContext databaseContext = new BibDatabaseContext(); + databaseContext.setMode(BibDatabaseMode.BIBTEX); + checker = new TitleChecker(databaseContext); + } + + @Test + public void FirstLetterAsOnlyCapitalLetterInSubTitle2() { + assertEquals(Optional.empty(), checker.checkValue("This is a sub title 1: This is a sub title 2")); + } + + @Test + public void NoCapitalLetterInSubTitle2() { + assertEquals(Optional.empty(), checker.checkValue("This is a sub title 1: this is a sub title 2")); + } + + @Test + public void TwoCapitalLettersInSubTitle2() { + assertNotEquals(Optional.empty(), checker.checkValue("This is a sub title 1: This is A sub title 2")); + } + + @Test + public void MiddleLetterAsOnlyCapitalLetterInSubTitle2() { + assertNotEquals(Optional.empty(), checker.checkValue("This is a sub title 1: this is A sub title 2")); + } + + @Test + public void TwoCapitalLettersInSubTitle2WithCurlyBrackets() { + assertEquals(Optional.empty(), checker.checkValue("This is a sub title 1: This is {A} sub title 2")); + } + + @Test + public void MiddleLetterAsOnlyCapitalLetterInSubTitle2WithCurlyBrackets() { + assertEquals(Optional.empty(), checker.checkValue("This is a sub title 1: this is {A} sub title 2")); + } + + @Test + public void FirstLetterAsOnlyCapitalLetterInSubTitle2AfterContinuousDelimiters() { + assertEquals(Optional.empty(), checker.checkValue("This is a sub title 1...This is a sub title 2")); + } + + @Test + public void MiddleLetterAsOnlyCapitalLetterInSubTitle2AfterContinuousDelimiters() { + assertNotEquals(Optional.empty(), checker.checkValue("This is a sub title 1... this is a sub Title 2")); + } + + @Test + public void FirstLetterAsOnlyCapitalLetterInEverySubTitleWithContinuousDelimiters() { + assertEquals(Optional.empty(), checker.checkValue("This is; A sub title 1.... This is a sub title 2")); + } + + @Test + public void FirstLetterAsOnlyCapitalLetterInEverySubTitleWithRandomDelimiters() { + assertEquals(Optional.empty(), checker.checkValue("This!is!!A!Title??")); + } + + @Test + public void MoreThanOneCapitalLetterInSubTitleWithoutCurlyBrackets() { + assertNotEquals(Optional.empty(), checker.checkValue("This!is!!A!TitlE??")); + } +} From 1b03f039aa4abf0812a3a8ae0ba248c08fdb39a3 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 17 Mar 2020 06:46:07 +0100 Subject: [PATCH 169/287] Remove obsolete usage of File in DatabaseContext (#6135) --- src/main/java/org/jabref/gui/BasePanel.java | 12 +++---- src/main/java/org/jabref/gui/JabRefFrame.java | 31 ++++++++----------- .../org/jabref/logic/layout/LayoutEntry.java | 6 ++-- .../model/database/BibDatabaseContext.java | 24 ++++++-------- .../LastFocusedTabPreferences.java | 14 ++++----- .../LastFocusedTabPreferencesTest.java | 6 ++-- 6 files changed, 38 insertions(+), 55 deletions(-) diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 548fe11456e..330463448ed 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -70,7 +70,6 @@ public class BasePanel extends StackPane { private final FileAnnotationCache annotationCache; private final JabRefFrame frame; - // The undo manager. private final CountingUndoManager undoManager; private final SidePaneManager sidePaneManager; @@ -80,13 +79,10 @@ public class BasePanel extends StackPane { private final DialogService dialogService; private MainTable mainTable; private BasePanelPreferences preferences; - // To contain instantiated entry editors. This is to save time - // As most enums, this must not be null private BasePanelMode mode = BasePanelMode.SHOWING_NOTHING; private SplitPane splitPane; private DatabaseChangePane changePane; private boolean saving; - // AutoCompleter used in the search bar private PersonNameSuggestionProvider searchAutoCompleter; private boolean baseChanged; private boolean nonUndoableChange; @@ -152,10 +148,10 @@ public String getTabTitle() { boolean isAutosaveEnabled = Globals.prefs.getBoolean(JabRefPreferences.LOCAL_AUTO_SAVE); if (databaseLocation == DatabaseLocation.LOCAL) { - if (this.bibDatabaseContext.getDatabaseFile().isPresent()) { + if (this.bibDatabaseContext.getDatabasePath().isPresent()) { // check if file is modified String changeFlag = isModified() && !isAutosaveEnabled ? "*" : ""; - title.append(this.bibDatabaseContext.getDatabaseFile().get().getName()).append(changeFlag); + title.append(this.bibDatabaseContext.getDatabasePath().get().getFileName()).append(changeFlag); } else { title.append(Localization.lang("untitled")); @@ -558,8 +554,8 @@ public synchronized void markChangedOrUnChanged() { } } else if (baseChanged && !nonUndoableChange) { baseChanged = false; - if (getBibDatabaseContext().getDatabaseFile().isPresent()) { - frame.setTabTitle(this, getTabTitle(), getBibDatabaseContext().getDatabaseFile().get().getAbsolutePath()); + if (getBibDatabaseContext().getDatabasePath().isPresent()) { + frame.setTabTitle(this, getTabTitle(), getBibDatabaseContext().getDatabasePath().get().toAbsolutePath().toString()); } else { frame.setTabTitle(this, Localization.lang("untitled"), null); } diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index f904f291fb5..ca09b4c1af8 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -1,7 +1,6 @@ package org.jabref.gui; import java.io.File; -import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -306,8 +305,8 @@ public void setWindowTitle() { if (panel.getBibDatabaseContext().getLocation() == DatabaseLocation.LOCAL) { String changeFlag = panel.isModified() && !isAutosaveEnabled ? "*" : ""; String databaseFile = panel.getBibDatabaseContext() - .getDatabaseFile() - .map(File::getPath) + .getDatabasePath() + .map(Path::toString) .orElse(Localization.lang("untitled")); //setTitle(FRAME_TITLE + " - " + databaseFile + changeFlag + modeInfo); } else if (panel.getBibDatabaseContext().getLocation() == DatabaseLocation.SHARED) { @@ -355,7 +354,7 @@ private void tearDownJabRef(List filenames) { prefs.remove(JabRefPreferences.LAST_EDITED); } else { prefs.putStringList(JabRefPreferences.LAST_EDITED, filenames); - File focusedDatabase = getCurrentBasePanel().getBibDatabaseContext().getDatabaseFile().orElse(null); + Path focusedDatabase = getCurrentBasePanel().getBibDatabaseContext().getDatabasePath().orElse(null); new LastFocusedTabPreferences(prefs).setLastFocusedTab(focusedDatabase); } } @@ -394,7 +393,7 @@ public boolean quit() { } AutosaveManager.shutdown(context); BackupManager.shutdown(context); - context.getDatabaseFile().map(File::getAbsolutePath).ifPresent(filenames::add); + context.getDatabasePath().map(Path::toAbsolutePath).map(Path::toString).ifPresent(filenames::add); } WaitForSaveFinishedDialog waitForSaveFinishedDialog = new WaitForSaveFinishedDialog(dialogService); @@ -953,15 +952,11 @@ private List collectDatabaseFilePaths() { List dbPaths = new ArrayList<>(getBasePanelCount()); for (BasePanel basePanel : getBasePanelList()) { - try { - // db file exists - if (basePanel.getBibDatabaseContext().getDatabaseFile().isPresent()) { - dbPaths.add(basePanel.getBibDatabaseContext().getDatabaseFile().get().getCanonicalPath()); - } else { - dbPaths.add(""); - } - } catch (IOException ex) { - LOGGER.error("Invalid database file path: " + ex.getMessage()); + // db file exists + if (basePanel.getBibDatabaseContext().getDatabasePath().isPresent()) { + dbPaths.add(basePanel.getBibDatabaseContext().getDatabasePath().get().toAbsolutePath().toString()); + } else { + dbPaths.add(""); } } return dbPaths; @@ -977,10 +972,10 @@ public void updateAllTabTitles() { List paths = getUniquePathParts(); for (int i = 0; i < getBasePanelCount(); i++) { String uniqPath = paths.get(i); - Optional file = getBasePanelAt(i).getBibDatabaseContext().getDatabaseFile(); + Optional file = getBasePanelAt(i).getBibDatabaseContext().getDatabasePath(); if (file.isPresent()) { - if (!uniqPath.equals(file.get().getName()) && uniqPath.contains(File.separator)) { + if (!uniqPath.equals(file.get().getFileName()) && uniqPath.contains(File.separator)) { // remove filename uniqPath = uniqPath.substring(0, uniqPath.lastIndexOf(File.separator)); tabbedPane.getTabs().get(i).setText(getBasePanelAt(i).getTabTitle() + " \u2014 " + uniqPath); @@ -991,7 +986,7 @@ public void updateAllTabTitles() { } else { tabbedPane.getTabs().get(i).setText(getBasePanelAt(i).getTabTitle()); } - tabbedPane.getTabs().get(i).setTooltip(new Tooltip(file.map(File::getAbsolutePath).orElse(null))); + tabbedPane.getTabs().get(i).setTooltip(new Tooltip(file.map(Path::toAbsolutePath).map(Path::toString).orElse(null))); } } @@ -1047,7 +1042,7 @@ private boolean readyForAutosave(BibDatabaseContext context) { return ((context.getLocation() == DatabaseLocation.SHARED) || ((context.getLocation() == DatabaseLocation.LOCAL) && Globals.prefs.getBoolean(JabRefPreferences.LOCAL_AUTO_SAVE))) && - context.getDatabaseFile().isPresent(); + context.getDatabasePath().isPresent(); } /** diff --git a/src/main/java/org/jabref/logic/layout/LayoutEntry.java b/src/main/java/org/jabref/logic/layout/LayoutEntry.java index a58245eb067..ec7d6067a7e 100644 --- a/src/main/java/org/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/org/jabref/logic/layout/LayoutEntry.java @@ -1,7 +1,7 @@ package org.jabref.logic.layout; -import java.io.File; import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -366,10 +366,8 @@ public String doLayout(BibDatabaseContext databaseContext, Charset encoding) { return encoding.displayName(); case LayoutHelper.IS_FILENAME: - return databaseContext.getDatabaseFile().map(File::getName).orElse(""); - case LayoutHelper.IS_FILEPATH: - return databaseContext.getDatabaseFile().map(File::getPath).orElse(""); + return databaseContext.getDatabasePath().map(Path::toAbsolutePath).map(Path::toString).orElse(""); default: break; diff --git a/src/main/java/org/jabref/model/database/BibDatabaseContext.java b/src/main/java/org/jabref/model/database/BibDatabaseContext.java index d2e10dec3c2..8866cdbbd15 100644 --- a/src/main/java/org/jabref/model/database/BibDatabaseContext.java +++ b/src/main/java/org/jabref/model/database/BibDatabaseContext.java @@ -74,21 +74,15 @@ public void setMode(BibDatabaseMode bibDatabaseMode) { metaData.setMode(bibDatabaseMode); } + public void setDatabasePath(Path file) { + this.file = Optional.ofNullable(file); + } + /** * Get the file where this database was last saved to or loaded from, if any. * * @return Optional of the relevant File, or Optional.empty() if none is defined. - * @deprecated use {@link #getDatabasePath()} instead */ - @Deprecated - public Optional getDatabaseFile() { - return file.map(Path::toFile); - } - - public void setDatabasePath(Path file) { - this.file = Optional.ofNullable(file); - } - public Optional getDatabasePath() { return file; } @@ -195,19 +189,19 @@ private String getFileDirectoryPath(String directoryName) { String dir = directoryName; // If this directory is relative, we try to interpret it as relative to // the file path of this BIB file: - Optional databaseFile = getDatabaseFile(); + Optional databaseFile = getDatabasePath(); if (!new File(dir).isAbsolute() && databaseFile.isPresent()) { - String relDir; + Path relDir; if (".".equals(dir)) { // if dir is only "current" directory, just use its parent (== real current directory) as path relDir = databaseFile.get().getParent(); } else { - relDir = databaseFile.get().getParent() + File.separator + dir; + relDir = databaseFile.get().getParent().resolve(dir); } // If this directory actually exists, it is very likely that the // user wants us to use it: - if (new File(relDir).exists()) { - dir = relDir; + if (Files.exists(relDir)) { + dir = relDir.toString(); } } return dir; diff --git a/src/main/java/org/jabref/preferences/LastFocusedTabPreferences.java b/src/main/java/org/jabref/preferences/LastFocusedTabPreferences.java index 793d27f0277..974761e4fdc 100644 --- a/src/main/java/org/jabref/preferences/LastFocusedTabPreferences.java +++ b/src/main/java/org/jabref/preferences/LastFocusedTabPreferences.java @@ -1,6 +1,6 @@ package org.jabref.preferences; -import java.io.File; +import java.nio.file.Path; import java.util.Objects; public class LastFocusedTabPreferences { @@ -11,21 +11,21 @@ public LastFocusedTabPreferences(JabRefPreferences preferences) { this.preferences = Objects.requireNonNull(preferences); } - public void setLastFocusedTab(File file) { - if (file == null) { + public void setLastFocusedTab(Path path) { + if (path == null) { return; } - String filePath = file.getAbsolutePath(); + String filePath = path.toAbsolutePath().toString(); preferences.put(JabRefPreferences.LAST_FOCUSED, filePath); } - public boolean hadLastFocus(File file) { - if (file == null) { + public boolean hadLastFocus(Path path) { + if (path == null) { return false; } String lastFocusedDatabase = preferences.get(JabRefPreferences.LAST_FOCUSED); - return file.getAbsolutePath().equals(lastFocusedDatabase); + return path.toAbsolutePath().toString().equals(lastFocusedDatabase); } } diff --git a/src/test/java/org/jabref/preferences/LastFocusedTabPreferencesTest.java b/src/test/java/org/jabref/preferences/LastFocusedTabPreferencesTest.java index 3e39b69fa63..b6cffbdf9f3 100644 --- a/src/test/java/org/jabref/preferences/LastFocusedTabPreferencesTest.java +++ b/src/test/java/org/jabref/preferences/LastFocusedTabPreferencesTest.java @@ -1,6 +1,6 @@ package org.jabref.preferences; -import java.io.File; +import java.nio.file.Path; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -27,7 +27,7 @@ public static void restorePreferenceLastFocus() { @Test public void testLastFocusedTab() { LastFocusedTabPreferences prefs = new LastFocusedTabPreferences(JabRefPreferences.getInstance()); - File whatever = new File("whatever"); + Path whatever = Path.of("whatever"); prefs.setLastFocusedTab(whatever); assertTrue(prefs.hadLastFocus(whatever)); } @@ -35,7 +35,7 @@ public void testLastFocusedTab() { @Test public void testLastFocusedTabNull() { LastFocusedTabPreferences prefs = new LastFocusedTabPreferences(JabRefPreferences.getInstance()); - File whatever = new File("whatever"); + Path whatever = Path.of("whatever"); prefs.setLastFocusedTab(whatever); assertTrue(prefs.hadLastFocus(whatever)); From eace7273f82dbd55ee6cc25f73723286183a5d7e Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 17 Mar 2020 08:42:41 +0100 Subject: [PATCH 170/287] Move "Manage field names & content" to "Edit" (#6137) --- CHANGELOG.md | 1 + src/main/java/org/jabref/gui/JabRefFrame.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86642cc2bf0..ed063a01f04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We improved the arXiv fetcher. Now it should find entries even more reliably and does no longer include the version (e.g `v1`) in the `eprint` field. [forum#1941](https://discourse.jabref.org/t/remove-version-in-arxiv-import/1941) - We moved the group search bar and the button "New group" from bottom to top position to make it more prominent. [#6112](https://github.com/JabRef/jabref/pull/6112) - We changed the buttons for import/export/show all/reset of preferences to smaller icon buttons in the preferences dialog. [#6130](https://github.com/JabRef/jabref/pull/6130) +- We moved the functionality "Manage field names & content" from the "Library" menu to the "Edit" menu, because it affects the selected entries and not the whole library ### Fixed diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index ca09b4c1af8..462786823ae 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -727,7 +727,8 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.MANAGE_KEYWORDS, new ManageKeywordsAction(stateManager)) + factory.createMenuItem(StandardActions.MANAGE_KEYWORDS, new ManageKeywordsAction(stateManager)), + factory.createMenuItem(StandardActions.MASS_SET_FIELDS, new MassSetFieldsAction(stateManager, dialogService, undoManager)) ); if (Globals.prefs.getBoolean(JabRefPreferences.SPECIALFIELDSENABLED)) { @@ -755,8 +756,7 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.LIBRARY_PROPERTIES, new LibraryPropertiesAction(this, dialogService, stateManager)), factory.createMenuItem(StandardActions.EDIT_PREAMBLE, new PreambleEditor(stateManager, undoManager, this.getDialogService())), factory.createMenuItem(StandardActions.EDIT_STRINGS, new BibtexStringEditorAction(stateManager)), - factory.createMenuItem(StandardActions.MANAGE_CITE_KEY_PATTERNS, new BibtexKeyPatternAction(this, stateManager)), - factory.createMenuItem(StandardActions.MASS_SET_FIELDS, new MassSetFieldsAction(stateManager, dialogService, undoManager)) + factory.createMenuItem(StandardActions.MANAGE_CITE_KEY_PATTERNS, new BibtexKeyPatternAction(this, stateManager)) ); quality.getItems().addAll( From 74408c054082dd0d4da2f20a8231f9a05c25c2bb Mon Sep 17 00:00:00 2001 From: Linus Dietz Date: Tue, 17 Mar 2020 09:42:32 +0100 Subject: [PATCH 171/287] Dependency updates (#6138) * Jython RC * JavaFX --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 9ede77b7f44..18e1e20617f 100644 --- a/build.gradle +++ b/build.gradle @@ -103,7 +103,7 @@ configurations { } javafx { - version = "13.0.2" + version = "14" modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.web', 'javafx.swing' ] } @@ -237,7 +237,7 @@ dependencyUpdates.resolutionStrategy = { } } rules.withModule("org.python:jython-standalone") { ComponentSelection selection -> - if (selection.candidate.version ==~ /2.7.2b\d/) { + if (selection.candidate.version ==~ /2.7.2b\d/ || selection.candidate.version ==~ /2.7.2rc\d/) { selection.reject('Release candidate') } } From a8abfcd2b0d94120ad32097aec74923ab1cb857f Mon Sep 17 00:00:00 2001 From: github actions Date: Tue, 17 Mar 2020 18:08:19 +0000 Subject: [PATCH 172/287] Squashed 'src/main/resources/csl-styles/' changes from 268df9ebc7..db8bd334bd db8bd334bd Create journal-of-breast-cancer.csl (#4630) git-subtree-dir: src/main/resources/csl-styles git-subtree-split: db8bd334bd0a68f0a42a6e435e08216da3eaf0f6 --- journal-of-breast-cancer.csl | 251 +++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 journal-of-breast-cancer.csl diff --git a/journal-of-breast-cancer.csl b/journal-of-breast-cancer.csl new file mode 100644 index 00000000000..4cabf921937 --- /dev/null +++ b/journal-of-breast-cancer.csl @@ -0,0 +1,251 @@ + + From edec608ab0562e7f09a493ea3c3c54b4cc5f82f6 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Wed, 18 Mar 2020 14:47:28 +0100 Subject: [PATCH 173/287] trigger build --- .github/workflows/deployment.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 9211173b3bf..5f4a449072a 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -158,3 +158,4 @@ jobs: ssh_options: '-p 9922' src: 'build/distribution/' dest: jrrsync@build-upload.jabref.org:/var/www/builds.jabref.org/www/${{ steps.gitversion.outputs.branchName }}/ + From 99183e1680fc7dfaa7b3b3f1628fa1331a041594 Mon Sep 17 00:00:00 2001 From: Christoph Date: Wed, 18 Mar 2020 20:28:36 +0100 Subject: [PATCH 174/287] Add APS Fetcher (refactored) (#6143) * Add APS fetcher * Fix case sensitivity bug * Refactor ApsFetcher * Add note about APS fetcher * Refactor findFulltext() * Refactor getId() * Parameterize ApsFetcherTest * Add link to APS changelog entry * Refactor APS Fetcher * make separate tests Co-authored-by: August Janse --- CHANGELOG.md | 2 + .../jabref/logic/importer/WebFetchers.java | 2 + .../logic/importer/fetcher/ApsFetcher.java | 93 +++++++++++++++++++ .../importer/fetcher/ApsFetcherTest.java | 48 ++++++++++ 4 files changed, 145 insertions(+) create mode 100644 src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java create mode 100644 src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index ed063a01f04..32c7ef06b39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - Filenames of external files can no longer contain curly braces. [#5926](https://github.com/JabRef/jabref/pull/5926) - We made the filters more easily accessible in the integrity check dialog. [#5955](https://github.com/JabRef/jabref/pull/5955) - We reimplemented and improved the dialog "Customize entry types". [#4719](https://github.com/JabRef/jabref/issues/4719) +- We reimplemented and improved the dialog "Customize entry types" [#4719](https://github.com/JabRef/jabref/issues/4719) +- We added an [American Physical Society](https://journals.aps.org/) fetcher. [#818](https://github.com/JabRef/jabref/issues/818) ### Fixed diff --git a/src/main/java/org/jabref/logic/importer/WebFetchers.java b/src/main/java/org/jabref/logic/importer/WebFetchers.java index f901ea0588a..72c3ace87ab 100644 --- a/src/main/java/org/jabref/logic/importer/WebFetchers.java +++ b/src/main/java/org/jabref/logic/importer/WebFetchers.java @@ -8,6 +8,7 @@ import java.util.TreeSet; import org.jabref.logic.importer.fetcher.ACS; +import org.jabref.logic.importer.fetcher.ApsFetcher; import org.jabref.logic.importer.fetcher.ArXiv; import org.jabref.logic.importer.fetcher.AstrophysicsDataSystem; import org.jabref.logic.importer.fetcher.CiteSeer; @@ -159,6 +160,7 @@ public static Set getFullTextFetchers(ImportFormatPreferences i fetchers.add(new ACS()); fetchers.add(new ArXiv(importFormatPreferences)); fetchers.add(new IEEE(importFormatPreferences)); + fetchers.add(new ApsFetcher()); // Meta search fetchers.add(new GoogleScholar(importFormatPreferences)); fetchers.add(new OpenAccessDoi()); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java new file mode 100644 index 00000000000..a0716f7cfe6 --- /dev/null +++ b/src/main/java/org/jabref/logic/importer/fetcher/ApsFetcher.java @@ -0,0 +1,93 @@ +package org.jabref.logic.importer.fetcher; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Objects; +import java.util.Optional; + +import org.jabref.logic.importer.FulltextFetcher; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.identifier.DOI; + +import kong.unirest.Unirest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * FulltextFetcher implementation that attempts to find a PDF URL at APS. Also see the API, although it isn't currently used. + */ +public class ApsFetcher implements FulltextFetcher { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApsFetcher.class); + + // The actual API needs either an API key or a header. This is a workaround. + private static final String DOI_URL = "https://www.doi.org/"; + private static final String PDF_URL = "https://journals.aps.org/prl/pdf/"; + + @Override + public Optional findFullText(BibEntry entry) throws IOException { + Objects.requireNonNull(entry); + + Optional doi = entry.getField(StandardField.DOI).flatMap(DOI::parse); + + if (!doi.isPresent()) { + return Optional.empty(); + } + + Optional id = getId(doi.get().getDOI()); + + if (id.isPresent()) { + + String pdfRequestUrl = PDF_URL + id.get(); + int code = Unirest.head(pdfRequestUrl).asJson().getStatus(); + + if (code == 200) { + LOGGER.info("Fulltext PDF found @ APS."); + try { + return Optional.of(new URL(pdfRequestUrl)); + } catch (MalformedURLException e) { + LOGGER.warn("APS returned malformed URL, cannot find PDF."); + } + } + } + return Optional.empty(); + } + + @Override + public TrustLevel getTrustLevel() { + return TrustLevel.PUBLISHER; + } + + /** + * Convert a DOI into an appropriate APS id. + * + * @param doi A case insensitive DOI + * @return A DOI cased as APS likes it + */ + private Optional getId(String doi) { + // DOI is not case sensitive, but the id for the PDF URL is, + // so we follow DOI.org redirects to get the proper id. + // https://stackoverflow.com/a/5270162/1729441 + + String doiRequest = DOI_URL + doi; + + URLConnection con; + try { + con = new URL(doiRequest).openConnection(); + con.connect(); + con.getInputStream(); + String[] urlParts = con.getURL().toString().split("abstract/"); + if (urlParts.length == 2) { + return Optional.of(urlParts[1]); + } + + } catch (IOException e) { + LOGGER.warn("Error connecting to APS", e); + } + return Optional.empty(); + } +} diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java new file mode 100644 index 00000000000..0e545a15064 --- /dev/null +++ b/src/test/java/org/jabref/logic/importer/fetcher/ApsFetcherTest.java @@ -0,0 +1,48 @@ +package org.jabref.logic.importer.fetcher; + +import java.net.URL; +import java.util.Optional; + +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.testutils.category.FetcherTest; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@FetcherTest +class ApsFetcherTest { + + private ApsFetcher finder; + + @BeforeEach + void setUp() { + finder = new ApsFetcher(); + } + + @Test + void findFullTextFromDoi() throws Exception { + BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1103/PhysRevLett.116.061102"); + assertEquals(Optional.of(new URL("https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.116.061102")), finder.findFullText(entry)); + } + + @Test + void findFullTextFromLowercaseDoi() throws Exception { + BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1103/physrevlett.124.029002"); + assertEquals(Optional.of(new URL("https://journals.aps.org/prl/pdf/10.1103/PhysRevLett.124.029002")), finder.findFullText(entry)); + } + + @Test + void notFindFullTextForUnauthorized() throws Exception { + BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1103/PhysRevLett.89.127401"); + assertEquals(Optional.empty(), finder.findFullText(entry)); + } + + @Test + void notFindFullTextForUnknownEntry() throws Exception { + BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1016/j.aasri.2014.0559.002"); + assertEquals(Optional.empty(), finder.findFullText(entry)); + } +} From 497fcd787f9bca1dd281787220a9d849eb67d98f Mon Sep 17 00:00:00 2001 From: Linus Dietz Date: Thu, 19 Mar 2020 21:07:34 +0100 Subject: [PATCH 175/287] Move Springer key to environment (#6139) --- .github/workflows/deployment.yml | 37 ++++++++------- .github/workflows/tests-fetchers.yml | 3 ++ .github/workflows/tests-oracle.yml | 3 ++ .github/workflows/tests.yml | 3 ++ build.gradle | 1 + src/main/java/org/jabref/Globals.java | 4 +- src/main/java/org/jabref/JabRefGUI.java | 2 +- src/main/java/org/jabref/JabRefMain.java | 8 ++-- src/main/java/org/jabref/cli/JabRefCLI.java | 2 +- .../gui/entryeditor/RelatedArticlesTab.java | 2 +- .../errorconsole/ErrorConsoleViewModel.java | 2 +- .../jabref/gui/help/AboutDialogViewModel.java | 10 ++-- .../gui/help/SearchForUpdateAction.java | 2 +- .../importer/fetcher/SpringerFetcher.java | 3 +- .../java/org/jabref/logic/util/BuildInfo.java | 47 ++++--------------- src/main/resources/build.properties | 1 + .../org/jabref/logic/util/BuildInfoTest.java | 8 ++-- 17 files changed, 63 insertions(+), 75 deletions(-) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 5f4a449072a..d4671771481 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -15,6 +15,9 @@ on: - 'src/test/**' - 'README.md' +env: + SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }} + jobs: build: strategy: @@ -22,21 +25,21 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] include: - - os: ubuntu-latest - displayName: linux - jpackageDownload: https://download.java.net/java/early_access/jdk14/34/GPL/openjdk-14-ea+34_linux-x64_bin.tar.gz - jdk14Path: /jdk-14 - archivePortable: tar -c -C build/distribution JabRef | pigz --rsyncable > build/distribution/JabRef-portable_linux.tar.gz && rm -R build/distribution/JabRef - - os: windows-latest - displayName: windows - jpackageDownload: https://download.java.net/java/early_access/jdk14/34/GPL/openjdk-14-ea+34_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/jdk14/34/GPL/openjdk-14-ea+34_osx-x64_bin.tar.gz - jdk14Path: /jdk-14.jdk/Contents/Home - archivePortable: brew install pigz && tar -c -C build/distribution JabRef.app | pigz --rsyncable > build/distribution/JabRef-portable_macos.tar.gz && rm -R build/distribution/JabRef.app + - os: ubuntu-latest + displayName: linux + jpackageDownload: https://download.java.net/java/early_access/jdk14/34/GPL/openjdk-14-ea+34_linux-x64_bin.tar.gz + jdk14Path: /jdk-14 + archivePortable: tar -c -C build/distribution JabRef | pigz --rsyncable > build/distribution/JabRef-portable_linux.tar.gz && rm -R build/distribution/JabRef + - os: windows-latest + displayName: windows + jpackageDownload: https://download.java.net/java/early_access/jdk14/34/GPL/openjdk-14-ea+34_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/jdk14/34/GPL/openjdk-14-ea+34_osx-x64_bin.tar.gz + jdk14Path: /jdk-14.jdk/Contents/Home + archivePortable: brew install pigz && tar -c -C build/distribution JabRef.app | pigz --rsyncable > build/distribution/JabRef-portable_macos.tar.gz && rm -R build/distribution/JabRef.app runs-on: ${{ matrix.os }} name: Create installer and portable version for ${{ matrix.displayName }} @@ -49,7 +52,7 @@ jobs: - name: Install GitVersion uses: gittools/actions/gitversion/setup@v0.9.1 with: - versionSpec: '5.1.3' + versionSpec: '5.1.3' - name: Run GitVersion id: gitversion uses: gittools/actions/gitversion/execute@v0.9.1 @@ -127,7 +130,7 @@ jobs: - name: Install GitVersion uses: gittools/actions/gitversion/setup@v0.9.1 with: - versionSpec: '5.1.3' + versionSpec: '5.1.3' - name: Run GitVersion id: gitversion uses: gittools/actions/gitversion/execute@v0.9.1 diff --git a/.github/workflows/tests-fetchers.yml b/.github/workflows/tests-fetchers.yml index 5cefdd1cdd3..dfdab9a3672 100644 --- a/.github/workflows/tests-fetchers.yml +++ b/.github/workflows/tests-fetchers.yml @@ -21,6 +21,9 @@ on: # run on each Wednesday - cron: '2 3 * * 3' +env: + SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }} + jobs: fetchertests: name: Fetcher tests diff --git a/.github/workflows/tests-oracle.yml b/.github/workflows/tests-oracle.yml index dbaf5ddb361..a79768fe6d7 100644 --- a/.github/workflows/tests-oracle.yml +++ b/.github/workflows/tests-oracle.yml @@ -18,6 +18,9 @@ on: # run on each Wednesday - cron: '2 3 * * 3' +env: + SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }} + jobs: oracletests: name: Oracle tests diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4b1f876f1b9..085ead03b89 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,6 +7,9 @@ on: pull_request: # always run on pull requests +env: + SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }} + jobs: checkstyle: name: Checkstyle diff --git a/build.gradle b/build.gradle index 18e1e20617f..af780ad755f 100644 --- a/build.gradle +++ b/build.gradle @@ -284,6 +284,7 @@ processResources { "authors": new File('AUTHORS').readLines().findAll { !it.startsWith("#") }.join(", "), "developers": new File('DEVELOPERS').readLines().findAll { !it.startsWith("#") }.join(", "), "azureInstrumentationKey": System.getenv('AzureInstrumentationKey'), + "springerNatureAPIKey": System.getenv('SpringerNatureAPIKey'), "minRequiredJavaVersion": minRequiredJavaVersion, "allowJava9": allowJava9 diff --git a/src/main/java/org/jabref/Globals.java b/src/main/java/org/jabref/Globals.java index 2524305194e..5f8177ffbca 100644 --- a/src/main/java/org/jabref/Globals.java +++ b/src/main/java/org/jabref/Globals.java @@ -113,10 +113,10 @@ private static void stopTelemetryClient() { private static void startTelemetryClient() { TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.getActive(); - telemetryConfiguration.setInstrumentationKey(Globals.BUILD_INFO.getAzureInstrumentationKey()); + telemetryConfiguration.setInstrumentationKey(Globals.BUILD_INFO.azureInstrumentationKey); telemetryConfiguration.setTrackingIsDisabled(!Globals.prefs.shouldCollectTelemetry()); telemetryClient = new TelemetryClient(telemetryConfiguration); - telemetryClient.getContext().getProperties().put("JabRef version", Globals.BUILD_INFO.getVersion().toString()); + telemetryClient.getContext().getProperties().put("JabRef version", Globals.BUILD_INFO.version.toString()); telemetryClient.getContext().getProperties().put("Java version", StandardSystemProperty.JAVA_VERSION.value()); telemetryClient.getContext().getUser().setId(Globals.prefs.getOrCreateUserId()); telemetryClient.getContext().getSession().setId(UUID.randomUUID().toString()); diff --git a/src/main/java/org/jabref/JabRefGUI.java b/src/main/java/org/jabref/JabRefGUI.java index d1f4057818b..1ace4ffca4a 100644 --- a/src/main/java/org/jabref/JabRefGUI.java +++ b/src/main/java/org/jabref/JabRefGUI.java @@ -51,7 +51,7 @@ public JabRefGUI(Stage mainStage, List databases, boolean isBlank) mainFrame = new JabRefFrame(mainStage); openWindow(mainStage); - new VersionWorker(Globals.BUILD_INFO.getVersion(), Globals.prefs.getVersionPreferences().getIgnoredVersion(), mainFrame.getDialogService(), Globals.TASK_EXECUTOR) + new VersionWorker(Globals.BUILD_INFO.version, Globals.prefs.getVersionPreferences().getIgnoredVersion(), mainFrame.getDialogService(), Globals.TASK_EXECUTOR) .checkForNewVersionDelayed(); } diff --git a/src/main/java/org/jabref/JabRefMain.java b/src/main/java/org/jabref/JabRefMain.java index ec1cf738ac8..64caaf3e373 100644 --- a/src/main/java/org/jabref/JabRefMain.java +++ b/src/main/java/org/jabref/JabRefMain.java @@ -109,19 +109,19 @@ private static void ensureCorrectJavaVersion() { // Check if we are running an acceptable version of Java final BuildInfo buildInfo = Globals.BUILD_INFO; JavaVersion checker = new JavaVersion(); - final boolean java9Fail = !buildInfo.isAllowJava9() && checker.isJava9(); - final boolean versionFail = !checker.isAtLeast(buildInfo.getMinRequiredJavaVersion()); + final boolean java9Fail = !buildInfo.allowJava9 && checker.isJava9(); + final boolean versionFail = !checker.isAtLeast(buildInfo.minRequiredJavaVersion); if (java9Fail || versionFail) { StringBuilder versionError = new StringBuilder( Localization.lang("Your current Java version (%0) is not supported. Please install version %1 or higher.", checker.getJavaVersion(), - buildInfo.getMinRequiredJavaVersion())); + buildInfo.minRequiredJavaVersion)); versionError.append("\n"); versionError.append(Localization.lang("Your Java Runtime Environment is located at %0.", checker.getJavaInstallationDirectory())); - if (!buildInfo.isAllowJava9()) { + if (!buildInfo.allowJava9) { versionError.append("\n"); versionError.append(Localization.lang("Note that currently, JabRef does not run with Java 9.")); } diff --git a/src/main/java/org/jabref/cli/JabRefCLI.java b/src/main/java/org/jabref/cli/JabRefCLI.java index a279a266aa4..0f3baecdf59 100644 --- a/src/main/java/org/jabref/cli/JabRefCLI.java +++ b/src/main/java/org/jabref/cli/JabRefCLI.java @@ -255,7 +255,7 @@ public static void printUsage() { } private String getVersionInfo() { - return String.format("JabRef %s", Globals.BUILD_INFO.getVersion()); + return String.format("JabRef %s", Globals.BUILD_INFO.version); } public List getLeftOver() { diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index d1174993247..1e20b41c7b1 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -61,7 +61,7 @@ private StackPane getRelatedArticlesPane(BibEntry entry) { progress.setMaxSize(100, 100); MrDLibFetcher fetcher = new MrDLibFetcher(Globals.prefs.get(JabRefPreferences.LANGUAGE), - Globals.BUILD_INFO.getVersion()); + Globals.BUILD_INFO.version); BackgroundTask .wrap(() -> fetcher.performSearch(entry)) .onRunning(() -> progress.setVisible(true)) diff --git a/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java b/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java index a47ba6f02be..dd3ac174be4 100644 --- a/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java +++ b/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java @@ -92,7 +92,7 @@ public void clearLog() { public void reportIssue() { try { // System info - String systemInfo = String.format("JabRef %s%n%s %s %s %nJava %s", buildInfo.getVersion(), BuildInfo.OS, + String systemInfo = String.format("JabRef %s%n%s %s %s %nJava %s", buildInfo.version, BuildInfo.OS, BuildInfo.OS_VERSION, BuildInfo.OS_ARCH, BuildInfo.JAVA_VERSION); // Steps to reproduce String howToReproduce = "Steps to reproduce:\n\n1. ...\n2. ...\n3. ..."; diff --git a/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java b/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java index f6534230b57..b6ab45a5016 100644 --- a/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java +++ b/src/main/java/org/jabref/gui/help/AboutDialogViewModel.java @@ -43,7 +43,7 @@ public class AboutDialogViewModel extends AbstractViewModel { public AboutDialogViewModel(DialogService dialogService, ClipBoardManager clipBoardManager, BuildInfo buildInfo) { this.dialogService = Objects.requireNonNull(dialogService); this.clipBoardManager = Objects.requireNonNull(clipBoardManager); - String[] version = buildInfo.getVersion().getFullVersion().split("--"); + String[] version = buildInfo.version.getFullVersion().split("--"); heading.set("JabRef " + version[0]); if (version.length == 1) { @@ -54,11 +54,11 @@ public AboutDialogViewModel(DialogService dialogService, ClipBoardManager clipBo Collectors.joining("--")); developmentVersion.set(dev); } - developers.set(buildInfo.getDevelopers()); - authors.set(buildInfo.getAuthors()); + developers.set(buildInfo.developers); + authors.set(buildInfo.authors); license.set(Localization.lang("License") + ":"); - changelogUrl = buildInfo.getVersion().getChangelogUrl(); - versionInfo = String.format("JabRef %s%n%s %s %s %nJava %s", buildInfo.getVersion(), BuildInfo.OS, + changelogUrl = buildInfo.version.getChangelogUrl(); + versionInfo = String.format("JabRef %s%n%s %s %s %nJava %s", buildInfo.version, BuildInfo.OS, BuildInfo.OS_VERSION, BuildInfo.OS_ARCH, BuildInfo.JAVA_VERSION); } diff --git a/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java b/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java index 3e85c2fc9e1..5e39a0e6d7c 100644 --- a/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java +++ b/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java @@ -22,7 +22,7 @@ public SearchForUpdateAction(BuildInfo buildInfo, VersionPreferences versionPref @Override public void execute() { - new VersionWorker(buildInfo.getVersion(), versionPreferences.getIgnoredVersion(), dialogService, taskExecutor) + new VersionWorker(buildInfo.version, versionPreferences.getIgnoredVersion(), dialogService, taskExecutor) .checkForNewVersionAsync(); } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java index 7eefe067392..817f07f76aa 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/SpringerFetcher.java @@ -14,6 +14,7 @@ import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.Parser; import org.jabref.logic.importer.SearchBasedParserFetcher; +import org.jabref.logic.util.BuildInfo; import org.jabref.logic.util.OS; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; @@ -38,7 +39,7 @@ public class SpringerFetcher implements SearchBasedParserFetcher { private static final Logger LOGGER = LoggerFactory.getLogger(SpringerFetcher.class); private static final String API_URL = "http://api.springernature.com/meta/v1/json"; - private static final String API_KEY = "a98b4a55181ffcd27259bea45edad12e"; + private static final String API_KEY = new BuildInfo().springerNatureAPIKey; /** * Convert a JSONObject obtained from http://api.springer.com/metadata/json to a BibEntry diff --git a/src/main/java/org/jabref/logic/util/BuildInfo.java b/src/main/java/org/jabref/logic/util/BuildInfo.java index adbd7e00a94..74ca72bb903 100644 --- a/src/main/java/org/jabref/logic/util/BuildInfo.java +++ b/src/main/java/org/jabref/logic/util/BuildInfo.java @@ -7,7 +7,7 @@ import java.util.Locale; import java.util.Properties; -public class BuildInfo { +public final class BuildInfo { public static final String UNKNOWN_VERSION = "*unknown*"; @@ -16,14 +16,14 @@ public class BuildInfo { public static final String OS_ARCH = System.getProperty("os.arch", UNKNOWN_VERSION).toLowerCase(Locale.ROOT); public static final String JAVA_VERSION = System.getProperty("java.version", UNKNOWN_VERSION).toLowerCase(Locale.ROOT); - private final Version version; - private final String authors; - private final String developers; - private final String year; - private final String azureInstrumentationKey; - private final String minRequiredJavaVersion; - private final boolean allowJava9; - + public final Version version; + public final String authors; + public final String developers; + public final String year; + public final String azureInstrumentationKey; + public final String springerNatureAPIKey; + public final String minRequiredJavaVersion; + public final boolean allowJava9; public BuildInfo() { this("/build.properties"); @@ -47,35 +47,8 @@ public BuildInfo(String path) { year = properties.getProperty("year", ""); developers = properties.getProperty("developers", ""); azureInstrumentationKey = properties.getProperty("azureInstrumentationKey", ""); + springerNatureAPIKey = properties.getProperty("springerNatureAPIKey", ""); minRequiredJavaVersion = properties.getProperty("minRequiredJavaVersion", "1.8"); allowJava9 = "true".equals(properties.getProperty("allowJava9", "")); } - - public Version getVersion() { - return version; - } - - public String getAuthors() { - return authors; - } - - public String getDevelopers() { - return developers; - } - - public String getYear() { - return year; - } - - public String getAzureInstrumentationKey() { - return azureInstrumentationKey; - } - - public String getMinRequiredJavaVersion() { - return minRequiredJavaVersion; - } - - public boolean isAllowJava9() { - return allowJava9; - } } diff --git a/src/main/resources/build.properties b/src/main/resources/build.properties index 4b0475757d0..1380abc9330 100644 --- a/src/main/resources/build.properties +++ b/src/main/resources/build.properties @@ -3,5 +3,6 @@ year=${year} authors=${authors} developers=${developers} azureInstrumentationKey=${azureInstrumentationKey} +springerNatureAPIKey=${springerNatureAPIKey} minRequiredJavaVersion = ${minRequiredJavaVersion} allowJava9 = ${allowJava9} diff --git a/src/test/java/org/jabref/logic/util/BuildInfoTest.java b/src/test/java/org/jabref/logic/util/BuildInfoTest.java index 68f9d9c94b2..45a9ecf4d87 100644 --- a/src/test/java/org/jabref/logic/util/BuildInfoTest.java +++ b/src/test/java/org/jabref/logic/util/BuildInfoTest.java @@ -11,19 +11,19 @@ public class BuildInfoTest { @Test public void testDefaults() { BuildInfo buildInfo = new BuildInfo("asdf"); - assertEquals("*unknown*", buildInfo.getVersion().getFullVersion()); + assertEquals("*unknown*", buildInfo.version.getFullVersion()); } @Test public void testFileImport() { BuildInfo buildInfo = new BuildInfo("/org/jabref/util/build.properties"); - assertEquals("42", buildInfo.getVersion().getFullVersion()); + assertEquals("42", buildInfo.version.getFullVersion()); } @Test public void azureInstrumentationKeyIsNotEmpty() { BuildInfo buildInfo = new BuildInfo(); - assertNotNull(buildInfo.getAzureInstrumentationKey()); - assertNotEquals("", buildInfo.getAzureInstrumentationKey()); + assertNotNull(buildInfo.azureInstrumentationKey); + assertNotEquals("", buildInfo.azureInstrumentationKey); } } From 052eddd4c6c4ee002cf56ebd91c7d8403a349b0f Mon Sep 17 00:00:00 2001 From: ShikunXiong <53288073+ShikunXiong@users.noreply.github.com> Date: Fri, 20 Mar 2020 06:05:20 -0700 Subject: [PATCH 176/287] Tooltips for entry editor fields (#6046) Co-authored-by: Tobias Diez --- CHANGELOG.md | 1 + .../gui/fieldeditors/FieldNameLabel.java | 143 ++++++++++++++++++ .../model/entry/field/StandardField.java | 2 + src/main/resources/l10n/JabRef_en.properties | 62 +++++++- 4 files changed, 206 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32c7ef06b39..013c8ee4518 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve ### Added - We added support for searching ShortScience for an entry through the user's browser. [#6018](https://github.com/JabRef/jabref/pull/6018) +- We added tooltips for most fields in the entry editor containing a short description. [#5847](https://github.com/JabRef/jabref/issues/5847) ### Changed diff --git a/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java b/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java index f36eafbb808..91b48f52721 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java @@ -3,8 +3,13 @@ import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; +import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.Field; +import org.jabref.model.entry.field.InternalField; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.strings.StringUtil; public class FieldNameLabel extends Label { @@ -14,5 +19,143 @@ public FieldNameLabel(Field field) { setPadding(new Insets(4, 0, 0, 0)); setAlignment(Pos.CENTER); setPrefHeight(Double.POSITIVE_INFINITY); + + String description = getDescription(field); + if (StringUtil.isNotBlank(description)) { + Tooltip tooltip = new Tooltip(); + tooltip.setText(description); + this.setTooltip(tooltip); + } + } + + public String getDescription(Field field) { + if (field.isStandardField()) { + StandardField standardField = (StandardField) field; + switch (standardField) { + case ADDENDUM: + return Localization.lang("Miscellaneous bibliographic data usually printed at the end of the entry."); + case AFTERWORD: + return Localization.lang("Author(s) of an afterword to the work."); + case ANNOTATOR: + return Localization.lang("Author(s) of annotations to the work."); + case AUTHOR: + return Localization.lang("Author(s) of the work."); + case BOOKTITLE: + return Localization.lang("Title of the main publication this work is part of."); + case CHAPTER: + return Localization.lang("Chapter or section or any other unit of a work."); + case COMMENTATOR: + return Localization.lang("Author(s) of a commentary to the work.") + "\n" + + Localization.lang("Note that this field is intended for commented editions which have a commentator in addition to the author. If the work is a stand-alone commentary, the commentator should be given in the author field."); + case DATE: + return Localization.lang("Publication date of the work."); + case DOI: + return Localization.lang("Digital Object Identifier of the work."); + case EDITION: + return Localization.lang("Edition of a printed publication."); + case EDITOR: + return Localization.lang("Editor(s) of the work or the main publication, depending on the type of the entry."); + case EID: + return Localization.lang("Electronic identifier of a work.") + "\n" + + Localization.lang("This field may replace the pages field for journals deviating from the classic pagination scheme of printed journals by only enumerating articles or papers and not pages."); + case EPRINT: + return Localization.lang("Electronic identifier of an online publication.") + "\n" + + Localization.lang("This is roughly comparable to a DOI but specific to a certain archive, repository, service, or system."); + case EPRINTCLASS: + case PRIMARYCLASS: + return Localization.lang("Additional information related to the resource indicated by the eprint field.") + "\n" + + Localization.lang("This could be a section of an archive, a path indicating a service, a classification of some sort."); + case EPRINTTYPE: + case ARCHIVEPREFIX: + return Localization.lang("Type of the eprint identifier, e. g., the name of the archive, repository, service, or system the eprint field refers to."); + case EVENTDATE: + return Localization.lang("Date of a conference, a symposium, or some other event."); + case EVENTTITLE: + return Localization.lang("Title of a conference, a symposium, or some other event.") + "\n" + + Localization.lang("Note that this field holds the plain title of the event. Things like \"Proceedings of the Fifth XYZ Conference\" go into the titleaddon or booktitleaddon field."); + case EVENTTITLEADDON: + return Localization.lang("Annex to the eventtitle field.") + "\n" + + Localization.lang("Can be used for known event acronyms."); + case FILE: + case PDF: + return Localization.lang("Link(s) to a local PDF or other document of the work."); + case HOWPUBLISHED: + return Localization.lang("Publication notice for unusual publications which do not fit into any of the common categories."); + case INSTITUTION: + case SCHOOL: + return Localization.lang("Name of a university or some other institution."); + case INTRODUCTION: + return Localization.lang("Author(s) of an introduction to the work."); + case ISBN: + return Localization.lang("International Standard Book Number of a book."); + case ISSUE: + return Localization.lang("Issue of a journal.") + "\n" + + Localization.lang("This field is intended for journals whose individual issues are identified by a designation such as \"Spring\" or \"Summer\" rather than the month or a number. Integer ranges and short designators are better written to the number field."); + case ISSUESUBTITLE: + return Localization.lang("Subtitle of a specific issue of a journal or other periodical."); + case ISSUETITLE: + return Localization.lang("Title of a specific issue of a journal or other periodical."); + case JOURNALTITLE: + case JOURNAL: + return Localization.lang("Name of a journal, a newspaper, or some other periodical."); + case LABEL: + return Localization.lang("Designation to be used by the citation style as a substitute for the regular label if any data required to generate the regular label is missing."); + case LIBRARY: + return Localization.lang("Information such as a library name and a call number."); + case LOCATION: + case ADDRESS: + return Localization.lang("The place(s) of publication, i. e., the location of the publisher or institution, depending on the entry type."); + case MAINTITLE: + return Localization.lang("Main title of a multi-volume book, such as \"Collected Works\"."); + case MONTH: + return Localization.lang("Publication month."); + case NOTE: + return Localization.lang("Miscellaneous bibliographic data which does not fit into any other field."); + case NUMBER: + return Localization.lang("Number of a journal or the volume/number of a book in a series."); + case ORGANIZATION: + return Localization.lang("Organization(s) that published a manual or an online resource, or sponsored a conference."); + case PAGES: + return Localization.lang("One or more page numbers or page ranges.") + "\n" + + Localization.lang("If the work is published as part of another one, such as an article in a journal or a collection, this field holds the relevant page range in that other work. It may also be used to limit the reference to a specific part of a work (a chapter in a book, for example). For papers in electronic journals with anon-classical pagination setup the eid field may be more suitable."); + case PAGETOTAL: + return Localization.lang("Total number of pages of the work."); + case PUBLISHER: + return Localization.lang("Name(s) of the publisher(s)."); + case PUBSTATE: + return Localization.lang("Publication state of the work, e. g., \"in press\"."); + case SERIES: + return Localization.lang("Name of a publication series, such as \"Studies in...\", or the number of a journal series."); + case SUBTITLE: + return Localization.lang("Subtitle of the work."); + case TITLE: + return Localization.lang("Title of the work."); + case URL: + return Localization.lang("URL of an online publication."); + case URLDATE: + return Localization.lang("Access date of the address specified in the url field."); + case VENUE: + return Localization.lang("Location of a conference, a symposium, or some other event."); + case VERSION: + return Localization.lang("Revision number of a piece of software, a manual, etc."); + case VOLUME: + return Localization.lang("Volume of a multi-volume book or a periodical."); + case VOLUMES: + return Localization.lang("Total number of volumes of a multi-volume work."); + case YEAR: + return Localization.lang("Year of publication."); + case KEYWORDS: + return Localization.lang("Separated list of keywords."); + } + } else if (field instanceof InternalField) { + InternalField internalField = (InternalField) field; + switch (internalField) { + case KEY_FIELD: + return Localization.lang("Key by which the work may be cited."); + case GROUPS: + return Localization.lang("Name(s) of the (manual) groups the entry belongs to."); + } + } + return ""; } } diff --git a/src/main/java/org/jabref/model/entry/field/StandardField.java b/src/main/java/org/jabref/model/entry/field/StandardField.java index 6fe1b1e5a8f..6f10d4e0c57 100644 --- a/src/main/java/org/jabref/model/entry/field/StandardField.java +++ b/src/main/java/org/jabref/model/entry/field/StandardField.java @@ -72,6 +72,8 @@ public enum StandardField implements Field { KEY("key"), KEYWORDS("keywords"), LANGUAGE("language", FieldProperty.LANGUAGE), + LABEL("label"), + LIBRARY("library"), LOCATION("location"), MAINSUBTITLE("mainsubtitle", FieldProperty.BOOK_NAME), MAINTITLE("maintitle", FieldProperty.BOOK_NAME), diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 3915f9ca525..04daaace2f5 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2100,7 +2100,6 @@ Required\ and\ optional\ fields=Required and optional fields Index=Index Remove\ entry\ type=Remove entry type Remove\ field\ %0\ from\ currently\ selected\ entry\ type=Remove field %0 from currently selected entry type - Optional=Optional Required=Required Entry\ type\ cannot\ be\ empty.\ Please\ enter\ a\ name.=Entry type cannot be empty. Please enter a name. @@ -2111,5 +2110,64 @@ Unable\ to\ open\ ShortScience.=Unable to open ShortScience. Shared\ database=Shared database Lookup=Lookup - +Access\ date\ of\ the\ address\ specified\ in\ the\ url\ field.=Access date of the address specified in the url field. +Additional\ information\ related\ to\ the\ resource\ indicated\ by\ the\ eprint\ field.=Additional information related to the resource indicated by the eprint field. +Annex\ to\ the\ eventtitle\ field.=Annex to the eventtitle field. +Author(s)\ of\ a\ commentary\ to\ the\ work.=Author(s) of a commentary to the work. +Author(s)\ of\ an\ afterword\ to\ the\ work.=Author(s) of an afterword to the work. +Author(s)\ of\ an\ introduction\ to\ the\ work.=Author(s) of an introduction to the work. +Author(s)\ of\ annotations\ to\ the\ work.=Author(s) of annotations to the work. +Author(s)\ of\ the\ work.=Author(s) of the work. +Can\ be\ used\ for\ known\ event\ acronyms.=Can be used for known event acronyms. +Chapter\ or\ section\ or\ any\ other\ unit\ of\ a\ work.=Chapter or section or any other unit of a work. +Date\ of\ a\ conference,\ a\ symposium,\ or\ some\ other\ event.=Date of a conference, a symposium, or some other event. +Designation\ to\ be\ used\ by\ the\ citation\ style\ as\ a\ substitute\ for\ the\ regular\ label\ if\ any\ data\ required\ to\ generate\ the\ regular\ label\ is\ missing.=Designation to be used by the citation style as a substitute for the regular label if any data required to generate the regular label is missing. +Digital\ Object\ Identifier\ of\ the\ work.=Digital Object Identifier of the work. +Edition\ of\ a\ printed\ publication.=Edition of a printed publication. +Editor(s)\ of\ the\ work\ or\ the\ main\ publication,\ depending\ on\ the\ type\ of\ the\ entry.=Editor(s) of the work or the main publication, depending on the type of the entry. +Electronic\ identifier\ of\ a\ work.=Electronic identifier of a work. +Electronic\ identifier\ of\ an\ online\ publication.=Electronic identifier of an online publication. +If\ the\ work\ is\ published\ as\ part\ of\ another\ one,\ such\ as\ an\ article\ in\ a\ journal\ or\ a\ collection,\ this\ field\ holds\ the\ relevant\ page\ range\ in\ that\ other\ work.\ It\ may\ also\ be\ used\ to\ limit\ the\ reference\ to\ a\ specific\ part\ of\ a\ work\ (a\ chapter\ in\ a\ book,\ for\ example).\ For\ papers\ in\ electronic\ journals\ with\ anon-classical\ pagination\ setup\ the\ eid\ field\ may\ be\ more\ suitable.=If the work is published as part of another one, such as an article in a journal or a collection, this field holds the relevant page range in that other work. It may also be used to limit the reference to a specific part of a work (a chapter in a book, for example). For papers in electronic journals with anon-classical pagination setup the eid field may be more suitable. +Information\ such\ as\ a\ library\ name\ and\ a\ call\ number.=Information such as a library name and a call number. +International\ Standard\ Book\ Number\ of\ a\ book.=International Standard Book Number of a book. +Issue\ of\ a\ journal.=Issue of a journal. +Key\ by\ which\ the\ work\ may\ be\ cited.=Key by which the work may be cited. +Link(s)\ to\ a\ local\ PDF\ or\ other\ document\ of\ the\ work.=Link(s) to a local PDF or other document of the work. +Location\ of\ a\ conference,\ a\ symposium,\ or\ some\ other\ event.=Location of a conference, a symposium, or some other event. +Main\ title\ of\ a\ multi-volume\ book,\ such\ as\ "Collected\ Works".=Main title of a multi-volume book, such as "Collected Works". +Miscellaneous\ bibliographic\ data\ usually\ printed\ at\ the\ end\ of\ the\ entry.=Miscellaneous bibliographic data usually printed at the end of the entry. +Miscellaneous\ bibliographic\ data\ which\ does\ not\ fit\ into\ any\ other\ field.=Miscellaneous bibliographic data which does not fit into any other field. +Name(s)\ of\ the\ (manual)\ groups\ the\ entry\ belongs\ to.=Name(s) of the (manual) groups the entry belongs to. +Name(s)\ of\ the\ publisher(s).=Name(s) of the publisher(s). +Name\ of\ a\ journal,\ a\ newspaper,\ or\ some\ other\ periodical.=Name of a journal, a newspaper, or some other periodical. +Name\ of\ a\ publication\ series,\ such\ as\ "Studies\ in...",\ or\ the\ number\ of\ a\ journal\ series.=Name of a publication series, such as "Studies in...", or the number of a journal series. +Name\ of\ a\ university\ or\ some\ other\ institution.=Name of a university or some other institution. +Note\ that\ this\ field\ holds\ the\ plain\ title\ of\ the\ event.\ Things\ like\ "Proceedings\ of\ the\ Fifth\ XYZ\ Conference"\ go\ into\ the\ titleaddon\ or\ booktitleaddon\ field.=Note that this field holds the plain title of the event. Things like "Proceedings of the Fifth XYZ Conference" go into the titleaddon or booktitleaddon field. +Note\ that\ this\ field\ is\ intended\ for\ commented\ editions\ which\ have\ a\ commentator\ in\ addition\ to\ the\ author.\ If\ the\ work\ is\ a\ stand-alone\ commentary,\ the\ commentator\ should\ be\ given\ in\ the\ author\ field.=Note that this field is intended for commented editions which have a commentator in addition to the author. If the work is a stand-alone commentary, the commentator should be given in the author field. +Number\ of\ a\ journal\ or\ the\ volume/number\ of\ a\ book\ in\ a\ series.=Number of a journal or the volume/number of a book in a series. +One\ or\ more\ page\ numbers\ or\ page\ ranges.=One or more page numbers or page ranges. +Organization(s)\ that\ published\ a\ manual\ or\ an\ online\ resource,\ or\ sponsored\ a\ conference.=Organization(s) that published a manual or an online resource, or sponsored a conference. +Publication\ date\ of\ the\ work.=Publication date of the work. +Publication\ month.=Publication month. +Publication\ notice\ for\ unusual\ publications\ which\ do\ not\ fit\ into\ any\ of\ the\ common\ categories.=Publication notice for unusual publications which do not fit into any of the common categories. +Publication\ state\ of\ the\ work,\ e.\ g.,\ "in\ press".=Publication state of the work, e. g., "in press". +Revision\ number\ of\ a\ piece\ of\ software,\ a\ manual,\ etc.=Revision number of a piece of software, a manual, etc. +Separated\ list\ of\ keywords.=Separated list of keywords. +Subtitle\ of\ a\ specific\ issue\ of\ a\ journal\ or\ other\ periodical.=Subtitle of a specific issue of a journal or other periodical. +Subtitle\ of\ the\ work.=Subtitle of the work. +The\ place(s)\ of\ publication,\ i.\ e.,\ the\ location\ of\ the\ publisher\ or\ institution,\ depending\ on\ the\ entry\ type.=The place(s) of publication, i. e., the location of the publisher or institution, depending on the entry type. +This\ could\ be\ a\ section\ of\ an\ archive,\ a\ path\ indicating\ a\ service,\ a\ classification\ of\ some\ sort.=This could be a section of an archive, a path indicating a service, a classification of some sort. +This\ field\ is\ intended\ for\ journals\ whose\ individual\ issues\ are\ identified\ by\ a\ designation\ such\ as\ "Spring"\ or\ "Summer"\ rather\ than\ the\ month\ or\ a\ number.\ Integer\ ranges\ and\ short\ designators\ are\ better\ written\ to\ the\ number\ field.=This field is intended for journals whose individual issues are identified by a designation such as "Spring" or "Summer" rather than the month or a number. Integer ranges and short designators are better written to the number field. +This\ field\ may\ replace\ the\ pages\ field\ for\ journals\ deviating\ from\ the\ classic\ pagination\ scheme\ of\ printed\ journals\ by\ only\ enumerating\ articles\ or\ papers\ and\ not\ pages.=This field may replace the pages field for journals deviating from the classic pagination scheme of printed journals by only enumerating articles or papers and not pages. +This\ is\ roughly\ comparable\ to\ a\ DOI\ but\ specific\ to\ a\ certain\ archive,\ repository,\ service,\ or\ system.=This is roughly comparable to a DOI but specific to a certain archive, repository, service, or system. +Title\ of\ a\ conference,\ a\ symposium,\ or\ some\ other\ event.=Title of a conference, a symposium, or some other event. +Title\ of\ a\ specific\ issue\ of\ a\ journal\ or\ other\ periodical.=Title of a specific issue of a journal or other periodical. +Title\ of\ the\ main\ publication\ this\ work\ is\ part\ of.=Title of the main publication this work is part of. +Title\ of\ the\ work.=Title of the work. +Total\ number\ of\ pages\ of\ the\ work.=Total number of pages of the work. +Total\ number\ of\ volumes\ of\ a\ multi-volume\ work.=Total number of volumes of a multi-volume work. +Type\ of\ the\ eprint\ identifier,\ e.\ g.,\ the\ name\ of\ the\ archive,\ repository,\ service,\ or\ system\ the\ eprint\ field\ refers\ to.=Type of the eprint identifier, e. g., the name of the archive, repository, service, or system the eprint field refers to. +URL\ of\ an\ online\ publication.=URL of an online publication. +Volume\ of\ a\ multi-volume\ book\ or\ a\ periodical.=Volume of a multi-volume book or a periodical. +Year\ of\ publication.=Year of publication. Remove\ formatter\ %0=Remove formatter %0 From 23b006499f6083fcbac454aaadcf022679112bb4 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 20 Mar 2020 14:15:36 +0100 Subject: [PATCH 177/287] [WIP] Update to JDK 14 (#6145) * Update to JDK 14 * Update check-outdated-dependencies.yml * Update guidelines-for-setting-up-a-local-workspace.md * Update tests-fetchers.yml * Update tests-oracle.yml * Update build.gradle * Update deployment.yml * Update README.md * Update gradle-wrapper.properties * Remove specification of old Jacoco version Co-authored-by: Oliver Kopp --- .../workflows/check-outdated-dependencies.yml | 2 +- .github/workflows/deployment.yml | 52 ++++--------------- .github/workflows/tests-fetchers.yml | 2 +- .github/workflows/tests-oracle.yml | 2 +- .github/workflows/tests.yml | 10 ++-- README.md | 2 +- build.gradle | 8 +-- ...elines-for-setting-up-a-local-workspace.md | 18 +++---- gradle/wrapper/gradle-wrapper.properties | 2 +- 9 files changed, 32 insertions(+), 66 deletions(-) diff --git a/.github/workflows/check-outdated-dependencies.yml b/.github/workflows/check-outdated-dependencies.yml index 0402436c1cc..58e87456d08 100644 --- a/.github/workflows/check-outdated-dependencies.yml +++ b/.github/workflows/check-outdated-dependencies.yml @@ -17,7 +17,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13.0.2 + java-version: 14 - name: Look for outdated dependencies run: ./gradlew -q checkOutdatedDependencies - name: Report issues diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index d4671771481..8f572c312da 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -25,21 +25,15 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] include: - - os: ubuntu-latest - displayName: linux - jpackageDownload: https://download.java.net/java/early_access/jdk14/34/GPL/openjdk-14-ea+34_linux-x64_bin.tar.gz - jdk14Path: /jdk-14 - archivePortable: tar -c -C build/distribution JabRef | pigz --rsyncable > build/distribution/JabRef-portable_linux.tar.gz && rm -R build/distribution/JabRef - - os: windows-latest - displayName: windows - jpackageDownload: https://download.java.net/java/early_access/jdk14/34/GPL/openjdk-14-ea+34_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/jdk14/34/GPL/openjdk-14-ea+34_osx-x64_bin.tar.gz - jdk14Path: /jdk-14.jdk/Contents/Home - archivePortable: brew install pigz && tar -c -C build/distribution JabRef.app | pigz --rsyncable > build/distribution/JabRef-portable_macos.tar.gz && rm -R build/distribution/JabRef.app + - os: ubuntu-latest + displayName: linux + archivePortable: tar -c -C build/distribution JabRef | pigz --rsyncable > build/distribution/JabRef-portable_linux.tar.gz && rm -R build/distribution/JabRef + - os: windows-latest + displayName: windows + archivePortable: 7z a -r build/distribution/JabRef-portable_windows.zip ./build/distribution/JabRef && rm -R build/distribution/JabRef + - os: macOS-latest + displayName: macOS + archivePortable: brew install pigz && tar -c -C build/distribution JabRef.app | pigz --rsyncable > build/distribution/JabRef-portable_macos.tar.gz && rm -R build/distribution/JabRef.app runs-on: ${{ matrix.os }} name: Create installer and portable version for ${{ matrix.displayName }} @@ -59,7 +53,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13.0.2 + java-version: 14 # configuration based on https://github.com/actions/cache/blob/master/examples.md#java---gradle - uses: actions/cache@v1 name: Restore gradle cache @@ -75,34 +69,10 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} - - name: Download jpackage - # We need to download jpackage from https://jdk.java.net/jpackage/ - run: | - import tarfile - import zipfile - import sys - if sys.version_info[0] >= 3: - from urllib.request import urlretrieve - else: - from urllib import urlretrieve - - url = "${{ matrix.jpackageDownload }}" - tmpfile, headers = urlretrieve(url) - if (url.endswith("tar.gz")): - tar = tarfile.open(tmpfile) - tar.extractall() - tar.close() - elif (url.endswith("zip")): - zip = zipfile.ZipFile(tmpfile) - zip.extractall() - zip.close() - shell: python - name: Build runtime image run: ./gradlew -PprojVersion="${{ steps.gitversion.outputs.AssemblySemVer }}" -PprojVersionInfo="${{ steps.gitversion.outputs.InformationalVersion }}" jlinkZip - name: Build installer - run: | - export BADASS_JLINK_JPACKAGE_HOME="${GITHUB_WORKSPACE}${{ matrix.jdk14Path }}" - ./gradlew -PprojVersion="${{ steps.gitversion.outputs.AssemblySemVer }}" -PprojVersionInfo="${{ steps.gitversion.outputs.InformationalVersion }}" jpackage + run: ./gradlew -PprojVersion="${{ steps.gitversion.outputs.AssemblySemVer }}" -PprojVersionInfo="${{ steps.gitversion.outputs.InformationalVersion }}" jpackage shell: bash - name: Package application image run: ${{ matrix.archivePortable }} diff --git a/.github/workflows/tests-fetchers.yml b/.github/workflows/tests-fetchers.yml index dfdab9a3672..8e517105b95 100644 --- a/.github/workflows/tests-fetchers.yml +++ b/.github/workflows/tests-fetchers.yml @@ -37,7 +37,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13.0.2 + java-version: 14 - uses: actions/cache@v1 name: Restore gradle chache with: diff --git a/.github/workflows/tests-oracle.yml b/.github/workflows/tests-oracle.yml index a79768fe6d7..610665e2575 100644 --- a/.github/workflows/tests-oracle.yml +++ b/.github/workflows/tests-oracle.yml @@ -34,7 +34,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13.0.2 + java-version: 14 - uses: actions/cache@v1 name: Restore gradle chache with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 085ead03b89..3d362fa27f5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,7 +20,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13.0.2 + java-version: 14 - uses: actions/cache@v1 name: Restore gradle cache with: @@ -46,7 +46,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13 + java-version: 14 - uses: actions/cache@v1 name: Restore gradle chache with: @@ -90,7 +90,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13 + java-version: 14 - uses: actions/cache@v1 name: Restore gradle chache with: @@ -136,7 +136,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13 + java-version: 14 - uses: actions/cache@v1 name: Restore gradle chache with: @@ -175,7 +175,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 13 + java-version: 14 - uses: actions/cache@v1 name: Restore gradle chache with: diff --git a/README.md b/README.md index 3afd47791ff..2c57b15a927 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ We will discuss improvements with you and agree to merge them once the [develope If you want a step-by-step walk-through on how to set-up your workspace, please check [this guideline](https://devdocs.jabref.org/guidelines-for-setting-up-a-local-workspace/). -To compile JabRef from source, you need a Java Development Kit 13 and `JAVA_HOME` pointing to this JDK. +To compile JabRef from source, you need a Java Development Kit 14 and `JAVA_HOME` pointing to this JDK. To run it, just execute `gradlew run`. When you want to develop, it is necessary to generate additional sources using `gradlew generateSource` and then generate the Eclipse `gradlew eclipse`. diff --git a/build.gradle b/build.gradle index af780ad755f..b3f1871f7ec 100644 --- a/build.gradle +++ b/build.gradle @@ -46,8 +46,8 @@ group = "org.jabref" version = project.findProperty('projVersion') ?: '100.0.0' java { - sourceCompatibility = JavaVersion.VERSION_13 - targetCompatibility = JavaVersion.VERSION_13 + sourceCompatibility = JavaVersion.VERSION_14 + targetCompatibility = JavaVersion.VERSION_14 } application { @@ -217,10 +217,6 @@ dependencies { jython 'org.python:jython-standalone:2.7.1' } -jacoco { - toolVersion = '0.8.3' -} - dependencyUpdates { outputFormatter = "json" } diff --git a/docs/guidelines-for-setting-up-a-local-workspace.md b/docs/guidelines-for-setting-up-a-local-workspace.md index de776fd9ab8..b90981ccc0a 100644 --- a/docs/guidelines-for-setting-up-a-local-workspace.md +++ b/docs/guidelines-for-setting-up-a-local-workspace.md @@ -8,9 +8,9 @@ For a complete step-by-step guide for Linux using IntellJ IDEA as the IDE, have ## Prerequisites -### Java Development Kit 13 +### Java Development Kit 14 -A working Java 13 installation is required. In the command line \(terminal in Linux, cmd in Windows\) run `javac -version` and make sure that the reported version is Java 13 \(e.g `javac 13.0.1`\). If `javac` is not found or a wrong version is reported, check your PATH environment variable, your JAVA\_HOME environment variable or install the most recent JDK. +A working Java 14 installation is required. In the command line \(terminal in Linux, cmd in Windows\) run `javac -version` and make sure that the reported version is Java 14 \(e.g `javac 14`\). If `javac` is not found or a wrong version is reported, check your PATH environment variable, your JAVA\_HOME environment variable or install the most recent JDK. ### git @@ -57,16 +57,16 @@ To configure IntelliJ IDEA for developing JabRef, you should first ensure that y the _Gradle_ and _Gradle Extension_ enabled. -After that, you can open `jabref/build.gradle` as a project. It is crucial that Java 13 is used consistently for the JabRef project which includes ensuring the right settings for your project structure, Gradle build, and run configurations. +After that, you can open `jabref/build.gradle` as a project. It is crucial that Java 14 is used consistently for the JabRef project which includes ensuring the right settings for your project structure, Gradle build, and run configurations. -* Ensure you have a Java 13 SDK configured by navigating to +* Ensure you have a Java 14 SDK configured by navigating to **File \| Project Structure \| Platform Settings \| SDKs**. If you don't have one, add a new Java JDK and point it to the - location of a JDK 13. + location of a JDK 14. -* Navigate to **File \| Project Structure \| Project** and ensure that the projects' SDK is Java 13 -* Navigate to **File \| Settings \| Build, Execution, Deployment \| Build Tools \| Gradle** and select the Java 13 SDK as +* Navigate to **File \| Project Structure \| Project** and ensure that the projects' SDK is Java 14 +* Navigate to **File \| Settings \| Build, Execution, Deployment \| Build Tools \| Gradle** and select the Java 14 SDK as the Gradle JVM at the bottom. @@ -119,7 +119,7 @@ To use IntelliJ IDEA's internal build system when you build JabRef through **Bui To use the "JabRef Main" run configuration, open **Run \| Edit Configurations... \| Application \| JabRef Main** and -* Verify, that your JDK 13 is used +* Verify, that your JDK 14 is used * Set "VM Options" to the following: ```text @@ -239,7 +239,7 @@ Got it running? GREAT! You are ready to lurk the code and contribute to JabRef. ### Java installation -An indication that `JAVA_HOME` is not correctly set or no JDK 13 is installed is following error message: +An indication that `JAVA_HOME` is not correctly set or no JDK 14 is installed is following error message: ```text compileJava FAILED diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a2bf1313b8a..b1332212d37 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-rc-3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From a44305bc42775851b0f7a6488f1335e4222c3197 Mon Sep 17 00:00:00 2001 From: Christoph Date: Fri, 20 Mar 2020 14:32:54 +0100 Subject: [PATCH 178/287] Add Eclipse hint for jdk14 --- docs/guidelines-for-setting-up-a-local-workspace.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/guidelines-for-setting-up-a-local-workspace.md b/docs/guidelines-for-setting-up-a-local-workspace.md index b90981ccc0a..b1f86616602 100644 --- a/docs/guidelines-for-setting-up-a-local-workspace.md +++ b/docs/guidelines-for-setting-up-a-local-workspace.md @@ -23,7 +23,7 @@ If you do not yet have a GitHub account, please [create one](https://github.com/ ### IDE -We suggest [IntelliJ IDEA](https://www.jetbrains.com/idea/) or [Eclipse](https://eclipse.org/) \(`2019-12` or newer\). +We suggest [IntelliJ IDEA](https://www.jetbrains.com/idea/) or [Eclipse (for advanced users)](https://eclipse.org/) \(`2020-03` or newer\). Under Ubuntu Linux, you can follow the [documentation from the Ubuntu Community](https://help.ubuntu.com/community/EclipseIDE#Download_Eclipse) or the [step-by-step guideline from Krizna](https://github.com/JabRef/jabref/tree/be9c788de804c2bd9e3abaf76b082b6b2e82e66f/docs/www.krizna.com/ubuntu/install-eclipse-in-ubuntu-12-04/README.md) to install Eclipse. Under Windows, download it from [www.eclipse.org](http://www.eclipse.org/downloads/) and run the installer. @@ -190,12 +190,13 @@ If you have configured Eclipse for the same project \(the required steps are des ### Setup for Eclipse -Make sure your Eclipse installation us up to date, Eclipse 2019-12 or newer is required. +Make sure your Eclipse installation us up to date, Eclipse 2020-03 or newer is required. +For Eclipse 2020-03 you need to install [jdk14 support](https://marketplace.eclipse.org/content/java-14-support-eclipse-2020-03-415) 1. Run `./gradlew run` to generate all resources and to check if JabRef runs. * The JabRef GUI should finally appear. * This step is only required once. -2. Run `./gradlew eclipse` +2. Run `./gradlew eclipse` * **This must always be executed, when there are new upstream changes.** 3. Copy the file `Log4jPlugins.java` from `build/generated/sources/annotationProcessor/java/main/org/jabref/gui/logging/plugins` to `src/main/java/org/jabref/gui/logging/plugins/` * Usually, the folder `plugins` must be created for that. From 31bdc20f1b6ff61c23cf263fa3cdc9ca02db6362 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Mar 2020 16:49:49 +0100 Subject: [PATCH 179/287] Refine Prerequisites --- ...elines-for-setting-up-a-local-workspace.md | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/docs/guidelines-for-setting-up-a-local-workspace.md b/docs/guidelines-for-setting-up-a-local-workspace.md index b1f86616602..df53e6a35a5 100644 --- a/docs/guidelines-for-setting-up-a-local-workspace.md +++ b/docs/guidelines-for-setting-up-a-local-workspace.md @@ -10,16 +10,41 @@ For a complete step-by-step guide for Linux using IntellJ IDEA as the IDE, have ### Java Development Kit 14 -A working Java 14 installation is required. In the command line \(terminal in Linux, cmd in Windows\) run `javac -version` and make sure that the reported version is Java 14 \(e.g `javac 14`\). If `javac` is not found or a wrong version is reported, check your PATH environment variable, your JAVA\_HOME environment variable or install the most recent JDK. +A working Java 14 installation is required. In the command line \(terminal in Linux, cmd in Windows\) run `javac -version` and make sure that the reported version is Java 14 \(e.g `javac 14`\). If `javac` is not found or a wrong version is reported, check your PATH environment variable, your `JAVA_HOME` environment variable or install the most recent JDK. + +Download the JDK from . On Windows, you can execute `choco install openjdk` (requires [installation of chocolatey - a package manager for Windows](https://chocolatey.org/install)). + +### GitHub Account + +If you do not yet have a GitHub account, please [create one](https://github.com/join). + +Proposals for account names: + +- Login similar to your university account. Example: `koppor` +- Use your last name prefixed by the first letter of your first name. Example: `okopp` +- Use `firstname.lastname`. Example: `oliver.kopp` + +You can hide your email adress by following the recommendations at . + +Most developers, though, do not hide their email adress. They use one mich may get public. +Mostly, they create a new email account for development only. +That account then be used for develoment mailing lists, mail exchange with other developers, etc. + +Examples: + +- Same login as in GitHub (see above). Example: `koppor@gmail.com` +- "`it`" in the name. Example: `kopp.it@gmail.com` +- Use the university login. Example: `st342435@stud.uni-stuttgart.de` ### git -It is strongly recommend that you have git installed: [official installation instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). +It is strongly recommend that you have git installed. * In Debian-based distros: `sudo apt-get install git` -* In Windows: [Download the installer](http://git-scm.com/download/win) and install it. For more advanced tooling, you may use [Git Extensions](http://gitextensions.github.io/) or [SourceTree](https://www.sourcetreeapp.com/). - See also our [tool recommendations](tools.md) for installation hints including [chocolatey](https://chocolatey.org/). - -If you do not yet have a GitHub account, please [create one](https://github.com/join). +* In Windows: [Download the installer](http://git-scm.com/download/win) and install it. + Using chocolatey, you can run `choco install git.install -y --params "/GitAndUnixToolsOnPath /WindowsTerminal` to a) install git and b) have linux commands such as `grep` available in your `PATH`. + For more advanced tooling, you may use [Fork - a fast and friendly git client for Mac and Windows](https://git-fork.com/): `choco install git-fork`. +* [official installation instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) ### IDE @@ -27,6 +52,10 @@ We suggest [IntelliJ IDEA](https://www.jetbrains.com/idea/) or [Eclipse (for adv Under Ubuntu Linux, you can follow the [documentation from the Ubuntu Community](https://help.ubuntu.com/community/EclipseIDE#Download_Eclipse) or the [step-by-step guideline from Krizna](https://github.com/JabRef/jabref/tree/be9c788de804c2bd9e3abaf76b082b6b2e82e66f/docs/www.krizna.com/ubuntu/install-eclipse-in-ubuntu-12-04/README.md) to install Eclipse. Under Windows, download it from [www.eclipse.org](http://www.eclipse.org/downloads/) and run the installer. +### Other Tooling + +See our [tool recommendations](tools.md). + ## Get the code ### Fork JabRef into your GitHub account From 4577cb9b51c6378446d21e4e14352d9f765775a9 Mon Sep 17 00:00:00 2001 From: github actions Date: Sat, 21 Mar 2020 16:50:17 +0000 Subject: [PATCH 180/287] Squashed 'src/main/resources/csl-styles/' changes from db8bd334bd..fa6bb226d2 fa6bb226d2 Create quaternaire (#4602) f2b4af45a8 Create the-journal-of-trauma-and-acute-care-surgery.csl (#4631) 0aa837e719 Update unified-style-sheet-for-linguistics.csl for "in" in chapters (#4632) git-subtree-dir: src/main/resources/csl-styles git-subtree-split: fa6bb226d27e542618b7bbd9292572b139aad4f0 --- quaternaire.csl | 350 ++++++++++++++++++ ...urnal-of-trauma-and-acute-care-surgery.csl | 245 ++++++++++++ unified-style-sheet-for-linguistics.csl | 19 +- 3 files changed, 609 insertions(+), 5 deletions(-) create mode 100644 quaternaire.csl create mode 100644 the-journal-of-trauma-and-acute-care-surgery.csl diff --git a/quaternaire.csl b/quaternaire.csl new file mode 100644 index 00000000000..457849e4f7e --- /dev/null +++ b/quaternaire.csl @@ -0,0 +1,350 @@ + + diff --git a/the-journal-of-trauma-and-acute-care-surgery.csl b/the-journal-of-trauma-and-acute-care-surgery.csl new file mode 100644 index 00000000000..d4c1163d9a3 --- /dev/null +++ b/the-journal-of-trauma-and-acute-care-surgery.csl @@ -0,0 +1,245 @@ + + diff --git a/unified-style-sheet-for-linguistics.csl b/unified-style-sheet-for-linguistics.csl index 32ea0f6ca2d..62da0287d01 100644 --- a/unified-style-sheet-for-linguistics.csl +++ b/unified-style-sheet-for-linguistics.csl @@ -26,7 +26,7 @@ - 2018-12-19T23:42:01+00:00 + 2020-03-19T16:21:55+00:00 This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License @@ -69,7 +69,6 @@ - @@ -164,7 +163,7 @@ - + @@ -372,6 +371,13 @@ + + + + + + + @@ -399,8 +405,11 @@ - - + + + + + From 107cadd80f1257da7c01208b42b96d9cdf67268e Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Mar 2020 22:51:44 +0100 Subject: [PATCH 181/287] Add hint to scroll down --- .../guidelines-for-setting-up-a-local-workspace.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/guidelines-for-setting-up-a-local-workspace.md b/docs/guidelines-for-setting-up-a-local-workspace.md index df53e6a35a5..954e77f87f7 100644 --- a/docs/guidelines-for-setting-up-a-local-workspace.md +++ b/docs/guidelines-for-setting-up-a-local-workspace.md @@ -2,12 +2,20 @@ This guide explains how to set up your environment for development of JabRef. It includes information about prerequisites, configuring your IDE, and running JabRef locally to verify your setup. +```diff +- The most important step is to configure your IDE. Please scroll down to see these steps. ++ For a step-by-step instruction, please just read on. +``` + For a complete step-by-step guide for Linux using IntellJ IDEA as the IDE, have a look at the following video instructions: [![](https://img.youtube.com/vi/JkFVJ6p0urw/mqdefault.jpg)](https://youtu.be/JkFVJ6p0urw) ## Prerequisites +This section list the prerequisites you need to get started to develop JabRef. +After this section, you are ready to get the code. + ### Java Development Kit 14 A working Java 14 installation is required. In the command line \(terminal in Linux, cmd in Windows\) run `javac -version` and make sure that the reported version is Java 14 \(e.g `javac 14`\). If `javac` is not found or a wrong version is reported, check your PATH environment variable, your `JAVA_HOME` environment variable or install the most recent JDK. @@ -58,6 +66,8 @@ See our [tool recommendations](tools.md). ## Get the code +This section explains how you get the JabRef code onto your machine in a form allowing you to make contributions. + ### Fork JabRef into your GitHub account 1. Log into your GitHub account @@ -76,6 +86,10 @@ See our [tool recommendations](tools.md). ## Configure your IDE +These steps are very important. +They allow you to focus on the content and ensure that the code formatting always goes well. +Did you know that [IntelliJ allows for reformatting selected code](https://www.jetbrains.com/help/idea/reformat-and-rearrange-code.html#reformat_code) if you press Ctrl+Alt+L? + ### Setup for IntelliJ IDEA IntelliJ IDEA fully supports Gradle as a build tool, but also has an internal build system which is usually faster. For JabRef, Gradle is required to make a full build but once set up, IntelliJ IDEA's internal system can be used for sub-sequent builds. From 9a6ddf493d47ed1c0476a06e8d5f5ec377e7a61a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Mar 2020 22:54:36 +0100 Subject: [PATCH 182/287] Fix formatting for GitBook --- docs/guidelines-for-setting-up-a-local-workspace.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/guidelines-for-setting-up-a-local-workspace.md b/docs/guidelines-for-setting-up-a-local-workspace.md index 954e77f87f7..1c8d1d8310a 100644 --- a/docs/guidelines-for-setting-up-a-local-workspace.md +++ b/docs/guidelines-for-setting-up-a-local-workspace.md @@ -2,9 +2,10 @@ This guide explains how to set up your environment for development of JabRef. It includes information about prerequisites, configuring your IDE, and running JabRef locally to verify your setup. -```diff -- The most important step is to configure your IDE. Please scroll down to see these steps. -+ For a step-by-step instruction, please just read on. +```text +The most important step is to configure your IDE. +In case you know how to install JDK14 and to fork JabRef's code, + please scroll down to the IDE setup. ``` For a complete step-by-step guide for Linux using IntellJ IDEA as the IDE, have a look at the following video instructions: From a38d7bd22059d3b6ebe2d50707c275dd75f7e2bc Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 22 Mar 2020 10:27:07 +0100 Subject: [PATCH 183/287] Fix: Only if `.sav` file has changes a recovery dialog is shown (#6116) When JabRef finds a `.sav` file without changes, there is no dialog asking for acceptance of changes anymore. Co-authored-by: Stefan Kolb --- CHANGELOG.md | 1 + src/main/java/org/jabref/JabRefGUI.java | 2 +- src/main/java/org/jabref/gui/JabRefFrame.java | 4 +- .../jabref/gui/dialogs/BackupUIManager.java | 1 - .../importer/actions/OpenDatabaseAction.java | 2 +- .../autosaveandbackup/BackupManager.java | 39 +++++++++++++------ .../logic/citationstyle/CSLAdapter.java | 2 +- .../autosaveandbackup/BackupManagerTest.java | 22 ++++++++++- .../logic/autosaveandbackup/changes.bib | 28 +++++++++++++ .../logic/autosaveandbackup/changes.bib.sav | 15 +++++++ .../logic/autosaveandbackup/no-autosave.bib | 28 +++++++++++++ .../logic/autosaveandbackup/no-changes.bib | 15 +++++++ .../autosaveandbackup/no-changes.bib.sav | 15 +++++++ 13 files changed, 155 insertions(+), 19 deletions(-) create mode 100644 src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib create mode 100644 src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib.sav create mode 100644 src/test/resources/org/jabref/logic/autosaveandbackup/no-autosave.bib create mode 100644 src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib create mode 100644 src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib.sav diff --git a/CHANGELOG.md b/CHANGELOG.md index 013c8ee4518..3878a3b541a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We improved the arXiv fetcher. Now it should find entries even more reliably and does no longer include the version (e.g `v1`) in the `eprint` field. [forum#1941](https://discourse.jabref.org/t/remove-version-in-arxiv-import/1941) - We moved the group search bar and the button "New group" from bottom to top position to make it more prominent. [#6112](https://github.com/JabRef/jabref/pull/6112) +- When JabRef finds a `.sav` file without changes, there is no dialog asking for acceptance of changes anymore. - We changed the buttons for import/export/show all/reset of preferences to smaller icon buttons in the preferences dialog. [#6130](https://github.com/JabRef/jabref/pull/6130) - We moved the functionality "Manage field names & content" from the "Library" menu to the "Edit" menu, because it affects the selected entries and not the whole library diff --git a/src/main/java/org/jabref/JabRefGUI.java b/src/main/java/org/jabref/JabRefGUI.java index 1ace4ffca4a..19be513cf87 100644 --- a/src/main/java/org/jabref/JabRefGUI.java +++ b/src/main/java/org/jabref/JabRefGUI.java @@ -247,7 +247,7 @@ private void openLastEditedDatabases() { continue; } - if (BackupManager.checkForBackupFile(dbFile.toPath())) { + if (BackupManager.backupFileDiffers(dbFile.toPath())) { BackupUIManager.showRestoreBackupDialog(mainFrame.getDialogService(), dbFile.toPath()); } diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 462786823ae..071ceeab881 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -379,7 +379,7 @@ public boolean quit() { List filenames = new ArrayList<>(); for (int i = 0; i < tabbedPane.getTabs().size(); i++) { BasePanel panel = getBasePanelAt(i); - BibDatabaseContext context = panel.getBibDatabaseContext(); + final BibDatabaseContext context = panel.getBibDatabaseContext(); if (panel.isModified() && (context.getLocation() == DatabaseLocation.LOCAL)) { tabbedPane.getSelectionModel().select(i); @@ -1153,7 +1153,7 @@ private void closeTab(BasePanel panel) { return; } - BibDatabaseContext context = panel.getBibDatabaseContext(); + final BibDatabaseContext context = panel.getBibDatabaseContext(); if (panel.isModified() && (context.getLocation() == DatabaseLocation.LOCAL)) { if (confirmClose(panel)) { diff --git a/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java b/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java index 5dca94d742b..2c7d5bcf232 100644 --- a/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java +++ b/src/main/java/org/jabref/gui/dialogs/BackupUIManager.java @@ -13,7 +13,6 @@ public class BackupUIManager { private BackupUIManager() { - } public static void showRestoreBackupDialog(DialogService dialogService, Path originalPath) { diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index a9701ce1b90..7515921fa03 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -181,7 +181,7 @@ private ParserResult loadDatabase(Path file) throws Exception { Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, fileToLoad.getParent().toString()); - if (BackupManager.checkForBackupFile(fileToLoad)) { + if (BackupManager.backupFileDiffers(fileToLoad)) { BackupUIManager.showRestoreBackupDialog(dialogService, fileToLoad); } diff --git a/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java b/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java index dded73499fc..d58ba62cf1b 100644 --- a/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java +++ b/src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java @@ -30,14 +30,15 @@ /** * Backups the given bib database file from {@link BibDatabaseContext} on every {@link BibDatabaseContextChangedEvent}. * An intelligent {@link ExecutorService} with a {@link BlockingQueue} prevents a high load while making backups and - * rejects all redundant backup tasks. - * This class does not manage the .bak file which is created when opening a database. + * rejects all redundant backup tasks. This class does not manage the .bak file which is created when opening a + * database. */ public class BackupManager { private static final Logger LOGGER = LoggerFactory.getLogger(BackupManager.class); - private static final String BACKUP_EXTENSION = ".sav"; + // This differs from org.jabref.logic.exporter.AtomicFileOutputStream.BACKUP_EXTENSION, which is used for copying the .bib away before overwriting on save. + private static final String AUTOSAVE_FILE_EXTENSION = ".sav"; private static Set runningInstances = new HashSet<>(); @@ -58,12 +59,12 @@ private BackupManager(BibDatabaseContext bibDatabaseContext, BibEntryTypesManage } static Path getBackupPath(Path originalPath) { - return FileUtil.addExtension(originalPath, BACKUP_EXTENSION); + return FileUtil.addExtension(originalPath, AUTOSAVE_FILE_EXTENSION); } /** - * Starts the BackupManager which is associated with the given {@link BibDatabaseContext}. - * As long as no database file is present in {@link BibDatabaseContext}, the {@link BackupManager} will do nothing. + * Starts the BackupManager which is associated with the given {@link BibDatabaseContext}. As long as no database + * file is present in {@link BibDatabaseContext}, the {@link BackupManager} will do nothing. * * @param bibDatabaseContext Associated {@link BibDatabaseContext} */ @@ -86,13 +87,27 @@ public static void shutdown(BibDatabaseContext bibDatabaseContext) { } /** - * Checks whether a backup file exists for the given database file. + * Checks whether a backup file exists for the given database file. If it exists, it is checked whether it is + * different from the original. * - * @param originalPath Path to the file a backup should be checked for. + * @param originalPath Path to the file a backup should be checked for. Example: jabref.bib. + * @return true if backup file exists AND differs from originalPath. false is the + * "default" return value in the good case. In the case of an exception true is returned to ensure that + * the user checks the output. */ - public static boolean checkForBackupFile(Path originalPath) { + public static boolean backupFileDiffers(Path originalPath) { Path backupPath = getBackupPath(originalPath); - return Files.exists(backupPath) && !Files.isDirectory(backupPath); + if (!Files.exists(backupPath) || Files.isDirectory(backupPath)) { + return false; + } + + try { + return Files.mismatch(originalPath, backupPath) != -1L; + } catch (IOException e) { + LOGGER.debug("Could not compare original file and backup file.", e); + // User has to investigate in this case + return true; + } } /** @@ -148,8 +163,8 @@ private void startBackupTask() { } /** - * Unregisters the BackupManager from the eventBus of {@link BibDatabaseContext} and deletes the backup file. - * This method should only be used when closing a database/JabRef legally. + * Unregisters the BackupManager from the eventBus of {@link BibDatabaseContext} and deletes the backup file. This + * method should only be used when closing a database/JabRef legally. */ private void shutdown() { changeFilter.unregisterListener(this); diff --git a/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java b/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java index 6d34c21c514..69b5d1395b4 100644 --- a/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java +++ b/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java @@ -84,7 +84,7 @@ private void initialize(String newStyle, CitationStyleOutputFormat newFormat) th */ private static class JabRefItemDataProvider implements ItemDataProvider { - private final ArrayList data = new ArrayList<>(); + private final List data = new ArrayList<>(); /** * Converts the {@link BibEntry} into {@link CSLItemData}. diff --git a/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerTest.java b/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerTest.java index fea23323f6c..20f2410cc78 100644 --- a/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerTest.java +++ b/src/test/java/org/jabref/logic/autosaveandbackup/BackupManagerTest.java @@ -6,13 +6,33 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; public class BackupManagerTest { @Test - public void backupFileNameIsCorrectlyGeneratedWithinTmpDirectory() { + public void autosaveFileNameIsCorrectlyGeneratedWithinTmpDirectory() { Path bibPath = Paths.get("tmp", "test.bib"); Path savPath = BackupManager.getBackupPath(bibPath); assertEquals(Paths.get("tmp", "test.bib.sav"), savPath); } + + @Test + public void autosaveFileIsEqualForNonExistingBackup() throws Exception { + Path originalFile = Path.of(BackupManagerTest.class.getResource("no-autosave.bib").toURI()); + assertFalse(BackupManager.backupFileDiffers(originalFile)); + } + + @Test + public void backupFileIsEqual() throws Exception { + Path originalFile = Path.of(BackupManagerTest.class.getResource("no-changes.bib").toURI()); + assertFalse(BackupManager.backupFileDiffers(originalFile)); + } + + @Test + public void backupFileDiffers() throws Exception { + Path originalFile = Path.of(BackupManagerTest.class.getResource("changes.bib").toURI()); + assertTrue(BackupManager.backupFileDiffers(originalFile)); + } } diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib b/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib new file mode 100644 index 00000000000..d733157bf3a --- /dev/null +++ b/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib @@ -0,0 +1,28 @@ +% Encoding: UTF-8 + +@Article{GarridoKallstromKummEtAl2016, + author = {Mario Garrido and Petter Kallstrom and Martin Kumm and Oscar Gustafsson}, + title = {{CORDIC} {II:} {A} New Improved {CORDIC} Algorithm}, + journal = {{IEEE} Trans. on Circuits and Systems}, + year = {2016}, + volume = {63-II}, + number = {2}, + pages = {186--190}, + bibsource = {dblp computer science bibliography, http://dblp.org}, + biburl = {http://dblp.uni-trier.de/rec/bib/journals/tcas/GarridoKKG16}, + doi = {10.1109/TCSII.2015.2483422}, + timestamp = {Mon, 08 Feb 2016 00:00:00 +0100}, +} + +@InProceedings{GustafssonJohansson2015, + author = {Oscar Gustafsson and H{\aa}kan Johansson}, + title = {Decimation filters for high-speed delta-sigma modulators with passband constraints: General versus CIC-based {FIR} filters}, + booktitle = {2015 {IEEE} International Symposium on Circuits and Systems, {ISCAS} 2015, Lisbon, Portugal, May 24-27, 2015}, + year = {2015}, + pages = {2205--2208}, + publisher = {{IEEE}}, + bibsource = {dblp computer science bibliography, http://dblp.org}, + biburl = {http://dblp.uni-trier.de/rec/bib/conf/iscas/GustafssonJ15}, + doi = {10.1109/ISCAS.2015.7169119}, + timestamp = {Wed, 05 Aug 2015 09:08:53 +0200}, +} diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib.sav b/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib.sav new file mode 100644 index 00000000000..c371a4e6757 --- /dev/null +++ b/src/test/resources/org/jabref/logic/autosaveandbackup/changes.bib.sav @@ -0,0 +1,15 @@ +% Encoding: UTF-8 + +@Article{GarridoKallstromKummEtAl2016, + author = {Mario Garrido and Petter Kallstrom and Martin Kumm and Oscar Gustafsson}, + title = {{CORDIC} {II:} {A} New Improved {CORDIC} Algorithm}, + journal = {{IEEE} Trans. on Circuits and Systems}, + year = {2016}, + volume = {63-II}, + number = {2}, + pages = {186--190}, + bibsource = {dblp computer science bibliography, http://dblp.org}, + biburl = {http://dblp.uni-trier.de/rec/bib/journals/tcas/GarridoKKG16}, + doi = {10.1109/TCSII.2015.2483422}, + timestamp = {Mon, 08 Feb 2016 00:00:00 +0100}, +} diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/no-autosave.bib b/src/test/resources/org/jabref/logic/autosaveandbackup/no-autosave.bib new file mode 100644 index 00000000000..d733157bf3a --- /dev/null +++ b/src/test/resources/org/jabref/logic/autosaveandbackup/no-autosave.bib @@ -0,0 +1,28 @@ +% Encoding: UTF-8 + +@Article{GarridoKallstromKummEtAl2016, + author = {Mario Garrido and Petter Kallstrom and Martin Kumm and Oscar Gustafsson}, + title = {{CORDIC} {II:} {A} New Improved {CORDIC} Algorithm}, + journal = {{IEEE} Trans. on Circuits and Systems}, + year = {2016}, + volume = {63-II}, + number = {2}, + pages = {186--190}, + bibsource = {dblp computer science bibliography, http://dblp.org}, + biburl = {http://dblp.uni-trier.de/rec/bib/journals/tcas/GarridoKKG16}, + doi = {10.1109/TCSII.2015.2483422}, + timestamp = {Mon, 08 Feb 2016 00:00:00 +0100}, +} + +@InProceedings{GustafssonJohansson2015, + author = {Oscar Gustafsson and H{\aa}kan Johansson}, + title = {Decimation filters for high-speed delta-sigma modulators with passband constraints: General versus CIC-based {FIR} filters}, + booktitle = {2015 {IEEE} International Symposium on Circuits and Systems, {ISCAS} 2015, Lisbon, Portugal, May 24-27, 2015}, + year = {2015}, + pages = {2205--2208}, + publisher = {{IEEE}}, + bibsource = {dblp computer science bibliography, http://dblp.org}, + biburl = {http://dblp.uni-trier.de/rec/bib/conf/iscas/GustafssonJ15}, + doi = {10.1109/ISCAS.2015.7169119}, + timestamp = {Wed, 05 Aug 2015 09:08:53 +0200}, +} diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib b/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib new file mode 100644 index 00000000000..c371a4e6757 --- /dev/null +++ b/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib @@ -0,0 +1,15 @@ +% Encoding: UTF-8 + +@Article{GarridoKallstromKummEtAl2016, + author = {Mario Garrido and Petter Kallstrom and Martin Kumm and Oscar Gustafsson}, + title = {{CORDIC} {II:} {A} New Improved {CORDIC} Algorithm}, + journal = {{IEEE} Trans. on Circuits and Systems}, + year = {2016}, + volume = {63-II}, + number = {2}, + pages = {186--190}, + bibsource = {dblp computer science bibliography, http://dblp.org}, + biburl = {http://dblp.uni-trier.de/rec/bib/journals/tcas/GarridoKKG16}, + doi = {10.1109/TCSII.2015.2483422}, + timestamp = {Mon, 08 Feb 2016 00:00:00 +0100}, +} diff --git a/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib.sav b/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib.sav new file mode 100644 index 00000000000..c371a4e6757 --- /dev/null +++ b/src/test/resources/org/jabref/logic/autosaveandbackup/no-changes.bib.sav @@ -0,0 +1,15 @@ +% Encoding: UTF-8 + +@Article{GarridoKallstromKummEtAl2016, + author = {Mario Garrido and Petter Kallstrom and Martin Kumm and Oscar Gustafsson}, + title = {{CORDIC} {II:} {A} New Improved {CORDIC} Algorithm}, + journal = {{IEEE} Trans. on Circuits and Systems}, + year = {2016}, + volume = {63-II}, + number = {2}, + pages = {186--190}, + bibsource = {dblp computer science bibliography, http://dblp.org}, + biburl = {http://dblp.uni-trier.de/rec/bib/journals/tcas/GarridoKKG16}, + doi = {10.1109/TCSII.2015.2483422}, + timestamp = {Mon, 08 Feb 2016 00:00:00 +0100}, +} From 64afe4ea631b6fe6b10f1d30ad43106bb1a265dc Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 22 Mar 2020 12:20:31 +0100 Subject: [PATCH 184/287] Remove duplicated line --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3878a3b541a..149ea8d8bc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,6 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - Filenames of external files can no longer contain curly braces. [#5926](https://github.com/JabRef/jabref/pull/5926) - We made the filters more easily accessible in the integrity check dialog. [#5955](https://github.com/JabRef/jabref/pull/5955) - We reimplemented and improved the dialog "Customize entry types". [#4719](https://github.com/JabRef/jabref/issues/4719) -- We reimplemented and improved the dialog "Customize entry types" [#4719](https://github.com/JabRef/jabref/issues/4719) - We added an [American Physical Society](https://journals.aps.org/) fetcher. [#818](https://github.com/JabRef/jabref/issues/818) ### Fixed From 1b9f572a5330fbd7c9a4ec0e8e489667f800e7a8 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 22 Mar 2020 15:50:07 +0100 Subject: [PATCH 185/287] Try comment:false Should work according to: https://community.codecov.io/t/prs-are-commented-even-with-comment-off/941/11?u=koppor --- codecov.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/codecov.yml b/codecov.yml index 66e0dca3e38..34bc965d211 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,6 +6,4 @@ coverage: project: default: threshold: 0.005 -comment: - branches: - - "do-not-add-comment-to-any-branch-please" +comment: false From 120a0afc515dc2bae4118b40c0c7b38833c041bb Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sun, 22 Mar 2020 16:32:30 +0100 Subject: [PATCH 186/287] Complete refactor of LibraryProperties to mvvm (#6107) --- src/main/java/org/jabref/gui/JabRefFrame.java | 2 +- .../gui/SaveOrderConfigDisplayViewModel.java | 128 -------- .../gui/cleanup/CleanupPresetPanel.fxml | 4 +- .../gui/cleanup/CleanupPresetPanel.java | 16 +- .../cleanup/FieldFormatterCleanupsPanel.java | 252 --------------- .../BibtexKeyPatternPanel.fxml} | 2 +- .../BibtexKeyPatternPanel.java} | 34 +- .../BibtexKeyPatternPanelItemModel.java} | 6 +- .../BibtexKeyPatternPanelViewModel.java} | 22 +- .../FieldFormatterCleanupsPanel.fxml | 77 +++++ .../FieldFormatterCleanupsPanel.java | 135 ++++++++ .../FieldFormatterCleanupsPanelViewModel.java | 78 +++++ .../SaveOrderConfigPanel.fxml} | 2 +- .../SaveOrderConfigPanel.java} | 91 ++++-- .../SaveOrderConfigPanelViewModel.java | 81 +++++ .../LibraryPropertiesAction.java | 10 +- .../LibraryPropertiesDialog.fxml | 92 +++--- .../LibraryPropertiesDialogView.java | 151 +++------ .../LibraryPropertiesDialogViewModel.java | 297 ++++++++++++++---- .../preferences/BibtexKeyPatternTabView.java | 6 +- .../BibtexKeyPatternTabViewModel.java | 14 +- .../gui/preferences/ExportSortingTab.fxml | 12 + .../gui/preferences/ExportSortingTabView.java | 47 +-- .../ExportSortingTabViewModel.java | 143 +++++++++ .../gui/preferences/NameFormatterTabView.java | 2 +- src/main/resources/l10n/JabRef_en.properties | 8 +- 26 files changed, 996 insertions(+), 716 deletions(-) delete mode 100644 src/main/java/org/jabref/gui/SaveOrderConfigDisplayViewModel.java delete mode 100644 src/main/java/org/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java rename src/main/java/org/jabref/gui/{bibtexkeypattern/BibtexKeyPatternTable.fxml => commonfxcontrols/BibtexKeyPatternPanel.fxml} (90%) rename src/main/java/org/jabref/gui/{bibtexkeypattern/BibtexKeyPatternTableView.java => commonfxcontrols/BibtexKeyPatternPanel.java} (79%) rename src/main/java/org/jabref/gui/{bibtexkeypattern/BibtexKeyPatternTableItemModel.java => commonfxcontrols/BibtexKeyPatternPanelItemModel.java} (88%) rename src/main/java/org/jabref/gui/{bibtexkeypattern/BibtexKeyPatternTableViewModel.java => commonfxcontrols/BibtexKeyPatternPanelViewModel.java} (83%) create mode 100644 src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.fxml create mode 100644 src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.java create mode 100644 src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanelViewModel.java rename src/main/java/org/jabref/gui/{SaveOrderConfigDisplay.fxml => commonfxcontrols/SaveOrderConfigPanel.fxml} (97%) rename src/main/java/org/jabref/gui/{SaveOrderConfigDisplayView.java => commonfxcontrols/SaveOrderConfigPanel.java} (55%) create mode 100644 src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanelViewModel.java create mode 100644 src/main/java/org/jabref/gui/preferences/ExportSortingTab.fxml create mode 100644 src/main/java/org/jabref/gui/preferences/ExportSortingTabViewModel.java diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 071ceeab881..09892d6d971 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -753,7 +753,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.LIBRARY_PROPERTIES, new LibraryPropertiesAction(this, dialogService, stateManager)), + factory.createMenuItem(StandardActions.LIBRARY_PROPERTIES, new LibraryPropertiesAction(this, stateManager)), factory.createMenuItem(StandardActions.EDIT_PREAMBLE, new PreambleEditor(stateManager, undoManager, this.getDialogService())), factory.createMenuItem(StandardActions.EDIT_STRINGS, new BibtexStringEditorAction(stateManager)), factory.createMenuItem(StandardActions.MANAGE_CITE_KEY_PATTERNS, new BibtexKeyPatternAction(this, stateManager)) diff --git a/src/main/java/org/jabref/gui/SaveOrderConfigDisplayViewModel.java b/src/main/java/org/jabref/gui/SaveOrderConfigDisplayViewModel.java deleted file mode 100644 index 89ef04f1c25..00000000000 --- a/src/main/java/org/jabref/gui/SaveOrderConfigDisplayViewModel.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.jabref.gui; - -import java.util.Objects; -import java.util.Set; - -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.model.entry.field.Field; -import org.jabref.model.entry.field.FieldFactory; -import org.jabref.model.metadata.SaveOrderConfig; -import org.jabref.model.metadata.SaveOrderConfig.SortCriterion; -import org.jabref.preferences.PreferencesService; - -public class SaveOrderConfigDisplayViewModel { - - private final ListProperty priSortFieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); - private final ListProperty secSortFieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); - private final ListProperty terSortFieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); - - private final BooleanProperty savePriDescPropertySelected = new SimpleBooleanProperty(); - private final BooleanProperty saveSecDescPropertySelected = new SimpleBooleanProperty(); - private final BooleanProperty saveTerDescPropertySelected = new SimpleBooleanProperty(); - - private final ObjectProperty savePriSortSelectedValueProperty = new SimpleObjectProperty<>(null); - private final ObjectProperty saveSecSortSelectedValueProperty = new SimpleObjectProperty<>(null); - private final ObjectProperty saveTerSortSelectedValueProperty = new SimpleObjectProperty<>(null); - - private final BooleanProperty saveInOriginalProperty = new SimpleBooleanProperty(); - private final BooleanProperty saveInTableOrderProperty = new SimpleBooleanProperty(); - private final BooleanProperty saveInSpecifiedOrderProperty = new SimpleBooleanProperty(); - - private final PreferencesService prefs; - - public SaveOrderConfigDisplayViewModel(PreferencesService prefs) { - this.prefs = prefs; - - Set fieldNames = FieldFactory.getCommonFields(); - priSortFieldsProperty.addAll(fieldNames); - secSortFieldsProperty.addAll(fieldNames); - terSortFieldsProperty.addAll(fieldNames); - } - - public ListProperty priSortFieldsProperty() { - return priSortFieldsProperty; - } - - public ListProperty secSortFieldsProperty() { - return secSortFieldsProperty; - } - - public ListProperty terSortFieldsProperty() { - return terSortFieldsProperty; - } - - public SaveOrderConfig getSaveOrderConfig() { - SortCriterion primary = new SortCriterion(savePriSortSelectedValueProperty.get(), savePriDescPropertySelected.getValue()); - SortCriterion secondary = new SortCriterion(saveSecSortSelectedValueProperty.get(), saveSecDescPropertySelected.getValue()); - SortCriterion tertiary = new SortCriterion(saveTerSortSelectedValueProperty.get(), saveTerDescPropertySelected.getValue()); - - return new SaveOrderConfig(saveInOriginalProperty.getValue(), saveInSpecifiedOrderProperty.getValue(), primary, secondary, tertiary); - } - - public void setSaveOrderConfig(SaveOrderConfig saveOrderConfig) { - Objects.requireNonNull(saveOrderConfig); - - savePriSortSelectedValueProperty.setValue(saveOrderConfig.getSortCriteria().get(0).field); - savePriDescPropertySelected.setValue(saveOrderConfig.getSortCriteria().get(0).descending); - saveSecSortSelectedValueProperty.setValue(saveOrderConfig.getSortCriteria().get(1).field); - saveSecDescPropertySelected.setValue(saveOrderConfig.getSortCriteria().get(1).descending); - saveTerSortSelectedValueProperty.setValue(saveOrderConfig.getSortCriteria().get(2).field); - saveTerDescPropertySelected.setValue(saveOrderConfig.getSortCriteria().get(2).descending); - - if (saveOrderConfig.saveInOriginalOrder()) { - saveInOriginalProperty.setValue(true); - } else if (saveOrderConfig.saveInSpecifiedOrder()) { - saveInSpecifiedOrderProperty.setValue(true); - } else { - saveInTableOrderProperty.setValue(true); - } - - } - - public BooleanProperty savePriDescPropertySelected() { - return savePriDescPropertySelected; - } - - public BooleanProperty saveSecDescPropertySelected() { - return saveSecDescPropertySelected; - } - - public BooleanProperty saveTerDescPropertySelected() { - return saveTerDescPropertySelected; - } - - public ObjectProperty savePriSortSelectedValueProperty() { - return savePriSortSelectedValueProperty; - } - - public ObjectProperty saveSecSortSelectedValueProperty() { - return saveSecSortSelectedValueProperty; - } - - public ObjectProperty saveTerSortSelectedValueProperty() { - return saveTerSortSelectedValueProperty; - } - - public void storeConfigInPrefs() { - prefs.storeExportSaveOrder(this.getSaveOrderConfig()); - } - - public BooleanProperty saveInOriginalProperty() { - return saveInOriginalProperty; - } - - public BooleanProperty saveInTableOrderProperty() { - return saveInTableOrderProperty; - } - - public BooleanProperty saveInSpecifiedOrderProperty() { - return this.saveInSpecifiedOrderProperty; - } -} diff --git a/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.fxml b/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.fxml index 1ca9d6ebafa..608cdc12823 100644 --- a/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.fxml +++ b/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.fxml @@ -4,6 +4,7 @@ + @@ -28,6 +29,5 @@ - - + diff --git a/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.java b/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.java index 563fb7ac9e4..3ea9fa7c8c7 100644 --- a/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.java +++ b/src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.java @@ -6,13 +6,16 @@ import java.util.Optional; import java.util.Set; +import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.layout.VBox; +import org.jabref.gui.commonfxcontrols.FieldFormatterCleanupsPanel; import org.jabref.logic.cleanup.CleanupPreset; import org.jabref.logic.l10n.Localization; +import org.jabref.model.cleanup.FieldFormatterCleanups; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.field.StandardField; import org.jabref.model.metadata.FilePreferences; @@ -33,8 +36,7 @@ public class CleanupPresetPanel extends VBox { @FXML private CheckBox cleanUpUpgradeExternalLinks; @FXML private CheckBox cleanUpBiblatex; @FXML private CheckBox cleanUpBibtex; - @FXML private VBox formatterContainer; - private FieldFormatterCleanupsPanel cleanUpFormatters; + @FXML private FieldFormatterCleanupsPanel formatterCleanupsPanel; public CleanupPresetPanel(BibDatabaseContext databaseContext, CleanupPreset cleanupPreset, FilePreferences filePreferences) { this.databaseContext = Objects.requireNonNull(databaseContext); @@ -63,9 +65,6 @@ private void init(CleanupPreset cleanupPreset, FilePreferences filePreferences) cleanUpUpgradeExternalLinks.setText(Localization.lang("Upgrade external PDF/PS links to use the '%0' field.", StandardField.FILE.getDisplayName())); - cleanUpFormatters = new FieldFormatterCleanupsPanel(Localization.lang("Run field formatter:")); - formatterContainer.getChildren().setAll(cleanUpFormatters); - String currentPattern = Localization.lang("Filename format pattern") .concat(": ") .concat(filePreferences.getFileNamePattern()); @@ -87,7 +86,8 @@ private void updateDisplay(CleanupPreset preset) { cleanUpBiblatex.setSelected(preset.isActive(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX)); cleanUpBibtex.setSelected(preset.isActive(CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX)); cleanUpISSN.setSelected(preset.isActive(CleanupPreset.CleanupStep.CLEAN_UP_ISSN)); - cleanUpFormatters.setValues(preset.getFormatterCleanups()); + formatterCleanupsPanel.cleanupsDisableProperty().setValue(!preset.getFormatterCleanups().isEnabled()); + formatterCleanupsPanel.cleanupsProperty().setValue(FXCollections.observableArrayList(preset.getFormatterCleanups().getConfiguredActions())); } public CleanupPreset getCleanupPreset() { @@ -127,6 +127,8 @@ public CleanupPreset getCleanupPreset() { activeJobs.add(CleanupPreset.CleanupStep.FIX_FILE_LINKS); - return new CleanupPreset(activeJobs, cleanUpFormatters.getFormatterCleanups()); + return new CleanupPreset(activeJobs, new FieldFormatterCleanups( + !formatterCleanupsPanel.cleanupsDisableProperty().getValue(), + formatterCleanupsPanel.cleanupsProperty())); } } diff --git a/src/main/java/org/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java b/src/main/java/org/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java deleted file mode 100644 index 70cc748e2b7..00000000000 --- a/src/main/java/org/jabref/gui/cleanup/FieldFormatterCleanupsPanel.java +++ /dev/null @@ -1,252 +0,0 @@ -package org.jabref.gui.cleanup; - -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; -import java.util.stream.Collectors; - -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.control.Button; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.ListView; -import javafx.scene.control.SelectionMode; -import javafx.scene.layout.ColumnConstraints; -import javafx.scene.layout.GridPane; -import javafx.scene.layout.RowConstraints; - -import org.jabref.Globals; -import org.jabref.JabRefGUI; -import org.jabref.gui.util.ViewModelListCellFactory; -import org.jabref.logic.cleanup.Cleanups; -import org.jabref.logic.formatter.casechanger.ProtectTermsFormatter; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.cleanup.FieldFormatterCleanup; -import org.jabref.model.cleanup.FieldFormatterCleanups; -import org.jabref.model.cleanup.Formatter; -import org.jabref.model.database.BibDatabaseContext; -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.metadata.MetaData; - -import org.fxmisc.easybind.EasyBind; - -public class FieldFormatterCleanupsPanel extends GridPane { - - private static final String DESCRIPTION = Localization.lang("Description") + ": "; - private final CheckBox cleanupEnabled; - private final List availableFormatters; - private FieldFormatterCleanups fieldFormatterCleanups; - private ListView actionsList; - private ComboBox formattersCombobox; - private ComboBox selectFieldCombobox; - private Button addButton; - private Label descriptionAreaText; - private Button removeSelectedButton; - private Button removeAllButton; - private Button recommendButton; - private ObservableList actions; - - public FieldFormatterCleanupsPanel(String description) { - cleanupEnabled = new CheckBox(description); - availableFormatters = Cleanups.getBuiltInFormatters(); - availableFormatters.add(new ProtectTermsFormatter(Globals.protectedTermsLoader)); - } - - public void setValues(MetaData metaData) { - Objects.requireNonNull(metaData); - Optional saveActions = metaData.getSaveActions(); - setValues(saveActions.orElse(Cleanups.DEFAULT_SAVE_ACTIONS)); - } - - public void setValues(FieldFormatterCleanups formatterCleanups) { - fieldFormatterCleanups = formatterCleanups; - - // first clear existing content - this.getChildren().clear(); - - List configuredActions = fieldFormatterCleanups.getConfiguredActions(); - actions = FXCollections.observableArrayList(configuredActions); - buildLayout(); - } - - private void buildLayout() { - setHgap(10.0); - setVgap(4.0); - - ColumnConstraints first = new ColumnConstraints(); - first.setPrefWidth(25); - ColumnConstraints second = new ColumnConstraints(); - second.setPrefWidth(175); - ColumnConstraints third = new ColumnConstraints(); - third.setPrefWidth(200); - ColumnConstraints fourth = new ColumnConstraints(); - fourth.setPrefWidth(200); - getColumnConstraints().addAll(first, second, third, fourth); - RowConstraints firstR = new RowConstraints(); - firstR.setPrefHeight(25); - RowConstraints secondR = new RowConstraints(); - secondR.setPrefHeight(100); - RowConstraints thirdR = new RowConstraints(); - thirdR.setPrefHeight(50); - RowConstraints fourthR = new RowConstraints(); - fourthR.setPrefHeight(50); - RowConstraints fifthR = new RowConstraints(); - fifthR.setPrefHeight(50); - getRowConstraints().addAll(firstR, secondR, thirdR, fourthR, fifthR); - add(cleanupEnabled, 0, 0, 4, 1); - - actionsList = new ListView<>(actions); - actionsList.setMinHeight(100.0); - actionsList.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); - - new ViewModelListCellFactory() - .withText(action -> action.getField().getDisplayName() + ": " + action.getFormatter().getName()) - .withStringTooltip(action -> action.getFormatter().getDescription()) - .install(actionsList); - add(actionsList, 1, 1, 3, 1); - - removeAllButton = new Button(Localization.lang("Remove all")); - removeAllButton.setOnAction(e -> actions.clear()); - - BibDatabaseContext databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getBibDatabaseContext(); - - recommendButton = new Button(Localization.lang("Reset to recommended")); - boolean isBiblatex = databaseContext.isBiblatexMode(); - - recommendButton.setOnAction(e -> { - if (isBiblatex) { - actions.setAll(Cleanups.RECOMMEND_BIBLATEX_ACTIONS.getConfiguredActions()); - } else { - actions.setAll(Cleanups.RECOMMEND_BIBTEX_ACTIONS.getConfiguredActions()); - } - }); - - removeSelectedButton = new Button(Localization.lang("Remove selected")); - removeSelectedButton.setOnAction(e -> actions.remove(actionsList.getSelectionModel().getSelectedItem())); - descriptionAreaText = new Label(DESCRIPTION); - descriptionAreaText.setWrapText(true); - - add(recommendButton, 1, 2, 1, 1); - add(removeSelectedButton, 2, 2, 1, 1); - add(removeAllButton, 3, 2, 1, 1); - add(getSelectorPanel(), 1, 3, 3, 1); - add(descriptionAreaText, 1, 4, 3, 1); - - updateDescription(); - - // make sure the layout is set according to the checkbox - cleanupEnabled.selectedProperty().addListener(new EnablementStatusListener<>(fieldFormatterCleanups.isEnabled())); - cleanupEnabled.setSelected(fieldFormatterCleanups.isEnabled()); - } - - private void updateDescription() { - FieldFormatterCleanup formatterCleanup = getFieldFormatterCleanup(); - if (formatterCleanup.getFormatter() != null) { - descriptionAreaText.setText(DESCRIPTION + formatterCleanup.getFormatter().getDescription()); - } else { - Formatter selectedFormatter = formattersCombobox.getValue(); - if (selectedFormatter != null) { - descriptionAreaText.setText(DESCRIPTION + selectedFormatter.getDescription()); - } else { - descriptionAreaText.setText(DESCRIPTION); - } - } - } - - /** - * This panel contains the two comboboxes and the Add button - */ - private GridPane getSelectorPanel() { - GridPane builder = new GridPane(); - builder.setHgap(10.0); - Set fields = FieldFactory.getCommonFields(); - fields.add(InternalField.KEY_FIELD); - Set fieldsString = fields.stream().map(Field::getDisplayName).sorted().collect(Collectors.toCollection(TreeSet::new)); - selectFieldCombobox = new ComboBox<>(FXCollections.observableArrayList(fieldsString)); - selectFieldCombobox.setEditable(true); - builder.add(selectFieldCombobox, 1, 1); - - formattersCombobox = new ComboBox<>(FXCollections.observableArrayList(availableFormatters)); - new ViewModelListCellFactory() - .withText(Formatter::getName) - .withStringTooltip(Formatter::getDescription) - .install(formattersCombobox); - EasyBind.subscribe(formattersCombobox.valueProperty(), e -> updateDescription()); - formattersCombobox.getSelectionModel().selectFirst(); - builder.add(formattersCombobox, 3, 1); - - addButton = new Button(Localization.lang("Add")); - addButton.setOnAction(e -> { - FieldFormatterCleanup newAction = getFieldFormatterCleanup(); - - if (!actions.contains(newAction)) { - actions.add(newAction); - } - }); - builder.add(addButton, 5, 1); - - return builder; - } - - public void storeSettings(MetaData metaData) { - Objects.requireNonNull(metaData); - - FieldFormatterCleanups formatterCleanups = getFormatterCleanups(); - - // if all actions have been removed, remove the save actions from the MetaData - if (formatterCleanups.getConfiguredActions().isEmpty()) { - metaData.clearSaveActions(); - return; - } - - metaData.setSaveActions(formatterCleanups); - } - - public FieldFormatterCleanups getFormatterCleanups() { - return new FieldFormatterCleanups(cleanupEnabled.isSelected(), actions); - } - - public boolean hasChanged() { - return !fieldFormatterCleanups.equals(getFormatterCleanups()); - } - - public boolean isDefaultSaveActions() { - return Cleanups.DEFAULT_SAVE_ACTIONS.equals(getFormatterCleanups()); - } - - private FieldFormatterCleanup getFieldFormatterCleanup() { - Formatter selectedFormatter = formattersCombobox.getValue(); - Field field = FieldFactory.parseField(selectFieldCombobox.getSelectionModel().getSelectedItem()); - return new FieldFormatterCleanup(field, selectedFormatter); - } - - class EnablementStatusListener implements ChangeListener { - - public EnablementStatusListener(boolean initialStatus) { - setStatus(initialStatus); - } - - private void setStatus(boolean status) { - actionsList.setDisable(!status); - selectFieldCombobox.setDisable(!status); - formattersCombobox.setDisable(!status); - addButton.setDisable(!status); - removeSelectedButton.setDisable(!status); - removeAllButton.setDisable(!status); - recommendButton.setDisable(!status); - } - - @Override - public void changed(ObservableValue observable, T oldValue, T newValue) { - setStatus(cleanupEnabled.isSelected()); - } - } -} diff --git a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTable.fxml b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanel.fxml similarity index 90% rename from src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTable.fxml rename to src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanel.fxml index 5b2924eb764..0031e6a1fd4 100644 --- a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTable.fxml +++ b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanel.fxml @@ -5,7 +5,7 @@ + fx:controller="org.jabref.gui.commonfxcontrols.BibtexKeyPatternPanel"> diff --git a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableView.java b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanel.java similarity index 79% rename from src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableView.java rename to src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanel.java index 124e8b8c48c..a6f96bb25b5 100644 --- a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableView.java +++ b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanel.java @@ -1,4 +1,4 @@ -package org.jabref.gui.bibtexkeypattern; +package org.jabref.gui.commonfxcontrols; import java.util.Collection; @@ -21,21 +21,21 @@ import com.airhacks.afterburner.views.ViewLoader; -public class BibtexKeyPatternTableView extends TableView { +public class BibtexKeyPatternPanel extends TableView { - @FXML public TableColumn entryTypeColumn; - @FXML public TableColumn patternColumn; - @FXML public TableColumn actionsColumn; + @FXML public TableColumn entryTypeColumn; + @FXML public TableColumn patternColumn; + @FXML public TableColumn actionsColumn; - private BibtexKeyPatternTableViewModel viewModel; + private BibtexKeyPatternPanelViewModel viewModel; private long lastKeyPressTime; private String tableSearchTerm; - public BibtexKeyPatternTableView(JabRefPreferences preferences, Collection entryTypeList, AbstractBibtexKeyPattern keyPattern) { + public BibtexKeyPatternPanel(JabRefPreferences preferences, Collection entryTypeList, AbstractBibtexKeyPattern keyPattern) { super(); - viewModel = new BibtexKeyPatternTableViewModel(preferences, entryTypeList, keyPattern); + viewModel = new BibtexKeyPatternPanelViewModel(preferences, entryTypeList, keyPattern); ViewLoader.view(this) .root(this) @@ -49,11 +49,11 @@ private void initialize() { entryTypeColumn.setSortable(true); entryTypeColumn.setReorderable(false); entryTypeColumn.setCellValueFactory(cellData -> cellData.getValue().entryType()); - new ValueTableCellFactory() + new ValueTableCellFactory() .withText(EntryType::getDisplayName) .install(entryTypeColumn); this.setOnSort(event -> - viewModel.patternListProperty().sort(BibtexKeyPatternTableViewModel.defaultOnTopComparator)); + viewModel.patternListProperty().sort(BibtexKeyPatternPanelViewModel.defaultOnTopComparator)); patternColumn.setSortable(true); patternColumn.setReorderable(false); @@ -61,13 +61,13 @@ private void initialize() { patternColumn.setCellFactory(TextFieldTableCell.forTableColumn()); patternColumn.setEditable(true); patternColumn.setOnEditCommit( - (TableColumn.CellEditEvent event) -> + (TableColumn.CellEditEvent event) -> event.getRowValue().setPattern(event.getNewValue())); actionsColumn.setSortable(false); actionsColumn.setReorderable(false); actionsColumn.setCellValueFactory(cellData -> cellData.getValue().entryType()); - new ValueTableCellFactory() + new ValueTableCellFactory() .withGraphic(entryType -> IconTheme.JabRefIcons.REFRESH.getGraphicNode()) .withTooltip(entryType -> String.format(Localization.lang("Reset %s to default value"), entryType.getDisplayName())) @@ -84,9 +84,9 @@ private void initialize() { public void resetAll() { viewModel.resetAll(); } - public ListProperty patternListProperty() { return viewModel.patternListProperty(); } + public ListProperty patternListProperty() { return viewModel.patternListProperty(); } - public ObjectProperty defaultKeyPatternProperty() { return viewModel.defaultKeyPatternProperty(); } + public ObjectProperty defaultKeyPatternProperty() { return viewModel.defaultKeyPatternProperty(); } private void jumpToSearchKey(KeyEvent keypressed) { if (keypressed.getCharacter() == null) { @@ -105,15 +105,15 @@ private void jumpToSearchKey(KeyEvent keypressed) { .findFirst().ifPresent(this::scrollTo); } - private static class HighlightTableRow extends TableRow { + private static class HighlightTableRow extends TableRow { @Override - public void updateItem(BibtexKeyPatternTableItemModel item, boolean empty) { + public void updateItem(BibtexKeyPatternPanelItemModel item, boolean empty) { super.updateItem(item, empty); if (item == null || item.getEntryType() == null) { setStyle(""); } else if (isSelected()) { setStyle("-fx-background-color: -fx-selection-bar"); - } else if (item.getEntryType().getName().equals(BibtexKeyPatternTableViewModel.ENTRY_TYPE_DEFAULT_NAME)) { + } else if (item.getEntryType().getName().equals(BibtexKeyPatternPanelViewModel.ENTRY_TYPE_DEFAULT_NAME)) { setStyle("-fx-background-color: -fx-default-button"); } else { setStyle(""); diff --git a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableItemModel.java b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanelItemModel.java similarity index 88% rename from src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableItemModel.java rename to src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanelItemModel.java index 7431346de46..f65180bd6a1 100644 --- a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableItemModel.java +++ b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanelItemModel.java @@ -1,4 +1,4 @@ -package org.jabref.gui.bibtexkeypattern; +package org.jabref.gui.commonfxcontrols; import java.util.Objects; @@ -9,11 +9,11 @@ import org.jabref.model.entry.types.EntryType; -public class BibtexKeyPatternTableItemModel { +public class BibtexKeyPatternPanelItemModel { private final ObjectProperty entryType = new SimpleObjectProperty<>(); private final StringProperty pattern = new SimpleStringProperty(""); - public BibtexKeyPatternTableItemModel(EntryType entryType, String pattern) { + public BibtexKeyPatternPanelItemModel(EntryType entryType, String pattern) { Objects.requireNonNull(entryType); Objects.requireNonNull(pattern); this.entryType.setValue(entryType); diff --git a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableViewModel.java b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanelViewModel.java similarity index 83% rename from src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableViewModel.java rename to src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanelViewModel.java index 971347b4b3f..ccd765635bf 100644 --- a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternTableViewModel.java +++ b/src/main/java/org/jabref/gui/commonfxcontrols/BibtexKeyPatternPanelViewModel.java @@ -1,4 +1,4 @@ -package org.jabref.gui.bibtexkeypattern; +package org.jabref.gui.commonfxcontrols; import java.util.Collection; import java.util.Comparator; @@ -15,11 +15,11 @@ import org.jabref.model.entry.types.EntryType; import org.jabref.preferences.JabRefPreferences; -public class BibtexKeyPatternTableViewModel { +public class BibtexKeyPatternPanelViewModel { public static final String ENTRY_TYPE_DEFAULT_NAME = "default"; - public static Comparator defaultOnTopComparator = (o1, o2) -> { + public static Comparator defaultOnTopComparator = (o1, o2) -> { String itemOneName = o1.getEntryType().getName(); String itemTwoName = o2.getEntryType().getName(); @@ -34,13 +34,13 @@ public class BibtexKeyPatternTableViewModel { return 0; }; - private final ListProperty patternListProperty = new SimpleListProperty<>(); - private final ObjectProperty defaultItemProperty = new SimpleObjectProperty<>(); + private final ListProperty patternListProperty = new SimpleListProperty<>(); + private final ObjectProperty defaultItemProperty = new SimpleObjectProperty<>(); private final AbstractBibtexKeyPattern initialKeyPattern; private final Collection bibEntryTypeList; private final JabRefPreferences preferences; - public BibtexKeyPatternTableViewModel(JabRefPreferences preferences, Collection entryTypeList, AbstractBibtexKeyPattern initialKeyPattern) { + public BibtexKeyPatternPanelViewModel(JabRefPreferences preferences, Collection entryTypeList, AbstractBibtexKeyPattern initialKeyPattern) { this.preferences = preferences; this.bibEntryTypeList = entryTypeList; this.initialKeyPattern = initialKeyPattern; @@ -54,7 +54,7 @@ public void setValues() { defaultPattern = initialKeyPattern.getDefaultValue().get(0); } - defaultItemProperty.setValue(new BibtexKeyPatternTableItemModel(new DefaultEntryType(), defaultPattern)); + defaultItemProperty.setValue(new BibtexKeyPatternPanelItemModel(new DefaultEntryType(), defaultPattern)); patternListProperty.setValue(FXCollections.observableArrayList()); patternListProperty.add(defaultItemProperty.getValue()); @@ -67,11 +67,11 @@ public void setValues() { } else { pattern = initialKeyPattern.getPatterns().get(entryType).get(0); } - patternListProperty.add(new BibtexKeyPatternTableItemModel(entryType, pattern)); + patternListProperty.add(new BibtexKeyPatternPanelItemModel(entryType, pattern)); }); } - public void setItemToDefaultPattern(BibtexKeyPatternTableItemModel item) { + public void setItemToDefaultPattern(BibtexKeyPatternPanelItemModel item) { item.setPattern((String) preferences.defaults.get(JabRefPreferences.DEFAULT_BIBTEX_KEY_PATTERN)); } @@ -80,9 +80,9 @@ public void resetAll() { defaultItemProperty.getValue().setPattern((String) preferences.defaults.get(JabRefPreferences.DEFAULT_BIBTEX_KEY_PATTERN)); } - public ListProperty patternListProperty() { return patternListProperty; } + public ListProperty patternListProperty() { return patternListProperty; } - public ObjectProperty defaultKeyPatternProperty() { return defaultItemProperty; } + public ObjectProperty defaultKeyPatternProperty() { return defaultItemProperty; } public static class DefaultEntryType implements EntryType { @Override diff --git a/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.fxml b/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.fxml new file mode 100644 index 00000000000..cecf5153b6b --- /dev/null +++ b/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.fxml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.java b/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.java new file mode 100644 index 00000000000..5f6e1e064b1 --- /dev/null +++ b/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanel.java @@ -0,0 +1,135 @@ +package org.jabref.gui.commonfxcontrols; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ListProperty; +import javafx.beans.property.ReadOnlyObjectWrapper; +import javafx.fxml.FXML; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.SelectionMode; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.VBox; + +import org.jabref.gui.icon.IconTheme; +import org.jabref.gui.util.FieldsUtil; +import org.jabref.gui.util.ValueTableCellFactory; +import org.jabref.gui.util.ViewModelListCellFactory; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.cleanup.FieldFormatterCleanup; +import org.jabref.model.cleanup.Formatter; +import org.jabref.model.entry.field.Field; + +import com.airhacks.afterburner.views.ViewLoader; + +public class FieldFormatterCleanupsPanel extends VBox { + + @FXML private CheckBox cleanupsEnabled; + @FXML private TableView cleanupsList; + @FXML private TableColumn fieldColumn; + @FXML private TableColumn formatterColumn; + @FXML private TableColumn actionsColumn; + @FXML private ComboBox addableFields; + @FXML private ComboBox addableFormatters; + + private FieldFormatterCleanupsPanelViewModel viewModel; + + public FieldFormatterCleanupsPanel() { + ViewLoader.view(this) + .root(this) + .load(); + } + + @FXML + private void initialize() { + this.viewModel = new FieldFormatterCleanupsPanelViewModel(); + + setupTable(); + setupCombos(); + setupBindings(); + } + + private void setupTable() { + cleanupsList.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + + // ToDo: To be editable the list needs a view model wrapper for FieldFormatterCleanup + + fieldColumn.setCellValueFactory(cellData -> new ReadOnlyObjectWrapper<>(cellData.getValue().getField())); + new ValueTableCellFactory() + .withText(Field::getDisplayName) + .install(fieldColumn); + + formatterColumn.setCellValueFactory(cellData -> new ReadOnlyObjectWrapper<>(cellData.getValue().getFormatter())); + new ValueTableCellFactory() + .withText(Formatter::getName) + .install(formatterColumn); + + actionsColumn.setCellValueFactory(cellData -> new ReadOnlyObjectWrapper<>(cellData.getValue().getField())); + new ValueTableCellFactory() + .withGraphic(field -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) + .withTooltip(field -> Localization.lang("Remove formatter for %0", field.getDisplayName())) + .withOnMouseClickedEvent(item -> event -> viewModel.removeCleanup(cleanupsList.getSelectionModel().getSelectedItem())) + .install(actionsColumn); + + viewModel.selectedCleanupProperty().setValue(cleanupsList.getSelectionModel()); + + cleanupsList.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.DELETE) { + viewModel.removeCleanup(cleanupsList.getSelectionModel().getSelectedItem()); + } + }); + } + + private void setupCombos() { + new ViewModelListCellFactory() + .withText(Field::getDisplayName) + .install(addableFields); + addableFields.setConverter(FieldsUtil.fieldStringConverter); + addableFields.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.TAB || event.getCode() == KeyCode.ENTER) { + addableFormatters.requestFocus(); + event.consume(); + } + }); + + new ViewModelListCellFactory() + .withText(Formatter::getName) + .withStringTooltip(Formatter::getDescription) + .install(addableFormatters); + addableFormatters.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.ENTER) { + viewModel.addCleanup(); + event.consume(); + } + }); + } + + private void setupBindings() { + cleanupsEnabled.selectedProperty().bindBidirectional(cleanupsDisableProperty()); + cleanupsList.itemsProperty().bind(viewModel.cleanupsListProperty()); + addableFields.itemsProperty().bind(viewModel.availableFieldsProperty()); + addableFields.valueProperty().bindBidirectional(viewModel.selectedFieldProperty()); + addableFormatters.itemsProperty().bind(viewModel.availableFormattersProperty()); + addableFormatters.valueProperty().bindBidirectional(viewModel.selectedFormatterProperty()); + } + + @FXML + private void resetToRecommended() { + viewModel.resetToRecommended(); + } + + @FXML + private void clearAll() { + viewModel.clearAll(); + } + + @FXML + private void addCleanup() { + viewModel.addCleanup(); + } + + public BooleanProperty cleanupsDisableProperty() { return viewModel.cleanupsDisableProperty(); } + + public ListProperty cleanupsProperty() { return viewModel.cleanupsListProperty(); } +} diff --git a/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanelViewModel.java b/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanelViewModel.java new file mode 100644 index 00000000000..86705892e2e --- /dev/null +++ b/src/main/java/org/jabref/gui/commonfxcontrols/FieldFormatterCleanupsPanelViewModel.java @@ -0,0 +1,78 @@ +package org.jabref.gui.commonfxcontrols; + +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 javafx.scene.control.SelectionModel; + +import org.jabref.Globals; +import org.jabref.gui.util.NoSelectionModel; +import org.jabref.logic.cleanup.Cleanups; +import org.jabref.model.cleanup.FieldFormatterCleanup; +import org.jabref.model.cleanup.Formatter; +import org.jabref.model.entry.field.Field; +import org.jabref.model.entry.field.FieldFactory; + +public class FieldFormatterCleanupsPanelViewModel { + + private final BooleanProperty cleanupsDisableProperty = new SimpleBooleanProperty(); + private final ListProperty cleanupsListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); + private final ObjectProperty> selectedCleanupProperty = new SimpleObjectProperty<>(new NoSelectionModel<>()); + private final ListProperty availableFieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList(FieldFactory.getCommonFields())); + private final ObjectProperty selectedFieldProperty = new SimpleObjectProperty<>(); + private final ListProperty availableFormattersProperty = new SimpleListProperty<>(FXCollections.observableArrayList(Cleanups.getBuiltInFormatters())); + private final ObjectProperty selectedFormatterProperty = new SimpleObjectProperty<>(); + + public FieldFormatterCleanupsPanelViewModel() { + } + + public void resetToRecommended() { + Globals.stateManager.getActiveDatabase().ifPresent(databaseContext -> { + if (databaseContext.isBiblatexMode()) { + cleanupsListProperty.setAll(Cleanups.RECOMMEND_BIBLATEX_ACTIONS.getConfiguredActions()); + } else { + cleanupsListProperty.setAll(Cleanups.RECOMMEND_BIBTEX_ACTIONS.getConfiguredActions()); + } + }); + } + + public void clearAll() { + cleanupsListProperty.clear(); + } + + public void addCleanup() { + if (selectedFieldProperty.getValue() == null || selectedFormatterProperty.getValue() == null) { + return; + } + + FieldFormatterCleanup cleanup = new FieldFormatterCleanup( + selectedFieldProperty.getValue(), + selectedFormatterProperty.getValue()); + + if (cleanupsListProperty.stream().noneMatch(item -> item.equals(cleanup))) { + cleanupsListProperty.add(cleanup); + } + } + + public void removeCleanup(FieldFormatterCleanup cleanup) { + cleanupsListProperty.remove(cleanup); + } + + public BooleanProperty cleanupsDisableProperty() { return cleanupsDisableProperty; } + + public ListProperty cleanupsListProperty() { return cleanupsListProperty; } + + public ObjectProperty> selectedCleanupProperty() { return selectedCleanupProperty; } + + public ListProperty availableFieldsProperty() { return availableFieldsProperty; } + + public ObjectProperty selectedFieldProperty() { return selectedFieldProperty; } + + public ListProperty availableFormattersProperty() { return availableFormattersProperty; } + + public ObjectProperty selectedFormatterProperty() { return selectedFormatterProperty; } +} diff --git a/src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml b/src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanel.fxml similarity index 97% rename from src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml rename to src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanel.fxml index 17e458f2e81..e0d26cf19d3 100644 --- a/src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml +++ b/src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanel.fxml @@ -12,7 +12,7 @@ + fx:controller="org.jabref.gui.commonfxcontrols.SaveOrderConfigPanel"> diff --git a/src/main/java/org/jabref/gui/SaveOrderConfigDisplayView.java b/src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanel.java similarity index 55% rename from src/main/java/org/jabref/gui/SaveOrderConfigDisplayView.java rename to src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanel.java index 15679bc9ac2..b3ae2db5549 100644 --- a/src/main/java/org/jabref/gui/SaveOrderConfigDisplayView.java +++ b/src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanel.java @@ -1,26 +1,23 @@ -package org.jabref.gui; - -import javax.inject.Inject; +package org.jabref.gui.commonfxcontrols; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ListProperty; +import javafx.beans.property.ObjectProperty; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.RadioButton; -import javafx.scene.control.ToggleGroup; import javafx.scene.layout.VBox; import org.jabref.gui.util.FieldsUtil; import org.jabref.gui.util.ViewModelListCellFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.Field; -import org.jabref.model.metadata.SaveOrderConfig; -import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.views.ViewLoader; -public class SaveOrderConfigDisplayView extends VBox { +public class SaveOrderConfigPanel extends VBox { - @FXML private ToggleGroup saveOrderToggleGroup; @FXML private RadioButton exportInSpecifiedOrder; @FXML private RadioButton exportInTableOrder; @FXML private RadioButton exportInOriginalOrder; @@ -30,11 +27,10 @@ public class SaveOrderConfigDisplayView extends VBox { @FXML private CheckBox savePriDesc; @FXML private CheckBox saveSecDesc; @FXML private CheckBox saveTerDesc; - @Inject private PreferencesService preferencesService; - private SaveOrderConfigDisplayViewModel viewModel; + private SaveOrderConfigPanelViewModel viewModel; - public SaveOrderConfigDisplayView() { + public SaveOrderConfigPanel() { ViewLoader.view(this) .root(this) .load(); @@ -42,8 +38,7 @@ public SaveOrderConfigDisplayView() { @FXML private void initialize() { - - viewModel = new SaveOrderConfigDisplayViewModel(preferencesService); + viewModel = new SaveOrderConfigPanelViewModel(); exportInOriginalOrder.selectedProperty().bindBidirectional(viewModel.saveInOriginalProperty()); exportInTableOrder.selectedProperty().bindBidirectional(viewModel.saveInTableOrderProperty()); @@ -52,32 +47,27 @@ private void initialize() { new ViewModelListCellFactory() .withText(FieldsUtil::getNameWithType) .install(savePriSort); - savePriSort.itemsProperty().bindBidirectional(viewModel.priSortFieldsProperty()); - savePriSort.valueProperty().bindBidirectional(viewModel.savePriSortSelectedValueProperty()); + savePriSort.itemsProperty().bindBidirectional(viewModel.primarySortFieldsProperty()); + savePriSort.valueProperty().bindBidirectional(viewModel.savePrimarySortSelectedValueProperty()); savePriSort.setConverter(FieldsUtil.fieldStringConverter); new ViewModelListCellFactory() .withText(FieldsUtil::getNameWithType) .install(saveSecSort); - saveSecSort.itemsProperty().bindBidirectional(viewModel.secSortFieldsProperty()); - saveSecSort.valueProperty().bindBidirectional(viewModel.saveSecSortSelectedValueProperty()); + saveSecSort.itemsProperty().bindBidirectional(viewModel.secondarySortFieldsProperty()); + saveSecSort.valueProperty().bindBidirectional(viewModel.saveSecondarySortSelectedValueProperty()); saveSecSort.setConverter(FieldsUtil.fieldStringConverter); new ViewModelListCellFactory() .withText(FieldsUtil::getNameWithType) .install(saveTerSort); - saveTerSort.itemsProperty().bindBidirectional(viewModel.terSortFieldsProperty()); - saveTerSort.valueProperty().bindBidirectional(viewModel.saveTerSortSelectedValueProperty()); + saveTerSort.itemsProperty().bindBidirectional(viewModel.tertiarySortFieldsProperty()); + saveTerSort.valueProperty().bindBidirectional(viewModel.saveTertiarySortSelectedValueProperty()); saveTerSort.setConverter(FieldsUtil.fieldStringConverter); - savePriDesc.selectedProperty().bindBidirectional(viewModel.savePriDescPropertySelected()); - saveSecDesc.selectedProperty().bindBidirectional(viewModel.saveSecDescPropertySelected()); - saveTerDesc.selectedProperty().bindBidirectional(viewModel.saveTerDescPropertySelected()); - - } - - public void setValues(SaveOrderConfig config) { - viewModel.setSaveOrderConfig(config); + savePriDesc.selectedProperty().bindBidirectional(viewModel.savePrimaryDescPropertySelected()); + saveSecDesc.selectedProperty().bindBidirectional(viewModel.saveSecondaryDescPropertySelected()); + saveTerDesc.selectedProperty().bindBidirectional(viewModel.saveTertiaryDescPropertySelected()); } public void changeExportDescriptionToSave() { @@ -86,12 +76,51 @@ public void changeExportDescriptionToSave() { exportInTableOrder.setText(Localization.lang("Save in current table sort order")); } - public void storeConfig() { - viewModel.storeConfigInPrefs(); + public BooleanProperty saveInOriginalProperty() { + return viewModel.saveInOriginalProperty(); + } + + public BooleanProperty saveInTableOrderProperty() { + return viewModel.saveInTableOrderProperty(); + } + + public BooleanProperty saveInSpecifiedOrderProperty() { + return viewModel.saveInSpecifiedOrderProperty(); + } + + public ListProperty primarySortFieldsProperty() { + return viewModel.primarySortFieldsProperty(); + } + + public ListProperty secondarySortFieldsProperty() { + return viewModel.secondarySortFieldsProperty(); + } + + public ListProperty tertiarySortFieldsProperty() { + return viewModel.tertiarySortFieldsProperty(); + } + + public ObjectProperty savePrimarySortSelectedValueProperty() { + return viewModel.savePrimarySortSelectedValueProperty(); + } + + public ObjectProperty saveSecondarySortSelectedValueProperty() { + return viewModel.saveSecondarySortSelectedValueProperty(); + } + + public ObjectProperty saveTertiarySortSelectedValueProperty() { + return viewModel.saveTertiarySortSelectedValueProperty(); } - public SaveOrderConfig getSaveOrderConfig() { - return viewModel.getSaveOrderConfig(); + public BooleanProperty savePrimaryDescPropertySelected() { + return viewModel.savePrimaryDescPropertySelected(); } + public BooleanProperty saveSecondaryDescPropertySelected() { + return viewModel.saveSecondaryDescPropertySelected(); + } + + public BooleanProperty saveTertiaryDescPropertySelected() { + return viewModel.saveTertiaryDescPropertySelected(); + } } diff --git a/src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanelViewModel.java b/src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanelViewModel.java new file mode 100644 index 00000000000..0fb898392b1 --- /dev/null +++ b/src/main/java/org/jabref/gui/commonfxcontrols/SaveOrderConfigPanelViewModel.java @@ -0,0 +1,81 @@ +package org.jabref.gui.commonfxcontrols; + +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.model.entry.field.Field; + +public class SaveOrderConfigPanelViewModel { + + private final ListProperty primarySortFieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); + private final ListProperty secondarySortFieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); + private final ListProperty tertiarySortFieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); + + private final BooleanProperty savePrimaryDescPropertySelected = new SimpleBooleanProperty(); + private final BooleanProperty saveSecondaryDescPropertySelected = new SimpleBooleanProperty(); + private final BooleanProperty saveTertiaryDescPropertySelected = new SimpleBooleanProperty(); + + private final ObjectProperty savePrimarySortSelectedValueProperty = new SimpleObjectProperty<>(null); + private final ObjectProperty saveSecondarySortSelectedValueProperty = new SimpleObjectProperty<>(null); + private final ObjectProperty saveTertiarySortSelectedValueProperty = new SimpleObjectProperty<>(null); + + private final BooleanProperty saveInOriginalProperty = new SimpleBooleanProperty(); + private final BooleanProperty saveInTableOrderProperty = new SimpleBooleanProperty(); + private final BooleanProperty saveInSpecifiedOrderProperty = new SimpleBooleanProperty(); + + public SaveOrderConfigPanelViewModel() { + } + + public BooleanProperty saveInOriginalProperty() { + return saveInOriginalProperty; + } + + public BooleanProperty saveInTableOrderProperty() { + return saveInTableOrderProperty; + } + + public BooleanProperty saveInSpecifiedOrderProperty() { + return saveInSpecifiedOrderProperty; + } + + public ListProperty primarySortFieldsProperty() { + return primarySortFieldsProperty; + } + + public ListProperty secondarySortFieldsProperty() { + return secondarySortFieldsProperty; + } + + public ListProperty tertiarySortFieldsProperty() { + return tertiarySortFieldsProperty; + } + + public ObjectProperty savePrimarySortSelectedValueProperty() { + return savePrimarySortSelectedValueProperty; + } + + public ObjectProperty saveSecondarySortSelectedValueProperty() { + return saveSecondarySortSelectedValueProperty; + } + + public ObjectProperty saveTertiarySortSelectedValueProperty() { + return saveTertiarySortSelectedValueProperty; + } + + public BooleanProperty savePrimaryDescPropertySelected() { + return savePrimaryDescPropertySelected; + } + + public BooleanProperty saveSecondaryDescPropertySelected() { + return saveSecondaryDescPropertySelected; + } + + public BooleanProperty saveTertiaryDescPropertySelected() { + return saveTertiaryDescPropertySelected; + } +} diff --git a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java index 6c513dbc9ce..e5a1960cd9f 100644 --- a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java +++ b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java @@ -1,6 +1,5 @@ package org.jabref.gui.libraryproperties; -import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; @@ -10,20 +9,15 @@ public class LibraryPropertiesAction extends SimpleCommand { private final JabRefFrame frame; - private final DialogService dialogService; - public LibraryPropertiesAction(JabRefFrame frame, DialogService dialogService, StateManager stateManager) { + public LibraryPropertiesAction(JabRefFrame frame, StateManager stateManager) { this.frame = frame; - this.dialogService = dialogService; - this.executable.bind(needsDatabase(stateManager)); } @Override public void execute() { - LibraryPropertiesDialogView propertiesDialog = new LibraryPropertiesDialogView(frame.getCurrentBasePanel(), dialogService); + LibraryPropertiesDialogView propertiesDialog = new LibraryPropertiesDialogView(frame.getCurrentBasePanel()); propertiesDialog.showAndWait(); - } - } diff --git a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml index 50faf887c78..e95edf125bb 100644 --- a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml +++ b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml @@ -2,7 +2,7 @@ - + @@ -16,65 +16,79 @@ + + + + - + - - - + + + - - - - - - - + + + + + + + -