diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 670407e4d4f..e3c75d04d5b 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -27,9 +27,10 @@ env: JAVA_OPTS: -Xmx4g concurrency: - group: ${{ github.head_ref }} + group: ${{ github.ref }} cancel-in-progress: true + jobs: build: strategy: diff --git a/CHANGELOG.md b/CHANGELOG.md index 51958628e8c..e8d88cebc9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We allowed the user to also preview the available citation styles in the preferences besides the selected ones [#8108](https://github.com/JabRef/jabref/issues/8108) - We added an option to search the available citation styles by name in the preferences [#8108](https://github.com/JabRef/jabref/issues/8108) - We added an option to generate bib-entries from ID through a popover in the toolbar. [#4183](https://github.com/JabRef/jabref/issues/4183) +- We added a menu option in the right click menu of the main table tabs to display the library properties. [#6527](https://github.com/JabRef/jabref/issues/6527) +- When a `.bib` file ("library") was saved successfully, a notification is shown ### Changed @@ -49,9 +51,11 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We present options to manually enter an article or return to the New Entry menu when the fetcher DOI fails to find an entry for an ID [#7870](https://github.com/JabRef/jabref/issues/7870) - We trim white space and non-ASCII characters from DOI [#8127](https://github.com/JabRef/jabref/issues/8127) - The duplicate checker now inspects other fields in case no difference in the required and optional fields are found. +- We reworked the library properties dialog and integrated the `Library > Preamble`, `Library > Citation key pattern` and `Library > String constants dialogs` [#8264](https://github.com/JabRef/jabref/pulls/8264) ### Fixed +- We fixed an issue where the actions to move a file to a directory were incorrectly disabled. [#7908](https://github.com/JabRef/jabref/issues/7908) - We fixed an issue where an exception occurred when a linked online file was edited in the entry editor [#8008](https://github.com/JabRef/jabref/issues/8008) - We fixed an issue when checking for a new version when JabRef is used behind a corporate proxy. [#7884](https://github.com/JabRef/jabref/issues/7884) - We fixed some icons that were drawn in the wrong color when JabRef used a custom theme. [#7853](https://github.com/JabRef/jabref/issues/7853) @@ -64,8 +68,10 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We fixed an issue where importing PDFs resulted in an uncaught exception [#8143](https://github.com/JabRef/jabref/issues/8143) - We fixed "The library has been modified by another program" showing up when line breaks change [#4877](https://github.com/JabRef/jabref/issues/4877) - The default directory of the "LaTeX Citations" tab is now the directory of the currently opened database (and not the directory chosen at the last open file dialog or the last database save) [koppor#538](https://github.com/koppor/jabref/issues/538) +- When writing a bib file, the `NegativeArraySizeException` should not occur [#8231](https://github.com/JabRef/jabref/issues/8231) [#8265](https://github.com/JabRef/jabref/issues/8265) - We fixed an issue where right-clicking on a tab and selecting close will close the focused tab even if it is not the tab we right-clicked [#8193](https://github.com/JabRef/jabref/pull/8193) - We fixed an issue where selecting a citation style in the preferences would sometimes produce an exception [#7860](https://github.com/JabRef/jabref/issues/7860) +- We fixed an issue where an exception would occur when clicking on a DOI link in the preview pane [#7706](https://github.com/JabRef/jabref/issues/7706) ### Removed diff --git a/build.gradle b/build.gradle index 9d03788da3e..50f88bf9a25 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ import org.jabref.build.xjc.XjcTask plugins { id 'application' - id "com.simonharrer.modernizer" version '2.1.0-1' + id 'com.github.andygoossens.modernizer' version '1.6.1' id 'me.champeau.gradle.jmh' version '0.5.3' @@ -178,7 +178,7 @@ dependencies { implementation 'org.controlsfx:controlsfx:11.1.0' implementation 'org.jsoup:jsoup:1.14.3' - implementation 'com.konghq:unirest-java:3.13.3' + implementation 'com.konghq:unirest-java:3.13.4' implementation 'org.slf4j:slf4j-api:2.0.0-alpha5' implementation group: 'org.apache.logging.log4j', name: 'log4j-jcl', version: '3.0.0-SNAPSHOT' @@ -209,14 +209,14 @@ dependencies { implementation group: 'net.harawata', name: 'appdirs', version: '1.2.1' - testImplementation 'io.github.classgraph:classgraph:4.8.130' + testImplementation 'io.github.classgraph:classgraph:4.8.137' testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' testImplementation 'org.junit.platform:junit-platform-launcher:1.8.1' - testImplementation 'net.bytebuddy:byte-buddy-parent:1.12.1' + testImplementation 'net.bytebuddy:byte-buddy-parent:1.12.2' testRuntimeOnly group: 'org.apache.logging.log4j', name: 'log4j-core', version: '3.0.0-SNAPSHOT' testRuntimeOnly group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '3.0.0-SNAPSHOT' - testImplementation 'org.mockito:mockito-core:4.0.0' + testImplementation 'org.mockito:mockito-core:4.1.0' testImplementation 'org.xmlunit:xmlunit-core:2.8.3' testImplementation 'org.xmlunit:xmlunit-matchers:2.8.3' testRuntimeOnly 'com.tngtech.archunit:archunit-junit5-engine:0.22.0' @@ -225,7 +225,7 @@ dependencies { testImplementation "org.testfx:testfx-junit5:4.0.17-alpha-SNAPSHOT" testImplementation "org.hamcrest:hamcrest-library:2.2" - checkstyle 'com.puppycrawl.tools:checkstyle:9.0.1' + checkstyle 'com.puppycrawl.tools:checkstyle:9.2' xjc group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: '2.3.3' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a2e01c0dffe..e750102e092 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=f581709a9c35e9cb92e16f585d2c4bc99b2b1a5f85d2badbd3dc6bff59e1e6dd -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787337f..c53aefaa5fc 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index 74b9c84d3c2..37009e28f25 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -310,20 +310,20 @@ private void writeMetadatatoPDFsOfEntry(BibDatabaseContext databaseContext, Stri try { if (writeXMP) { if (xmpPdfExporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, entry, List.of(entry))) { - System.out.println(String.format("Successfully written XMP metadata on at least one linked file of %s", citeKey)); + System.out.printf("Successfully written XMP metadata on at least one linked file of %s%n", citeKey); } else { - System.err.println(String.format("Cannot write XMP metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.", citeKey)); + System.err.printf("Cannot write XMP metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.%n", citeKey); } } if (embeddBibfile) { if (embeddedBibFilePdfExporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, entry, List.of(entry))) { - System.out.println(String.format("Successfully embedded metadata on at least one linked file of %s", citeKey)); + System.out.printf("Successfully embedded metadata on at least one linked file of %s%n", citeKey); } else { - System.out.println(String.format("Cannot embedd metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.", citeKey)); + System.out.printf("Cannot embedd metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.%n", citeKey); } } } catch (Exception e) { - LOGGER.error(String.format("Failed writing metadata on a linked file of %s.", citeKey)); + LOGGER.error("Failed writing metadata on a linked file of {}.", citeKey); } } @@ -331,7 +331,7 @@ private void writeMetadatatoPdfByCitekey(BibDatabaseContext databaseContext, Bib for (String citeKey : citeKeys) { List bibEntryList = dataBase.getEntriesByCitationKey(citeKey); if (bibEntryList.isEmpty()) { - System.err.println(String.format("Skipped - Cannot find %s in library.", citeKey)); + System.err.printf("Skipped - Cannot find %s in library.%n", citeKey); continue; } for (BibEntry entry : bibEntryList) { @@ -350,25 +350,25 @@ private void writeMetadatatoPdfByFileNames(BibDatabaseContext databaseContext, B try { if (writeXMP) { if (xmpPdfExporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, filePath)) { - System.out.println(String.format("Successfully written XMP metadata of at least one entry to %s", fileName)); + System.out.printf("Successfully written XMP metadata of at least one entry to %s%n", fileName); } else { - System.out.println(String.format("File %s is not linked to any entry in database.", fileName)); + System.out.printf("File %s is not linked to any entry in database.%n", fileName); } } if (embeddBibfile) { if (embeddedBibFilePdfExporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, filePath)) { - System.out.println(String.format("Successfully embedded XMP metadata of at least one entry to %s", fileName)); + System.out.printf("Successfully embedded XMP metadata of at least one entry to %s%n", fileName); } else { - System.out.println(String.format("File %s is not linked to any entry in database.", fileName)); + System.out.printf("File %s is not linked to any entry in database.%n", fileName); } } } catch (IOException e) { LOGGER.error("Error accessing file '{}'.", fileName); } catch (Exception e) { - LOGGER.error(String.format("Error writing entry to %s.", fileName)); + LOGGER.error("Error writing entry to {}.", fileName); } } else { - LOGGER.error(String.format("Skipped - PDF %s does not exist", fileName)); + LOGGER.error("Skipped - PDF {} does not exist", fileName); } } } diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java index 367b81bda0d..26cf46c00a1 100644 --- a/src/main/java/org/jabref/gui/DialogService.java +++ b/src/main/java/org/jabref/gui/DialogService.java @@ -215,7 +215,7 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String Optional showBackgroundProgressDialogAndWait(String title, String content, StateManager stateManager); /** - * Notify the user in an non-blocking way (i.e., in form of toast in a snackbar). + * Notify the user in a non-blocking way (i.e., in form of toast in a snackbar). * * @param message the message to show. */ diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 073371ea4bf..edb26429e3b 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -54,7 +54,6 @@ import org.jabref.gui.actions.StandardActions; import org.jabref.gui.auximport.NewSubLibraryAction; import org.jabref.gui.bibtexextractor.ExtractBibtexAction; -import org.jabref.gui.citationkeypattern.CitationKeyPatternAction; import org.jabref.gui.citationkeypattern.GenerateCitationKeyAction; import org.jabref.gui.cleanup.CleanupAction; import org.jabref.gui.contentselector.ManageContentSelectorAction; @@ -101,8 +100,6 @@ 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.preview.CopyCitationAction; import org.jabref.gui.push.PushToApplicationAction; @@ -754,19 +751,20 @@ private MenuBar createMenu() { factory.createMenuItem(StandardActions.MASS_SET_FIELDS, new MassSetFieldsAction(stateManager, dialogService, undoManager)) ); - if (prefs.getSpecialFieldsPreferences().isSpecialFieldsEnabled()) { - edit.getItems().addAll( - new SeparatorMenuItem(), - // ToDo: SpecialField needs the active BasePanel to mark it as changed. - // Refactor BasePanel, should mark the BibDatabaseContext or the UndoManager as dirty instead! - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, this, dialogService, prefs, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, this, dialogService, prefs, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, this, dialogService, prefs, undoManager, stateManager), - SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, this, dialogService, prefs, undoManager, stateManager), - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, this, dialogService, prefs, undoManager, stateManager), - SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, this, dialogService, prefs, undoManager, stateManager) - ); - } + SeparatorMenuItem specialFieldsSeparator = new SeparatorMenuItem(); + specialFieldsSeparator.visibleProperty().bind(prefs.getSpecialFieldsPreferences().specialFieldsEnabledProperty()); + + edit.getItems().addAll( + specialFieldsSeparator, + // ToDo: SpecialField needs the active BasePanel to mark it as changed. + // Refactor BasePanel, should mark the BibDatabaseContext or the UndoManager as dirty instead! + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.RANKING, factory, this, dialogService, prefs, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.RELEVANCE, factory, this, dialogService, prefs, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.QUALITY, factory, this, dialogService, prefs, undoManager, stateManager), + SpecialFieldMenuItemFactory.getSpecialFieldSingleItem(SpecialField.PRINTED, factory, this, dialogService, prefs, undoManager, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.PRIORITY, factory, this, dialogService, prefs, undoManager, stateManager), + SpecialFieldMenuItemFactory.createSpecialFieldMenu(SpecialField.READ_STATUS, factory, this, dialogService, prefs, undoManager, stateManager) + ); // @formatter:off library.getItems().addAll( @@ -776,10 +774,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.LIBRARY_PROPERTIES, new LibraryPropertiesAction(this, stateManager)), - factory.createMenuItem(StandardActions.EDIT_PREAMBLE, new PreambleEditor(stateManager, undoManager, this.getDialogService())), - factory.createMenuItem(StandardActions.EDIT_STRINGS, new BibtexStringEditorAction(stateManager)), - factory.createMenuItem(StandardActions.MANAGE_CITE_KEY_PATTERNS, new CitationKeyPatternAction(this, stateManager)) + factory.createMenuItem(StandardActions.LIBRARY_PROPERTIES, new LibraryPropertiesAction(stateManager)) ); quality.getItems().addAll( @@ -1050,6 +1045,7 @@ private ContextMenu createTabContextMenuFor(LibraryTab tab, KeyBindingRepository ActionFactory factory = new ActionFactory(keyBindingRepository); contextMenu.getItems().addAll( + factory.createMenuItem(StandardActions.LIBRARY_PROPERTIES, new LibraryPropertiesAction(tab.getBibDatabaseContext(), stateManager)), factory.createMenuItem(StandardActions.OPEN_DATABASE_FOLDER, new OpenDatabaseFolder(tab.getBibDatabaseContext())), factory.createMenuItem(StandardActions.OPEN_CONSOLE, new OpenConsoleAction(tab.getBibDatabaseContext(), stateManager, prefs)), new SeparatorMenuItem(), @@ -1192,7 +1188,7 @@ private Boolean confirmEmptyEntry(LibraryTab libraryTab, BibDatabaseContext cont if (response.isPresent() && response.get().equals(deleteEmptyEntries)) { // The user wants to delete. try { - for (BibEntry currentEntry : new ArrayList(context.getEntries())) { + for (BibEntry currentEntry : new ArrayList<>(context.getEntries())) { if (currentEntry.getFields().isEmpty()) { context.getDatabase().removeEntries(Collections.singletonList(currentEntry)); } diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java index c139ae93a26..4edab4cd9ff 100644 --- a/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/src/main/java/org/jabref/gui/JabRefGUI.java @@ -59,9 +59,9 @@ public JabRefGUI(Stage mainStage, List databases, boolean isBlank, openWindow(mainStage); new VersionWorker(Globals.BUILD_INFO.version, - preferencesService.getVersionPreferences().getIgnoredVersion(), mainFrame.getDialogService(), - Globals.TASK_EXECUTOR) + Globals.TASK_EXECUTOR, + preferencesService.getVersionPreferences()) .checkForNewVersionDelayed(); } diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index 2e75f23a18f..cf5504b591f 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -31,7 +31,6 @@ import org.jabref.gui.importer.actions.OpenDatabaseAction; import org.jabref.gui.maintable.MainTable; import org.jabref.gui.maintable.MainTableDataModel; -import org.jabref.gui.specialfields.SpecialFieldDatabaseChangeListener; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; @@ -465,8 +464,6 @@ public void editEntryAndFocusField(BibEntry entry, Field field) { } private void createMainTable() { - bibDatabaseContext.getDatabase().registerListener(SpecialFieldDatabaseChangeListener.INSTANCE); - mainTable = new MainTable(tableModel, this, bibDatabaseContext, diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 9c2b75fe9e1..23fc048529c 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -113,7 +113,6 @@ public enum StandardActions implements Action { MANAGE_JOURNALS(Localization.lang("Manage journal abbreviations")), CUSTOMIZE_KEYBINDING(Localization.lang("Customize key bindings"), IconTheme.JabRefIcons.KEY_BINDINGS), MANAGE_CONTENT_SELECTORS(Localization.lang("Manage content selectors"), IconTheme.JabRefIcons.SELECTORS), - MANAGE_CITE_KEY_PATTERNS(Localization.lang("Citation key patterns")), EDIT_ENTRY(Localization.lang("Open entry editor"), IconTheme.JabRefIcons.EDIT_ENTRY, KeyBinding.EDIT_ENTRY), SHOW_PDF_VIEWER(Localization.lang("Open document viewer"), IconTheme.JabRefIcons.PDF_FILE), @@ -129,8 +128,6 @@ public enum StandardActions implements Action { NEW_ARTICLE(Localization.lang("New article"), IconTheme.JabRefIcons.ADD_ARTICLE), NEW_ENTRY_FROM_PLAIN_TEXT(Localization.lang("New entry from plain text"), IconTheme.JabRefIcons.NEW_ENTRY_FROM_PLAIN_TEXT, KeyBinding.NEW_ENTRY_FROM_PLAIN_TEXT), LIBRARY_PROPERTIES(Localization.lang("Library properties")), - EDIT_PREAMBLE(Localization.lang("Edit preamble")), - EDIT_STRINGS(Localization.lang("Edit string constants"), IconTheme.JabRefIcons.EDIT_STRINGS, KeyBinding.EDIT_STRINGS), FIND_DUPLICATES(Localization.lang("Find duplicates"), IconTheme.JabRefIcons.FIND_DUPLICATES), MERGE_ENTRIES(Localization.lang("Merge entries"), IconTheme.JabRefIcons.MERGE_ENTRIES, KeyBinding.MERGE_ENTRIES), RESOLVE_DUPLICATE_KEYS(Localization.lang("Resolve duplicate citation keys"), Localization.lang("Find and remove duplicate citation keys"), KeyBinding.RESOLVE_DUPLICATE_CITATION_KEYS), diff --git a/src/main/java/org/jabref/gui/auximport/FromAuxDialog.java b/src/main/java/org/jabref/gui/auximport/FromAuxDialog.java index 7280deb9819..ae7de0b43e0 100644 --- a/src/main/java/org/jabref/gui/auximport/FromAuxDialog.java +++ b/src/main/java/org/jabref/gui/auximport/FromAuxDialog.java @@ -93,7 +93,7 @@ private void browseButtonClicked() { FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .addExtensionFilter(StandardFileType.AUX) .withDefaultExtension(StandardFileType.AUX) - .withInitialDirectory(preferences.getWorkingDir()).build(); + .withInitialDirectory(preferences.getFilePreferences().getWorkingDirectory()).build(); dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(file -> auxFileField.setText(file.toAbsolutePath().toString())); } } diff --git a/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternAction.java b/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternAction.java deleted file mode 100644 index cb7676fbc08..00000000000 --- a/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternAction.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.jabref.gui.citationkeypattern; - -import org.jabref.gui.DialogService; -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.StateManager; -import org.jabref.gui.actions.SimpleCommand; - -import com.airhacks.afterburner.injection.Injector; - -import static org.jabref.gui.actions.ActionHelper.needsDatabase; - -public class CitationKeyPatternAction extends SimpleCommand { - - private final JabRefFrame frame; - - public CitationKeyPatternAction(JabRefFrame frame, StateManager stateManager) { - this.frame = frame; - - this.executable.bind(needsDatabase(stateManager)); - } - - @Override - public void execute() { - DialogService dialogService = Injector.instantiateModelOrService(DialogService.class); - dialogService.showCustomDialogAndWait(new CitationKeyPatternDialog(frame.getCurrentLibraryTab())); - } -} diff --git a/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternDialog.java b/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternDialog.java deleted file mode 100644 index d92f35c7b35..00000000000 --- a/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternDialog.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.jabref.gui.citationkeypattern; - -import javafx.scene.control.ButtonType; - -import org.jabref.gui.Globals; -import org.jabref.gui.LibraryTab; -import org.jabref.gui.util.BaseDialog; -import org.jabref.logic.citationkeypattern.AbstractCitationKeyPattern; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.metadata.MetaData; - -public class CitationKeyPatternDialog extends BaseDialog { - - private final MetaData metaData; - private final LibraryTab libraryTab; - private final CitationKeyPatternPanel citationKeyPatternPanel; - - public CitationKeyPatternDialog(LibraryTab libraryTab) { - this.citationKeyPatternPanel = new CitationKeyPatternPanel(libraryTab.getBibDatabaseContext()); - this.libraryTab = libraryTab; - this.metaData = libraryTab.getBibDatabaseContext().getMetaData(); - AbstractCitationKeyPattern keyPattern = metaData.getCiteKeyPattern(Globals.prefs.getGlobalCitationKeyPattern()); - citationKeyPatternPanel.setValues(keyPattern); - init(); - } - - private void init() { - - this.setTitle(Localization.lang("Citation key patterns")); - - this.getDialogPane().setContent(citationKeyPatternPanel.getPanel()); - this.getDialogPane().getButtonTypes().addAll(ButtonType.APPLY, ButtonType.CANCEL); - - this.setResultConverter(button -> { - if (button == ButtonType.APPLY) { - metaData.setCiteKeyPattern(citationKeyPatternPanel.getKeyPatternAsDatabaseKeyPattern()); - libraryTab.markNonUndoableBaseChanged(); - } - - return null; - }); - - // Keep this for later conversion of the library-properties -/* void storeSettings() { - DataBaseKeyPattern newKeyPattern = new DatabaseBibtexKeyPattern(preferences.getKeyPattern()); - - bibtexKeyPatternTableView.patternListProperty.forEach(item -> { - String patternString = item.getPattern(); - if (!item.getEntryType().getName().equals("default")) { - if (!patternString.trim().isEmpty()) { - newKeyPattern.addBibtexKeyPattern(item.getEntryType(), patternString); - } - } - }); - - if (!defaultItem.getPattern().trim().isEmpty()) { - // we do not trim the value at the assignment to enable users to have spaces at the beginning and - // at the end of the pattern - newKeyPattern.setDefaultValue(defaultItemProperty.getPattern()); - } - } */ - - } -} diff --git a/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternPanel.java b/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternPanel.java deleted file mode 100644 index 9f1115d8c52..00000000000 --- a/src/main/java/org/jabref/gui/citationkeypattern/CitationKeyPatternPanel.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.jabref.gui.citationkeypattern; - -import java.util.HashMap; -import java.util.Map; - -import javafx.scene.Node; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; -import javafx.scene.layout.GridPane; -import javafx.scene.layout.Pane; - -import org.jabref.gui.Globals; -import org.jabref.gui.actions.ActionFactory; -import org.jabref.gui.actions.StandardActions; -import org.jabref.gui.help.HelpAction; -import org.jabref.logic.citationkeypattern.AbstractCitationKeyPattern; -import org.jabref.logic.citationkeypattern.DatabaseCitationKeyPattern; -import org.jabref.logic.help.HelpFile; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.database.BibDatabaseMode; -import org.jabref.model.entry.BibEntryType; -import org.jabref.model.entry.types.EntryType; -import org.jabref.preferences.JabRefPreferences; - -public class CitationKeyPatternPanel extends Pane { - - // default pattern - protected final TextField defaultPat = new TextField(); - - // one field for each type - private final Map textFields = new HashMap<>(); - private final BibDatabaseContext databaseContext; - private final GridPane gridPane = new GridPane(); - - public CitationKeyPatternPanel(BibDatabaseContext databaseContext) { - this.databaseContext = databaseContext; - gridPane.setHgap(10); - gridPane.setVgap(5); - buildGUI(); - } - - private static void setValue(TextField tf, EntryType fieldName, AbstractCitationKeyPattern keyPattern) { - if (keyPattern.isDefaultValue(fieldName)) { - tf.setText(""); - } else { - tf.setText(keyPattern.getValue(fieldName).get(0)); - } - } - - private void buildGUI() { - BibDatabaseMode mode = databaseContext.getMode(); - - // The following got irrelevant - global settings for CitationKeyPattern are handled by - // commonfxcontrols/CitationKeyPatternPanel.java - // ToDo: this one should be abandoned - /* - // check mode of currently used DB - if (panel != null) { - mode = panel.getBibDatabaseContext().getMode(); - } else { - // use preferences value if no DB is open - mode = Globals.prefs.getDefaultBibDatabaseMode(); - } - */ - - int rowIndex = 1; - int columnIndex = 0; - // The header - can be removed - int columnsNumber = 2; - for (int i = 0; i < columnsNumber; i++) { - Label label = new Label(Localization.lang("Entry type")); - Label keyPattern = new Label(Localization.lang("Key pattern")); - gridPane.add(label, ++columnIndex, rowIndex); - gridPane.add(keyPattern, ++columnIndex, rowIndex); - columnIndex++; - } - - rowIndex++; - Label defaultPattern = new Label(Localization.lang("Default pattern")); - Button button = new Button("Default"); - button.setOnAction(e -> defaultPat.setText((String) Globals.prefs.defaults.get(JabRefPreferences.DEFAULT_CITATION_KEY_PATTERN))); - gridPane.add(defaultPattern, 1, rowIndex); - gridPane.add(defaultPat, 2, rowIndex); - gridPane.add(button, 3, rowIndex); - - columnIndex = 1; - for (BibEntryType type : Globals.entryTypesManager.getAllTypes(mode)) { - Label label1 = new Label(type.getType().getDisplayName()); - TextField textField = new TextField(); - Button button1 = new Button("Default"); - button1.setOnAction(e1 -> textField.setText((String) Globals.prefs.defaults.get(JabRefPreferences.DEFAULT_CITATION_KEY_PATTERN))); - - gridPane.add(label1, 1 + (columnIndex * 3), rowIndex); - gridPane.add(textField, 2 + (columnIndex * 3), rowIndex); - gridPane.add(button1, 3 + (columnIndex * 3), rowIndex); - - textFields.put(type.getType(), textField); - - if (columnIndex == (columnsNumber - 1)) { - columnIndex = 0; - rowIndex++; - } else { - columnIndex++; - } - } - - rowIndex++; - - ActionFactory factory = new ActionFactory(Globals.prefs.getKeyBindingRepository()); - Button help = factory.createIconButton(StandardActions.HELP_KEY_PATTERNS, new HelpAction(HelpFile.CITATION_KEY_PATTERN)); - gridPane.add(help, 1, rowIndex); - - Button btnDefaultAll1 = new Button(Localization.lang("Reset all")); - btnDefaultAll1.setOnAction(e -> { - // reset all fields - for (TextField field : textFields.values()) { - field.setText(""); - } - defaultPat.setText((String) Globals.prefs.defaults.get(JabRefPreferences.DEFAULT_CITATION_KEY_PATTERN)); - }); - gridPane.add(btnDefaultAll1, 2, rowIndex); - } - - public DatabaseCitationKeyPattern getKeyPatternAsDatabaseKeyPattern() { - DatabaseCitationKeyPattern res = new DatabaseCitationKeyPattern(Globals.prefs.getGlobalCitationKeyPattern()); - fillPatternUsingPanelData(res); - return res; - } - - /** - * fill the given LabelPattern by values generated from the text fields - */ - private void fillPatternUsingPanelData(AbstractCitationKeyPattern keypatterns) { - // each entry type - for (Map.Entry entry : textFields.entrySet()) { - String text = entry.getValue().getText(); - if (!text.trim().isEmpty()) { - keypatterns.addCitationKeyPattern(entry.getKey(), text); - } - } - - // default value - String text = defaultPat.getText(); - if (!text.trim().isEmpty()) { // we do not trim the value at the assignment to enable users to have spaces at the beginning and at the end of the pattern - keypatterns.setDefaultValue(text); - } - } - - /** - * Fills the current values to the text fields - * - * @param keyPattern the CitationKeyPattern to use as initial value - */ - public void setValues(AbstractCitationKeyPattern keyPattern) { - for (Map.Entry entry : textFields.entrySet()) { - setValue(entry.getValue(), entry.getKey(), keyPattern); - } - - if ((keyPattern.getDefaultValue() == null) || keyPattern.getDefaultValue().isEmpty()) { - defaultPat.setText(""); - } else { - defaultPat.setText(keyPattern.getDefaultValue().get(0)); - } - } - - public Node getPanel() { - return gridPane; - } -} diff --git a/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java b/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java index 72ec5c64266..29bc0716b59 100644 --- a/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java @@ -14,40 +14,40 @@ import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.LinkedFile; import org.jabref.model.util.OptionalUtil; -import org.jabref.preferences.PreferencesService; +import org.jabref.preferences.FilePreferences; public class CopySingleFileAction extends SimpleCommand { private final LinkedFile linkedFile; private final DialogService dialogService; private final BibDatabaseContext databaseContext; - private final PreferencesService preferencesService; + private final FilePreferences filePreferences; private final BiFunction resolvePathFilename = (path, file) -> path.resolve(file.getFileName()); - public CopySingleFileAction(LinkedFile linkedFile, DialogService dialogService, BibDatabaseContext databaseContext, PreferencesService preferencesService) { + public CopySingleFileAction(LinkedFile linkedFile, DialogService dialogService, BibDatabaseContext databaseContext, FilePreferences filePreferences) { this.linkedFile = linkedFile; this.dialogService = dialogService; this.databaseContext = databaseContext; - this.preferencesService = preferencesService; + this.filePreferences = filePreferences; this.executable.bind(Bindings.createBooleanBinding( () -> !linkedFile.isOnlineLink() - && linkedFile.findIn(databaseContext, preferencesService.getFilePreferences()).isPresent(), + && linkedFile.findIn(databaseContext, this.filePreferences).isPresent(), linkedFile.linkProperty())); } @Override public void execute() { DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder() - .withInitialDirectory(preferencesService.getWorkingDir()) + .withInitialDirectory(filePreferences.getWorkingDirectory()) .build(); Optional exportPath = dialogService.showDirectorySelectionDialog(dirDialogConfiguration); exportPath.ifPresent(this::copyFileToDestination); } private void copyFileToDestination(Path exportPath) { - Optional fileToExport = linkedFile.findIn(databaseContext, preferencesService.getFilePreferences()); + Optional fileToExport = linkedFile.findIn(databaseContext, filePreferences); Optional newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename); if (newPath.isPresent()) { diff --git a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java index 7673eb62d2b..fbfbb5c37e3 100644 --- a/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java +++ b/src/main/java/org/jabref/gui/entryeditor/LatexCitationsTabViewModel.java @@ -60,14 +60,16 @@ enum Status { private LatexParserResult latexParserResult; private BibEntry currentEntry; - public LatexCitationsTabViewModel(BibDatabaseContext databaseContext, PreferencesService preferencesService, - TaskExecutor taskExecutor, DialogService dialogService) { + public LatexCitationsTabViewModel(BibDatabaseContext databaseContext, + PreferencesService preferencesService, + TaskExecutor taskExecutor, + DialogService dialogService) { this.databaseContext = databaseContext; this.preferencesService = preferencesService; this.taskExecutor = taskExecutor; this.dialogService = dialogService; - this.directory = new SimpleObjectProperty(databaseContext.getMetaData().getLatexFileDirectory(preferencesService.getUser()) - .orElse(FileUtil.getInitialDirectory(databaseContext, preferencesService))); + this.directory = new SimpleObjectProperty<>(databaseContext.getMetaData().getLatexFileDirectory(preferencesService.getFilePreferences().getUser()) + .orElse(FileUtil.getInitialDirectory(databaseContext, preferencesService.getFilePreferences().getWorkingDirectory()))); this.citationList = FXCollections.observableArrayList(); this.status = new SimpleObjectProperty<>(Status.IN_PROGRESS); this.searchError = new SimpleStringProperty(""); @@ -128,8 +130,8 @@ private void cancelSearch() { private Collection searchAndParse(String citeKey) throws IOException { // we need to check whether the user meanwhile set the LaTeX file directory or the database changed locations - Path newDirectory = databaseContext.getMetaData().getLatexFileDirectory(preferencesService.getUser()) - .orElse(FileUtil.getInitialDirectory(databaseContext, preferencesService)); + Path newDirectory = databaseContext.getMetaData().getLatexFileDirectory(preferencesService.getFilePreferences().getUser()) + .orElse(FileUtil.getInitialDirectory(databaseContext, preferencesService.getFilePreferences().getWorkingDirectory())); if (latexParserResult == null || !newDirectory.equals(directory.get())) { directory.set(newDirectory); @@ -170,7 +172,7 @@ public void setLatexDirectory() { .withInitialDirectory(directory.get()).build(); dialogService.showDirectorySelectionDialog(directoryDialogConfiguration).ifPresent(selectedDirectory -> - databaseContext.getMetaData().setLatexFileDirectory(preferencesService.getUser(), selectedDirectory.toAbsolutePath())); + databaseContext.getMetaData().setLatexFileDirectory(preferencesService.getFilePreferences().getUser(), selectedDirectory.toAbsolutePath())); init(currentEntry); } diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 9757b885615..c6bdf64e531 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -160,10 +160,10 @@ private Optional askForSavePath() { FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .addExtensionFilter(StandardFileType.BIBTEX_DB) .withDefaultExtension(StandardFileType.BIBTEX_DB) - .withInitialDirectory(preferences.getWorkingDir()) + .withInitialDirectory(preferences.getFilePreferences().getWorkingDirectory()) .build(); Optional selectedPath = dialogService.showFileSaveDialog(fileDialogConfiguration); - selectedPath.ifPresent(path -> preferences.setWorkingDirectory(path.getParent())); + selectedPath.ifPresent(path -> preferences.getFilePreferences().setWorkingDirectory(path.getParent())); if (selectedPath.isPresent()) { Path savePath = selectedPath.get(); // Workaround for linux systems not adding file extension @@ -214,6 +214,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { libraryTab.getUndoManager().markUnchanged(); libraryTab.resetChangedProperties(); } + dialogService.notify(Localization.lang("Library saved")); return success; } catch (SaveException ex) { LOGGER.error(String.format("A problem occurred when trying to save the file %s", targetPath), ex); diff --git a/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java b/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java index 69c62af874a..c516be37f86 100644 --- a/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java +++ b/src/main/java/org/jabref/gui/externalfiles/UnlinkedFilesDialogViewModel.java @@ -80,8 +80,13 @@ public class UnlinkedFilesDialogViewModel { private final FunctionBasedValidator scanDirectoryValidator; - public UnlinkedFilesDialogViewModel(DialogService dialogService, ExternalFileTypes externalFileTypes, UndoManager undoManager, - FileUpdateMonitor fileUpdateMonitor, PreferencesService preferences, StateManager stateManager, TaskExecutor taskExecutor) { + public UnlinkedFilesDialogViewModel(DialogService dialogService, + ExternalFileTypes externalFileTypes, + UndoManager undoManager, + FileUpdateMonitor fileUpdateMonitor, + PreferencesService preferences, + StateManager stateManager, + TaskExecutor taskExecutor) { this.preferences = preferences; this.dialogService = dialogService; this.taskExecutor = taskExecutor; @@ -95,9 +100,9 @@ public UnlinkedFilesDialogViewModel(DialogService dialogService, ExternalFileTyp stateManager); this.fileFilterList = FXCollections.observableArrayList( - new FileExtensionViewModel(StandardFileType.ANY_FILE, externalFileTypes), - new FileExtensionViewModel(StandardFileType.BIBTEX_DB, externalFileTypes), - new FileExtensionViewModel(StandardFileType.PDF, externalFileTypes)); + new FileExtensionViewModel(StandardFileType.ANY_FILE, externalFileTypes), + new FileExtensionViewModel(StandardFileType.BIBTEX_DB, externalFileTypes), + new FileExtensionViewModel(StandardFileType.PDF, externalFileTypes)); this.dateFilterList = FXCollections.observableArrayList(DateRange.values()); @@ -175,7 +180,7 @@ public void startExport() { } FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() - .withInitialDirectory(preferences.getWorkingDir()) + .withInitialDirectory(preferences.getFilePreferences().getWorkingDirectory()) .addExtensionFilter(StandardFileType.TXT) .withDefaultExtension(StandardFileType.TXT) .build(); @@ -218,12 +223,12 @@ public void cancelTasks() { public void browseFileDirectory() { DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() - .withInitialDirectory(preferences.getWorkingDir()).build(); + .withInitialDirectory(preferences.getFilePreferences().getWorkingDirectory()).build(); dialogService.showDirectorySelectionDialog(directoryDialogConfiguration) .ifPresent(selectedDirectory -> { directoryPath.setValue(selectedDirectory.toAbsolutePath().toString()); - preferences.setWorkingDirectory(selectedDirectory.toAbsolutePath()); + preferences.getFilePreferences().setWorkingDirectory(selectedDirectory.toAbsolutePath()); }); } diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 6d3d3ac2988..50f27f6bb5e 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -61,6 +61,7 @@ import org.jabref.model.strings.StringUtil; import org.jabref.model.util.FileHelper; import org.jabref.model.util.OptionalUtil; +import org.jabref.preferences.FilePreferences; import org.jabref.preferences.PreferencesService; import de.saxsys.mvvmfx.utils.validation.FunctionBasedValidator; @@ -332,9 +333,26 @@ public boolean isGeneratedNameSameAsOriginal() { * @return true if suggested filepath is same as existing filepath. */ public boolean isGeneratedPathSameAsOriginal() { - Optional newDir = databaseContext.getFirstExistingFileDir(preferences.getFilePreferences()); + FilePreferences filePreferences = preferences.getFilePreferences(); + Optional baseDir = databaseContext.getFirstExistingFileDir(filePreferences); + if (baseDir.isEmpty()) { + // could not find default path + return false; + } + + // append File directory pattern if exits + String targetDirectoryName = FileUtil.createDirNameFromPattern( + databaseContext.getDatabase(), + entry, + filePreferences.getFileDirectoryPattern()); + + Optional targetDir = baseDir.map(dir -> dir.resolve(targetDirectoryName)); Optional currentDir = linkedFile.findIn(databaseContext, preferences.getFilePreferences()).map(Path::getParent); + if (currentDir.isEmpty()) { + // Could not find file + return false; + } BiPredicate equality = (fileA, fileB) -> { try { @@ -343,7 +361,7 @@ public boolean isGeneratedPathSameAsOriginal() { return false; } }; - return OptionalUtil.equals(newDir, currentDir, equality); + return OptionalUtil.equals(targetDir, currentDir, equality); } public void moveToDefaultDirectoryAndRename() { diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java index a13eeb6a310..ab8bac582aa 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java @@ -275,7 +275,7 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) { factory.createMenuItem(StandardActions.RENAME_FILE_TO_NAME, new ContextAction(StandardActions.RENAME_FILE_TO_NAME, linkedFile, preferencesService)), factory.createMenuItem(StandardActions.MOVE_FILE_TO_FOLDER, new ContextAction(StandardActions.MOVE_FILE_TO_FOLDER, linkedFile, preferencesService)), factory.createMenuItem(StandardActions.MOVE_FILE_TO_FOLDER_AND_RENAME, new ContextAction(StandardActions.MOVE_FILE_TO_FOLDER_AND_RENAME, linkedFile, preferencesService)), - factory.createMenuItem(StandardActions.COPY_FILE_TO_FOLDER, new CopySingleFileAction(linkedFile.getFile(), dialogService, databaseContext, preferencesService)), + factory.createMenuItem(StandardActions.COPY_FILE_TO_FOLDER, new CopySingleFileAction(linkedFile.getFile(), dialogService, databaseContext, preferencesService.getFilePreferences())), factory.createMenuItem(StandardActions.REMOVE_LINK, new ContextAction(StandardActions.REMOVE_LINK, linkedFile, preferencesService)), factory.createMenuItem(StandardActions.DELETE_FILE, new ContextAction(StandardActions.DELETE_FILE, linkedFile, preferencesService)) ); @@ -294,12 +294,12 @@ public ContextAction(StandardActions command, LinkedFileViewModel linkedFile, Pr this.executable.bind( switch (command) { - case RENAME_FILE_TO_PATTERN, MOVE_FILE_TO_FOLDER_AND_RENAME -> Bindings.createBooleanBinding( + case RENAME_FILE_TO_PATTERN -> Bindings.createBooleanBinding( () -> !linkedFile.getFile().isOnlineLink() && linkedFile.getFile().findIn(databaseContext, preferencesService.getFilePreferences()).isPresent() && !linkedFile.isGeneratedNameSameAsOriginal(), linkedFile.getFile().linkProperty(), bibEntry.getValue().map(BibEntry::getFieldsObservable).orElse(null)); - case MOVE_FILE_TO_FOLDER -> Bindings.createBooleanBinding( + case MOVE_FILE_TO_FOLDER, MOVE_FILE_TO_FOLDER_AND_RENAME -> Bindings.createBooleanBinding( () -> !linkedFile.getFile().isOnlineLink() && linkedFile.getFile().findIn(databaseContext, preferencesService.getFilePreferences()).isPresent() && !linkedFile.isGeneratedPathSameAsOriginal(), diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java index e3f542e4a95..f9c7f1e67e5 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java @@ -137,7 +137,7 @@ public ListProperty filesProperty() { public void addNewFile() { Path workingDirectory = databaseContext.getFirstExistingFileDir(preferences.getFilePreferences()) - .orElse(preferences.getWorkingDir()); + .orElse(preferences.getFilePreferences().getWorkingDirectory()); FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .withInitialDirectory(workingDirectory) diff --git a/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java b/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java index 7714fcdcfa0..522d129bb08 100644 --- a/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupDialogViewModel.java @@ -83,7 +83,7 @@ public class GroupDialogViewModel { private final BooleanProperty keywordGroupRegexProperty = new SimpleBooleanProperty(); private final StringProperty searchGroupSearchTermProperty = new SimpleStringProperty(""); - private final ObjectProperty> searchFlagsProperty = new SimpleObjectProperty(EnumSet.noneOf(SearchFlags.class)); + private final ObjectProperty> searchFlagsProperty = new SimpleObjectProperty<>(EnumSet.noneOf(SearchFlags.class)); private final BooleanProperty autoGroupKeywordsOptionProperty = new SimpleBooleanProperty(); private final StringProperty autoGroupKeywordsFieldProperty = new SimpleStringProperty(""); @@ -236,7 +236,7 @@ private void setupValidation() { return false; } return FileUtil.getFileExtension(input) - .map(extension -> extension.toLowerCase().equals("aux")) + .map(extension -> extension.equalsIgnoreCase("aux")) .orElse(false); } }, @@ -273,7 +273,7 @@ private void setupValidation() { * @return an absolute path if LatexFileDirectory exists; otherwise, returns input */ private Path getAbsoluteTexGroupPath(String input) { - Optional latexFileDirectory = currentDatabase.getMetaData().getLatexFileDirectory(preferencesService.getUser()); + Optional latexFileDirectory = currentDatabase.getMetaData().getLatexFileDirectory(preferencesService.getFilePreferences().getUser()); return latexFileDirectory.map(path -> path.resolve(input)).orElse(Path.of(input)); } @@ -436,8 +436,8 @@ public void texGroupBrowse() { .addExtensionFilter(StandardFileType.AUX) .withDefaultExtension(StandardFileType.AUX) .withInitialDirectory(currentDatabase.getMetaData() - .getLatexFileDirectory(preferencesService.getUser()) - .orElse(FileUtil.getInitialDirectory(currentDatabase, preferencesService))).build(); + .getLatexFileDirectory(preferencesService.getFilePreferences().getUser()) + .orElse(FileUtil.getInitialDirectory(currentDatabase, preferencesService.getFilePreferences().getWorkingDirectory()))).build(); dialogService.showFileOpenDialog(fileDialogConfiguration) .ifPresent(file -> texGroupFilePathProperty.setValue( FileUtil.relativize(file.toAbsolutePath(), getFileDirectoriesAsPaths()).toString() diff --git a/src/main/java/org/jabref/gui/help/NewVersionDialog.java b/src/main/java/org/jabref/gui/help/NewVersionDialog.java index 5c61943d2aa..2ab73b250a5 100644 --- a/src/main/java/org/jabref/gui/help/NewVersionDialog.java +++ b/src/main/java/org/jabref/gui/help/NewVersionDialog.java @@ -7,14 +7,12 @@ import javafx.scene.control.Label; import javafx.scene.layout.VBox; -import org.jabref.gui.Globals; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.util.BaseDialog; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.Version; -import org.jabref.preferences.VersionPreferences; -public class NewVersionDialog extends BaseDialog { +public class NewVersionDialog extends BaseDialog { public NewVersionDialog(Version currentVersion, Version latestVersion) { this.setTitle(Localization.lang("New version available")); @@ -25,11 +23,11 @@ public NewVersionDialog(Version currentVersion, Version latestVersion) { this.getDialogPane().getButtonTypes().addAll(btnIgnoreUpdate, btnDownloadUpdate, btnRemindMeLater); this.setResultConverter(button -> { if (button == btnIgnoreUpdate) { - Globals.prefs.storeVersionPreferences(new VersionPreferences(latestVersion)); + return false; } else if (button == btnDownloadUpdate) { JabRefDesktop.openBrowserShowPopup(Version.JABREF_DOWNLOAD_URL); } - return null; + return true; }); Button defaultButton = (Button) this.getDialogPane().lookupButton(btnDownloadUpdate); defaultButton.setDefaultButton(true); diff --git a/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java b/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java index 5e39a0e6d7c..ddf013c2ded 100644 --- a/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java +++ b/src/main/java/org/jabref/gui/help/SearchForUpdateAction.java @@ -22,7 +22,7 @@ public SearchForUpdateAction(BuildInfo buildInfo, VersionPreferences versionPref @Override public void execute() { - new VersionWorker(buildInfo.version, versionPreferences.getIgnoredVersion(), dialogService, taskExecutor) + new VersionWorker(buildInfo.version, dialogService, taskExecutor, versionPreferences) .checkForNewVersionAsync(); } } diff --git a/src/main/java/org/jabref/gui/help/VersionWorker.java b/src/main/java/org/jabref/gui/help/VersionWorker.java index 139565c9df8..e22ed8aa583 100644 --- a/src/main/java/org/jabref/gui/help/VersionWorker.java +++ b/src/main/java/org/jabref/gui/help/VersionWorker.java @@ -11,6 +11,7 @@ import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.Version; +import org.jabref.preferences.VersionPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,19 +33,19 @@ public class VersionWorker { */ private final Version installedVersion; - /** - * The version which was previously ignored by the user - */ - private final Version toBeIgnored; - private final DialogService dialogService; private final TaskExecutor taskExecutor; + private final VersionPreferences versionPreferences; - public VersionWorker(Version installedVersion, Version toBeIgnored, DialogService dialogService, TaskExecutor taskExecutor) { + public VersionWorker(Version installedVersion, + + DialogService dialogService, + TaskExecutor taskExecutor, + VersionPreferences versionPreferences) { this.installedVersion = Objects.requireNonNull(installedVersion); - this.toBeIgnored = Objects.requireNonNull(toBeIgnored); this.dialogService = Objects.requireNonNull(dialogService); this.taskExecutor = Objects.requireNonNull(taskExecutor); + this.versionPreferences = versionPreferences; } /** @@ -88,13 +89,15 @@ private void showConnectionError(Exception exception, boolean manualExecution) { */ private void showUpdateInfo(Optional newerVersion, boolean manualExecution) { // no new version could be found, only respect the ignored version on automated version checks - if (!newerVersion.isPresent() || (newerVersion.get().equals(toBeIgnored) && !manualExecution)) { + if (newerVersion.isEmpty() || (newerVersion.get().equals(versionPreferences.getIgnoredVersion()) && !manualExecution)) { if (manualExecution) { dialogService.notify(Localization.lang("JabRef is up-to-date.")); } } else { // notify the user about a newer version - dialogService.showCustomDialogAndWait(new NewVersionDialog(installedVersion, newerVersion.get())); + if (dialogService.showCustomDialogAndWait(new NewVersionDialog(installedVersion, newerVersion.get())).orElse(true)) { + versionPreferences.setIgnoredVersion(newerVersion.get()); + } } } } 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 bd1bbee5af4..39b22f76f55 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -94,10 +94,10 @@ public void execute() { */ private Path getInitialDirectory() { if (frame.getBasePanelCount() == 0) { - return preferencesService.getWorkingDir(); + return preferencesService.getFilePreferences().getWorkingDirectory(); } else { Optional databasePath = frame.getCurrentLibraryTab().getBibDatabaseContext().getDatabasePath(); - return databasePath.map(Path::getParent).orElse(preferencesService.getWorkingDir()); + return databasePath.map(Path::getParent).orElse(preferencesService.getFilePreferences().getWorkingDirectory()); } } @@ -181,7 +181,7 @@ private ParserResult loadDatabase(Path file) throws Exception { dialogService.notify(Localization.lang("Opening") + ": '" + file + "'"); - preferencesService.setWorkingDirectory(fileToLoad.getParent()); + preferencesService.getFilePreferences().setWorkingDirectory(fileToLoad.getParent()); if (BackupManager.backupFileDiffers(fileToLoad)) { BackupUIManager.showRestoreBackupDialog(dialogService, fileToLoad); diff --git a/src/main/java/org/jabref/gui/libraryproperties/AbstractPropertiesTabView.java b/src/main/java/org/jabref/gui/libraryproperties/AbstractPropertiesTabView.java new file mode 100644 index 00000000000..b69dd997a4b --- /dev/null +++ b/src/main/java/org/jabref/gui/libraryproperties/AbstractPropertiesTabView.java @@ -0,0 +1,37 @@ +package org.jabref.gui.libraryproperties; + +import javax.inject.Inject; + +import javafx.scene.Node; +import javafx.scene.layout.VBox; + +import org.jabref.gui.DialogService; +import org.jabref.model.database.BibDatabaseContext; + +public abstract class AbstractPropertiesTabView extends VBox implements PropertiesTab { + + @Inject protected DialogService dialogService; + + protected BibDatabaseContext databaseContext; + protected T viewModel; + + @Override + public Node getBuilder() { + return this; + } + + @Override + public void setValues() { + viewModel.setValues(); + } + + @Override + public void storeSettings() { + viewModel.storeSettings(); + } + + @Override + public boolean validateSettings() { + return viewModel.validateSettings(); + } +} diff --git a/src/main/java/org/jabref/gui/libraryproperties/LibraryProperties.fxml b/src/main/java/org/jabref/gui/libraryproperties/LibraryProperties.fxml new file mode 100644 index 00000000000..b3eaec62c19 --- /dev/null +++ b/src/main/java/org/jabref/gui/libraryproperties/LibraryProperties.fxml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java index 6846c779831..6cd8d27213c 100644 --- a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java +++ b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesAction.java @@ -1,26 +1,44 @@ package org.jabref.gui.libraryproperties; import org.jabref.gui.DialogService; -import org.jabref.gui.JabRefFrame; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; +import org.jabref.model.database.BibDatabaseContext; import com.airhacks.afterburner.injection.Injector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static org.jabref.gui.actions.ActionHelper.needsDatabase; public class LibraryPropertiesAction extends SimpleCommand { + private static final Logger LOGGER = LoggerFactory.getLogger(LibraryPropertiesAction.class); - private final JabRefFrame frame; + private final StateManager stateManager; + private final BibDatabaseContext alternateDatabase; - public LibraryPropertiesAction(JabRefFrame frame, StateManager stateManager) { - this.frame = frame; + public LibraryPropertiesAction(StateManager stateManager) { + this(null, stateManager); this.executable.bind(needsDatabase(stateManager)); } + public LibraryPropertiesAction(BibDatabaseContext databaseContext, StateManager stateManager) { + this.stateManager = stateManager; + this.alternateDatabase = databaseContext; + } + @Override public void execute() { DialogService dialogService = Injector.instantiateModelOrService(DialogService.class); - dialogService.showCustomDialogAndWait(new LibraryPropertiesDialogView(frame.getCurrentLibraryTab())); + + if (alternateDatabase != null) { + dialogService.showCustomDialogAndWait(new LibraryPropertiesView(alternateDatabase)); + } else { + if (stateManager.getActiveDatabase().isPresent()) { + dialogService.showCustomDialogAndWait(new LibraryPropertiesView(stateManager.getActiveDatabase().get())); + } else { + LOGGER.warn("No database selected."); + } + } } } diff --git a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml b/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml deleted file mode 100644 index a21e814b1e2..00000000000 --- a/src/main/java/org/jabref/gui/libraryproperties/LibraryPropertiesDialog.fxml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -