diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 1da5e9c58e1..055eaba332f 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -30,20 +30,20 @@ import org.jabref.JabRefExecutorService; import org.jabref.gui.actions.Actions; import org.jabref.gui.actions.BaseAction; -import org.jabref.gui.actions.CleanupAction; -import org.jabref.gui.actions.CopyBibTeXKeyAndLinkAction; -import org.jabref.gui.actions.GenerateBibtexKeyAction; -import org.jabref.gui.actions.WriteXMPAction; import org.jabref.gui.autocompleter.AutoCompletePreferences; import org.jabref.gui.autocompleter.AutoCompleteUpdater; import org.jabref.gui.autocompleter.PersonNameSuggestionProvider; import org.jabref.gui.autocompleter.SuggestionProviders; +import org.jabref.gui.bibtexkeypattern.GenerateBibtexKeyAction; +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.exporter.WriteXMPAction; import org.jabref.gui.externalfiles.FindFullTextAction; import org.jabref.gui.externalfiletype.ExternalFileMenuItem; import org.jabref.gui.externalfiletype.ExternalFileType; @@ -294,7 +294,7 @@ private void setupActions() { // The action for cleaning up entry. actions.put(Actions.CLEANUP, cleanUpAction); - actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame).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); @@ -432,7 +432,7 @@ private void delete(boolean cut, List entries) { compound = new NamedCompound((entries.size() > 1 ? Localization.lang("delete entries") : Localization.lang("delete entry"))); } for (BibEntry entry : entries) { - compound.addEdit(new UndoableRemoveEntry(bibDatabaseContext.getDatabase(), entry, BasePanel.this)); + compound.addEdit(new UndoableRemoveEntry(bibDatabaseContext.getDatabase(), entry)); bibDatabaseContext.getDatabase().removeEntry(entry); ensureNotShowingBottomPanel(entry); } diff --git a/src/main/java/org/jabref/gui/EntryTypeViewModel.java b/src/main/java/org/jabref/gui/EntryTypeViewModel.java index 766d449f6c4..f6956a4ac23 100644 --- a/src/main/java/org/jabref/gui/EntryTypeViewModel.java +++ b/src/main/java/org/jabref/gui/EntryTypeViewModel.java @@ -14,6 +14,7 @@ import javafx.concurrent.Task; import javafx.concurrent.Worker; +import org.jabref.gui.duplicationFinder.DuplicateResolverDialog; import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.bibtexkeypattern.BibtexKeyGenerator; import org.jabref.logic.importer.FetcherException; diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 9b2a792ec93..2fff7ba1116 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -1,6 +1,5 @@ package org.jabref.gui; -import java.awt.Component; import java.awt.Window; import java.io.File; import java.io.IOException; @@ -8,7 +7,6 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -16,15 +14,12 @@ import java.util.TimerTask; import java.util.stream.Collectors; -import javax.swing.Action; import javax.swing.JOptionPane; -import javax.swing.JPanel; import javax.swing.SwingUtilities; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; -import javafx.collections.ListChangeListener; import javafx.geometry.Orientation; import javafx.scene.Node; import javafx.scene.control.Alert; @@ -55,54 +50,55 @@ import org.jabref.JabRefExecutorService; import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.Actions; -import org.jabref.gui.actions.BibtexKeyPatternAction; -import org.jabref.gui.actions.ConnectToSharedDatabaseCommand; -import org.jabref.gui.actions.CopyFilesAction; -import org.jabref.gui.actions.CustomizeKeyBindingAction; -import org.jabref.gui.actions.EditExternalFileTypesAction; -import org.jabref.gui.actions.ErrorConsoleAction; -import org.jabref.gui.actions.LibraryPropertiesAction; -import org.jabref.gui.actions.LookupIdentifierAction; -import org.jabref.gui.actions.ManageContentSelectorAction; -import org.jabref.gui.actions.ManageCustomExportsAction; -import org.jabref.gui.actions.ManageCustomImportsAction; -import org.jabref.gui.actions.ManageJournalsAction; -import org.jabref.gui.actions.NewDatabaseAction; -import org.jabref.gui.actions.NewEntryAction; -import org.jabref.gui.actions.NewSubLibraryAction; import org.jabref.gui.actions.OldDatabaseCommandWrapper; -import org.jabref.gui.actions.OpenBrowserAction; -import org.jabref.gui.actions.SearchForUpdateAction; -import org.jabref.gui.actions.SetupGeneralFieldsAction; -import org.jabref.gui.actions.ShowDocumentViewerAction; -import org.jabref.gui.actions.ShowPreferencesAction; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.actions.StandardActions; +import org.jabref.gui.auximport.NewSubLibraryAction; +import org.jabref.gui.bibtexkeypattern.BibtexKeyPatternAction; +import org.jabref.gui.contentselector.ManageContentSelectorAction; +import org.jabref.gui.copyfiles.CopyFilesAction; +import org.jabref.gui.customizefields.SetupGeneralFieldsAction; import org.jabref.gui.dialogs.AutosaveUIManager; +import org.jabref.gui.documentviewer.ShowDocumentViewerAction; +import org.jabref.gui.duplicationFinder.DuplicateSearch; import org.jabref.gui.edit.ManageKeywordsAction; import org.jabref.gui.edit.MassSetFieldsAction; +import org.jabref.gui.edit.OpenBrowserAction; 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.externalfiles.AutoLinkFilesAction; import org.jabref.gui.externalfiles.FindUnlinkedFilesAction; +import org.jabref.gui.externalfiletype.EditExternalFileTypesAction; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.help.AboutAction; +import org.jabref.gui.help.ErrorConsoleAction; import org.jabref.gui.help.HelpAction; +import org.jabref.gui.help.SearchForUpdateAction; import org.jabref.gui.importer.ImportCommand; import org.jabref.gui.importer.ImportEntriesDialog; +import org.jabref.gui.importer.ManageCustomImportsAction; +import org.jabref.gui.importer.NewDatabaseAction; +import org.jabref.gui.importer.NewEntryAction; import org.jabref.gui.importer.actions.OpenDatabaseAction; +import org.jabref.gui.importer.fetcher.LookupIdentifierAction; import org.jabref.gui.integrity.IntegrityCheckAction; +import org.jabref.gui.journals.ManageJournalsAction; +import org.jabref.gui.keyboard.CustomizeKeyBindingAction; import org.jabref.gui.keyboard.KeyBinding; +import org.jabref.gui.libraryproperties.LibraryPropertiesAction; import org.jabref.gui.menus.FileHistoryMenu; import org.jabref.gui.mergeentries.MergeEntriesAction; import org.jabref.gui.metadata.BibtexStringEditorAction; import org.jabref.gui.metadata.PreambleEditor; +import org.jabref.gui.preferences.ShowPreferencesAction; import org.jabref.gui.protectedterms.ManageProtectedTermsAction; import org.jabref.gui.push.PushToApplicationAction; -import org.jabref.gui.push.PushToApplications; +import org.jabref.gui.push.PushToApplicationsManager; import org.jabref.gui.search.GlobalSearchBar; +import org.jabref.gui.shared.ConnectToSharedDatabaseCommand; import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.BackgroundTask; @@ -153,52 +149,20 @@ public class JabRefFrame extends BorderPane { private final ProgressBar progressBar = new ProgressBar(); private final FileHistoryMenu fileHistory = new FileHistoryMenu(prefs, this); - // Lists containing different subsets of actions for different purposes - private final List specialFieldButtons = new LinkedList<>(); - private final List openDatabaseOnlyActions = new LinkedList<>(); - private final List severalDatabasesOnlyActions = new LinkedList<>(); - private final List openAndSavedDatabasesOnlyActions = new LinkedList<>(); - private final List sharedDatabaseOnlyActions = new LinkedList<>(); - private final List noSharedDatabaseActions = new LinkedList<>(); - private final List oneEntryOnlyActions = new LinkedList<>(); - private final List oneEntryWithFileOnlyActions = new LinkedList<>(); - private final List oneEntryWithURLorDOIOnlyActions = new LinkedList<>(); - private final List twoEntriesOnlyActions = new LinkedList<>(); - private final List atLeastOneEntryActions = new LinkedList<>(); private final Stage mainStage; - // The sidepane manager takes care of populating the sidepane. + private final StateManager stateManager; + private final CountingUndoManager undoManager; private SidePaneManager sidePaneManager; private TabPane tabbedPane; - private PushToApplications pushApplications; + private PushToApplicationsManager pushApplications; private final DialogService dialogService; private SidePane sidePane; public JabRefFrame(Stage mainStage) { this.mainStage = mainStage; this.dialogService = new JabRefDialogService(mainStage, this); - } - - /** - * Takes a list of Object and calls the method setEnabled on them, depending on whether it is an Action or a - * Component. - * - * @param list List that should contain Actions and Components. - */ - private static void setEnabled(List list, boolean enabled) { - for (Object actionOrComponent : list) { - if (actionOrComponent instanceof Action) { - ((Action) actionOrComponent).setEnabled(enabled); - } - if (actionOrComponent instanceof Component) { - ((Component) actionOrComponent).setEnabled(enabled); - if (actionOrComponent instanceof JPanel) { - JPanel root = (JPanel) actionOrComponent; - for (int index = 0; index < root.getComponentCount(); index++) { - root.getComponent(index).setEnabled(enabled); - } - } - } - } + this.stateManager = Globals.stateManager; + this.undoManager = Globals.undoManager; } public void init() { @@ -210,8 +174,6 @@ public void init() { initLayout(); - initActions(); - initKeyBindings(); tabbedPane.setOnDragOver(event -> { @@ -249,7 +211,7 @@ public void init() { */ EasyBind.subscribe(tabbedPane.getSelectionModel().selectedItemProperty(), e -> { if (e == null) { - Globals.stateManager.activeDatabaseProperty().setValue(Optional.empty()); + stateManager.activeDatabaseProperty().setValue(Optional.empty()); return; } @@ -259,8 +221,8 @@ public void init() { } // Poor-mans binding to global state - // We need to invoke this in the JavaFX thread as all the listeners sit there - Platform.runLater(() -> Globals.stateManager.activeDatabaseProperty().setValue(Optional.of(currentBasePanel.getBibDatabaseContext()))); + stateManager.activeDatabaseProperty().setValue(Optional.of(currentBasePanel.getBibDatabaseContext())); + stateManager.setSelectedEntries(currentBasePanel.getSelectedEntries()); // Update search query String content = ""; @@ -489,7 +451,7 @@ public boolean quit() { private void initLayout() { setProgressBarVisible(false); - pushApplications = new PushToApplications(this.getDialogService()); + pushApplications = new PushToApplicationsManager(this.getDialogService()); BorderPane head = new BorderPane(); head.setTop(createMenu()); @@ -553,27 +515,27 @@ private Node createToolbar() { HBox leftSide = new HBox( newLibrary, factory.createIconButton(StandardActions.OPEN_LIBRARY, new OpenDatabaseAction(this)), - factory.createIconButton(StandardActions.SAVE_LIBRARY, new OldDatabaseCommandWrapper(Actions.SAVE, this, Globals.stateManager)), + factory.createIconButton(StandardActions.SAVE_LIBRARY, new OldDatabaseCommandWrapper(Actions.SAVE, this, stateManager)), leftSpacer ); leftSide.setMinWidth(100); leftSide.prefWidthProperty().bind(sidePane.widthProperty()); leftSide.maxWidthProperty().bind(sidePane.widthProperty()); - PushToApplicationAction pushToApplicationAction = new PushToApplicationAction(this, Globals.stateManager); + PushToApplicationAction pushToApplicationAction = new PushToApplicationAction(stateManager, this.getPushApplications(), this.getDialogService()); HBox rightSide = new HBox( - factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(this, BiblatexEntryTypes.ARTICLE, dialogService, Globals.prefs)), - factory.createIconButton(StandardActions.DELETE_ENTRY, new OldDatabaseCommandWrapper(Actions.DELETE, this, Globals.stateManager)), + factory.createIconButton(StandardActions.NEW_ARTICLE, new NewEntryAction(this, BiblatexEntryTypes.ARTICLE, dialogService, Globals.prefs, stateManager)), + factory.createIconButton(StandardActions.DELETE_ENTRY, new OldDatabaseCommandWrapper(Actions.DELETE, this, stateManager)), new Separator(Orientation.VERTICAL), - factory.createIconButton(StandardActions.UNDO, new OldDatabaseCommandWrapper(Actions.UNDO, this, Globals.stateManager)), - factory.createIconButton(StandardActions.REDO, new OldDatabaseCommandWrapper(Actions.REDO, this, Globals.stateManager)), - factory.createIconButton(StandardActions.CUT, new OldDatabaseCommandWrapper(Actions.CUT, this, Globals.stateManager)), - factory.createIconButton(StandardActions.COPY, new OldDatabaseCommandWrapper(Actions.COPY, this, Globals.stateManager)), - factory.createIconButton(StandardActions.PASTE, new OldDatabaseCommandWrapper(Actions.PASTE, this, Globals.stateManager)), + factory.createIconButton(StandardActions.UNDO, new OldDatabaseCommandWrapper(Actions.UNDO, this, stateManager)), + factory.createIconButton(StandardActions.REDO, new OldDatabaseCommandWrapper(Actions.REDO, this, stateManager)), + factory.createIconButton(StandardActions.CUT, new OldDatabaseCommandWrapper(Actions.CUT, this, stateManager)), + factory.createIconButton(StandardActions.COPY, new OldDatabaseCommandWrapper(Actions.COPY, this, stateManager)), + factory.createIconButton(StandardActions.PASTE, new OldDatabaseCommandWrapper(Actions.PASTE, this, stateManager)), new Separator(Orientation.VERTICAL), factory.createIconButton(pushToApplicationAction.getActionInformation(), pushToApplicationAction), - factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new OldDatabaseCommandWrapper(Actions.MAKE_KEY, this, Globals.stateManager)), - factory.createIconButton(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, Globals.stateManager)), + factory.createIconButton(StandardActions.GENERATE_CITE_KEYS, new OldDatabaseCommandWrapper(Actions.MAKE_KEY, this, stateManager)), + factory.createIconButton(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, stateManager)), new Separator(Orientation.VERTICAL), factory.createIconButton(StandardActions.FORK_ME, new OpenBrowserAction("https://github.com/JabRef/jabref")), factory.createIconButton(StandardActions.OPEN_FACEBOOK, new OpenBrowserAction("https://www.facebook.com/JabRef/")), @@ -682,24 +644,24 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.OPEN_LIBRARY, getOpenDatabaseAction()), fileHistory, - factory.createMenuItem(StandardActions.SAVE_LIBRARY, new OldDatabaseCommandWrapper(Actions.SAVE, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new OldDatabaseCommandWrapper(Actions.SAVE_AS, this, Globals.stateManager)), + factory.createMenuItem(StandardActions.SAVE_LIBRARY, new OldDatabaseCommandWrapper(Actions.SAVE, this, stateManager)), + factory.createMenuItem(StandardActions.SAVE_LIBRARY_AS, new OldDatabaseCommandWrapper(Actions.SAVE_AS, this, stateManager)), factory.createMenuItem(StandardActions.SAVE_ALL, new SaveAllAction(this)), new SeparatorMenuItem(), factory.createSubMenu(StandardActions.IMPORT, - factory.createMenuItem(StandardActions.MERGE_DATABASE, new OldDatabaseCommandWrapper(Actions.MERGE_DATABASE, this, Globals.stateManager)), // TODO: merge with import + factory.createMenuItem(StandardActions.MERGE_DATABASE, new OldDatabaseCommandWrapper(Actions.MERGE_DATABASE, this, stateManager)), // TODO: merge with import factory.createMenuItem(StandardActions.IMPORT_INTO_CURRENT_LIBRARY, new ImportCommand(this, false)), factory.createMenuItem(StandardActions.IMPORT_INTO_NEW_LIBRARY, new ImportCommand(this, true))), factory.createSubMenu(StandardActions.EXPORT, factory.createMenuItem(StandardActions.EXPORT_ALL, new ExportCommand(this, false, Globals.prefs)), factory.createMenuItem(StandardActions.EXPORT_SELECTED, new ExportCommand(this, true, Globals.prefs)), - factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new OldDatabaseCommandWrapper(Actions.SAVE_SELECTED_AS_PLAIN, this, Globals.stateManager))), + factory.createMenuItem(StandardActions.SAVE_SELECTED_AS_PLAIN_BIBTEX, new OldDatabaseCommandWrapper(Actions.SAVE_SELECTED_AS_PLAIN, this, stateManager))), factory.createMenuItem(StandardActions.CONNECT_TO_SHARED_DB, new ConnectToSharedDatabaseCommand(this)), - factory.createMenuItem(StandardActions.PULL_CHANGES_FROM_SHARED_DB, new OldDatabaseCommandWrapper(Actions.PULL_CHANGES_FROM_SHARED_DATABASE, this, Globals.stateManager)), + factory.createMenuItem(StandardActions.PULL_CHANGES_FROM_SHARED_DB, new OldDatabaseCommandWrapper(Actions.PULL_CHANGES_FROM_SHARED_DATABASE, this, stateManager)), new SeparatorMenuItem(), @@ -708,8 +670,8 @@ private MenuBar createMenu() { ); edit.getItems().addAll( - factory.createMenuItem(StandardActions.UNDO, new OldDatabaseCommandWrapper(Actions.UNDO, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.REDO, new OldDatabaseCommandWrapper(Actions.REDO, this, Globals.stateManager)), + factory.createMenuItem(StandardActions.UNDO, new OldDatabaseCommandWrapper(Actions.UNDO, this, stateManager)), + factory.createMenuItem(StandardActions.REDO, new OldDatabaseCommandWrapper(Actions.REDO, this, stateManager)), new SeparatorMenuItem(), @@ -717,25 +679,25 @@ 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, Globals.stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY, new OldDatabaseCommandWrapper(Actions.COPY_KEY, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.COPY_CITE_KEY, new OldDatabaseCommandWrapper(Actions.COPY_CITE_KEY, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY_AND_TITLE, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_TITLE, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.COPY_KEY_AND_LINK, new OldDatabaseCommandWrapper(Actions.COPY_KEY_AND_LINK, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.COPY_CITATION_PREVIEW, new OldDatabaseCommandWrapper(Actions.COPY_CITATION_HTML, this, Globals.stateManager)), + 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_CITATION_PREVIEW, new OldDatabaseCommandWrapper(Actions.COPY_CITATION_HTML, this, stateManager)), factory.createMenuItem(StandardActions.EXPORT_SELECTED_TO_CLIPBOARD, new ExportToClipboardAction(this, dialogService))), factory.createMenuItem(StandardActions.PASTE, new EditAction(Actions.PASTE)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.MANAGE_KEYWORDS, new ManageKeywordsAction(this)) + factory.createMenuItem(StandardActions.MANAGE_KEYWORDS, new ManageKeywordsAction(stateManager)) ); if (Globals.prefs.getBoolean(JabRefPreferences.SPECIALFIELDSENABLED)) { boolean menuItemAdded = false; if (Globals.prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_RANKING)) { - edit.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.RANKING, factory, Globals.undoManager)); + edit.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.RANKING, factory, undoManager)); menuItemAdded = true; } @@ -755,12 +717,12 @@ private MenuBar createMenu() { } if (Globals.prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_PRIORITY)) { - edit.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.PRIORITY, factory, Globals.undoManager)); + edit.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.PRIORITY, factory, undoManager)); menuItemAdded = true; } if (Globals.prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_READ)) { - edit.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.READ_STATUS, factory, Globals.undoManager)); + edit.getItems().add(SpecialFieldMenuItemFactory.createSpecialFieldMenuForActiveDatabase(SpecialField.READ_STATUS, factory, undoManager)); menuItemAdded = true; } @@ -770,59 +732,59 @@ private MenuBar createMenu() { } //@formatter:off library.getItems().addAll( - factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(this, dialogService, Globals.prefs)), - factory.createMenuItem(StandardActions.DELETE_ENTRY, new OldDatabaseCommandWrapper(Actions.DELETE, this, Globals.stateManager)), + factory.createMenuItem(StandardActions.NEW_ENTRY, new NewEntryAction(this, dialogService, Globals.prefs, stateManager)), + factory.createMenuItem(StandardActions.DELETE_ENTRY, new OldDatabaseCommandWrapper(Actions.DELETE, this, stateManager)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.LIBRARY_PROPERTIES, new LibraryPropertiesAction(this, dialogService)), - factory.createMenuItem(StandardActions.EDIT_PREAMBLE, new PreambleEditor(this)), - factory.createMenuItem(StandardActions.EDIT_STRINGS, new BibtexStringEditorAction(this)), - factory.createMenuItem(StandardActions.MANAGE_CITE_KEY_PATTERNS, new BibtexKeyPatternAction(this)), - factory.createMenuItem(StandardActions.MASS_SET_FIELDS, new MassSetFieldsAction(this)) + 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)) ); Menu lookupIdentifiers = factory.createSubMenu(StandardActions.LOOKUP_DOC_IDENTIFIER); for (IdFetcher fetcher : WebFetchers.getIdFetchers(Globals.prefs.getImportFormatPreferences())) { - LookupIdentifierAction identifierAction = new LookupIdentifierAction<>(this, fetcher); + LookupIdentifierAction identifierAction = new LookupIdentifierAction<>(this, fetcher, stateManager, undoManager); lookupIdentifiers.getItems().add(factory.createMenuItem(identifierAction.getAction(), identifierAction)); } quality.getItems().addAll( - factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this, dialogService)), - factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this)), - factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(this)), - factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, Globals.stateManager)), + factory.createMenuItem(StandardActions.FIND_DUPLICATES, new DuplicateSearch(this, dialogService, stateManager)), + factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(this, stateManager)), + factory.createMenuItem(StandardActions.CHECK_INTEGRITY, new IntegrityCheckAction(this, stateManager, Globals.TASK_EXECUTOR)), + factory.createMenuItem(StandardActions.CLEANUP_ENTRIES, new OldDatabaseCommandWrapper(Actions.CLEANUP, this, stateManager)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.SET_FILE_LINKS, new AutoLinkFilesAction(this, prefs)) + factory.createMenuItem(StandardActions.SET_FILE_LINKS, new AutoLinkFilesAction(this, prefs, stateManager, undoManager)) ); - final PushToApplicationAction pushToApplicationAction = new PushToApplicationAction(this, Globals.stateManager); + final PushToApplicationAction pushToApplicationAction = new PushToApplicationAction(stateManager, this.getPushApplications(), this.getDialogService()); tools.getItems().addAll( - factory.createMenuItem(StandardActions.NEW_SUB_LIBRARY_FROM_AUX, new NewSubLibraryAction(this)), - factory.createMenuItem(StandardActions.FIND_UNLINKED_FILES, new FindUnlinkedFilesAction(this)), - factory.createMenuItem(StandardActions.WRITE_XMP, new OldDatabaseCommandWrapper(Actions.WRITE_XMP, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.COPY_LINKED_FILES, new CopyFilesAction(this)), + 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.COPY_LINKED_FILES, new CopyFilesAction(stateManager, this.getDialogService())), new SeparatorMenuItem(), lookupIdentifiers, - factory.createMenuItem(StandardActions.DOWNLOAD_FULL_TEXT, new OldDatabaseCommandWrapper(Actions.DOWNLOAD_FULL_TEXT, this, Globals.stateManager)), + factory.createMenuItem(StandardActions.DOWNLOAD_FULL_TEXT, new OldDatabaseCommandWrapper(Actions.DOWNLOAD_FULL_TEXT, this, stateManager)), new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.GENERATE_CITE_KEYS, new OldDatabaseCommandWrapper(Actions.MAKE_KEY, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.REPLACE_ALL, new OldDatabaseCommandWrapper(Actions.REPLACE_ALL, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new OldDatabaseCommandWrapper(Actions.SEND_AS_EMAIL, this, Globals.stateManager)), + 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(pushToApplicationAction.getActionInformation(), pushToApplicationAction), factory.createSubMenu(StandardActions.ABBREVIATE, - factory.createMenuItem(StandardActions.ABBREVIATE_ISO, new OldDatabaseCommandWrapper(Actions.ABBREVIATE_ISO, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.ABBREVIATE_MEDLINE, new OldDatabaseCommandWrapper(Actions.ABBREVIATE_MEDLINE, this, Globals.stateManager))), + factory.createMenuItem(StandardActions.ABBREVIATE_ISO, new OldDatabaseCommandWrapper(Actions.ABBREVIATE_ISO, this, stateManager)), + factory.createMenuItem(StandardActions.ABBREVIATE_MEDLINE, new OldDatabaseCommandWrapper(Actions.ABBREVIATE_MEDLINE, this, stateManager))), - factory.createMenuItem(StandardActions.UNABBREVIATE, new OldDatabaseCommandWrapper(Actions.UNABBREVIATE, this, Globals.stateManager)) + factory.createMenuItem(StandardActions.UNABBREVIATE, new OldDatabaseCommandWrapper(Actions.UNABBREVIATE, this, stateManager)) ); SidePaneComponent webSearch = sidePaneManager.getComponent(SidePaneType.WEB_SEARCH); @@ -839,15 +801,15 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createCheckMenuItem(StandardActions.TOGGLE_PREVIEW, new OldDatabaseCommandWrapper(Actions.TOGGLE_PREVIEW, this, Globals.stateManager), Globals.prefs.getPreviewPreferences().isPreviewPanelEnabled()), - factory.createMenuItem(StandardActions.NEXT_PREVIEW_STYLE, new OldDatabaseCommandWrapper(Actions.NEXT_PREVIEW_STYLE, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.PREVIOUS_PREVIEW_STYLE, new OldDatabaseCommandWrapper(Actions.PREVIOUS_PREVIEW_STYLE, this, Globals.stateManager)), + factory.createCheckMenuItem(StandardActions.TOGGLE_PREVIEW, new OldDatabaseCommandWrapper(Actions.TOGGLE_PREVIEW, this, stateManager), Globals.prefs.getPreviewPreferences().isPreviewPanelEnabled()), + 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)), new SeparatorMenuItem(), factory.createMenuItem(StandardActions.SHOW_PDF_VIEWER, new ShowDocumentViewerAction()), - factory.createMenuItem(StandardActions.EDIT_ENTRY, new OldDatabaseCommandWrapper(Actions.EDIT, this, Globals.stateManager)), - factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OldDatabaseCommandWrapper(Actions.OPEN_CONSOLE, this, Globals.stateManager)) + factory.createMenuItem(StandardActions.EDIT_ENTRY, new OldDatabaseCommandWrapper(Actions.EDIT, this, stateManager)), + factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OldDatabaseCommandWrapper(Actions.OPEN_CONSOLE, this, stateManager)) ); }); @@ -866,7 +828,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.MANAGE_CONTENT_SELECTORS, new ManageContentSelectorAction(this)) + factory.createMenuItem(StandardActions.MANAGE_CONTENT_SELECTORS, new ManageContentSelectorAction(this, stateManager)) // TODO: Reenable customize entry types feature (https://github.com/JabRef/jabref/issues/4719) //factory.createMenuItem(StandardActions.CUSTOMIZE_ENTRY_TYPES, new CustomizeEntryAction(this)), ); @@ -943,84 +905,6 @@ public void addParserResult(ParserResult pr, boolean focusPanel) { } } - private void initActions() { - /* - openDatabaseOnlyActions.clear(); - openDatabaseOnlyActions.addAll(Arrays.asList(manageSelectors, mergeDatabaseAction, newSubDatabaseAction, save, copyPreview, - saveAs, saveSelectedAs, saveSelectedAsPlain, undo, redo, cut, deleteEntry, copy, paste, mark, markSpecific, unmark, - unmarkAll, rankSubMenu, editEntry, selectAll, copyKey, copyCiteKey, copyKeyAndTitle, copyKeyAndLink, editPreamble, editStrings, - groupSidePane.getToggleCommand(), makeKeyAction, normalSearch, generalFetcher.getToggleCommand(), mergeEntries, cleanupEntries, exportToClipboard, replaceAll, - sendAsEmail, downloadFullText, lookupIdentifiers, writeXmpAction, openOfficePanel.getToggleCommand(), findUnlinkedFiles, addToGroup, removeFromGroup, - moveToGroup, autoLinkFile, resolveDuplicateKeys, openUrl, openFolder, openFile, togglePreview, - dupliCheck, autoSetFile, newEntryAction, newSpec, customizeAction, plainTextImport, getMassSetField(), getManageKeywords(), - pushExternalButton.getMenuAction(), closeDatabaseAction, getNextPreviewStyleAction(), getPreviousPreviewStyleAction(), checkIntegrity, - databaseProperties, abbreviateIso, abbreviateMedline, - unabbreviate, exportAll, exportSelected, importCurrent, saveAll, focusTable, increaseFontSize, decreseFontSize, defaultFontSize, - toggleRelevance, toggleQualityAssured, togglePrinted, pushExternalButton.getComponent())); - openDatabaseOnlyActions.addAll(newSpecificEntryAction); - openDatabaseOnlyActions.addAll(specialFieldButtons); - severalDatabasesOnlyActions.clear(); - severalDatabasesOnlyActions.addAll(Arrays - .asList(nextTab, prevTab, sortTabs)); - openAndSavedDatabasesOnlyActions.addAll(Collections.singletonList(openConsole)); - sharedDatabaseOnlyActions.addAll(Collections.singletonList(pullChangesFromSharedDatabase)); - noSharedDatabaseActions.addAll(Arrays.asList(save, saveAll)); - oneEntryOnlyActions.clear(); - oneEntryOnlyActions.addAll(Arrays.asList(editEntry)); - oneEntryWithFileOnlyActions.clear(); - oneEntryWithFileOnlyActions.addAll(Arrays.asList(openFolder, openFile)); - oneEntryWithURLorDOIOnlyActions.clear(); - oneEntryWithURLorDOIOnlyActions.addAll(Arrays.asList(openUrl)); - twoEntriesOnlyActions.clear(); - twoEntriesOnlyActions.addAll(Arrays.asList(mergeEntries)); - atLeastOneEntryActions.clear(); - atLeastOneEntryActions.addAll(Arrays.asList(downloadFullText, lookupIdentifiers, exportLinkedFiles)); - tabbedPane.getTabs().addListener(this::updateEnabledState); - */ - } - - /** - * Enable or Disable all actions based on the number of open tabs. - *

- * The action that are affected are set in initActions. - */ - public void updateEnabledState(ListChangeListener.Change change) { - int tabCount = tabbedPane.getTabs().size(); - if (!change.next()) { - return; - } - if (change.wasAdded() || change.wasRemoved()) { - setEnabled(openDatabaseOnlyActions, tabCount > 0); - setEnabled(severalDatabasesOnlyActions, tabCount > 1); - } - if (tabCount == 0) { - setEnabled(openAndSavedDatabasesOnlyActions, false); - setEnabled(sharedDatabaseOnlyActions, false); - setEnabled(oneEntryOnlyActions, false); - } - - if (tabCount > 0) { - BasePanel current = getCurrentBasePanel(); - boolean saved = current.getBibDatabaseContext().getDatabasePath().isPresent(); - setEnabled(openAndSavedDatabasesOnlyActions, saved); - - boolean isShared = current.getBibDatabaseContext().getLocation() == DatabaseLocation.SHARED; - setEnabled(sharedDatabaseOnlyActions, isShared); - setEnabled(noSharedDatabaseActions, !isShared); - - boolean oneEntrySelected = current.getSelectedEntries().size() == 1; - setEnabled(oneEntryOnlyActions, oneEntrySelected); - setEnabled(oneEntryWithFileOnlyActions, isExistFile(current.getSelectedEntries())); - setEnabled(oneEntryWithURLorDOIOnlyActions, isExistURLorDOI(current.getSelectedEntries())); - - boolean twoEntriesSelected = current.getSelectedEntries().size() == 2; - setEnabled(twoEntriesOnlyActions, twoEntriesSelected); - - boolean atLeastOneEntrySelected = !current.getSelectedEntries().isEmpty(); - setEnabled(atLeastOneEntryActions, atLeastOneEntrySelected); - } - } - /** * This method causes all open BasePanels to set up their tables anew. When called from PrefsDialog3, this updates * to the new settings. @@ -1310,7 +1194,7 @@ public SidePaneManager getSidePaneManager() { return sidePaneManager; } - public PushToApplications getPushApplications() { + public PushToApplicationsManager getPushApplications() { return pushApplications; } @@ -1319,7 +1203,7 @@ public GlobalSearchBar getGlobalSearchBar() { } public CountingUndoManager getUndoManager() { - return Globals.undoManager; + return undoManager; } public DialogService getDialogService() { diff --git a/src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml b/src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml index 4bee6851ab0..14c2655be95 100644 --- a/src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml +++ b/src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml @@ -8,7 +8,6 @@ - diff --git a/src/main/java/org/jabref/gui/StateManager.java b/src/main/java/org/jabref/gui/StateManager.java index 2acc073ae7b..630d5511eb9 100644 --- a/src/main/java/org/jabref/gui/StateManager.java +++ b/src/main/java/org/jabref/gui/StateManager.java @@ -6,23 +6,19 @@ import java.util.stream.Collectors; import javafx.beans.binding.Bindings; -import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyListProperty; import javafx.beans.property.ReadOnlyListWrapper; -import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; +import org.jabref.gui.util.OptionalObjectProperty; import org.jabref.logic.search.SearchQuery; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.util.OptionalUtil; -import org.fxmisc.easybind.EasyBind; -import org.fxmisc.easybind.monadic.MonadicBinding; - /** * This class manages the GUI-state of JabRef, including: * - currently selected database @@ -33,22 +29,21 @@ */ public class StateManager { - private final ObjectProperty> activeDatabase = new SimpleObjectProperty<>(Optional.empty()); + private final OptionalObjectProperty activeDatabase = OptionalObjectProperty.empty(); private final ReadOnlyListWrapper activeGroups = new ReadOnlyListWrapper<>(FXCollections.observableArrayList()); private final ObservableList selectedEntries = FXCollections.observableArrayList(); private final ObservableMap> selectedGroups = FXCollections.observableHashMap(); - private final ObjectProperty> activeSearchQuery = new SimpleObjectProperty<>(Optional.empty()); + private final OptionalObjectProperty activeSearchQuery = OptionalObjectProperty.empty(); public StateManager() { - MonadicBinding currentDatabase = EasyBind.map(activeDatabase, database -> database.orElse(null)); - activeGroups.bind(Bindings.valueAt(selectedGroups, currentDatabase)); + activeGroups.bind(Bindings.valueAt(selectedGroups, activeDatabase.orElse(null))); } - public ObjectProperty> activeDatabaseProperty() { + public OptionalObjectProperty activeDatabaseProperty() { return activeDatabase; } - public ObjectProperty> activeSearchQueryProperty() { + public OptionalObjectProperty activeSearchQueryProperty() { return activeSearchQuery; } diff --git a/src/main/java/org/jabref/gui/actions/ActionFactory.java b/src/main/java/org/jabref/gui/actions/ActionFactory.java index 69c5531db65..07a8ddb3f2f 100644 --- a/src/main/java/org/jabref/gui/actions/ActionFactory.java +++ b/src/main/java/org/jabref/gui/actions/ActionFactory.java @@ -1,24 +1,35 @@ package org.jabref.gui.actions; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Objects; import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.ButtonBase; import javafx.scene.control.CheckMenuItem; +import javafx.scene.control.Label; import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; +import javafx.scene.control.Tooltip; import org.jabref.gui.keyboard.KeyBindingRepository; +import org.jabref.model.strings.StringUtil; +import com.sun.javafx.scene.control.skin.ContextMenuContent; import de.saxsys.mvvmfx.utils.commands.Command; import org.controlsfx.control.action.ActionUtils; +import org.fxmisc.easybind.EasyBind; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Helper class to create and style controls according to an {@link Action}. */ public class ActionFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(ActionFactory.class); + private final KeyBindingRepository keyBindingRepository; public ActionFactory(KeyBindingRepository keyBindingRepository) { @@ -33,14 +44,64 @@ private static void setGraphic(MenuItem node, Action action) { action.getIcon().ifPresent(icon -> node.setGraphic(icon.getGraphicNode())); } - public MenuItem configureMenuItem(Action action, Command command, MenuItem menuItem) { - return ActionUtils.configureMenuItem(new JabRefAction(action, command, keyBindingRepository), menuItem); + /* + * Returns MenuItemContainer node associated with this menu item + * which can contain: + * 1. label node of type Label for displaying menu item text, + * 2. right node of type Label for displaying accelerator text, + * or an arrow if it's a Menu, + * 3. graphic node for displaying menu item icon, and + * 4. left node for displaying either radio button or check box. + * + * This is basically rewritten impl_styleableGetNode() which + * should not be used since it's marked as deprecated. + */ + private static Label getAssociatedNode(MenuItem menuItem) { + ContextMenuContent.MenuItemContainer container = (ContextMenuContent.MenuItemContainer) menuItem.impl_styleableGetNode(); + + if (container == null) { + return null; + } else { + // We have to use reflection to get the associated label + try { + Method getLabel = ContextMenuContent.MenuItemContainer.class.getDeclaredMethod("getLabel"); + getLabel.setAccessible(true); + return (Label) getLabel.invoke(container); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + LOGGER.warn("Could not get label of menu item", e); + } + } + return null; } - public MenuItem createMenuItem(Action action, Command command) { - MenuItem menuItem = ActionUtils.createMenuItem(new JabRefAction(action, command, keyBindingRepository)); + public MenuItem configureMenuItem(Action action, Command command, MenuItem menuItem) { + ActionUtils.configureMenuItem(new JabRefAction(action, command, keyBindingRepository), menuItem); setGraphic(menuItem, action); + // Show tooltips + if (command instanceof SimpleCommand) { + EasyBind.subscribe( + ((SimpleCommand) command).statusMessageProperty(), + message -> { + Label label = getAssociatedNode(menuItem); + if (label != null) { + label.setMouseTransparent(false); + if (StringUtil.isBlank(message)) { + label.setTooltip(null); + } else { + label.setTooltip(new Tooltip(message)); + } + } + } + ); + } + + return menuItem; + } + + public MenuItem createMenuItem(Action action, Command command) { + MenuItem menuItem = new MenuItem(); + configureMenuItem(action, command, menuItem); return menuItem; } diff --git a/src/main/java/org/jabref/gui/actions/ActionHelper.java b/src/main/java/org/jabref/gui/actions/ActionHelper.java new file mode 100644 index 00000000000..dfd66772a3a --- /dev/null +++ b/src/main/java/org/jabref/gui/actions/ActionHelper.java @@ -0,0 +1,16 @@ +package org.jabref.gui.actions; + +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanExpression; + +import org.jabref.gui.StateManager; + +public class ActionHelper { + public static BooleanExpression needsDatabase(StateManager stateManager) { + return stateManager.activeDatabaseProperty().isPresent(); + } + + public static BooleanExpression needsEntriesSelected(StateManager stateManager) { + return Bindings.isNotEmpty(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 f115eda059c..5348e3394ae 100644 --- a/src/main/java/org/jabref/gui/actions/Actions.java +++ b/src/main/java/org/jabref/gui/actions/Actions.java @@ -3,6 +3,7 @@ /** * Global String constants for GUI actions */ +@Deprecated public enum Actions { ABBREVIATE_ISO, diff --git a/src/main/java/org/jabref/gui/actions/BaseAction.java b/src/main/java/org/jabref/gui/actions/BaseAction.java index a29c3a8573e..0af963e1a30 100644 --- a/src/main/java/org/jabref/gui/actions/BaseAction.java +++ b/src/main/java/org/jabref/gui/actions/BaseAction.java @@ -4,8 +4,11 @@ * BaseAction is used to define actions that are called from the * base frame through runCommand(). runCommand() finds the * appropriate BaseAction object, and runs its action() method. + * + * @deprecated use {@link SimpleCommand} instead */ @FunctionalInterface +@Deprecated public interface BaseAction { void action() throws Exception; diff --git a/src/main/java/org/jabref/gui/actions/BibtexKeyPatternAction.java b/src/main/java/org/jabref/gui/actions/BibtexKeyPatternAction.java deleted file mode 100644 index 7eaae3af4df..00000000000 --- a/src/main/java/org/jabref/gui/actions/BibtexKeyPatternAction.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.jabref.gui.actions; - -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.bibtexkeypattern.BibtexKeyPatternDialog; - -public class BibtexKeyPatternAction extends SimpleCommand { - - private final JabRefFrame frame; - - public BibtexKeyPatternAction(JabRefFrame frame) { - this.frame = frame; - } - - @Override - public void execute() { - new BibtexKeyPatternDialog(frame.getCurrentBasePanel()).showAndWait(); - } -} diff --git a/src/main/java/org/jabref/gui/actions/JabRefAction.java b/src/main/java/org/jabref/gui/actions/JabRefAction.java index a1188ad8115..de4c8983ecd 100644 --- a/src/main/java/org/jabref/gui/actions/JabRefAction.java +++ b/src/main/java/org/jabref/gui/actions/JabRefAction.java @@ -1,5 +1,7 @@ package org.jabref.gui.actions; +import javafx.beans.binding.Bindings; + import org.jabref.Globals; import org.jabref.gui.keyboard.KeyBindingRepository; @@ -10,7 +12,6 @@ */ class JabRefAction extends org.controlsfx.control.action.Action { - public JabRefAction(Action action, KeyBindingRepository keyBindingRepository) { super(action.getText()); action.getIcon() @@ -19,7 +20,6 @@ public JabRefAction(Action action, KeyBindingRepository keyBindingRepository) { .ifPresent(keyBinding -> setAccelerator(keyBindingRepository.getKeyCombination(keyBinding))); setLongText(action.getDescription()); - } public JabRefAction(Action action, Command command, KeyBindingRepository keyBindingRepository) { @@ -27,14 +27,27 @@ public JabRefAction(Action action, Command command, KeyBindingRepository keyBind setEventHandler(event -> { command.execute(); - trackExecute(); + trackExecute(getActionName(action, command)); }); disabledProperty().bind(command.executableProperty().not()); + + if (command instanceof SimpleCommand) { + SimpleCommand ourCommand = (SimpleCommand) command; + longTextProperty().bind(Bindings.concat(action.getDescription(), ourCommand.statusMessageProperty())); + } + } + + private String getActionName(Action action, Command command) { + if (command.getClass().isAnonymousClass()) { + return action.getText(); + } else { + return command.getClass().getSimpleName(); + } } - private void trackExecute() { + private void trackExecute(String actionName) { Globals.getTelemetryClient() - .ifPresent(telemetryClient -> telemetryClient.trackEvent(getText())); + .ifPresent(telemetryClient -> telemetryClient.trackEvent(actionName)); } } diff --git a/src/main/java/org/jabref/gui/actions/ManageContentSelectorAction.java b/src/main/java/org/jabref/gui/actions/ManageContentSelectorAction.java deleted file mode 100644 index 31e2b1e1149..00000000000 --- a/src/main/java/org/jabref/gui/actions/ManageContentSelectorAction.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.jabref.gui.actions; - -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.contentselector.ContentSelectorDialogView; -import org.jabref.logic.l10n.Localization; - -public class ManageContentSelectorAction extends SimpleCommand { - - private final JabRefFrame jabRefFrame; - - public ManageContentSelectorAction(JabRefFrame jabRefFrame) { - this.jabRefFrame = jabRefFrame; - } - - @Override - public void execute() { - BasePanel basePanel = jabRefFrame.getCurrentBasePanel(); - if (noActiveConnectionExists(basePanel)) { - jabRefFrame.getDialogService().showErrorDialogAndWait(Localization.lang("Active database connection do not exists!")); - return; - } - new ContentSelectorDialogView(basePanel).showAndWait(); - } - - private boolean noActiveConnectionExists(BasePanel basePanel) { - return basePanel == null || basePanel.getBibDatabaseContext() == null; - } -} diff --git a/src/main/java/org/jabref/gui/actions/OldCommandWrapper.java b/src/main/java/org/jabref/gui/actions/OldCommandWrapper.java index c187b412684..4a37747726a 100644 --- a/src/main/java/org/jabref/gui/actions/OldCommandWrapper.java +++ b/src/main/java/org/jabref/gui/actions/OldCommandWrapper.java @@ -13,6 +13,7 @@ * This wraps the old Swing commands so that they fit into the new infrastructure. * In the long term, this class should be removed. */ +@Deprecated public class OldCommandWrapper extends CommandBase { private static final Logger LOGGER = LoggerFactory.getLogger(OldCommandWrapper.class); diff --git a/src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java b/src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java index d0807faee27..23c2f6b86c9 100644 --- a/src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java +++ b/src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java @@ -13,6 +13,7 @@ * This wraps the old Swing commands so that they fit into the new infrastructure. * In the long term, this class should be removed. */ +@Deprecated public class OldCommandWrapperForActiveDatabase extends CommandBase { private static final Logger LOGGER = LoggerFactory.getLogger(OldCommandWrapperForActiveDatabase.class); diff --git a/src/main/java/org/jabref/gui/actions/SetupGeneralFieldsAction.java b/src/main/java/org/jabref/gui/actions/SetupGeneralFieldsAction.java deleted file mode 100644 index a6254ef288c..00000000000 --- a/src/main/java/org/jabref/gui/actions/SetupGeneralFieldsAction.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.jabref.gui.actions; - -import org.jabref.gui.customizefields.CustomizeGeneralFieldsDialogView; - -public class SetupGeneralFieldsAction extends SimpleCommand { - - @Override - public void execute() { - new CustomizeGeneralFieldsDialogView().show(); - - } - -} diff --git a/src/main/java/org/jabref/gui/actions/SimpleCommand.java b/src/main/java/org/jabref/gui/actions/SimpleCommand.java index 78b52e7f206..39e3b7ae1ad 100644 --- a/src/main/java/org/jabref/gui/actions/SimpleCommand.java +++ b/src/main/java/org/jabref/gui/actions/SimpleCommand.java @@ -1,6 +1,8 @@ package org.jabref.gui.actions; import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.ReadOnlyStringProperty; +import javafx.beans.property.ReadOnlyStringWrapper; import org.jabref.gui.util.BindingsHelper; @@ -10,6 +12,17 @@ * A simple command that does not track progress of the action. */ public abstract class SimpleCommand extends CommandBase { + + protected ReadOnlyStringWrapper statusMessage = new ReadOnlyStringWrapper(""); + + public String getStatusMessage() { + return statusMessage.get(); + } + + public ReadOnlyStringProperty statusMessageProperty() { + return statusMessage.getReadOnlyProperty(); + } + @Override public double getProgress() { return 0; diff --git a/src/main/java/org/jabref/gui/actions/NewSubLibraryAction.java b/src/main/java/org/jabref/gui/auximport/NewSubLibraryAction.java similarity index 56% rename from src/main/java/org/jabref/gui/actions/NewSubLibraryAction.java rename to src/main/java/org/jabref/gui/auximport/NewSubLibraryAction.java index a4f42eca838..85c766f10c3 100644 --- a/src/main/java/org/jabref/gui/actions/NewSubLibraryAction.java +++ b/src/main/java/org/jabref/gui/auximport/NewSubLibraryAction.java @@ -1,7 +1,10 @@ -package org.jabref.gui.actions; +package org.jabref.gui.auximport; import org.jabref.gui.JabRefFrame; -import org.jabref.gui.auximport.FromAuxDialog; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; /** * The action concerned with generate a new (sub-)database from latex AUX file. @@ -10,8 +13,10 @@ public class NewSubLibraryAction extends SimpleCommand { private final JabRefFrame jabRefFrame; - public NewSubLibraryAction(JabRefFrame jabRefFrame) { + public NewSubLibraryAction(JabRefFrame jabRefFrame, StateManager stateManager) { this.jabRefFrame = jabRefFrame; + + this.executable.bind(needsDatabase(stateManager)); } @Override diff --git a/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternAction.java b/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternAction.java new file mode 100644 index 00000000000..4564ea7b83b --- /dev/null +++ b/src/main/java/org/jabref/gui/bibtexkeypattern/BibtexKeyPatternAction.java @@ -0,0 +1,23 @@ +package org.jabref.gui.bibtexkeypattern; + +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 BibtexKeyPatternAction extends SimpleCommand { + + private final JabRefFrame frame; + + public BibtexKeyPatternAction(JabRefFrame frame, StateManager stateManager) { + this.frame = frame; + + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + new BibtexKeyPatternDialog(frame.getCurrentBasePanel()).showAndWait(); + } +} diff --git a/src/main/java/org/jabref/gui/actions/GenerateBibtexKeyAction.java b/src/main/java/org/jabref/gui/bibtexkeypattern/GenerateBibtexKeyAction.java similarity index 98% rename from src/main/java/org/jabref/gui/actions/GenerateBibtexKeyAction.java rename to src/main/java/org/jabref/gui/bibtexkeypattern/GenerateBibtexKeyAction.java index 744db49711c..d11de1046b7 100644 --- a/src/main/java/org/jabref/gui/actions/GenerateBibtexKeyAction.java +++ b/src/main/java/org/jabref/gui/bibtexkeypattern/GenerateBibtexKeyAction.java @@ -1,10 +1,11 @@ -package org.jabref.gui.actions; +package org.jabref.gui.bibtexkeypattern; import java.util.List; import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; +import org.jabref.gui.actions.BaseAction; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableKeyChange; import org.jabref.gui.util.BackgroundTask; diff --git a/src/main/java/org/jabref/gui/actions/GenerateBibtexKeySingleAction.java b/src/main/java/org/jabref/gui/bibtexkeypattern/GenerateBibtexKeySingleAction.java similarity index 94% rename from src/main/java/org/jabref/gui/actions/GenerateBibtexKeySingleAction.java rename to src/main/java/org/jabref/gui/bibtexkeypattern/GenerateBibtexKeySingleAction.java index 0ad4345cd4a..678256e4cee 100644 --- a/src/main/java/org/jabref/gui/actions/GenerateBibtexKeySingleAction.java +++ b/src/main/java/org/jabref/gui/bibtexkeypattern/GenerateBibtexKeySingleAction.java @@ -1,8 +1,9 @@ -package org.jabref.gui.actions; +package org.jabref.gui.bibtexkeypattern; import javax.swing.undo.UndoManager; import org.jabref.gui.DialogService; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.entryeditor.EntryEditorPreferences; import org.jabref.gui.undo.UndoableKeyChange; import org.jabref.logic.bibtexkeypattern.BibtexKeyGenerator; diff --git a/src/main/java/org/jabref/gui/actions/CleanupAction.java b/src/main/java/org/jabref/gui/cleanup/CleanupAction.java similarity index 98% rename from src/main/java/org/jabref/gui/actions/CleanupAction.java rename to src/main/java/org/jabref/gui/cleanup/CleanupAction.java index 4a0f89e8b61..ee47ea19ce4 100644 --- a/src/main/java/org/jabref/gui/actions/CleanupAction.java +++ b/src/main/java/org/jabref/gui/cleanup/CleanupAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.cleanup; import java.util.List; import java.util.Optional; @@ -6,7 +6,7 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; -import org.jabref.gui.cleanup.CleanupDialog; +import org.jabref.gui.actions.BaseAction; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.util.BackgroundTask; diff --git a/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java b/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java index 3efe55cb530..82996fa1e28 100644 --- a/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java +++ b/src/main/java/org/jabref/gui/collab/EntryDeleteChangeViewModel.java @@ -41,7 +41,7 @@ public EntryDeleteChangeViewModel(BibEntry memEntry, BibEntry tmpEntry) { @Override public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) { database.getDatabase().removeEntry(memEntry); - undoEdit.addEdit(new UndoableRemoveEntry(database.getDatabase(), memEntry, null)); + undoEdit.addEdit(new UndoableRemoveEntry(database.getDatabase(), memEntry)); } @Override diff --git a/src/main/java/org/jabref/gui/contentselector/ContentSelectorDialog.fxml b/src/main/java/org/jabref/gui/contentselector/ContentSelectorDialog.fxml index 94744038b42..091f3b3ab91 100644 --- a/src/main/java/org/jabref/gui/contentselector/ContentSelectorDialog.fxml +++ b/src/main/java/org/jabref/gui/contentselector/ContentSelectorDialog.fxml @@ -9,7 +9,6 @@ - diff --git a/src/main/java/org/jabref/gui/contentselector/ManageContentSelectorAction.java b/src/main/java/org/jabref/gui/contentselector/ManageContentSelectorAction.java new file mode 100644 index 00000000000..555afe1dc20 --- /dev/null +++ b/src/main/java/org/jabref/gui/contentselector/ManageContentSelectorAction.java @@ -0,0 +1,25 @@ +package org.jabref.gui.contentselector; + +import org.jabref.gui.BasePanel; +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 ManageContentSelectorAction extends SimpleCommand { + + private final JabRefFrame jabRefFrame; + + public ManageContentSelectorAction(JabRefFrame jabRefFrame, StateManager stateManager) { + this.jabRefFrame = jabRefFrame; + + this.executable.bind(needsDatabase(stateManager)); + } + + @Override + public void execute() { + BasePanel basePanel = jabRefFrame.getCurrentBasePanel(); + new ContentSelectorDialogView(basePanel).showAndWait(); + } +} diff --git a/src/main/java/org/jabref/gui/actions/CopyFilesAction.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java similarity index 66% rename from src/main/java/org/jabref/gui/actions/CopyFilesAction.java rename to src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java index d45a78eb803..5235f164088 100644 --- a/src/main/java/org/jabref/gui/actions/CopyFilesAction.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.copyfiles; import java.nio.file.Path; import java.nio.file.Paths; @@ -9,58 +9,55 @@ import org.jabref.Globals; import org.jabref.gui.DialogService; -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.copyfiles.CopyFilesDialogView; -import org.jabref.gui.copyfiles.CopyFilesResultItemViewModel; -import org.jabref.gui.copyfiles.CopyFilesResultListDependency; -import org.jabref.gui.copyfiles.CopyFilesTask; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.preferences.JabRefPreferences; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; +import static org.jabref.gui.actions.ActionHelper.needsEntriesSelected; + public class CopyFilesAction extends SimpleCommand { private final DialogService dialogService; - private BibDatabaseContext databaseContext; - private List entries; - private final JabRefFrame frame; + private final StateManager stateManager; + + public CopyFilesAction(StateManager stateManager, DialogService dialogService) { + this.stateManager = stateManager; + this.dialogService = dialogService; - public CopyFilesAction(JabRefFrame frame) { - this.frame = frame; - this.dialogService = frame.getDialogService(); + this.executable.bind(needsDatabase(this.stateManager).and(needsEntriesSelected(stateManager))); } - private void showDialog(List data) { + private void showDialog(List data, BibDatabaseContext database) { if (data.isEmpty()) { dialogService.showInformationDialogAndWait(Localization.lang("Copy linked files to folder..."), Localization.lang("No linked files found for export.")); return; } - CopyFilesDialogView dialog = new CopyFilesDialogView(databaseContext, new CopyFilesResultListDependency(data)); + CopyFilesDialogView dialog = new CopyFilesDialogView(database, new CopyFilesResultListDependency(data)); dialog.showAndWait(); } @Override public void execute() { + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + List entries = stateManager.getSelectedEntries(); + DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder() .withInitialDirectory(Paths.get(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY))) .build(); - entries = frame.getCurrentBasePanel().getSelectedEntries(); - Optional exportPath = dialogService.showDirectorySelectionDialog(dirDialogConfiguration); - exportPath.ifPresent(path -> { - databaseContext = frame.getCurrentBasePanel().getBibDatabaseContext(); - - Task> exportTask = new CopyFilesTask(databaseContext, entries, path); + Task> exportTask = new CopyFilesTask(database, entries, path); dialogService.showProgressDialogAndWait( Localization.lang("Copy linked files to folder..."), Localization.lang("Copy linked files to folder..."), exportTask); Globals.TASK_EXECUTOR.execute(exportTask); - exportTask.setOnSucceeded((e) -> showDialog(exportTask.getValue())); + exportTask.setOnSucceeded((e) -> showDialog(exportTask.getValue(), database)); }); - } } diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java index 0938f717905..2b78f4dd74d 100644 --- a/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java @@ -15,7 +15,6 @@ import javafx.concurrent.Task; import org.jabref.Globals; -import org.jabref.gui.actions.CopyFilesAction; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; import org.jabref.logic.util.io.FileUtil; diff --git a/src/main/java/org/jabref/gui/customentrytypes/CustomEntryTypesManager.java b/src/main/java/org/jabref/gui/customentrytypes/CustomEntryTypesManager.java deleted file mode 100644 index e3bf628cadc..00000000000 --- a/src/main/java/org/jabref/gui/customentrytypes/CustomEntryTypesManager.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.jabref.gui.customentrytypes; - -import java.util.List; -import java.util.stream.Collectors; - -import org.jabref.model.EntryTypes; -import org.jabref.model.database.BibDatabaseMode; -import org.jabref.model.entry.CustomEntryType; -import org.jabref.preferences.JabRefPreferences; - -public class CustomEntryTypesManager { - - private CustomEntryTypesManager() { - } - - /** - * Iterate through all entry types, and store those that are - * custom defined to preferences. This method is called from - * JabRefFrame when the program closes. - */ - public static void saveCustomEntryTypes(JabRefPreferences prefs) { - saveCustomEntryTypes(prefs, BibDatabaseMode.BIBTEX); - saveCustomEntryTypes(prefs, BibDatabaseMode.BIBLATEX); - - } - - private static void saveCustomEntryTypes(JabRefPreferences prefs, BibDatabaseMode mode) { - List customBiblatexTypes = EntryTypes.getAllValues(mode).stream() - .filter(type -> type instanceof CustomEntryType) - .map(entryType -> (CustomEntryType) entryType).collect(Collectors.toList()); - - prefs.storeCustomEntryTypes(customBiblatexTypes, mode); - } - -} diff --git a/src/main/java/org/jabref/gui/customizefields/SetupGeneralFieldsAction.java b/src/main/java/org/jabref/gui/customizefields/SetupGeneralFieldsAction.java new file mode 100644 index 00000000000..35fe7eb61a7 --- /dev/null +++ b/src/main/java/org/jabref/gui/customizefields/SetupGeneralFieldsAction.java @@ -0,0 +1,11 @@ +package org.jabref.gui.customizefields; + +import org.jabref.gui.actions.SimpleCommand; + +public class SetupGeneralFieldsAction extends SimpleCommand { + + @Override + public void execute() { + new CustomizeGeneralFieldsDialogView().showAndWait(); + } +} diff --git a/src/main/java/org/jabref/gui/actions/ShowDocumentViewerAction.java b/src/main/java/org/jabref/gui/documentviewer/ShowDocumentViewerAction.java similarity index 63% rename from src/main/java/org/jabref/gui/actions/ShowDocumentViewerAction.java rename to src/main/java/org/jabref/gui/documentviewer/ShowDocumentViewerAction.java index 7c15ae6d119..9c91ca7c472 100644 --- a/src/main/java/org/jabref/gui/actions/ShowDocumentViewerAction.java +++ b/src/main/java/org/jabref/gui/documentviewer/ShowDocumentViewerAction.java @@ -1,6 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.documentviewer; -import org.jabref.gui.documentviewer.DocumentViewerView; +import org.jabref.gui.actions.SimpleCommand; public class ShowDocumentViewerAction extends SimpleCommand { diff --git a/src/main/java/org/jabref/gui/DuplicateResolverDialog.java b/src/main/java/org/jabref/gui/duplicationFinder/DuplicateResolverDialog.java similarity index 97% rename from src/main/java/org/jabref/gui/DuplicateResolverDialog.java rename to src/main/java/org/jabref/gui/duplicationFinder/DuplicateResolverDialog.java index a56da356f6f..7c1a8c418c5 100644 --- a/src/main/java/org/jabref/gui/DuplicateResolverDialog.java +++ b/src/main/java/org/jabref/gui/duplicationFinder/DuplicateResolverDialog.java @@ -1,4 +1,4 @@ -package org.jabref.gui; +package org.jabref.gui.duplicationFinder; import javafx.scene.control.Button; import javafx.scene.control.ButtonBar; @@ -6,7 +6,7 @@ import javafx.scene.control.ButtonType; import javafx.scene.layout.BorderPane; -import org.jabref.gui.DuplicateResolverDialog.DuplicateResolverResult; +import org.jabref.gui.duplicationFinder.DuplicateResolverDialog.DuplicateResolverResult; import org.jabref.gui.help.HelpAction; import org.jabref.gui.mergeentries.MergeEntries; import org.jabref.gui.util.BaseDialog; diff --git a/src/main/java/org/jabref/gui/DuplicateSearch.java b/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java similarity index 89% rename from src/main/java/org/jabref/gui/DuplicateSearch.java rename to src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java index 0db4c5df1c2..bce7d2c5554 100644 --- a/src/main/java/org/jabref/gui/DuplicateSearch.java +++ b/src/main/java/org/jabref/gui/duplicationFinder/DuplicateSearch.java @@ -1,4 +1,4 @@ -package org.jabref.gui; +package org.jabref.gui.duplicationFinder; import java.util.ArrayList; import java.util.Arrays; @@ -14,9 +14,13 @@ import org.jabref.Globals; import org.jabref.JabRefExecutorService; -import org.jabref.gui.DuplicateResolverDialog.DuplicateResolverResult; -import org.jabref.gui.DuplicateResolverDialog.DuplicateResolverType; +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.SimpleCommand; +import org.jabref.gui.duplicationFinder.DuplicateResolverDialog.DuplicateResolverResult; +import org.jabref.gui.duplicationFinder.DuplicateResolverDialog.DuplicateResolverType; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertEntry; import org.jabref.gui.undo.UndoableRemoveEntry; @@ -24,9 +28,12 @@ import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntry; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + public class DuplicateSearch extends SimpleCommand { private final JabRefFrame frame; @@ -36,18 +43,22 @@ public class DuplicateSearch extends SimpleCommand { private final AtomicBoolean autoRemoveExactDuplicates = new AtomicBoolean(); private final AtomicInteger duplicateCount = new AtomicInteger(); private final DialogService dialogService; + private final StateManager stateManager; - public DuplicateSearch(JabRefFrame frame, DialogService dialogService) { + public DuplicateSearch(JabRefFrame frame, DialogService dialogService, StateManager stateManager) { this.frame = frame; this.dialogService = dialogService; + this.stateManager = stateManager; + + this.executable.bind(needsDatabase(stateManager)); } @Override public void execute() { - BasePanel panel = frame.getCurrentBasePanel(); + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); dialogService.notify(Localization.lang("Searching for duplicates...")); - List entries = panel.getDatabase().getEntries(); + List entries = database.getEntries(); duplicates.clear(); libraryAnalyzed.set(false); autoRemoveExactDuplicates.set(false); @@ -57,7 +68,7 @@ public void execute() { return; } - JabRefExecutorService.INSTANCE.executeInterruptableTask(() -> searchPossibleDuplicates(entries, panel.getBibDatabaseContext().getMode()), "DuplicateSearcher"); + JabRefExecutorService.INSTANCE.executeInterruptableTask(() -> searchPossibleDuplicates(entries, database.getMode()), "DuplicateSearcher"); BackgroundTask.wrap(this::verifyDuplicates) .onSuccess(this::handleDuplicates) .executeWith(Globals.TASK_EXECUTOR); @@ -153,7 +164,7 @@ private void handleDuplicates(DuplicateSearchResult result) { if (!result.getToRemove().isEmpty()) { for (BibEntry entry : result.getToRemove()) { panel.getDatabase().removeEntry(entry); - compoundEdit.addEdit(new UndoableRemoveEntry(panel.getDatabase(), entry, panel)); + compoundEdit.addEdit(new UndoableRemoveEntry(panel.getDatabase(), entry)); } panel.markBaseChanged(); } diff --git a/src/main/java/org/jabref/gui/actions/CopyBibTeXKeyAndLinkAction.java b/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java similarity index 97% rename from src/main/java/org/jabref/gui/actions/CopyBibTeXKeyAndLinkAction.java rename to src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java index 9c6b1e21f4a..9b528d7d66a 100644 --- a/src/main/java/org/jabref/gui/actions/CopyBibTeXKeyAndLinkAction.java +++ b/src/main/java/org/jabref/gui/edit/CopyBibTeXKeyAndLinkAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.edit; import java.util.List; import java.util.stream.Collectors; @@ -6,6 +6,7 @@ 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; diff --git a/src/main/java/org/jabref/gui/actions/CopyDoiUrlAction.java b/src/main/java/org/jabref/gui/edit/CopyDoiUrlAction.java similarity index 93% rename from src/main/java/org/jabref/gui/actions/CopyDoiUrlAction.java rename to src/main/java/org/jabref/gui/edit/CopyDoiUrlAction.java index e541cd58d5a..bbc936366ed 100644 --- a/src/main/java/org/jabref/gui/actions/CopyDoiUrlAction.java +++ b/src/main/java/org/jabref/gui/edit/CopyDoiUrlAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.edit; import java.util.Optional; @@ -6,6 +6,7 @@ import org.jabref.Globals; import org.jabref.JabRefGUI; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.identifier.DOI; diff --git a/src/main/java/org/jabref/gui/edit/ManageKeywordsAction.java b/src/main/java/org/jabref/gui/edit/ManageKeywordsAction.java index 333e206cd02..79a348f4c18 100644 --- a/src/main/java/org/jabref/gui/edit/ManageKeywordsAction.java +++ b/src/main/java/org/jabref/gui/edit/ManageKeywordsAction.java @@ -1,34 +1,31 @@ package org.jabref.gui.edit; -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.util.BindingsHelper; import org.jabref.logic.l10n.Localization; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; +import static org.jabref.gui.actions.ActionHelper.needsEntriesSelected; + /** * An Action for launching keyword managing dialog * */ public class ManageKeywordsAction extends SimpleCommand { - private final JabRefFrame frame; + private final StateManager stateManager; + + public ManageKeywordsAction(StateManager stateManager) { + this.stateManager = stateManager; - public ManageKeywordsAction(JabRefFrame frame) { - this.frame = frame; + this.executable.bind(needsDatabase(stateManager).and(needsEntriesSelected(stateManager))); + this.statusMessage.bind(BindingsHelper.ifThenElse(this.executable, "", Localization.lang("Select at least one entry to manage keywords."))); } @Override public void execute() { - BasePanel basePanel = frame.getCurrentBasePanel(); - if (basePanel == null) { - return; - } - if (basePanel.getSelectedEntries().isEmpty()) { - basePanel.output(Localization.lang("Select at least one entry to manage keywords.")); - return; - } - - ManageKeywordsDialog dialog = new ManageKeywordsDialog(basePanel.getSelectedEntries()); + ManageKeywordsDialog dialog = new ManageKeywordsDialog(stateManager.getSelectedEntries()); dialog.showAndWait(); } } diff --git a/src/main/java/org/jabref/gui/edit/MassSetFieldsAction.java b/src/main/java/org/jabref/gui/edit/MassSetFieldsAction.java index 31abaec6000..a448651d0f6 100644 --- a/src/main/java/org/jabref/gui/edit/MassSetFieldsAction.java +++ b/src/main/java/org/jabref/gui/edit/MassSetFieldsAction.java @@ -1,11 +1,14 @@ package org.jabref.gui.edit; -import java.util.List; +import javax.swing.undo.UndoManager; -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.model.entry.BibEntry; +import org.jabref.model.database.BibDatabaseContext; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; +import static org.jabref.gui.actions.ActionHelper.needsEntriesSelected; /** * An Action for launching mass field. @@ -17,21 +20,22 @@ */ public class MassSetFieldsAction extends SimpleCommand { - private final JabRefFrame frame; + private final StateManager stateManager; + private DialogService dialogService; + private UndoManager undoManager; + + public MassSetFieldsAction(StateManager stateManager, DialogService dialogService, UndoManager undoManager) { + this.stateManager = stateManager; + this.dialogService = dialogService; + this.undoManager = undoManager; - public MassSetFieldsAction(JabRefFrame frame) { - this.frame = frame; + this.executable.bind(needsDatabase(stateManager).and(needsEntriesSelected(stateManager))); } @Override public void execute() { - BasePanel bp = frame.getCurrentBasePanel(); - if (bp == null) { - return; - } - - List entries = bp.getSelectedEntries(); - MassSetFieldsDialog dialog = new MassSetFieldsDialog(entries, bp); + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + MassSetFieldsDialog dialog = new MassSetFieldsDialog(stateManager.getSelectedEntries(), database, dialogService, undoManager); dialog.showAndWait(); } diff --git a/src/main/java/org/jabref/gui/edit/MassSetFieldsDialog.java b/src/main/java/org/jabref/gui/edit/MassSetFieldsDialog.java index bef87619d19..d63c9b0342b 100644 --- a/src/main/java/org/jabref/gui/edit/MassSetFieldsDialog.java +++ b/src/main/java/org/jabref/gui/edit/MassSetFieldsDialog.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Optional; +import javax.swing.undo.UndoManager; import javax.swing.undo.UndoableEdit; import javafx.application.Platform; @@ -18,13 +19,13 @@ import javafx.scene.control.Tooltip; import javafx.scene.layout.GridPane; -import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.IconValidationDecorator; import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.strings.StringUtil; @@ -37,7 +38,7 @@ public class MassSetFieldsDialog extends BaseDialog { private final List entries; - private final BasePanel bp; + private final BibDatabaseContext database; private final DialogService dialogService; private RadioButton clearRadioButton; @@ -49,11 +50,13 @@ public class MassSetFieldsDialog extends BaseDialog { private TextField appendTextField; private TextField renameTextField; private CheckBox overwriteCheckBox; + private UndoManager undoManager; - MassSetFieldsDialog(List entries, BasePanel bp) { + MassSetFieldsDialog(List entries, BibDatabaseContext database, DialogService dialogService, UndoManager undoManager) { this.entries = entries; - this.bp = bp; - this.dialogService = bp.frame().getDialogService(); + this.database = database; + this.dialogService = dialogService; + this.undoManager = undoManager; init(); this.setTitle("Set/clear/append/rename fields"); @@ -76,7 +79,6 @@ public class MassSetFieldsDialog extends BaseDialog { * @return A CompoundEdit for the entire operation. */ private static UndoableEdit massAppendField(Collection entries, String field, String textToAppend) { - String newValue = ""; if (textToAppend != null) { @@ -140,7 +142,6 @@ private static UndoableEdit massRenameField(Collection entries, String */ private static UndoableEdit massSetField(Collection entries, String field, String textToSet, boolean overwriteValues) { - NamedCompound compoundEdit = new NamedCompound(Localization.lang("Set field")); for (BibEntry entry : entries) { Optional oldValue = entry.getField(field); @@ -164,7 +165,7 @@ private static UndoableEdit massSetField(Collection entries, String fi private void init() { fieldComboBox = new ComboBox<>(); fieldComboBox.setEditable(true); - fieldComboBox.getItems().addAll(bp.getDatabase().getAllVisibleFields()); + fieldComboBox.getItems().addAll(database.getDatabase().getAllVisibleFields()); ToggleGroup toggleGroup = new ToggleGroup(); clearRadioButton = new RadioButton(Localization.lang("Clear fields")); @@ -236,6 +237,6 @@ private void performEdits() { overwriteCheckBox.isSelected())); } compoundEdit.end(); - bp.getUndoManager().addEdit(compoundEdit); + undoManager.addEdit(compoundEdit); } } diff --git a/src/main/java/org/jabref/gui/actions/OpenBrowserAction.java b/src/main/java/org/jabref/gui/edit/OpenBrowserAction.java similarity index 82% rename from src/main/java/org/jabref/gui/actions/OpenBrowserAction.java rename to src/main/java/org/jabref/gui/edit/OpenBrowserAction.java index 9cd0b92524e..559063b631f 100644 --- a/src/main/java/org/jabref/gui/actions/OpenBrowserAction.java +++ b/src/main/java/org/jabref/gui/edit/OpenBrowserAction.java @@ -1,5 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.edit; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.desktop.JabRefDesktop; public class OpenBrowserAction extends SimpleCommand { @@ -13,7 +14,6 @@ public OpenBrowserAction(String urlToOpen) { @Override public void execute() { JabRefDesktop.openBrowserShowPopup(urlToOpen); - } } diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 4ebdb2b1b72..a85e7909357 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -28,8 +28,8 @@ import org.jabref.gui.DialogService; import org.jabref.gui.GUIGlobals; import org.jabref.gui.actions.ActionFactory; -import org.jabref.gui.actions.GenerateBibtexKeySingleAction; import org.jabref.gui.actions.StandardActions; +import org.jabref.gui.bibtexkeypattern.GenerateBibtexKeySingleAction; import org.jabref.gui.entryeditor.fileannotationtab.FileAnnotationTab; import org.jabref.gui.externalfiles.ExternalFilesEntryLinker; import org.jabref.gui.externalfiletype.ExternalFileTypes; diff --git a/src/main/java/org/jabref/gui/actions/ManageCustomExportsAction.java b/src/main/java/org/jabref/gui/exporter/ManageCustomExportsAction.java similarity index 64% rename from src/main/java/org/jabref/gui/actions/ManageCustomExportsAction.java rename to src/main/java/org/jabref/gui/exporter/ManageCustomExportsAction.java index 60298e05555..07dcde775cc 100644 --- a/src/main/java/org/jabref/gui/actions/ManageCustomExportsAction.java +++ b/src/main/java/org/jabref/gui/exporter/ManageCustomExportsAction.java @@ -1,6 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.exporter; -import org.jabref.gui.exporter.ExportCustomizationDialogView; +import org.jabref.gui.actions.SimpleCommand; public class ManageCustomExportsAction extends SimpleCommand { diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index db4a591b1ec..edd299537a3 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -83,7 +83,7 @@ private boolean saveDatabase(Path file, boolean selectedOnly, Charset encoding, } catch (UnsupportedCharsetException ex) { throw new SaveException(Localization.lang("Character encoding '%0' is not supported.", encoding.displayName()), ex); } catch (IOException ex) { - throw new SaveException(ex); + throw new SaveException("Problems saving:", ex); } return true; diff --git a/src/main/java/org/jabref/gui/actions/WriteXMPAction.java b/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java similarity index 99% rename from src/main/java/org/jabref/gui/actions/WriteXMPAction.java rename to src/main/java/org/jabref/gui/exporter/WriteXMPAction.java index 67a1217a113..043ceac725d 100644 --- a/src/main/java/org/jabref/gui/actions/WriteXMPAction.java +++ b/src/main/java/org/jabref/gui/exporter/WriteXMPAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.exporter; import java.nio.file.Files; import java.nio.file.Path; @@ -24,6 +24,7 @@ import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.FXDialog; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.BackgroundTask; import org.jabref.logic.l10n.Localization; import org.jabref.logic.xmp.XmpUtilWriter; @@ -101,7 +102,6 @@ private void writeXMP() { } for (BibEntry entry : entries) { - // Make a list of all PDFs linked from this entry: List files = entry.getFiles().stream() .filter(file -> file.getFileType().equalsIgnoreCase("pdf")) diff --git a/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java b/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java index 967243e840b..74a9d3aea77 100644 --- a/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java +++ b/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java @@ -2,17 +2,25 @@ import java.util.List; +import javax.swing.undo.UndoManager; + import javafx.concurrent.Task; import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.undo.NamedCompound; +import org.jabref.gui.util.BindingsHelper; import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.preferences.JabRefPreferences; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; +import static org.jabref.gui.actions.ActionHelper.needsEntriesSelected; + /** * This Action may only be used in a menu or button. * Never in the entry editor. FileListEditor and EntryEditor have other ways to update the file links @@ -20,25 +28,28 @@ public class AutoLinkFilesAction extends SimpleCommand { private final DialogService dialogService; - private final JabRefFrame frame; private final JabRefPreferences preferences; + private final StateManager stateManager; + private UndoManager undoManager; - public AutoLinkFilesAction(JabRefFrame frame, JabRefPreferences preferences) { - this.frame = frame; + public AutoLinkFilesAction(JabRefFrame frame, JabRefPreferences preferences, StateManager stateManager, UndoManager undoManager) { this.dialogService = frame.getDialogService(); this.preferences = preferences; + this.stateManager = stateManager; + this.undoManager = undoManager; + + this.executable.bind(needsDatabase(this.stateManager).and(needsEntriesSelected(stateManager))); + this.statusMessage.bind(BindingsHelper.ifThenElse(executable, "", Localization.lang("This operation requires one or more entries to be selected."))); + } @Override public void execute() { - List entries = frame.getCurrentBasePanel().getSelectedEntries(); - if (entries.isEmpty()) { - dialogService.notify(Localization.lang("This operation requires one or more entries to be selected.")); - return; - } + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + List entries = stateManager.getSelectedEntries(); final NamedCompound nc = new NamedCompound(Localization.lang("Automatically set file links")); - AutoSetFileLinksUtil util = new AutoSetFileLinksUtil(frame.getCurrentBasePanel().getBibDatabaseContext(), preferences.getFilePreferences(), preferences.getAutoLinkPreferences(), ExternalFileTypes.getInstance()); + AutoSetFileLinksUtil util = new AutoSetFileLinksUtil(database, preferences.getFilePreferences(), preferences.getAutoLinkPreferences(), ExternalFileTypes.getInstance()); Task> linkFilesTask = new Task>() { @Override protected List call() { @@ -50,7 +61,7 @@ protected void succeeded() { if (!getValue().isEmpty()) { if (nc.hasEdits()) { nc.end(); - frame.getCurrentBasePanel().getUndoManager().addEdit(nc); + undoManager.addEdit(nc); } dialogService.notify(Localization.lang("Finished automatically setting external links.")); } else { diff --git a/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesAction.java b/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesAction.java index 5684869d9ff..0212978d442 100644 --- a/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesAction.java @@ -1,19 +1,28 @@ package org.jabref.gui.externalfiles; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; +import org.jabref.model.database.BibDatabaseContext; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; public class FindUnlinkedFilesAction extends SimpleCommand { private final JabRefFrame jabRefFrame; + private final StateManager stateManager; - public FindUnlinkedFilesAction(JabRefFrame jabRefFrame) { + public FindUnlinkedFilesAction(JabRefFrame jabRefFrame, StateManager stateManager) { this.jabRefFrame = jabRefFrame; + this.stateManager = stateManager; + + this.executable.bind(needsDatabase(this.stateManager)); } @Override public void execute() { - FindUnlinkedFilesDialog dlg = new FindUnlinkedFilesDialog(jabRefFrame); + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + FindUnlinkedFilesDialog dlg = new FindUnlinkedFilesDialog(database, jabRefFrame.getDialogService(), jabRefFrame.getUndoManager()); dlg.showAndWait(); } diff --git a/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesDialog.java b/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesDialog.java index a4892565632..ff250cb7a6b 100644 --- a/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesDialog.java +++ b/src/main/java/org/jabref/gui/externalfiles/FindUnlinkedFilesDialog.java @@ -38,10 +38,10 @@ import org.jabref.Globals; import org.jabref.gui.DialogService; -import org.jabref.gui.JabRefFrame; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.importer.UnlinkedFilesCrawler; +import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.DirectoryDialogConfiguration; @@ -63,7 +63,6 @@ public class FindUnlinkedFilesDialog extends BaseDialog { private static final Logger LOGGER = LoggerFactory.getLogger(FindUnlinkedFilesDialog.class); - private final JabRefFrame frame; private final BibDatabaseContext databaseContext; private final ImportHandler importHandler; private final JabRefPreferences preferences = Globals.prefs; @@ -77,13 +76,12 @@ public class FindUnlinkedFilesDialog extends BaseDialog { private VBox panelSearchProgress; private BackgroundTask findUnlinkedFilesTask; - public FindUnlinkedFilesDialog(JabRefFrame frame) { + public FindUnlinkedFilesDialog(BibDatabaseContext database, DialogService dialogService, CountingUndoManager undoManager) { super(); this.setTitle(Localization.lang("Find unlinked files")); - this.frame = frame; - dialogService = frame.getDialogService(); + this.dialogService = dialogService; - databaseContext = frame.getCurrentBasePanel().getBibDatabaseContext(); + databaseContext = database; importHandler = new ImportHandler( dialogService, databaseContext, @@ -92,7 +90,7 @@ public FindUnlinkedFilesDialog(JabRefFrame frame) { Globals.prefs.getImportFormatPreferences(), Globals.prefs.getUpdateFieldPreferences(), Globals.getFileUpdateMonitor(), - frame.getUndoManager(), + undoManager, Globals.stateManager); initialize(); diff --git a/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypeEntryDialog.fxml b/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypeEntryDialog.fxml index 11da6fc3712..49501a19e19 100644 --- a/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypeEntryDialog.fxml +++ b/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypeEntryDialog.fxml @@ -10,7 +10,6 @@ - diff --git a/src/main/java/org/jabref/gui/actions/EditExternalFileTypesAction.java b/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypesAction.java similarity index 69% rename from src/main/java/org/jabref/gui/actions/EditExternalFileTypesAction.java rename to src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypesAction.java index c5ea26bb8cb..d7450556f4f 100644 --- a/src/main/java/org/jabref/gui/actions/EditExternalFileTypesAction.java +++ b/src/main/java/org/jabref/gui/externalfiletype/EditExternalFileTypesAction.java @@ -1,6 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.externalfiletype; -import org.jabref.gui.externalfiletype.CustomizeExternalFileTypesDialog; +import org.jabref.gui.actions.SimpleCommand; public class EditExternalFileTypesAction extends SimpleCommand { diff --git a/src/main/java/org/jabref/gui/fieldeditors/BibtexKeyEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/BibtexKeyEditorViewModel.java index bb190108497..fa3a4a8f622 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/BibtexKeyEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/BibtexKeyEditorViewModel.java @@ -3,8 +3,8 @@ import javax.swing.undo.UndoManager; import org.jabref.gui.DialogService; -import org.jabref.gui.actions.GenerateBibtexKeySingleAction; import org.jabref.gui.autocompleter.AutoCompleteSuggestionProvider; +import org.jabref.gui.bibtexkeypattern.GenerateBibtexKeySingleAction; import org.jabref.gui.entryeditor.EntryEditorPreferences; import org.jabref.logic.integrity.FieldCheckers; import org.jabref.model.database.BibDatabaseContext; diff --git a/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java b/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java index baaabbe8f93..abdb9700909 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java +++ b/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java @@ -14,8 +14,8 @@ import org.jabref.Globals; import org.jabref.gui.actions.ActionFactory; -import org.jabref.gui.actions.CopyDoiUrlAction; import org.jabref.gui.actions.StandardActions; +import org.jabref.gui.edit.CopyDoiUrlAction; import org.jabref.logic.formatter.bibtexfields.CleanupURLFormatter; import org.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter; import org.jabref.logic.l10n.Localization; diff --git a/src/main/java/org/jabref/gui/groups/GroupDialog.java b/src/main/java/org/jabref/gui/groups/GroupDialog.java index 9fc080c8749..bfe8032f3b7 100644 --- a/src/main/java/org/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/org/jabref/gui/groups/GroupDialog.java @@ -424,8 +424,6 @@ groupName, getContext(), texGroupFilePath.setText(group.getFilePath().toString()); } } - - setResizable(false); getDialogPane().getScene().getWindow().sizeToScene(); } diff --git a/src/main/java/org/jabref/gui/actions/ErrorConsoleAction.java b/src/main/java/org/jabref/gui/help/ErrorConsoleAction.java similarity index 86% rename from src/main/java/org/jabref/gui/actions/ErrorConsoleAction.java rename to src/main/java/org/jabref/gui/help/ErrorConsoleAction.java index 2ac2dbf6623..3919b35a17b 100644 --- a/src/main/java/org/jabref/gui/actions/ErrorConsoleAction.java +++ b/src/main/java/org/jabref/gui/help/ErrorConsoleAction.java @@ -1,5 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.help; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.errorconsole.ErrorConsoleView; /** diff --git a/src/main/java/org/jabref/gui/actions/SearchForUpdateAction.java b/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java similarity index 92% rename from src/main/java/org/jabref/gui/actions/SearchForUpdateAction.java rename to src/main/java/org/jabref/gui/help/SearchForUpdateAction.java index be3415c2120..c1d951aaa01 100644 --- a/src/main/java/org/jabref/gui/actions/SearchForUpdateAction.java +++ b/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java @@ -1,7 +1,7 @@ -package org.jabref.gui.actions; +package org.jabref.gui.help; import org.jabref.gui.DialogService; -import org.jabref.gui.help.VersionWorker; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.util.BuildInfo; import org.jabref.preferences.VersionPreferences; diff --git a/src/main/java/org/jabref/gui/importer/AppendDatabaseDialog.java b/src/main/java/org/jabref/gui/importer/AppendDatabaseDialog.java index 10a86d95d15..221a93b0d66 100644 --- a/src/main/java/org/jabref/gui/importer/AppendDatabaseDialog.java +++ b/src/main/java/org/jabref/gui/importer/AppendDatabaseDialog.java @@ -38,12 +38,11 @@ private void init() { getDialogPane().setContent(container); container.setHgap(10); container.setVgap(10); - container.setPadding(new Insets(15, 5, 0, 0)); container.add(entries, 0, 0); container.add(strings, 0, 1); container.add(groups, 0, 2); container.add(selector, 0, 3); - container.setPadding(new Insets(15, 5, 0, 0)); + container.setPadding(new Insets(15, 5, 0, 5)); container.setGridLinesVisible(false); } diff --git a/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialog.fxml b/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialog.fxml new file mode 100644 index 00000000000..6efedfbdd11 --- /dev/null +++ b/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialog.fxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialog.java b/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialog.java new file mode 100644 index 00000000000..1d8ad964228 --- /dev/null +++ b/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialog.java @@ -0,0 +1,61 @@ +package org.jabref.gui.importer; + +import java.util.List; + +import javax.inject.Inject; + +import javafx.beans.binding.Bindings; +import javafx.fxml.FXML; +import javafx.scene.control.ButtonType; +import javafx.scene.layout.VBox; + +import org.jabref.gui.util.BaseDialog; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseMode; +import org.jabref.model.entry.EntryType; +import org.jabref.preferences.PreferencesService; + +import com.airhacks.afterburner.views.ViewLoader; +import org.controlsfx.control.CheckListView; + +public class ImportCustomEntryTypesDialog extends BaseDialog { + + @FXML private CheckListView unknownEntryTypesCheckList; + @FXML private VBox boxDifferentCustomization; + @FXML private CheckListView differentCustomizationCheckList; + @Inject private PreferencesService preferencesService; + + private ImportCustomEntryTypesDialogViewModel viewModel; + + private final BibDatabaseMode mode; + private final List customEntryTypes; + + public ImportCustomEntryTypesDialog(BibDatabaseMode mode, List customEntryTypes) { + this.mode = mode; + this.customEntryTypes = customEntryTypes; + + ViewLoader.view(this) + .load() + .setAsDialogPane(this); + + setResultConverter(btn -> { + if (btn == ButtonType.OK) { + viewModel.importCustomEntryTypes(unknownEntryTypesCheckList.getCheckModel().getCheckedItems(), differentCustomizationCheckList.getCheckModel().getCheckedItems()); + } + return null; + }); + + setTitle(Localization.lang("Custom entry types")); + + } + + @FXML + public void initialize() { + viewModel = new ImportCustomEntryTypesDialogViewModel(mode, customEntryTypes, preferencesService); + + boxDifferentCustomization.managedProperty().bind(Bindings.isNotEmpty(viewModel.differentCustomizations())); + unknownEntryTypesCheckList.setItems(viewModel.newTypes()); + differentCustomizationCheckList.setItems(viewModel.differentCustomizations()); + } + +} diff --git a/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialogViewModel.java b/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialogViewModel.java new file mode 100644 index 00000000000..ebac412c8d7 --- /dev/null +++ b/src/main/java/org/jabref/gui/importer/ImportCustomEntryTypesDialogViewModel.java @@ -0,0 +1,58 @@ +package org.jabref.gui.importer; + +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import org.jabref.model.EntryTypes; +import org.jabref.model.database.BibDatabaseMode; +import org.jabref.model.entry.CustomEntryType; +import org.jabref.model.entry.EntryType; +import org.jabref.preferences.PreferencesService; + +public class ImportCustomEntryTypesDialogViewModel { + + private final BibDatabaseMode mode; + private final PreferencesService preferencesService; + + private final ObservableList newTypes = FXCollections.observableArrayList(); + private final ObservableList differentCustomizationTypes = FXCollections.observableArrayList(); + + public ImportCustomEntryTypesDialogViewModel(BibDatabaseMode mode, List customEntryTypes, PreferencesService preferencesService) { + this.mode = mode; + this.preferencesService = preferencesService; + + for (EntryType customType : customEntryTypes) { + if (!EntryTypes.getType(customType.getName(), mode).isPresent()) { + newTypes.add(customType); + } else { + EntryType currentlyStoredType = EntryTypes.getType(customType.getName(), mode).get(); + if (!EntryTypes.isEqualNameAndFieldBased(customType, currentlyStoredType)) { + differentCustomizationTypes.add(customType); + } + } + } + + } + + public ObservableList newTypes() { + return this.newTypes; + } + + public ObservableList differentCustomizations() { + return this.differentCustomizationTypes; + } + + public void importCustomEntryTypes(List checkedUnknownEntryTypes, List checkedDifferentEntryTypes) { + if (!checkedUnknownEntryTypes.isEmpty()) { + checkedUnknownEntryTypes.forEach(type -> EntryTypes.addOrModifyCustomEntryType((CustomEntryType) type, mode)); + preferencesService.saveCustomEntryTypes(); + } + if (!checkedDifferentEntryTypes.isEmpty()) { + checkedUnknownEntryTypes.forEach(type -> EntryTypes.addOrModifyCustomEntryType((CustomEntryType) type, mode)); + preferencesService.saveCustomEntryTypes(); + } + + } +} diff --git a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java index a28a437400b..6f0b2fad4ad 100644 --- a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java +++ b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java @@ -12,8 +12,8 @@ import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; -import org.jabref.gui.DuplicateResolverDialog; import org.jabref.gui.StateManager; +import org.jabref.gui.duplicationFinder.DuplicateResolverDialog; import org.jabref.gui.externalfiles.ImportHandler; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.util.BackgroundTask; diff --git a/src/main/java/org/jabref/gui/actions/ManageCustomImportsAction.java b/src/main/java/org/jabref/gui/importer/ManageCustomImportsAction.java similarity index 70% rename from src/main/java/org/jabref/gui/actions/ManageCustomImportsAction.java rename to src/main/java/org/jabref/gui/importer/ManageCustomImportsAction.java index e36ea7ac07c..7c9d36002a0 100644 --- a/src/main/java/org/jabref/gui/actions/ManageCustomImportsAction.java +++ b/src/main/java/org/jabref/gui/importer/ManageCustomImportsAction.java @@ -1,6 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.importer; -import org.jabref.gui.importer.ImportCustomizationDialog; +import org.jabref.gui.actions.SimpleCommand; public class ManageCustomImportsAction extends SimpleCommand { diff --git a/src/main/java/org/jabref/gui/actions/NewDatabaseAction.java b/src/main/java/org/jabref/gui/importer/NewDatabaseAction.java similarity index 92% rename from src/main/java/org/jabref/gui/actions/NewDatabaseAction.java rename to src/main/java/org/jabref/gui/importer/NewDatabaseAction.java index e00604e3a1b..5372a81ead2 100644 --- a/src/main/java/org/jabref/gui/actions/NewDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/NewDatabaseAction.java @@ -1,6 +1,7 @@ -package org.jabref.gui.actions; +package org.jabref.gui.importer; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.logic.l10n.Localization; import org.jabref.model.Defaults; import org.jabref.model.database.BibDatabaseContext; diff --git a/src/main/java/org/jabref/gui/actions/NewEntryAction.java b/src/main/java/org/jabref/gui/importer/NewEntryAction.java similarity index 80% rename from src/main/java/org/jabref/gui/actions/NewEntryAction.java rename to src/main/java/org/jabref/gui/importer/NewEntryAction.java index a5b483a4d67..7aaa203d991 100644 --- a/src/main/java/org/jabref/gui/actions/NewEntryAction.java +++ b/src/main/java/org/jabref/gui/importer/NewEntryAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.importer; import java.util.HashMap; import java.util.Map; @@ -8,6 +8,8 @@ import org.jabref.gui.DialogService; import org.jabref.gui.EntryTypeView; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.EntryType; import org.jabref.preferences.JabRefPreferences; @@ -15,6 +17,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + public class NewEntryAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(NewEntryAction.class); @@ -23,22 +27,23 @@ public class NewEntryAction extends SimpleCommand { /** * The type of the entry to create. */ - private final Optional type; + private Optional type; private final DialogService dialogService; private final JabRefPreferences preferences; - public NewEntryAction(JabRefFrame jabRefFrame, DialogService dialogService, JabRefPreferences preferences) { + public NewEntryAction(JabRefFrame jabRefFrame, DialogService dialogService, JabRefPreferences preferences, StateManager stateManager) { this.jabRefFrame = jabRefFrame; - this.type = Optional.empty(); this.dialogService = dialogService; this.preferences = preferences; + + this.type = Optional.empty(); + + this.executable.bind(needsDatabase(stateManager)); } - public NewEntryAction(JabRefFrame jabRefFrame, EntryType type, DialogService dialogService, JabRefPreferences preferences) { - this.jabRefFrame = jabRefFrame; + public NewEntryAction(JabRefFrame jabRefFrame, EntryType type, DialogService dialogService, JabRefPreferences preferences, StateManager stateManager) { + this(jabRefFrame, dialogService, preferences, stateManager); this.type = Optional.of(type); - this.dialogService = dialogService; - this.preferences = preferences; } @Override diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java index 674238292a9..a62dfe74838 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForNewEntryTypesAction.java @@ -1,27 +1,14 @@ package org.jabref.gui.importer.actions; -import java.awt.Font; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; -import javax.swing.BoxLayout; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; - import org.jabref.Globals; import org.jabref.gui.BasePanel; -import org.jabref.gui.customentrytypes.CustomEntryTypesManager; +import org.jabref.gui.importer.ImportCustomEntryTypesDialog; import org.jabref.logic.importer.ParserResult; -import org.jabref.logic.l10n.Localization; import org.jabref.model.EntryTypes; import org.jabref.model.database.BibDatabaseMode; -import org.jabref.model.entry.CustomEntryType; import org.jabref.model.entry.EntryType; /** @@ -39,94 +26,18 @@ public boolean isActionNecessary(ParserResult parserResult) { public void performAction(BasePanel panel, ParserResult parserResult) { BibDatabaseMode mode = getBibDatabaseModeFromParserResult(parserResult); - List typesToStore = determineEntryTypesToSave(panel, getListOfUnknownAndUnequalCustomizations(parserResult), mode); + ImportCustomEntryTypesDialog importCustomEntryTypesDialog = new ImportCustomEntryTypesDialog(mode, getListOfUnknownAndUnequalCustomizations(parserResult)); + importCustomEntryTypesDialog.showAndWait(); - if (!typesToStore.isEmpty()) { - typesToStore.forEach(type -> EntryTypes.addOrModifyCustomEntryType((CustomEntryType) type, mode)); - CustomEntryTypesManager.saveCustomEntryTypes(Globals.prefs); - } } private List getListOfUnknownAndUnequalCustomizations(ParserResult parserResult) { BibDatabaseMode mode = getBibDatabaseModeFromParserResult(parserResult); return parserResult.getEntryTypes().values().stream() - .filter(type -> - (!EntryTypes.getType(type.getName(), mode).isPresent()) - || !EntryTypes.isEqualNameAndFieldBased(type, EntryTypes.getType(type.getName(), mode).get())) - .collect(Collectors.toList()); - } - - private List determineEntryTypesToSave(BasePanel panel, List allCustomizedEntryTypes, BibDatabaseMode databaseMode) { - List newTypes = new ArrayList<>(); - List differentCustomizations = new ArrayList<>(); - - for (EntryType customType : allCustomizedEntryTypes) { - if (!EntryTypes.getType(customType.getName(), databaseMode).isPresent()) { - newTypes.add(customType); - } else { - EntryType currentlyStoredType = EntryTypes.getType(customType.getName(), databaseMode).get(); - if (!EntryTypes.isEqualNameAndFieldBased(customType, currentlyStoredType)) { - differentCustomizations.add(customType); - } - } - } - - Map typeCheckBoxMap = new HashMap<>(); - - JPanel checkboxPanel = createCheckBoxPanel(newTypes, differentCustomizations, typeCheckBoxMap); - - int answer = JOptionPane.showConfirmDialog(null, - checkboxPanel, - Localization.lang("Custom entry types"), - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE); - - if (answer == JOptionPane.YES_OPTION) { - return typeCheckBoxMap.entrySet().stream().filter(entry -> entry.getValue().isSelected()) - .map(Map.Entry::getKey).collect(Collectors.toList()); - } else { - return Collections.emptyList(); - } - - } - - private JPanel createCheckBoxPanel(List newTypes, List differentCustomizations, - Map typeCheckBoxMap) { - JPanel checkboxPanel = new JPanel(); - checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.PAGE_AXIS)); - - JLabel customFoundLabel = new JLabel(Localization.lang("Custom entry types found in file") + "."); - Font boldStandardFont = new Font(customFoundLabel.getFont().getFontName(), Font.BOLD, customFoundLabel.getFont().getSize()); - customFoundLabel.setFont(boldStandardFont); - checkboxPanel.add(customFoundLabel); - - JLabel selectLabel = new JLabel(Localization.lang("Select all customized types to be stored in local preferences") + ":"); - selectLabel.setFont(boldStandardFont); - checkboxPanel.add(selectLabel); - - checkboxPanel.add(new JLabel(" ")); - - // add all unknown types: - if (!newTypes.isEmpty()) { - checkboxPanel.add(new JLabel(Localization.lang("Currently unknown") + ":")); - for (EntryType type : newTypes) { - JCheckBox box = new JCheckBox(type.getName(), true); - checkboxPanel.add(box); - typeCheckBoxMap.put(type, box); - } - } - - // add all different customizations - if (!differentCustomizations.isEmpty()) { - checkboxPanel.add(new JLabel(Localization.lang("Different customization, current settings will be overwritten") + ":")); - for (EntryType type : differentCustomizations) { - JCheckBox box = new JCheckBox(type.getName(), true); - checkboxPanel.add(box); - typeCheckBoxMap.put(type, box); - } - } - return checkboxPanel; + .filter(type -> (!EntryTypes.getType(type.getName(), mode).isPresent()) + || !EntryTypes.isEqualNameAndFieldBased(type, EntryTypes.getType(type.getName(), mode).get())) + .collect(Collectors.toList()); } private BibDatabaseMode getBibDatabaseModeFromParserResult(ParserResult parserResult) { 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 b8be7090041..d57f8bdc490 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -13,10 +13,7 @@ import java.util.Optional; import java.util.stream.Collectors; -import javax.swing.SwingUtilities; - import org.jabref.Globals; -import org.jabref.JabRefExecutorService; import org.jabref.gui.BasePanel; import org.jabref.gui.BasePanelPreferences; import org.jabref.gui.DialogService; @@ -26,7 +23,7 @@ import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.importer.ParserResultWarningDialog; import org.jabref.gui.shared.SharedDatabaseUIManager; -import org.jabref.gui.util.DefaultTaskExecutor; +import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.autosaveandbackup.BackupManager; import org.jabref.logic.importer.OpenDatabase; @@ -49,17 +46,18 @@ public class OpenDatabaseAction extends SimpleCommand { // List of actions that may need to be called after opening the file. Such as // upgrade actions etc. that may depend on the JabRef version that wrote the file: private static final List POST_OPEN_ACTIONS = Arrays.asList( - // Migrations: - // Warning for migrating the Review into the Comment field - new MergeReviewIntoCommentAction(), - // Check for new custom entry types loaded from the BIB file: - new CheckForNewEntryTypesAction() - ); + // Migrations: + // Warning for migrating the Review into the Comment field + new MergeReviewIntoCommentAction(), + // Check for new custom entry types loaded from the BIB file: + new CheckForNewEntryTypesAction()); private final JabRefFrame frame; + private final DialogService dialogService; public OpenDatabaseAction(JabRefFrame frame) { this.frame = frame; + this.dialogService = frame.getDialogService(); } /** @@ -81,14 +79,13 @@ public static void performPostOpenActions(BasePanel panel, ParserResult result) public void execute() { List filesToOpen = new ArrayList<>(); - DialogService ds = frame.getDialogService(); FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() - .addExtensionFilter(StandardFileType.BIBTEX_DB) - .withDefaultExtension(StandardFileType.BIBTEX_DB) - .withInitialDirectory(getInitialDirectory()) - .build(); + .addExtensionFilter(StandardFileType.BIBTEX_DB) + .withDefaultExtension(StandardFileType.BIBTEX_DB) + .withInitialDirectory(getInitialDirectory()) + .build(); - List chosenFiles = ds.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration); + List chosenFiles = dialogService.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration); filesToOpen.addAll(chosenFiles); openFiles(filesToOpen, true); @@ -144,7 +141,7 @@ public void openFiles(List filesToOpen, boolean raisePanel) { for (int i = 0; i < frame.getTabbedPane().getTabs().size(); i++) { BasePanel basePanel = frame.getBasePanelAt(i); if ((basePanel.getBibDatabaseContext().getDatabasePath().isPresent()) - && basePanel.getBibDatabaseContext().getDatabasePath().get().equals(file)) { + && basePanel.getBibDatabaseContext().getDatabasePath().get().equals(file)) { iterator.remove(); removed++; // See if we removed the final one. If so, we must perhaps @@ -162,11 +159,11 @@ public void openFiles(List filesToOpen, boolean raisePanel) { // locking until the file is loaded. if (!filesToOpen.isEmpty()) { final List theFiles = Collections.unmodifiableList(filesToOpen); - JabRefExecutorService.INSTANCE.execute(() -> { - for (Path theFile : theFiles) { - openTheFile(theFile, raisePanel); - } - }); + + for (Path theFile : theFiles) { + openTheFile(theFile, raisePanel); + } + for (Path theFile : theFiles) { frame.getFileHistory().newFile(theFile); } @@ -174,59 +171,63 @@ public void openFiles(List filesToOpen, boolean raisePanel) { // If no files are remaining to open, this could mean that a file was // already open. If so, we may have to raise the correct tab: else if (toRaise != null) { - frame.getDialogService().notify(Localization.lang("File '%0' is already open.", - toRaise.getBibDatabaseContext().getDatabaseFile().get().getPath())); + dialogService.notify(Localization.lang("File '%0' is already open.", + toRaise.getBibDatabaseContext().getDatabasePath().get().getFileName().toString())); frame.showBasePanel(toRaise); } - frame.getDialogService().notify(Localization.lang("Files opened") + ": " + (filesToOpen.size())); + dialogService.notify(Localization.lang("Files opened") + ": " + (filesToOpen.size())); } /** * @param file the file, may be null or not existing + * @return */ private void openTheFile(Path file, boolean raisePanel) { Objects.requireNonNull(file); if (Files.exists(file)) { - Path fileToLoad = file.toAbsolutePath(); - frame.getDialogService().notify(Localization.lang("Opening") + ": '" + file + "'"); + BackgroundTask.wrap(() -> loadDatabase(file)) + .onSuccess(result -> { + BasePanel panel = addNewDatabase(result, file, raisePanel); + OpenDatabaseAction.performPostOpenActions(panel, result); + }) + .onFailure(ex -> dialogService.showErrorDialogAndWait(Localization.lang("Connection error"), + ex.getMessage() + "\n\n" + Localization.lang("A local copy will be opened."))) + .executeWith(Globals.TASK_EXECUTOR); + } + + } - Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, fileToLoad.getParent().toString()); + private ParserResult loadDatabase(Path file) throws Exception { + Path fileToLoad = file.toAbsolutePath(); - if (BackupManager.checkForBackupFile(fileToLoad)) { - BackupUIManager.showRestoreBackupDialog(frame.getDialogService(), fileToLoad); - } + dialogService.notify(Localization.lang("Opening") + ": '" + file + "'"); - ParserResult result; - result = OpenDatabase.loadDatabase(fileToLoad.toString(), - Globals.prefs.getImportFormatPreferences(), Globals.getFileUpdateMonitor()); + Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, fileToLoad.getParent().toString()); - if (result.getDatabase().isShared()) { - try { - new SharedDatabaseUIManager(frame).openSharedDatabaseFromParserResult(result); - } catch (SQLException | DatabaseNotSupportedException | InvalidDBMSConnectionPropertiesException | - NotASharedDatabaseException e) { - result.getDatabaseContext().clearDatabaseFile(); // do not open the original file - result.getDatabase().clearSharedDatabaseID(); - LOGGER.error("Connection error", e); + if (BackupManager.checkForBackupFile(fileToLoad)) { + BackupUIManager.showRestoreBackupDialog(dialogService, fileToLoad); + } - frame.getDialogService().showErrorDialogAndWait(Localization.lang("Connection error"), - e.getMessage() + "\n\n" + Localization.lang("A local copy will be opened.")); + ParserResult result = OpenDatabase.loadDatabase(fileToLoad.toString(), + Globals.prefs.getImportFormatPreferences(), Globals.getFileUpdateMonitor()); - } - } + if (result.getDatabase().isShared()) { + try { + new SharedDatabaseUIManager(frame).openSharedDatabaseFromParserResult(result); + } catch (SQLException | DatabaseNotSupportedException | InvalidDBMSConnectionPropertiesException | + NotASharedDatabaseException e) { + result.getDatabaseContext().clearDatabaseFile(); // do not open the original file + result.getDatabase().clearSharedDatabaseID(); + LOGGER.error("Connection error", e); - BasePanel panel = addNewDatabase(result, file, raisePanel); + throw e; - // After adding the database, go through our list and see if - // any post open actions need to be done. For instance, checking - // if we found new entry types that can be imported, or checking - // if the database contents should be modified due to new features - // in this version of JabRef: - final ParserResult finalReferenceToResult = result; - SwingUtilities.invokeLater(() -> OpenDatabaseAction.performPostOpenActions(panel, finalReferenceToResult)); + } } + return result; + } private BasePanel addNewDatabase(ParserResult result, final Path file, boolean raisePanel) { @@ -234,21 +235,19 @@ private BasePanel addNewDatabase(ParserResult result, final Path file, boolean r BibDatabase database = result.getDatabase(); if (result.hasWarnings()) { - JabRefExecutorService.INSTANCE - .execute(() -> ParserResultWarningDialog.showParserResultWarningDialog(result, frame)); + ParserResultWarningDialog.showParserResultWarningDialog(result, frame); } if (Objects.nonNull(file)) { - frame.getDialogService().notify(Localization.lang("Opened library") + " '" + file.toString() + "' " - + Localization.lang("with") - + " " - + database.getEntryCount() + " " + Localization.lang("entries") + "."); + dialogService.notify(Localization.lang("Opened library") + " '" + file.toString() + "' " + + Localization.lang("with") + + " " + + database.getEntryCount() + " " + Localization.lang("entries") + "."); } - return DefaultTaskExecutor.runInJavaFXThread(() -> { - BasePanel basePanel = new BasePanel(frame, BasePanelPreferences.from(Globals.prefs), result.getDatabaseContext(), ExternalFileTypes.getInstance()); - frame.addTab(basePanel, raisePanel); - return basePanel; - }); + BasePanel basePanel = new BasePanel(frame, BasePanelPreferences.from(Globals.prefs), result.getDatabaseContext(), ExternalFileTypes.getInstance()); + frame.addTab(basePanel, raisePanel); + return basePanel; + } } diff --git a/src/main/java/org/jabref/gui/actions/LookupIdentifierAction.java b/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java similarity index 78% rename from src/main/java/org/jabref/gui/actions/LookupIdentifierAction.java rename to src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java index a2d6c7372d9..31c03ca36fc 100644 --- a/src/main/java/org/jabref/gui/actions/LookupIdentifierAction.java +++ b/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java @@ -1,17 +1,21 @@ -package org.jabref.gui.actions; +package org.jabref.gui.importer.fetcher; import java.util.List; -import java.util.Objects; import java.util.Optional; +import javax.swing.undo.UndoManager; + import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.Action; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.icon.JabRefIcon; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.util.BackgroundTask; +import org.jabref.gui.util.BindingsHelper; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.IdFetcher; @@ -23,6 +27,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; +import static org.jabref.gui.actions.ActionHelper.needsEntriesSelected; + public class LookupIdentifierAction extends SimpleCommand { private static final Logger LOGGER = LoggerFactory.getLogger(LookupIdentifierAction.class); @@ -30,16 +37,23 @@ public class LookupIdentifierAction extends SimpleCommand private final JabRefFrame frame; private final IdFetcher fetcher; + private final StateManager stateManager; + private UndoManager undoManager; - public LookupIdentifierAction(JabRefFrame frame, IdFetcher fetcher) { + public LookupIdentifierAction(JabRefFrame frame, IdFetcher fetcher, StateManager stateManager, UndoManager undoManager) { this.frame = frame; this.fetcher = fetcher; + this.stateManager = stateManager; + this.undoManager = undoManager; + + this.executable.bind(needsDatabase(this.stateManager).and(needsEntriesSelected(this.stateManager))); + this.statusMessage.bind(BindingsHelper.ifThenElse(executable, "", Localization.lang("This operation requires one or more entries to be selected."))); } @Override public void execute() { try { - BackgroundTask.wrap(this::lookupIdentifiers) + BackgroundTask.wrap(() -> lookupIdentifiers(stateManager.getSelectedEntries())) .onSuccess(frame.getDialogService()::notify) .executeWith(Globals.TASK_EXECUTOR); } catch (Exception e) { @@ -72,13 +86,7 @@ public String getDescription() { }; } - private String lookupIdentifiers() { - BasePanel basePanel = Objects.requireNonNull(frame.getCurrentBasePanel()); - List bibEntries = basePanel.getSelectedEntries(); - if (bibEntries.isEmpty()) { - return Localization.lang("This operation requires one or more entries to be selected."); - } - + private String lookupIdentifiers(List bibEntries) { String totalCount = Integer.toString(bibEntries.size()); NamedCompound namedCompound = new NamedCompound(Localization.lang("Look up %0", fetcher.getIdentifierName())); int count = 0; @@ -107,8 +115,7 @@ private String lookupIdentifiers() { } namedCompound.end(); if (foundCount > 0) { - basePanel.getUndoManager().addEdit(namedCompound); - basePanel.markBaseChanged(); + undoManager.addEdit(namedCompound); } return Localization.lang("Determined %0 for %1 entries", fetcher.getIdentifierName(), Integer.toString(foundCount)); } diff --git a/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java b/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java index 0bf4c182db8..4cedba33962 100644 --- a/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java +++ b/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java @@ -10,6 +10,7 @@ import org.jabref.gui.Dialog; import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.integrity.IntegrityCheck; @@ -19,22 +20,28 @@ import org.jabref.model.entry.BibEntry; import org.jabref.preferences.JabRefPreferences; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + public class IntegrityCheckAction extends SimpleCommand { - private final JabRefFrame frame; private final TaskExecutor taskExecutor; private final DialogService dialogService; + private final JabRefFrame frame; + private final StateManager stateManager; - public IntegrityCheckAction(JabRefFrame frame) { + public IntegrityCheckAction(JabRefFrame frame, StateManager stateManager, TaskExecutor taskExecutor) { this.frame = frame; - this.taskExecutor = Globals.TASK_EXECUTOR; + this.stateManager = stateManager; + this.taskExecutor = taskExecutor; this.dialogService = frame.getDialogService(); + + this.executable.bind(needsDatabase(this.stateManager)); } @Override public void execute() { - BibDatabaseContext databaseContext = frame.getCurrentBasePanel().getBibDatabaseContext(); - IntegrityCheck check = new IntegrityCheck(databaseContext, + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + IntegrityCheck check = new IntegrityCheck(database, Globals.prefs.getFilePreferences(), Globals.prefs.getBibtexKeyPatternPreferences(), Globals.journalAbbreviationLoader.getRepository(Globals.prefs.getJournalAbbreviationPreferences()), @@ -45,7 +52,7 @@ public void execute() { protected List call() { List result = new ArrayList<>(); - ObservableList entries = databaseContext.getDatabase().getEntries(); + ObservableList entries = database.getDatabase().getEntries(); for (int i = 0; i < entries.size(); i++) { if (isCancelled()) { break; diff --git a/src/main/java/org/jabref/gui/actions/ManageJournalsAction.java b/src/main/java/org/jabref/gui/journals/ManageJournalsAction.java similarity index 63% rename from src/main/java/org/jabref/gui/actions/ManageJournalsAction.java rename to src/main/java/org/jabref/gui/journals/ManageJournalsAction.java index b089a505a9e..bd3b79907d2 100644 --- a/src/main/java/org/jabref/gui/actions/ManageJournalsAction.java +++ b/src/main/java/org/jabref/gui/journals/ManageJournalsAction.java @@ -1,6 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.journals; -import org.jabref.gui.journals.ManageJournalAbbreviationsView; +import org.jabref.gui.actions.SimpleCommand; public class ManageJournalsAction extends SimpleCommand { diff --git a/src/main/java/org/jabref/gui/actions/CustomizeKeyBindingAction.java b/src/main/java/org/jabref/gui/keyboard/CustomizeKeyBindingAction.java similarity index 65% rename from src/main/java/org/jabref/gui/actions/CustomizeKeyBindingAction.java rename to src/main/java/org/jabref/gui/keyboard/CustomizeKeyBindingAction.java index fdaa5538ff4..44f5861fac1 100644 --- a/src/main/java/org/jabref/gui/actions/CustomizeKeyBindingAction.java +++ b/src/main/java/org/jabref/gui/keyboard/CustomizeKeyBindingAction.java @@ -1,6 +1,6 @@ -package org.jabref.gui.actions; +package org.jabref.gui.keyboard; -import org.jabref.gui.keyboard.KeyBindingsDialogView; +import org.jabref.gui.actions.SimpleCommand; public class CustomizeKeyBindingAction extends SimpleCommand { diff --git a/src/main/java/org/jabref/gui/actions/LibraryPropertiesAction.java b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java similarity index 66% rename from src/main/java/org/jabref/gui/actions/LibraryPropertiesAction.java rename to src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java index 1b2299e3f06..6c513dbc9ce 100644 --- a/src/main/java/org/jabref/gui/actions/LibraryPropertiesAction.java +++ b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java @@ -1,17 +1,22 @@ -package org.jabref.gui.actions; +package org.jabref.gui.libraryproperties; import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; -import org.jabref.gui.libraryproperties.LibraryPropertiesDialogView; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; public class LibraryPropertiesAction extends SimpleCommand { private final JabRefFrame frame; private final DialogService dialogService; - public LibraryPropertiesAction(JabRefFrame frame, DialogService dialogService) { + public LibraryPropertiesAction(JabRefFrame frame, DialogService dialogService, StateManager stateManager) { this.frame = frame; this.dialogService = dialogService; + + this.executable.bind(needsDatabase(stateManager)); } @Override diff --git a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml index 2cb00861431..76aa87d595c 100644 --- a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml +++ b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml @@ -11,7 +11,6 @@ - diff --git a/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java b/src/main/java/org/jabref/gui/mergeentries/MergeEntriesAction.java index 22ba15d7d8a..71bae10e73b 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.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableInsertEntry; @@ -13,14 +14,18 @@ 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 DialogService dialogService; - public MergeEntriesAction(JabRefFrame jabRefFrame) { + public MergeEntriesAction(JabRefFrame jabRefFrame, StateManager stateManager) { this.jabRefFrame = jabRefFrame; - dialogService = jabRefFrame.getDialogService(); + this.dialogService = jabRefFrame.getDialogService(); + + this.executable.bind(needsDatabase(stateManager)); } @Override @@ -52,9 +57,9 @@ public void execute() { // 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 UndoableInsertEntry(basePanel.getDatabase(), mergedEntry.get())); - ce.addEdit(new UndoableRemoveEntry(basePanel.getDatabase(), one, basePanel)); + ce.addEdit(new UndoableRemoveEntry(basePanel.getDatabase(), one)); basePanel.getDatabase().removeEntry(one); - ce.addEdit(new UndoableRemoveEntry(basePanel.getDatabase(), two, basePanel)); + ce.addEdit(new UndoableRemoveEntry(basePanel.getDatabase(), two)); basePanel.getDatabase().removeEntry(two); ce.end(); basePanel.getUndoManager().addEdit(ce); diff --git a/src/main/java/org/jabref/gui/metadata/BibtexStringEditorAction.java b/src/main/java/org/jabref/gui/metadata/BibtexStringEditorAction.java index 7e37e175319..af36819dd91 100644 --- a/src/main/java/org/jabref/gui/metadata/BibtexStringEditorAction.java +++ b/src/main/java/org/jabref/gui/metadata/BibtexStringEditorAction.java @@ -1,20 +1,24 @@ package org.jabref.gui.metadata; -import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; public class BibtexStringEditorAction extends SimpleCommand { - private final JabRefFrame frame; + private final StateManager stateManager; + + public BibtexStringEditorAction(StateManager stateManager) { + this.stateManager = stateManager; - public BibtexStringEditorAction(JabRefFrame jabRefFrame) { - this.frame = jabRefFrame; + this.executable.bind(needsDatabase(this.stateManager)); } @Override public void execute() { - BibDatabase database = frame.getCurrentBasePanel().getDatabase(); - new BibtexStringEditorDialogView(database).showAndWait(); + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + new BibtexStringEditorDialogView(database.getDatabase()).showAndWait(); } } diff --git a/src/main/java/org/jabref/gui/metadata/BibtexStringEditorDialog.fxml b/src/main/java/org/jabref/gui/metadata/BibtexStringEditorDialog.fxml index a9ceca60cd6..728897bd5db 100644 --- a/src/main/java/org/jabref/gui/metadata/BibtexStringEditorDialog.fxml +++ b/src/main/java/org/jabref/gui/metadata/BibtexStringEditorDialog.fxml @@ -7,7 +7,6 @@ - diff --git a/src/main/java/org/jabref/gui/metadata/PreambleEditor.java b/src/main/java/org/jabref/gui/metadata/PreambleEditor.java index 757c12aa732..00f28aea5b7 100644 --- a/src/main/java/org/jabref/gui/metadata/PreambleEditor.java +++ b/src/main/java/org/jabref/gui/metadata/PreambleEditor.java @@ -2,41 +2,45 @@ import java.util.Optional; +import javax.swing.undo.UndoManager; + import javafx.scene.control.ButtonType; import javafx.scene.control.DialogPane; import javafx.scene.control.TextArea; -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.undo.UndoablePreambleChange; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabase; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; + public class PreambleEditor extends SimpleCommand { - private final TextArea editor = new TextArea(); + private DialogService dialogService; + private final StateManager stateManager; + private UndoManager undoManager; - private final JabRefFrame frame; + public PreambleEditor(StateManager stateManager, UndoManager undoManager, DialogService dialogService) { + this.dialogService = dialogService; + this.stateManager = stateManager; + this.undoManager = undoManager; - public PreambleEditor(JabRefFrame frame) { - this.frame = frame; + this.executable.bind(needsDatabase(stateManager)); } @Override public void execute() { - BasePanel panel = frame.getCurrentBasePanel(); - BibDatabase database = frame.getCurrentBasePanel().getDatabase(); + BibDatabase database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")).getDatabase(); + TextArea editor = new TextArea(); + editor.setText(database.getPreamble().orElse("")); DialogPane pane = new DialogPane(); - - editor.setText(frame.getCurrentBasePanel() - .getDatabase() - .getPreamble() - .orElse("")); pane.setContent(editor); - Optional pressedButton = frame.getDialogService().showCustomDialogAndWait(Localization.lang("Edit Preamble"), pane, ButtonType.APPLY, ButtonType.CANCEL); + Optional pressedButton = dialogService.showCustomDialogAndWait(Localization.lang("Edit Preamble"), pane, ButtonType.APPLY, ButtonType.CANCEL); if (pressedButton.isPresent() && pressedButton.get().equals(ButtonType.APPLY)) { String newPreamble = editor.getText(); @@ -44,15 +48,10 @@ public void execute() { // We check if the field has changed, since we don't want to mark the // base as changed unless we have a real change. if (!database.getPreamble().orElse("").equals(newPreamble)) { - - panel.getUndoManager().addEdit( - new UndoablePreambleChange(database, database.getPreamble().orElse(null), newPreamble)); + undoManager.addEdit(new UndoablePreambleChange(database, database.getPreamble().orElse(null), newPreamble)); database.setPreamble(newPreamble); - - panel.markBaseChanged(); } } - } } diff --git a/src/main/java/org/jabref/gui/preferences/ExternalTab.java b/src/main/java/org/jabref/gui/preferences/ExternalTab.java index fc6603f9a95..381ece611a8 100644 --- a/src/main/java/org/jabref/gui/preferences/ExternalTab.java +++ b/src/main/java/org/jabref/gui/preferences/ExternalTab.java @@ -12,11 +12,11 @@ import org.jabref.Globals; import org.jabref.gui.DialogService; import org.jabref.gui.JabRefFrame; -import org.jabref.gui.actions.EditExternalFileTypesAction; +import org.jabref.gui.externalfiletype.EditExternalFileTypesAction; import org.jabref.gui.push.PushToApplication; import org.jabref.gui.push.PushToApplicationSettings; import org.jabref.gui.push.PushToApplicationSettingsDialog; -import org.jabref.gui.push.PushToApplications; +import org.jabref.gui.push.PushToApplicationsManager; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; @@ -174,7 +174,7 @@ public Node getBuilder() { } private void addSettingsButton(final PushToApplication application, GridPane panel, int index) { - PushToApplicationSettings settings = PushToApplications.getSettings(application); + PushToApplicationSettings settings = PushToApplicationsManager.getSettings(application); Button button = new Button(Localization.lang("Settings for %0", application.getApplicationName())); button.setPrefSize(150, 20); button.setOnAction(e -> PushToApplicationSettingsDialog.showSettingsDialog(dialogService, settings, index)); diff --git a/src/main/java/org/jabref/gui/preferences/PreferencesDialog.fxml b/src/main/java/org/jabref/gui/preferences/PreferencesDialog.fxml index 2e41e88e6c2..d28949c1983 100644 --- a/src/main/java/org/jabref/gui/preferences/PreferencesDialog.fxml +++ b/src/main/java/org/jabref/gui/preferences/PreferencesDialog.fxml @@ -1,6 +1,5 @@ - - + diff --git a/src/main/java/org/jabref/gui/actions/ShowPreferencesAction.java b/src/main/java/org/jabref/gui/preferences/ShowPreferencesAction.java similarity index 87% rename from src/main/java/org/jabref/gui/actions/ShowPreferencesAction.java rename to src/main/java/org/jabref/gui/preferences/ShowPreferencesAction.java index e6c0a29684c..b47321f0095 100644 --- a/src/main/java/org/jabref/gui/actions/ShowPreferencesAction.java +++ b/src/main/java/org/jabref/gui/preferences/ShowPreferencesAction.java @@ -1,7 +1,7 @@ -package org.jabref.gui.actions; +package org.jabref.gui.preferences; import org.jabref.gui.JabRefFrame; -import org.jabref.gui.preferences.PreferencesDialog; +import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.TaskExecutor; public class ShowPreferencesAction extends SimpleCommand { diff --git a/src/main/java/org/jabref/gui/preferences/TableColumnsTab.java b/src/main/java/org/jabref/gui/preferences/TableColumnsTab.java index 18049b23385..7f5d8ba1198 100644 --- a/src/main/java/org/jabref/gui/preferences/TableColumnsTab.java +++ b/src/main/java/org/jabref/gui/preferences/TableColumnsTab.java @@ -316,6 +316,9 @@ public void setValues() { if (extraFileColumns.isSelected()) { List desiredColumns = prefs.getStringList(JabRefPreferences.LIST_OF_FILE_COLUMNS); int listSize = listOfFileColumns.getSelectionModel().getSelectedIndex(); + if (listSize < 0) { + listSize = 0; + } int[] indicesToSelect = new int[listSize]; for (int i = 0; i < listSize; i++) { indicesToSelect[i] = listSize + 1; diff --git a/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java b/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java index 0f6b18daad0..bbd62196773 100644 --- a/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java +++ b/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java @@ -4,13 +4,11 @@ import java.util.List; import org.jabref.Globals; -import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.metadata.MetaData; import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; @@ -47,8 +45,7 @@ public String getTooltip() { } @Override - public void pushEntries(BibDatabase database, List entries, String keyString, MetaData metaData) { - + public void pushEntries(BibDatabaseContext database, List entries, String keyString) { couldNotConnect = false; couldNotCall = false; notDefined = false; @@ -95,18 +92,21 @@ public void pushEntries(BibDatabase database, List entries, String key } @Override - public void operationCompleted(BasePanel panel) { + public void operationCompleted() { if (notDefined) { - panel.output(Localization.lang("Error") + ": " - + Localization.lang("Path to %0 not defined", getApplicationName()) + "."); + dialogService.showErrorDialogAndWait( + Localization.lang("Error pushing entries"), + Localization.lang("Path to %0 not defined", getApplicationName()) + "."); } else if (couldNotCall) { - panel.output(Localization.lang("Error") + ": " - + Localization.lang("Could not call executable") + " '" + commandPath + "'."); + dialogService.showErrorDialogAndWait( + Localization.lang("Error pushing entries"), + Localization.lang("Could not call executable") + " '" + commandPath + "'."); } else if (couldNotConnect) { - panel.output(Localization.lang("Error") + ": " - + Localization.lang("Could not connect to %0", getApplicationName()) + "."); + dialogService.showErrorDialogAndWait( + Localization.lang("Error pushing entries"), + Localization.lang("Could not connect to %0", getApplicationName()) + "."); } else { - panel.output(Localization.lang("Pushed citations to %0", getApplicationName()) + "."); + dialogService.notify(Localization.lang("Pushed citations to %0", getApplicationName()) + "."); } } diff --git a/src/main/java/org/jabref/gui/push/PushToApplication.java b/src/main/java/org/jabref/gui/push/PushToApplication.java index a892becd602..cea92bc0ae1 100644 --- a/src/main/java/org/jabref/gui/push/PushToApplication.java +++ b/src/main/java/org/jabref/gui/push/PushToApplication.java @@ -2,11 +2,9 @@ import java.util.List; -import org.jabref.gui.BasePanel; import org.jabref.gui.icon.JabRefIcon; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.metadata.MetaData; /** * Class that defines interaction with an external application in the form of "pushing" selected entries to it. @@ -25,17 +23,13 @@ public interface PushToApplication { /** * The actual operation. This method will not be called on the event dispatch thread, so it should not do GUI * operations without utilizing invokeLater(). - * - * @param database - * @param entries - * @param metaData */ - void pushEntries(BibDatabase database, List entries, String keyString, MetaData metaData); + void pushEntries(BibDatabaseContext database, List entries, String keyString); /** * Reporting etc., this method is called on the event dispatch thread after pushEntries() returns. */ - void operationCompleted(BasePanel panel); + void operationCompleted(); /** * Check whether this operation requires BibTeX keys to be set for the entries. If true is returned an error message diff --git a/src/main/java/org/jabref/gui/push/PushToApplicationAction.java b/src/main/java/org/jabref/gui/push/PushToApplicationAction.java index 3231a2a5e21..ecfb54763ad 100644 --- a/src/main/java/org/jabref/gui/push/PushToApplicationAction.java +++ b/src/main/java/org/jabref/gui/push/PushToApplicationAction.java @@ -4,19 +4,21 @@ import java.util.Optional; import org.jabref.Globals; -import org.jabref.gui.BasePanel; -import org.jabref.gui.JabRefFrame; +import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.actions.Action; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.icon.JabRefIcon; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.util.BackgroundTask; +import org.jabref.gui.util.BindingsHelper; import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.preferences.JabRefPreferences; +import org.jabref.model.strings.StringUtil; -import org.fxmisc.easybind.EasyBind; +import static org.jabref.gui.actions.ActionHelper.needsDatabase; +import static org.jabref.gui.actions.ActionHelper.needsEntriesSelected; /** * An Action class representing the process of invoking a PushToApplication operation. @@ -24,26 +26,16 @@ public class PushToApplicationAction extends SimpleCommand { private final PushToApplication operation; - private final JabRefFrame frame; - private BasePanel panel; - private List entries; - - public PushToApplicationAction(final JabRefFrame frame, final StateManager stateManager) { - this.frame = frame; - this.operation = getLastUsedApplication(frame.getPushApplications().getApplications()); - this.executable.bind(EasyBind.map(stateManager.activeDatabaseProperty(), Optional::isPresent)); - } + private final StateManager stateManager; + private final DialogService dialogService; - private PushToApplication getLastUsedApplication(List pushActions) { - String appSelected = Globals.prefs.get(JabRefPreferences.PUSH_TO_APPLICATION); - for (PushToApplication application : pushActions) { - if (application.getApplicationName().equals(appSelected)) { - return application; - } - } + public PushToApplicationAction(StateManager stateManager, PushToApplicationsManager pushToApplicationsManager, DialogService dialogService) { + this.operation = pushToApplicationsManager.getLastUsedApplication(Globals.prefs); + this.stateManager = stateManager; + this.dialogService = dialogService; - // Nothing found, pick first - return pushActions.get(0); + this.executable.bind(needsDatabase(stateManager).and(needsEntriesSelected(stateManager))); + this.statusMessage.bind(BindingsHelper.ifThenElse(this.executable, "", Localization.lang("This operation requires one or more entries to be selected."))); } public Action getActionInformation() { @@ -71,57 +63,14 @@ public String getDescription() { }; } - @Override - public void execute() { - panel = frame.getCurrentBasePanel(); - - // Check if a BasePanel exists: - if (panel == null) { - return; - } - - // Check if any entries are selected: - entries = panel.getSelectedEntries(); - if (entries.isEmpty()) { - frame.getDialogService().showErrorDialogAndWait(operation.getApplicationName(), - Localization.lang("This operation requires one or more entries to be selected.")); - - return; - } - - // If required, check that all entries have BibTeX keys defined: - if (operation.requiresBibtexKeys()) { - for (BibEntry entry : entries) { - if (!(entry.getCiteKeyOptional().isPresent()) || entry.getCiteKeyOptional().get().trim().isEmpty()) { - frame.getDialogService().showErrorDialogAndWait(operation.getApplicationName(), - Localization.lang("This operation requires all selected entries to have BibTeX keys defined.")); - - return; - } - } - } - - // All set, call the operation in a new thread: - - BackgroundTask.wrap(this::pushentries) - .onSuccess(s -> operation.operationCompleted(panel)) - .executeWith(Globals.TASK_EXECUTOR); - - } - - private void pushentries() { - operation.pushEntries(panel.getDatabase(), entries, getKeyString(entries), panel.getBibDatabaseContext().getMetaData()); - } - - private static String getKeyString(List bibentries) { + private static String getKeyString(List entries) { StringBuilder result = new StringBuilder(); Optional citeKey; boolean first = true; - for (BibEntry bes : bibentries) { + for (BibEntry bes : entries) { citeKey = bes.getCiteKeyOptional(); - // if the key is empty we give a warning and ignore this entry - // TODO: Give warning if (!(citeKey.isPresent()) || citeKey.get().isEmpty()) { + // Should never occur, because we made sure that all entries have keys continue; } if (first) { @@ -133,4 +82,31 @@ private static String getKeyString(List bibentries) { } return result.toString(); } + + @Override + public void execute() { + // If required, check that all entries have BibTeX keys defined: + if (operation.requiresBibtexKeys()) { + for (BibEntry entry : stateManager.getSelectedEntries()) { + if (StringUtil.isBlank(entry.getCiteKeyOptional())) { + dialogService.showErrorDialogAndWait( + operation.getApplicationName(), + Localization.lang("This operation requires all selected entries to have BibTeX keys defined.")); + + return; + } + } + } + + // All set, call the operation in a new thread: + BackgroundTask.wrap(this::pushEntries) + .onSuccess(s -> operation.operationCompleted()) + .executeWith(Globals.TASK_EXECUTOR); + + } + + private void pushEntries() { + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + operation.pushEntries(database, stateManager.getSelectedEntries(), getKeyString(stateManager.getSelectedEntries())); + } } diff --git a/src/main/java/org/jabref/gui/push/PushToApplications.java b/src/main/java/org/jabref/gui/push/PushToApplicationsManager.java similarity index 67% rename from src/main/java/org/jabref/gui/push/PushToApplications.java rename to src/main/java/org/jabref/gui/push/PushToApplicationsManager.java index 0fe5024dee7..32a13f1226b 100644 --- a/src/main/java/org/jabref/gui/push/PushToApplications.java +++ b/src/main/java/org/jabref/gui/push/PushToApplicationsManager.java @@ -4,14 +4,14 @@ import java.util.List; import org.jabref.gui.DialogService; +import org.jabref.preferences.JabRefPreferences; -public class PushToApplications { +public class PushToApplicationsManager { private final List applications; - public PushToApplications(DialogService dialogService) { + public PushToApplicationsManager(DialogService dialogService) { // Set up the current available choices: - applications = new ArrayList<>(); applications.add(new PushToEmacs(dialogService)); applications.add(new PushToLyx(dialogService)); @@ -36,4 +36,12 @@ public static PushToApplicationSettings getSettings(PushToApplication applicatio return new PushToApplicationSettings(); } } + + public PushToApplication getLastUsedApplication(JabRefPreferences preferences) { + String appSelected = preferences.get(JabRefPreferences.PUSH_TO_APPLICATION); + return applications.stream() + .filter(application -> application.getApplicationName().equals(appSelected)) + .findAny() + .orElse(applications.get(0)); + } } diff --git a/src/main/java/org/jabref/gui/push/PushToEmacs.java b/src/main/java/org/jabref/gui/push/PushToEmacs.java index 3603bd646cb..72cbf7228f9 100644 --- a/src/main/java/org/jabref/gui/push/PushToEmacs.java +++ b/src/main/java/org/jabref/gui/push/PushToEmacs.java @@ -6,15 +6,13 @@ import org.jabref.Globals; import org.jabref.JabRefExecutorService; -import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.icon.JabRefIcon; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.metadata.MetaData; import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; @@ -39,8 +37,7 @@ public JabRefIcon getIcon() { } @Override - public void pushEntries(BibDatabase database, List entries, String keys, MetaData metaData) { - + public void pushEntries(BibDatabaseContext database, List entries, String keys) { couldNotConnect = false; couldNotCall = false; notDefined = false; @@ -105,9 +102,8 @@ public void pushEntries(BibDatabase database, List entries, String key } @Override - public void operationCompleted(BasePanel panel) { + public void operationCompleted() { if (couldNotConnect) { - dialogService.showErrorDialogAndWait(Localization.lang("Error pushing entries"), Localization.lang("Could not connect to a running gnuserv process. Make sure that " + "Emacs or XEmacs is running, and that the server has been started " @@ -119,7 +115,7 @@ public void operationCompleted(BasePanel panel) { + "the emacsclient/gnuclient program installed and available in the PATH.")); } else { - super.operationCompleted(panel); + super.operationCompleted(); } } diff --git a/src/main/java/org/jabref/gui/push/PushToLyx.java b/src/main/java/org/jabref/gui/push/PushToLyx.java index f1b58c1ec6f..38906bd3b39 100644 --- a/src/main/java/org/jabref/gui/push/PushToLyx.java +++ b/src/main/java/org/jabref/gui/push/PushToLyx.java @@ -8,14 +8,12 @@ import org.jabref.Globals; import org.jabref.JabRefExecutorService; -import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.icon.JabRefIcon; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.metadata.MetaData; import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; @@ -45,22 +43,20 @@ protected void initParameters() { } @Override - public void operationCompleted(BasePanel panel) { + public void operationCompleted() { if (couldNotConnect) { - panel.output(Localization.lang("Error") + ": " + + dialogService.showErrorDialogAndWait(Localization.lang("Error pushing entries"), Localization.lang("verify that LyX is running and that the lyxpipe is valid") + ". [" + commandPath + "]"); } else if (couldNotCall) { - panel.output(Localization.lang("Error") + ": " + - Localization.lang("unable to write to") + " " + commandPath + - ".in"); + dialogService.showErrorDialogAndWait(Localization.lang("unable to write to") + " " + commandPath + ".in"); } else { - super.operationCompleted(panel); + super.operationCompleted(); } } @Override - public void pushEntries(BibDatabase database, final List entries, final String keyString, MetaData metaData) { + public void pushEntries(BibDatabaseContext database, final List entries, final String keyString) { couldNotConnect = false; couldNotCall = false; notDefined = false; @@ -90,13 +86,8 @@ public void pushEntries(BibDatabase database, final List entries, fina JabRefExecutorService.INSTANCE.executeAndWait(() -> { try (FileWriter fw = new FileWriter(lyxpipe); BufferedWriter lyxOut = new BufferedWriter(fw)) { - String citeStr; - - citeStr = "LYXCMD:sampleclient:citation-insert:" + keyString; + String citeStr = "LYXCMD:sampleclient:citation-insert:" + keyString; lyxOut.write(citeStr + "\n"); - - lyxOut.close(); - fw.close(); } catch (IOException excep) { couldNotCall = true; LOGGER.warn("Problem pushing to LyX/Kile.", excep); diff --git a/src/main/java/org/jabref/gui/push/PushToVim.java b/src/main/java/org/jabref/gui/push/PushToVim.java index 46af5b2556d..ba0fafa1da2 100644 --- a/src/main/java/org/jabref/gui/push/PushToVim.java +++ b/src/main/java/org/jabref/gui/push/PushToVim.java @@ -6,14 +6,12 @@ import org.jabref.Globals; import org.jabref.JabRefExecutorService; -import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.icon.JabRefIcon; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.metadata.MetaData; import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; @@ -38,8 +36,7 @@ public JabRefIcon getIcon() { } @Override - public void pushEntries(BibDatabase database, List entries, String keys, MetaData metaData) { - + public void pushEntries(BibDatabaseContext database, List entries, String keys) { couldNotConnect = false; couldNotCall = false; notDefined = false; @@ -88,9 +85,8 @@ public void pushEntries(BibDatabase database, List entries, String key } @Override - public void operationCompleted(BasePanel panel) { + public void operationCompleted() { if (couldNotConnect) { - dialogService.showErrorDialogAndWait(Localization.lang("Error pushing entries"), Localization.lang("Could not connect to Vim server. Make sure that Vim is running with correct server name.")); @@ -99,7 +95,7 @@ public void operationCompleted(BasePanel panel) { Localization.lang("Could not run the 'vim' program.")); } else { - super.operationCompleted(panel); + super.operationCompleted(); } } diff --git a/src/main/java/org/jabref/gui/actions/ConnectToSharedDatabaseCommand.java b/src/main/java/org/jabref/gui/shared/ConnectToSharedDatabaseCommand.java similarity index 82% rename from src/main/java/org/jabref/gui/actions/ConnectToSharedDatabaseCommand.java rename to src/main/java/org/jabref/gui/shared/ConnectToSharedDatabaseCommand.java index 792aff5bf34..6d8aee1b301 100644 --- a/src/main/java/org/jabref/gui/actions/ConnectToSharedDatabaseCommand.java +++ b/src/main/java/org/jabref/gui/shared/ConnectToSharedDatabaseCommand.java @@ -1,7 +1,7 @@ -package org.jabref.gui.actions; +package org.jabref.gui.shared; import org.jabref.gui.JabRefFrame; -import org.jabref.gui.shared.SharedDatabaseLoginDialogView; +import org.jabref.gui.actions.SimpleCommand; /** * Opens a shared database. diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialog.fxml b/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialog.fxml index 30808026c50..f6f681e3c40 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialog.fxml +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialog.fxml @@ -1,6 +1,5 @@ - @@ -9,11 +8,11 @@ + - diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index 94bc02ddc5b..1d9de038f98 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java @@ -91,7 +91,7 @@ public void listen(SharedEntryNotPresentEvent event) { BasePanel panel = jabRefFrame.getCurrentBasePanel(); EntryEditor entryEditor = panel.getEntryEditor(); - panel.getUndoManager().addEdit(new UndoableRemoveEntry(panel.getDatabase(), event.getBibEntry(), panel)); + panel.getUndoManager().addEdit(new UndoableRemoveEntry(panel.getDatabase(), event.getBibEntry())); if (Objects.nonNull(entryEditor) && (entryEditor.getEntry() == event.getBibEntry())) { diff --git a/src/main/java/org/jabref/gui/undo/UndoableRemoveEntry.java b/src/main/java/org/jabref/gui/undo/UndoableRemoveEntry.java index 3190356a34d..21362cbfac8 100644 --- a/src/main/java/org/jabref/gui/undo/UndoableRemoveEntry.java +++ b/src/main/java/org/jabref/gui/undo/UndoableRemoveEntry.java @@ -1,6 +1,5 @@ package org.jabref.gui.undo; -import org.jabref.gui.BasePanel; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; @@ -22,13 +21,9 @@ public class UndoableRemoveEntry extends AbstractUndoableJabRefEdit { private final BibDatabase base; private final BibEntry entry; - private final BasePanel panel; - - public UndoableRemoveEntry(BibDatabase base, BibEntry entry, - BasePanel panel) { + public UndoableRemoveEntry(BibDatabase base, BibEntry entry) { this.base = base; this.entry = entry; - this.panel = panel; } @Override @@ -50,8 +45,6 @@ public void redo() { // Redo the change. try { base.removeEntry(entry); - // If the entry has an editor currently open, we must close it. - panel.ensureNotShowingBottomPanel(entry); } catch (Throwable ex) { LOGGER.warn("Problem to redo `remove entry`", ex); } diff --git a/src/main/java/org/jabref/gui/util/BindingsHelper.java b/src/main/java/org/jabref/gui/util/BindingsHelper.java index f53509c3f11..e3d8ad19a85 100644 --- a/src/main/java/org/jabref/gui/util/BindingsHelper.java +++ b/src/main/java/org/jabref/gui/util/BindingsHelper.java @@ -22,6 +22,7 @@ import javafx.css.PseudoClass; import javafx.scene.Node; +import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.PreboundBinding; /** @@ -187,6 +188,16 @@ public static ObservableList forUI(ObservableList list) { return new UiThreadList<>(list); } + public static ObservableValue ifThenElse(ObservableValue condition, T value, T other) { + return EasyBind.map(condition, conditionValue -> { + if (conditionValue) { + return value; + } else { + return other; + } + }); + } + private static class BidirectionalBinding { private final ObservableValue propertyA; diff --git a/src/main/java/org/jabref/gui/util/OptionalObjectProperty.java b/src/main/java/org/jabref/gui/util/OptionalObjectProperty.java new file mode 100644 index 00000000000..f8e9e5d7263 --- /dev/null +++ b/src/main/java/org/jabref/gui/util/OptionalObjectProperty.java @@ -0,0 +1,45 @@ +package org.jabref.gui.util; + +import java.util.Optional; + +import javafx.beans.binding.BooleanExpression; +import javafx.beans.binding.ObjectBinding; +import javafx.beans.property.SimpleObjectProperty; + +import org.fxmisc.easybind.PreboundBinding; + +/** + * Similar to {@link org.fxmisc.easybind.monadic.MonadicObservableValue} + */ +public class OptionalObjectProperty extends SimpleObjectProperty> { + + private OptionalObjectProperty(Optional initialValue) { + super(initialValue); + } + + public static OptionalObjectProperty empty() { + return new OptionalObjectProperty<>(Optional.empty()); + } + + /** + * Returns a new ObservableValue that holds the value held by this + * ObservableValue, or {@code other} when this ObservableValue is empty. + */ + public ObjectBinding orElse(T other) { + return new PreboundBinding(this) { + @Override + protected T computeValue() { + return OptionalObjectProperty.this.getValue().orElse(other); + } + }; + } + + public BooleanExpression isPresent() { + return BooleanExpression.booleanExpression(new PreboundBinding(this) { + @Override + protected Boolean computeValue() { + return OptionalObjectProperty.this.getValue().isPresent(); + } + }); + } +} diff --git a/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGenerator.java b/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGenerator.java index 6309b297168..02a2fce80ac 100644 --- a/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGenerator.java +++ b/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGenerator.java @@ -26,7 +26,7 @@ public class BibtexKeyGenerator extends BracketedPattern { */ public static final String APPENDIX_CHARACTERS = "abcdefghijklmnopqrstuvwxyz"; private static final Logger LOGGER = LoggerFactory.getLogger(BibtexKeyGenerator.class); - private static final String KEY_ILLEGAL_CHARACTERS = "{}(),\\\"-#~^':`"; + private static final String KEY_ILLEGAL_CHARACTERS = "{}(),\\\"-#~^:'`ʹ"; private static final String KEY_UNWANTED_CHARACTERS = "{}(),\\\"-"; private final AbstractBibtexKeyPattern citeKeyPattern; private final BibDatabase database; diff --git a/src/main/java/org/jabref/logic/exporter/SaveException.java b/src/main/java/org/jabref/logic/exporter/SaveException.java index 88ef9693aed..b3e8c2171c9 100644 --- a/src/main/java/org/jabref/logic/exporter/SaveException.java +++ b/src/main/java/org/jabref/logic/exporter/SaveException.java @@ -15,7 +15,7 @@ public class SaveException extends Exception { public static final SaveException BACKUP_CREATION = new SaveException("Unable to create backup", Localization.lang("Unable to create backup")); - private final BibEntry entry; + private BibEntry entry; private int status; private String localizedMessage; @@ -46,18 +46,18 @@ public SaveException(String message, BibEntry entry) { this.entry = entry; } - public SaveException(String message, String localizedMessage, BibEntry entry) { - super(message); + public SaveException(String message, String localizedMessage, BibEntry entry, Throwable base) { + super(message, base); this.localizedMessage = localizedMessage; this.entry = entry; } public SaveException(Throwable base) { - this(base.getMessage(), base.getLocalizedMessage()); + super(base.getMessage(), base); } public SaveException(Throwable base, BibEntry entry) { - this(base.getMessage(), base.getLocalizedMessage(), entry); + this(base.getMessage(), base.getLocalizedMessage(), entry, base); } public int getStatus() { diff --git a/src/main/java/org/jabref/migrations/CustomEntryTypePreferenceMigration.java b/src/main/java/org/jabref/migrations/CustomEntryTypePreferenceMigration.java index f4573c62236..d01bf652a52 100644 --- a/src/main/java/org/jabref/migrations/CustomEntryTypePreferenceMigration.java +++ b/src/main/java/org/jabref/migrations/CustomEntryTypePreferenceMigration.java @@ -5,7 +5,6 @@ import java.util.Optional; import org.jabref.Globals; -import org.jabref.gui.customentrytypes.CustomEntryTypesManager; import org.jabref.model.EntryTypes; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.CustomEntryType; @@ -36,7 +35,7 @@ static void upgradeStoredCustomEntryTypes(BibDatabaseMode defaultBibDatabaseMode number++; } - CustomEntryTypesManager.saveCustomEntryTypes(prefs); + prefs.saveCustomEntryTypes(); } /** diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index 6351d9bde36..be2842e5f88 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -45,7 +45,7 @@ public class BibEntry implements Cloneable { public static final String OBSOLETE_TYPE_HEADER = "bibtextype"; public static final String KEY_FIELD = "bibtexkey"; public static final String DEFAULT_TYPE = "misc"; - protected static final String ID_FIELD = "id"; + protected static final String INTERNAL_ID_FIELD = "JabRef-internal-id"; private static final Logger LOGGER = LoggerFactory.getLogger(BibEntry.class); private static final Pattern REMOVE_TRAILING_WHITESPACE = Pattern.compile("\\s+$"); private final SharedBibEntryData sharedBibEntryData; @@ -161,7 +161,7 @@ public void setId(String id) { String oldId = this.id; - eventBus.post(new FieldChangedEvent(this, BibEntry.ID_FIELD, id, oldId)); + eventBus.post(new FieldChangedEvent(this, BibEntry.INTERNAL_ID_FIELD, id, oldId)); this.id = id; changed = true; } @@ -408,10 +408,6 @@ public Optional setField(String name, String value, EntryEventSourc return Optional.empty(); } - if (BibEntry.ID_FIELD.equals(fieldName)) { - throw new IllegalArgumentException("The field name '" + name + "' is reserved"); - } - changed = true; fields.put(fieldName, value.intern()); @@ -463,10 +459,6 @@ public Optional clearField(String name) { public Optional clearField(String name, EntryEventSource eventSource) { String fieldName = toLowerCase(name); - if (BibEntry.ID_FIELD.equals(fieldName)) { - throw new IllegalArgumentException("The field name '" + name + "' is reserved"); - } - Optional oldValue = getField(fieldName); if (!oldValue.isPresent()) { return Optional.empty(); diff --git a/src/main/java/org/jabref/model/entry/BiblatexEntryType.java b/src/main/java/org/jabref/model/entry/BiblatexEntryType.java index 44d05b7a292..420b6ff9322 100644 --- a/src/main/java/org/jabref/model/entry/BiblatexEntryType.java +++ b/src/main/java/org/jabref/model/entry/BiblatexEntryType.java @@ -56,4 +56,9 @@ private boolean isPrimary(String field) { public int compareTo(EntryType o) { return getName().compareTo(o.getName()); } + + @Override + public String toString() { + return getName(); + } } diff --git a/src/main/java/org/jabref/model/entry/BibtexEntryType.java b/src/main/java/org/jabref/model/entry/BibtexEntryType.java index bfbcfc0eaae..e347fc35b9a 100644 --- a/src/main/java/org/jabref/model/entry/BibtexEntryType.java +++ b/src/main/java/org/jabref/model/entry/BibtexEntryType.java @@ -56,4 +56,9 @@ public Set getSecondaryOptionalFields() { private boolean isPrimary(String field) { return getPrimaryOptionalFields().contains(field); } + + @Override + public String toString() { + return getName(); + } } diff --git a/src/main/java/org/jabref/model/entry/CustomEntryType.java b/src/main/java/org/jabref/model/entry/CustomEntryType.java index 8ee5bc96f79..c9e2a0ce9fe 100644 --- a/src/main/java/org/jabref/model/entry/CustomEntryType.java +++ b/src/main/java/org/jabref/model/entry/CustomEntryType.java @@ -129,4 +129,9 @@ public String getAsString() { builder.append("]"); return builder.toString(); } + + @Override + public String toString() { + return getName(); + } } diff --git a/src/main/java/org/jabref/model/entry/EntryType.java b/src/main/java/org/jabref/model/entry/EntryType.java index aa582893e4f..d0232a3d044 100644 --- a/src/main/java/org/jabref/model/entry/EntryType.java +++ b/src/main/java/org/jabref/model/entry/EntryType.java @@ -102,4 +102,5 @@ default Set getOptionalFieldsAndAliases() { } return optionalFieldsAndAliases; } + } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 6c9217ba0fc..f977a0262cb 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -88,6 +88,7 @@ import org.jabref.logic.util.io.AutoLinkPreferences; import org.jabref.logic.util.io.FileHistory; import org.jabref.logic.xmp.XmpPreferences; +import org.jabref.model.EntryTypes; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; import org.jabref.model.cleanup.FieldFormatterCleanups; import org.jabref.model.database.BibDatabaseMode; @@ -872,11 +873,11 @@ private static Optional getNextUnit(Reader data) throws IOException { private static void insertDefaultCleanupPreset(Map storage) { EnumSet deactivatedJobs = EnumSet.of( - CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS, - CleanupPreset.CleanupStep.MOVE_PDF, - CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS, - CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX, - CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX); + CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS, + CleanupPreset.CleanupStep.MOVE_PDF, + CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS, + CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX, + CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX); for (CleanupPreset.CleanupStep action : EnumSet.allOf(CleanupPreset.CleanupStep.class)) { storage.put(JabRefPreferences.CLEANUP + action.name(), !deactivatedJobs.contains(action)); @@ -1437,8 +1438,8 @@ public FilePreferences getFilePreferences() { @Override public UpdateFieldPreferences getUpdateFieldPreferences() { return new UpdateFieldPreferences(getBoolean(USE_OWNER), getBoolean(OVERWRITE_OWNER), get(DEFAULT_OWNER), - getBoolean(USE_TIME_STAMP), getBoolean(OVERWRITE_TIME_STAMP), get(TIME_STAMP_FIELD), - get(TIME_STAMP_FORMAT)); + getBoolean(USE_TIME_STAMP), getBoolean(OVERWRITE_TIME_STAMP), get(TIME_STAMP_FIELD), + get(TIME_STAMP_FORMAT)); } public LatexFieldFormatterPreferences getLatexFieldFormatterPreferences() { @@ -1453,14 +1454,14 @@ public FieldContentParserPreferences getFieldContentParserPreferences() { @Override public boolean isKeywordSyncEnabled() { return getBoolean(JabRefPreferences.SPECIALFIELDSENABLED) - && getBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS); + && getBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS); } @Override public ImportFormatPreferences getImportFormatPreferences() { return new ImportFormatPreferences(customImports, getDefaultEncoding(), getKeywordDelimiter(), - getBibtexKeyPatternPreferences(), getFieldContentParserPreferences(), getXMPPreferences(), - isKeywordSyncEnabled()); + getBibtexKeyPatternPreferences(), getFieldContentParserPreferences(), getXMPPreferences(), + isKeywordSyncEnabled()); } @Override @@ -1475,32 +1476,32 @@ public SavePreferences loadForExportFromPreferences() { } } return new SavePreferences( - saveInOriginalOrder, - saveOrder, - this.getDefaultEncoding(), - this.getBoolean(JabRefPreferences.BACKUP), - SavePreferences.DatabaseSaveType.ALL, - false, - this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), - this.getLatexFieldFormatterPreferences(), - this.getKeyPattern(), - getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), - getBibtexKeyPatternPreferences()); + saveInOriginalOrder, + saveOrder, + this.getDefaultEncoding(), + this.getBoolean(JabRefPreferences.BACKUP), + SavePreferences.DatabaseSaveType.ALL, + false, + this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), + this.getLatexFieldFormatterPreferences(), + this.getKeyPattern(), + getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), + getBibtexKeyPatternPreferences()); } public SavePreferences loadForSaveFromPreferences() { return new SavePreferences( - false, - null, - this.getDefaultEncoding(), - this.getBoolean(JabRefPreferences.BACKUP), - SavePreferences.DatabaseSaveType.ALL, - true, - this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), - this.getLatexFieldFormatterPreferences(), - this.getKeyPattern(), - getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), - getBibtexKeyPatternPreferences()); + false, + null, + this.getDefaultEncoding(), + this.getBoolean(JabRefPreferences.BACKUP), + SavePreferences.DatabaseSaveType.ALL, + true, + this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), + this.getLatexFieldFormatterPreferences(), + this.getKeyPattern(), + getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), + getBibtexKeyPatternPreferences()); } public ExporterFactory getExporterFactory(JournalAbbreviationLoader abbreviationLoader) { @@ -1541,14 +1542,14 @@ public XmpPreferences getXMPPreferences() { @Override public OpenOfficePreferences getOpenOfficePreferences() { return new OpenOfficePreferences( - this.get(JabRefPreferences.OO_JARS_PATH), - this.get(JabRefPreferences.OO_EXECUTABLE_PATH), - this.get(JabRefPreferences.OO_PATH), - this.getBoolean(JabRefPreferences.OO_USE_ALL_OPEN_BASES), - this.getBoolean(JabRefPreferences.OO_SYNC_WHEN_CITING), - this.getBoolean(JabRefPreferences.OO_SHOW_PANEL), - this.getStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES), - this.get(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE)); + this.get(JabRefPreferences.OO_JARS_PATH), + this.get(JabRefPreferences.OO_EXECUTABLE_PATH), + this.get(JabRefPreferences.OO_PATH), + this.getBoolean(JabRefPreferences.OO_USE_ALL_OPEN_BASES), + this.getBoolean(JabRefPreferences.OO_SYNC_WHEN_CITING), + this.getBoolean(JabRefPreferences.OO_SHOW_PANEL), + this.getStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES), + this.get(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE)); } @Override @@ -1728,10 +1729,9 @@ private SaveOrderConfig loadTableSaveOrder() { @Override public SaveOrderConfig loadExportSaveOrder() { return new SaveOrderConfig(getBoolean(EXPORT_IN_ORIGINAL_ORDER), getBoolean(EXPORT_IN_SPECIFIED_ORDER), - new SaveOrderConfig.SortCriterion(get(EXPORT_PRIMARY_SORT_FIELD), getBoolean(EXPORT_PRIMARY_SORT_DESCENDING)), - new SaveOrderConfig.SortCriterion(get(EXPORT_SECONDARY_SORT_FIELD), getBoolean(EXPORT_SECONDARY_SORT_DESCENDING)), - new SaveOrderConfig.SortCriterion(get(EXPORT_TERTIARY_SORT_FIELD), getBoolean(EXPORT_TERTIARY_SORT_DESCENDING)) - ); + new SaveOrderConfig.SortCriterion(get(EXPORT_PRIMARY_SORT_FIELD), getBoolean(EXPORT_PRIMARY_SORT_DESCENDING)), + new SaveOrderConfig.SortCriterion(get(EXPORT_SECONDARY_SORT_FIELD), getBoolean(EXPORT_SECONDARY_SORT_DESCENDING)), + new SaveOrderConfig.SortCriterion(get(EXPORT_TERTIARY_SORT_FIELD), getBoolean(EXPORT_TERTIARY_SORT_DESCENDING))); } @Override @@ -2008,7 +2008,7 @@ public List getCustomExportFormats(JournalAbbreviationLoader l filename = formatData.get(EXPORTER_FILENAME_INDEX); extension = formatData.get(EXPORTER_EXTENSION_INDEX); TemplateExporter format = new TemplateExporter(exporterName, filename, extension, - layoutPreferences, savePreferences); + layoutPreferences, savePreferences); format.setCustomExport(true); formats.add(format); i++; @@ -2060,4 +2060,19 @@ public boolean shouldWarnAboutDuplicatesForImport() { public void setShouldWarnAboutDuplicatesForImport(boolean value) { putBoolean(JabRefPreferences.WARN_ABOUT_DUPLICATES_IN_INSPECTION, value); } + + @Override + public void saveCustomEntryTypes() { + saveCustomEntryTypes(BibDatabaseMode.BIBTEX); + saveCustomEntryTypes(BibDatabaseMode.BIBLATEX); + } + + private void saveCustomEntryTypes(BibDatabaseMode bibDatabaseMode) { + List customBiblatexBibTexTypes = EntryTypes.getAllValues(bibDatabaseMode).stream() + .filter(type -> type instanceof CustomEntryType) + .map(entryType -> (CustomEntryType) entryType).collect(Collectors.toList()); + + storeCustomEntryTypes(customBiblatexBibTexTypes, bibDatabaseMode); + + } } diff --git a/src/main/java/org/jabref/preferences/PreferencesService.java b/src/main/java/org/jabref/preferences/PreferencesService.java index fea7e8d52b7..4947c9da8bc 100644 --- a/src/main/java/org/jabref/preferences/PreferencesService.java +++ b/src/main/java/org/jabref/preferences/PreferencesService.java @@ -87,4 +87,6 @@ public interface PreferencesService { boolean shouldWarnAboutDuplicatesForImport(); void setShouldWarnAboutDuplicatesForImport(boolean value); + + void saveCustomEntryTypes(); } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 1546ff133c3..bff936deccc 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1854,8 +1854,8 @@ Could\ not\ find\ any\ bibliographic\ information.=Could not find any bibliograp BibTeX\ key\ deviates\ from\ generated\ key=BibTeX key deviates from generated key DOI\ %0\ is\ invalid=DOI %0 is invalid -Select\ all\ customized\ types\ to\ be\ stored\ in\ local\ preferences=Select all customized types to be stored in local preferences -Currently\ unknown=Currently\ unknown +Select\ all\ customized\ types\ to\ be\ stored\ in\ local\ preferences\:=Select all customized types to be stored in local preferences\: +Currently\ unknown\:=Currently unknown\: Different\ customization,\ current\ settings\ will\ be\ overwritten=Different customization, current settings will be overwritten Entry\ type\ %0\ is\ only\ defined\ for\ Biblatex\ but\ not\ for\ BibTeX=Entry type %0 is only defined for Biblatex but not for BibTeX @@ -2038,7 +2038,6 @@ Add\ new\ String=Add new String Remove\ selected\ Strings=Remove selected Strings Must\ not\ be\ empty\!=Must not be empty\! Open\ Help\ page=Open Help page -Active\ database\ connection\ do\ not\ exists\!=Active database connection do not exists! Add\ new\ field\ name=Add new field name Field\ name\:=Field name: Field\ name\ \"%0\"\ already\ exists=Field name "%0" already exists diff --git a/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java b/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java index ad6e2d86e1c..f93a07ee22e 100644 --- a/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java +++ b/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyGeneratorTest.java @@ -236,6 +236,12 @@ public void testMakeLabelAndCheckLegalKeysAccentGrave() throws ParseException { assertEquals("DAl", BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", new BibDatabase()), true)); + + entry0 = BibtexParser.singleFromString("@ARTICLE{kohn, author={Andrés Aʹrnold}, year={2000}}", + importFormatPreferences, fileMonitor); + assertEquals("Arn", + BibtexKeyGenerator.cleanKey(BibtexKeyGenerator.generateKey(entry0.get(), "auth3", + new BibDatabase()), true)); } /** diff --git a/src/test/java/org/jabref/model/entry/BibEntryTest.java b/src/test/java/org/jabref/model/entry/BibEntryTest.java index 5f7e95f52ac..58261a29bc1 100644 --- a/src/test/java/org/jabref/model/entry/BibEntryTest.java +++ b/src/test/java/org/jabref/model/entry/BibEntryTest.java @@ -12,7 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; public class BibEntryTest { @@ -28,16 +27,6 @@ public void tearDown() { entry = null; } - @Test - public void notOverrideReservedFields() { - assertThrows(IllegalArgumentException.class, () -> entry.setField(BibEntry.ID_FIELD, "somevalue")); - } - - @Test - public void notClearReservedFields() { - assertThrows(IllegalArgumentException.class, () -> entry.clearField(BibEntry.ID_FIELD)); - } - @Test public void getFieldIsCaseInsensitive() throws Exception { entry.setField("TeSt", "value");