diff --git a/src/jmh/java/org/jabref/benchmarks/Benchmarks.java b/src/jmh/java/org/jabref/benchmarks/Benchmarks.java
index e553c87ceec2..291f7420d554 100644
--- a/src/jmh/java/org/jabref/benchmarks/Benchmarks.java
+++ b/src/jmh/java/org/jabref/benchmarks/Benchmarks.java
@@ -1,10 +1,8 @@
package org.jabref.benchmarks;
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.Random;
+import static org.mockito.Mockito.mock;
+
+import com.airhacks.afterburner.injection.Injector;
import org.jabref.logic.bibtex.FieldPreferences;
import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences;
@@ -31,8 +29,6 @@
import org.jabref.model.groups.KeywordGroup;
import org.jabref.model.groups.WordKeywordGroup;
import org.jabref.model.metadata.MetaData;
-
-import com.airhacks.afterburner.injection.Injector;
import org.openjdk.jmh.Main;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
@@ -40,7 +36,11 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.RunnerException;
-import static org.mockito.Mockito.mock;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Random;
@State(Scope.Thread)
public class Benchmarks {
@@ -59,7 +59,9 @@ public void init() throws Exception {
BibEntry entry = new BibEntry();
entry.setCitationKey("id" + i);
entry.setField(StandardField.TITLE, "This is my title " + i);
- entry.setField(StandardField.AUTHOR, "Firstname Lastname and FirstnameA LastnameA and FirstnameB LastnameB" + i);
+ entry.setField(
+ StandardField.AUTHOR,
+ "Firstname Lastname and FirstnameA LastnameA and FirstnameB LastnameB" + i);
entry.setField(StandardField.JOURNAL, "Journal Title " + i);
entry.setField(StandardField.KEYWORDS, "testkeyword");
entry.setField(StandardField.YEAR, "1" + i);
@@ -69,21 +71,25 @@ public void init() throws Exception {
bibtexString = getOutputWriter().toString();
- latexConversionString = "{A} \\textbf{bold} approach {\\it to} ${{\\Sigma}}{\\Delta}$ modulator \\textsuperscript{2} \\$";
+ latexConversionString =
+ "{A} \\textbf{bold} approach {\\it to} ${{\\Sigma}}{\\Delta}$ modulator \\textsuperscript{2} \\$";
- htmlConversionString = "Österreich – & characters ⪢ italic";
+ htmlConversionString =
+ "Österreich – & characters ⪢ italic";
}
private StringWriter getOutputWriter() throws IOException {
StringWriter outputWriter = new StringWriter();
BibWriter bibWriter = new BibWriter(outputWriter, OS.NEWLINE);
- BibtexDatabaseWriter databaseWriter = new BibtexDatabaseWriter(
- bibWriter,
- mock(SelfContainedSaveConfiguration.class),
- mock(FieldPreferences.class),
- mock(CitationKeyPatternPreferences.class),
- new BibEntryTypesManager());
- databaseWriter.savePartOfDatabase(new BibDatabaseContext(database, new MetaData()), database.getEntries());
+ BibtexDatabaseWriter databaseWriter =
+ new BibtexDatabaseWriter(
+ bibWriter,
+ mock(SelfContainedSaveConfiguration.class),
+ mock(FieldPreferences.class),
+ mock(CitationKeyPatternPreferences.class),
+ new BibEntryTypesManager());
+ databaseWriter.savePartOfDatabase(
+ new BibDatabaseContext(database, new MetaData()), database.getEntries());
return outputWriter;
}
@@ -136,7 +142,15 @@ public String htmlToLatexConversion() {
@Benchmark
public boolean keywordGroupContains() {
- KeywordGroup group = new WordKeywordGroup("testGroup", GroupHierarchyType.INDEPENDENT, StandardField.KEYWORDS, "testkeyword", false, ',', false);
+ KeywordGroup group =
+ new WordKeywordGroup(
+ "testGroup",
+ GroupHierarchyType.INDEPENDENT,
+ StandardField.KEYWORDS,
+ "testkeyword",
+ false,
+ ',',
+ false);
return group.containsAll(database.getEntries());
}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 852af1ba3961..6cd6e00dc8d6 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -12,35 +12,34 @@
requires javafx.controls;
requires javafx.web;
requires javafx.fxml;
-
requires afterburner.fx;
- provides com.airhacks.afterburner.views.ResourceLocator
- with org.jabref.gui.util.JabRefResourceLocator;
+
+ provides com.airhacks.afterburner.views.ResourceLocator with
+ org.jabref.gui.util.JabRefResourceLocator;
requires com.dlsc.gemsfx;
+
uses com.dlsc.gemsfx.TagsField;
+
// Provides number input fields for parameters in AI expert settings
requires com.dlsc.unitfx;
-
requires com.tobiasdiez.easybind;
-
requires de.saxsys.mvvmfx;
requires de.saxsys.mvvmfx.validation;
-
requires org.controlsfx.controls;
requires org.fxmisc.flowless;
requires org.fxmisc.richtext;
-
requires org.kordamp.ikonli.core;
requires org.kordamp.ikonli.javafx;
requires org.kordamp.ikonli.materialdesign2;
+
uses org.kordamp.ikonli.IkonHandler;
uses org.kordamp.ikonli.IkonProvider;
- provides org.kordamp.ikonli.IkonHandler
- with org.jabref.gui.icon.JabRefIkonHandler;
- provides org.kordamp.ikonli.IkonProvider
- with org.jabref.gui.icon.JabrefIconProvider;
+ provides org.kordamp.ikonli.IkonHandler with
+ org.jabref.gui.icon.JabRefIkonHandler;
+ provides org.kordamp.ikonli.IkonProvider with
+ org.jabref.gui.icon.JabrefIconProvider;
requires reactfx;
// endregion
@@ -52,10 +51,11 @@
requires org.tinylog.api;
requires org.tinylog.api.slf4j;
requires org.tinylog.impl;
+
// endregion
- provides org.tinylog.writers.Writer
- with org.jabref.gui.logging.GuiWriter;
+ provides org.tinylog.writers.Writer with
+ org.jabref.gui.logging.GuiWriter;
// Preferences and XML
requires java.prefs;
@@ -100,7 +100,9 @@
requires ojdbc10;
requires org.postgresql.jdbc;
requires org.mariadb.jdbc;
+
uses org.mariadb.jdbc.credential.CredentialPlugin;
+
// endregion
// region: Apache Commons and other (similar) helper libraries
@@ -123,23 +125,17 @@
requires jbibtex;
requires citeproc.java;
-
requires snuggletex.core;
-
requires org.apache.pdfbox;
requires org.apache.xmpbox;
requires com.ibm.icu;
-
requires flexmark;
requires flexmark.html2md.converter;
requires flexmark.util.ast;
requires flexmark.util.data;
-
requires com.h2database.mvstore;
-
requires java.keyring;
requires org.freedesktop.dbus;
-
requires org.jooq.jool;
// region AI
@@ -153,6 +149,7 @@
requires langchain4j.hugging.face;
requires langchain4j.mistral.ai;
requires langchain4j.open.ai;
+
uses ai.djl.engine.EngineProvider;
uses ai.djl.repository.RepositoryFactory;
uses ai.djl.repository.zoo.ZooProvider;
@@ -164,6 +161,7 @@
* In case the version is updated, please also increment {@link org.jabref.model.search.SearchFieldConstants#VERSION} to trigger reindexing.
*/
uses org.apache.lucene.codecs.lucene99.Lucene99Codec;
+
requires org.apache.lucene.analysis.common;
requires org.apache.lucene.core;
requires org.apache.lucene.highlighter;
@@ -173,8 +171,8 @@
requires net.harawata.appdirs;
requires com.sun.jna;
requires com.sun.jna.platform;
-
requires org.eclipse.jgit;
+
uses org.eclipse.jgit.transport.SshSessionFactory;
uses org.eclipse.jgit.lib.Signer;
@@ -189,5 +187,5 @@
requires mslinks;
requires org.antlr.antlr4.runtime;
requires org.libreoffice.uno;
- // endregion
+// endregion
}
diff --git a/src/main/java/org/jabref/Launcher.java b/src/main/java/org/jabref/Launcher.java
index 947c2f3dd343..493f4c8758e2 100644
--- a/src/main/java/org/jabref/Launcher.java
+++ b/src/main/java/org/jabref/Launcher.java
@@ -1,16 +1,8 @@
package org.jabref;
-import java.io.File;
-import java.io.IOException;
-import java.net.Authenticator;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
+import com.airhacks.afterburner.injection.Injector;
+import org.apache.commons.cli.ParseException;
import org.jabref.cli.ArgumentProcessor;
import org.jabref.cli.JabRefCLI;
import org.jabref.gui.JabRefGUI;
@@ -37,14 +29,22 @@
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.util.DirectoryMonitor;
import org.jabref.model.util.FileUpdateMonitor;
-
-import com.airhacks.afterburner.injection.Injector;
-import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.tinylog.configuration.Configuration;
+import java.io.File;
+import java.io.IOException;
+import java.net.Authenticator;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
/**
* The main entry point for the JabRef application.
*
@@ -76,8 +76,13 @@ public static void main(String[] args) {
PreferencesMigrations.runMigrations(preferences, entryTypesManager);
- Injector.setModelOrService(JournalAbbreviationRepository.class, JournalAbbreviationLoader.loadRepository(preferences.getJournalAbbreviationPreferences()));
- Injector.setModelOrService(ProtectedTermsLoader.class, new ProtectedTermsLoader(preferences.getProtectedTermsPreferences()));
+ Injector.setModelOrService(
+ JournalAbbreviationRepository.class,
+ JournalAbbreviationLoader.loadRepository(
+ preferences.getJournalAbbreviationPreferences()));
+ Injector.setModelOrService(
+ ProtectedTermsLoader.class,
+ new ProtectedTermsLoader(preferences.getProtectedTermsPreferences()));
configureProxy(preferences.getProxyPreferences());
configureSSL(preferences.getSSLPreferences());
@@ -87,19 +92,21 @@ public static void main(String[] args) {
try {
DefaultFileUpdateMonitor fileUpdateMonitor = new DefaultFileUpdateMonitor();
Injector.setModelOrService(FileUpdateMonitor.class, fileUpdateMonitor);
- HeadlessExecutorService.INSTANCE.executeInterruptableTask(fileUpdateMonitor, "FileUpdateMonitor");
+ HeadlessExecutorService.INSTANCE.executeInterruptableTask(
+ fileUpdateMonitor, "FileUpdateMonitor");
DirectoryMonitor directoryMonitor = new DefaultDirectoryMonitor();
Injector.setModelOrService(DirectoryMonitor.class, directoryMonitor);
// Process arguments
- ArgumentProcessor argumentProcessor = new ArgumentProcessor(
- args,
- ArgumentProcessor.Mode.INITIAL_START,
- preferences,
- preferences,
- fileUpdateMonitor,
- entryTypesManager);
+ ArgumentProcessor argumentProcessor =
+ new ArgumentProcessor(
+ args,
+ ArgumentProcessor.Mode.INITIAL_START,
+ preferences,
+ preferences,
+ fileUpdateMonitor,
+ entryTypesManager);
argumentProcessor.processArguments();
if (argumentProcessor.shouldShutDown()) {
LOGGER.debug("JabRef shut down after processing command line arguments");
@@ -151,15 +158,18 @@ private static void initLogging(String[] args) {
// The "Shared File Writer" is explained at
// https://tinylog.org/v2/configuration/#shared-file-writer
- Map configuration = Map.of(
- "level", isDebugEnabled ? "debug" : "info",
- "writerFile", "rolling file",
- "writerFile.level", isDebugEnabled ? "debug" : "info",
- // We need to manually join the path, because ".resolve" does not work on Windows, because ":" is not allowed in file names on Windows
- "writerFile.file", directory + File.separator + "log_{date:yyyy-MM-dd_HH-mm-ss}.txt",
- "writerFile.charset", "UTF-8",
- "writerFile.policies", "startup",
- "writerFile.backups", "30");
+ Map configuration =
+ Map.of(
+ "level", isDebugEnabled ? "debug" : "info",
+ "writerFile", "rolling file",
+ "writerFile.level", isDebugEnabled ? "debug" : "info",
+ // We need to manually join the path, because ".resolve" does not work on
+ // Windows, because ":" is not allowed in file names on Windows
+ "writerFile.file",
+ directory + File.separator + "log_{date:yyyy-MM-dd_HH-mm-ss}.txt",
+ "writerFile.charset", "UTF-8",
+ "writerFile.policies", "startup",
+ "writerFile.backups", "30");
configuration.forEach(Configuration::set);
LOGGER = LoggerFactory.getLogger(Launcher.class);
@@ -168,7 +178,8 @@ private static void initLogging(String[] args) {
/**
* @return true if JabRef should continue starting up, false if it should quit.
*/
- private static boolean handleMultipleAppInstances(String[] args, RemotePreferences remotePreferences) throws InterruptedException {
+ private static boolean handleMultipleAppInstances(
+ String[] args, RemotePreferences remotePreferences) throws InterruptedException {
LOGGER.trace("Checking for remote handling...");
if (remotePreferences.useRemoteServer()) {
// Try to contact already running JabRef
@@ -176,15 +187,20 @@ private static boolean handleMultipleAppInstances(String[] args, RemotePreferenc
if (remoteClient.ping()) {
LOGGER.debug("Pinging other instance succeeded.");
if (args.length == 0) {
- // There is already a server out there, avoid showing log "Passing arguments" while no arguments are provided.
- LOGGER.warn("This JabRef instance is already running. Please switch to that instance.");
+ // There is already a server out there, avoid showing log "Passing arguments"
+ // while no arguments are provided.
+ LOGGER.warn(
+ "This JabRef instance is already running. Please switch to that instance.");
} else {
- // We are not alone, there is already a server out there, send command line arguments to other instance
+ // We are not alone, there is already a server out there, send command line
+ // arguments to other instance
LOGGER.debug("Passing arguments passed on to running JabRef...");
if (remoteClient.sendCommandLineArguments(args)) {
// So we assume it's all taken care of, and quit.
- // Output to both to the log and the screen. Therefore, we do not have an additional System.out.println.
- LOGGER.info("Arguments passed on to running JabRef instance. Shutting down.");
+ // Output to both to the log and the screen. Therefore, we do not have an
+ // additional System.out.println.
+ LOGGER.info(
+ "Arguments passed on to running JabRef instance. Shutting down.");
} else {
LOGGER.warn("Could not communicate with other running JabRef instance.");
}
@@ -206,7 +222,8 @@ private static void configureProxy(ProxyPreferences proxyPreferences) {
}
private static void configureSSL(SSLPreferences sslPreferences) {
- TrustStoreManager.createTruststoreFileIfNotExist(Path.of(sslPreferences.getTruststorePath()));
+ TrustStoreManager.createTruststoreFileIfNotExist(
+ Path.of(sslPreferences.getTruststorePath()));
}
private static void clearOldSearchIndices() {
@@ -221,7 +238,9 @@ private static void clearOldSearchIndices() {
try (DirectoryStream stream = Files.newDirectoryStream(appData)) {
for (Path path : stream) {
- if (Files.isDirectory(path) && !path.toString().endsWith("ssl") && path.toString().contains("lucene")
+ if (Files.isDirectory(path)
+ && !path.toString().endsWith("ssl")
+ && path.toString().contains("lucene")
&& !path.equals(currentIndexPath)) {
LOGGER.info("Deleting out-of-date fulltext search index at {}.", path);
Files.walk(path)
diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java
index 64edddac7a4f..26624075e34c 100644
--- a/src/main/java/org/jabref/cli/ArgumentProcessor.java
+++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java
@@ -1,17 +1,7 @@
package org.jabref.cli;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Optional;
-import java.util.Set;
-import java.util.prefs.BackingStoreException;
+import com.airhacks.afterburner.injection.Injector;
+import com.google.common.base.Throwables;
import org.jabref.gui.externalfiles.AutoSetFileLinksUtil;
import org.jabref.gui.preferences.GuiPreferences;
@@ -59,16 +49,29 @@
import org.jabref.model.strings.StringUtil;
import org.jabref.model.util.DummyFileUpdateMonitor;
import org.jabref.model.util.FileUpdateMonitor;
-
-import com.airhacks.afterburner.injection.Injector;
-import com.google.common.base.Throwables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.Set;
+import java.util.prefs.BackingStoreException;
+
public class ArgumentProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(ArgumentProcessor.class);
- public enum Mode { INITIAL_START, REMOTE_START }
+ public enum Mode {
+ INITIAL_START,
+ REMOTE_START
+ }
private final JabRefCLI cli;
@@ -88,12 +91,13 @@ public enum Mode { INITIAL_START, REMOTE_START }
*
* @implNote both cli and gui preferences are passed to make the dependency to GUI parts explicit
*/
- public ArgumentProcessor(String[] args,
- Mode startupMode,
- CliPreferences cliPreferences,
- GuiPreferences guiPreferences,
- FileUpdateMonitor fileUpdateMonitor,
- BibEntryTypesManager entryTypesManager)
+ public ArgumentProcessor(
+ String[] args,
+ Mode startupMode,
+ CliPreferences cliPreferences,
+ GuiPreferences guiPreferences,
+ FileUpdateMonitor fileUpdateMonitor,
+ BibEntryTypesManager entryTypesManager)
throws org.apache.commons.cli.ParseException {
this.cli = new JabRefCLI(args);
this.startupMode = startupMode;
@@ -114,7 +118,8 @@ private Optional importToOpenBase(String importArguments) {
return result;
}
- private Optional importBibtexToOpenBase(String argument, ImportFormatPreferences importFormatPreferences) {
+ private Optional importBibtexToOpenBase(
+ String argument, ImportFormatPreferences importFormatPreferences) {
BibtexParser parser = new BibtexParser(importFormatPreferences);
try {
List entries = parser.parseEntries(argument);
@@ -122,7 +127,10 @@ private Optional importBibtexToOpenBase(String argument, ImportFor
result.setToOpenTab();
return Optional.of(result);
} catch (ParseException e) {
- System.err.println(Localization.lang("Error occurred when parsing entry") + ": " + e.getLocalizedMessage());
+ System.err.println(
+ Localization.lang("Error occurred when parsing entry")
+ + ": "
+ + e.getLocalizedMessage());
return Optional.empty();
}
}
@@ -137,12 +145,16 @@ private Optional importFile(String importArguments) {
String address = data[0];
Path file;
- if (address.startsWith("http://") || address.startsWith("https://") || address.startsWith("ftp://")) {
+ if (address.startsWith("http://")
+ || address.startsWith("https://")
+ || address.startsWith("ftp://")) {
// Download web resource to temporary file
try {
file = new URLDownload(address).toTemporaryFile();
} catch (FetcherException | MalformedURLException e) {
- System.err.println(Localization.lang("Problem downloading from %1", address) + e.getLocalizedMessage());
+ System.err.println(
+ Localization.lang("Problem downloading from %1", address)
+ + e.getLocalizedMessage());
return Optional.empty();
}
} else {
@@ -161,22 +173,23 @@ private Optional importFile(String importArguments) {
}
Optional importResult = importFile(file, importFormat);
- importResult.ifPresent(result -> {
- if (result.hasWarnings()) {
- System.out.println(result.getErrorMessage());
- }
- });
+ importResult.ifPresent(
+ result -> {
+ if (result.hasWarnings()) {
+ System.out.println(result.getErrorMessage());
+ }
+ });
return importResult;
}
private Optional importFile(Path file, String importFormat) {
try {
- ImportFormatReader importFormatReader = new ImportFormatReader(
- cliPreferences.getImporterPreferences(),
- cliPreferences.getImportFormatPreferences(),
- cliPreferences.getCitationKeyPatternPreferences(),
- fileUpdateMonitor
- );
+ ImportFormatReader importFormatReader =
+ new ImportFormatReader(
+ cliPreferences.getImporterPreferences(),
+ cliPreferences.getImportFormatPreferences(),
+ cliPreferences.getCitationKeyPatternPreferences(),
+ fileUpdateMonitor);
if (!"*".equals(importFormat)) {
System.out.println(Localization.lang("Importing %0", file));
@@ -193,7 +206,10 @@ private Optional importFile(Path file, String importFormat) {
return Optional.of(importResult.parserResult());
}
} catch (ImportException ex) {
- System.err.println(Localization.lang("Error opening file '%0'", file) + "\n" + ex.getLocalizedMessage());
+ System.err.println(
+ Localization.lang("Error opening file '%0'", file)
+ + "\n"
+ + ex.getLocalizedMessage());
return Optional.empty();
}
}
@@ -235,7 +251,8 @@ public void processArguments() {
return;
}
} else {
- System.err.println(Localization.lang("The output option depends on a valid input option."));
+ System.err.println(
+ Localization.lang("The output option depends on a valid input option."));
}
}
@@ -247,13 +264,17 @@ public void processArguments() {
automaticallySetFileLinks(loaded);
}
- if ((cli.isWriteXmpToPdf() && cli.isEmbedBibFileInPdf()) || (cli.isWriteMetadataToPdf() && (cli.isWriteXmpToPdf() || cli.isEmbedBibFileInPdf()))) {
- System.err.println("Give only one of [writeXmpToPdf, embedBibFileInPdf, writeMetadataToPdf]");
+ if ((cli.isWriteXmpToPdf() && cli.isEmbedBibFileInPdf())
+ || (cli.isWriteMetadataToPdf()
+ && (cli.isWriteXmpToPdf() || cli.isEmbedBibFileInPdf()))) {
+ System.err.println(
+ "Give only one of [writeXmpToPdf, embedBibFileInPdf, writeMetadataToPdf]");
}
if (cli.isWriteMetadataToPdf() || cli.isWriteXmpToPdf() || cli.isEmbedBibFileInPdf()) {
if (!loaded.isEmpty()) {
- writeMetadataToPdf(loaded,
+ writeMetadataToPdf(
+ loaded,
cli.getWriteMetadataToPdf(),
cliPreferences.getXmpPreferences(),
cliPreferences.getFilePreferences(),
@@ -271,7 +292,8 @@ public void processArguments() {
exportFile(loaded, cli.getFileExport().split(","));
LOGGER.debug("Finished export");
} else {
- System.err.println(Localization.lang("The output option depends on a valid import option."));
+ System.err.println(
+ Localization.lang("The output option depends on a valid import option."));
}
}
@@ -300,16 +322,17 @@ public void processArguments() {
}
}
- private void writeMetadataToPdf(List loaded,
- String filesAndCiteKeys,
- XmpPreferences xmpPreferences,
- FilePreferences filePreferences,
- BibDatabaseMode databaseMode,
- BibEntryTypesManager entryTypesManager,
- FieldPreferences fieldPreferences,
- JournalAbbreviationRepository abbreviationRepository,
- boolean writeXMP,
- boolean embeddBibfile) {
+ private void writeMetadataToPdf(
+ List loaded,
+ String filesAndCiteKeys,
+ XmpPreferences xmpPreferences,
+ FilePreferences filePreferences,
+ BibDatabaseMode databaseMode,
+ BibEntryTypesManager entryTypesManager,
+ FieldPreferences fieldPreferences,
+ JournalAbbreviationRepository abbreviationRepository,
+ boolean writeXMP,
+ boolean embeddBibfile) {
if (loaded.isEmpty()) {
LOGGER.error("The write xmp option depends on a valid import option.");
return;
@@ -318,7 +341,8 @@ private void writeMetadataToPdf(List loaded,
BibDatabaseContext databaseContext = pr.getDatabaseContext();
XmpPdfExporter xmpPdfExporter = new XmpPdfExporter(xmpPreferences);
- EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter = new EmbeddedBibFilePdfExporter(databaseMode, entryTypesManager, fieldPreferences);
+ EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter =
+ new EmbeddedBibFilePdfExporter(databaseMode, entryTypesManager, fieldPreferences);
if ("all".equals(filesAndCiteKeys)) {
for (BibEntry entry : databaseContext.getEntries()) {
@@ -366,28 +390,47 @@ private void writeMetadataToPdf(List loaded,
embeddBibfile);
}
- private void writeMetadataToPDFsOfEntry(BibDatabaseContext databaseContext,
- String citeKey,
- BibEntry entry,
- FilePreferences filePreferences,
- XmpPdfExporter xmpPdfExporter,
- EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter,
- JournalAbbreviationRepository abbreviationRepository,
- boolean writeXMP,
- boolean embedBibfile) {
+ private void writeMetadataToPDFsOfEntry(
+ BibDatabaseContext databaseContext,
+ String citeKey,
+ BibEntry entry,
+ FilePreferences filePreferences,
+ XmpPdfExporter xmpPdfExporter,
+ EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter,
+ JournalAbbreviationRepository abbreviationRepository,
+ boolean writeXMP,
+ boolean embedBibfile) {
try {
if (writeXMP) {
- if (xmpPdfExporter.exportToAllFilesOfEntry(databaseContext, filePreferences, entry, List.of(entry), abbreviationRepository)) {
- System.out.printf("Successfully written XMP metadata on at least one linked file of %s%n", citeKey);
+ if (xmpPdfExporter.exportToAllFilesOfEntry(
+ databaseContext,
+ filePreferences,
+ entry,
+ List.of(entry),
+ abbreviationRepository)) {
+ System.out.printf(
+ "Successfully written XMP metadata on at least one linked file of %s%n",
+ citeKey);
} else {
- 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);
+ 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 (embedBibfile) {
- if (embeddedBibFilePdfExporter.exportToAllFilesOfEntry(databaseContext, filePreferences, entry, List.of(entry), abbreviationRepository)) {
- System.out.printf("Successfully embedded metadata on at least one linked file of %s%n", citeKey);
+ if (embeddedBibFilePdfExporter.exportToAllFilesOfEntry(
+ databaseContext,
+ filePreferences,
+ entry,
+ List.of(entry),
+ abbreviationRepository)) {
+ System.out.printf(
+ "Successfully embedded metadata on at least one linked file of %s%n",
+ citeKey);
} else {
- System.out.printf("Cannot embed metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.%n", citeKey);
+ System.out.printf(
+ "Cannot embed 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) {
@@ -395,53 +438,85 @@ private void writeMetadataToPDFsOfEntry(BibDatabaseContext databaseContext,
}
}
- private void writeMetadataToPdfByCitekey(BibDatabaseContext databaseContext,
- List citeKeys,
- FilePreferences filePreferences,
- XmpPdfExporter xmpPdfExporter,
- EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter,
- JournalAbbreviationRepository abbreviationRepository,
- boolean writeXMP,
- boolean embeddBibfile) {
+ private void writeMetadataToPdfByCitekey(
+ BibDatabaseContext databaseContext,
+ List citeKeys,
+ FilePreferences filePreferences,
+ XmpPdfExporter xmpPdfExporter,
+ EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter,
+ JournalAbbreviationRepository abbreviationRepository,
+ boolean writeXMP,
+ boolean embeddBibfile) {
for (String citeKey : citeKeys) {
- List bibEntryList = databaseContext.getDatabase().getEntriesByCitationKey(citeKey);
+ List bibEntryList =
+ databaseContext.getDatabase().getEntriesByCitationKey(citeKey);
if (bibEntryList.isEmpty()) {
System.err.printf("Skipped - Cannot find %s in library.%n", citeKey);
continue;
}
for (BibEntry entry : bibEntryList) {
- writeMetadataToPDFsOfEntry(databaseContext, citeKey, entry, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, abbreviationRepository, writeXMP, embeddBibfile);
+ writeMetadataToPDFsOfEntry(
+ databaseContext,
+ citeKey,
+ entry,
+ filePreferences,
+ xmpPdfExporter,
+ embeddedBibFilePdfExporter,
+ abbreviationRepository,
+ writeXMP,
+ embeddBibfile);
}
}
}
- private void writeMetadataToPdfByFileNames(BibDatabaseContext databaseContext,
- List pdfs,
- FilePreferences filePreferences,
- XmpPdfExporter xmpPdfExporter,
- EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter,
- JournalAbbreviationRepository abbreviationRepository,
- boolean writeXMP,
- boolean embeddBibfile) {
+ private void writeMetadataToPdfByFileNames(
+ BibDatabaseContext databaseContext,
+ List pdfs,
+ FilePreferences filePreferences,
+ XmpPdfExporter xmpPdfExporter,
+ EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter,
+ JournalAbbreviationRepository abbreviationRepository,
+ boolean writeXMP,
+ boolean embeddBibfile) {
for (String fileName : pdfs) {
Path filePath = Path.of(fileName);
if (!filePath.isAbsolute()) {
- filePath = FileUtil.find(fileName, databaseContext.getFileDirectories(filePreferences)).orElse(FileUtil.find(fileName, List.of(Path.of("").toAbsolutePath())).orElse(filePath));
+ filePath =
+ FileUtil.find(fileName, databaseContext.getFileDirectories(filePreferences))
+ .orElse(
+ FileUtil.find(
+ fileName,
+ List.of(Path.of("").toAbsolutePath()))
+ .orElse(filePath));
}
if (Files.exists(filePath)) {
try {
if (writeXMP) {
- if (xmpPdfExporter.exportToFileByPath(databaseContext, filePreferences, filePath, abbreviationRepository)) {
- System.out.printf("Successfully written XMP metadata of at least one entry to %s%n", fileName);
+ if (xmpPdfExporter.exportToFileByPath(
+ databaseContext,
+ filePreferences,
+ filePath,
+ abbreviationRepository)) {
+ System.out.printf(
+ "Successfully written XMP metadata of at least one entry to %s%n",
+ fileName);
} else {
- System.out.printf("File %s is not linked to any entry in database.%n", fileName);
+ System.out.printf(
+ "File %s is not linked to any entry in database.%n", fileName);
}
}
if (embeddBibfile) {
- if (embeddedBibFilePdfExporter.exportToFileByPath(databaseContext, filePreferences, filePath, abbreviationRepository)) {
- System.out.printf("Successfully embedded XMP metadata of at least one entry to %s%n", fileName);
+ if (embeddedBibFilePdfExporter.exportToFileByPath(
+ databaseContext,
+ filePreferences,
+ filePath,
+ abbreviationRepository)) {
+ System.out.printf(
+ "Successfully embedded XMP metadata of at least one entry to %s%n",
+ fileName);
} else {
- System.out.printf("File %s is not linked to any entry in database.%n", fileName);
+ System.out.printf(
+ "File %s is not linked to any entry in database.%n", fileName);
}
}
} catch (IOException e) {
@@ -468,7 +543,13 @@ private boolean exportMatches(List loaded) {
List matches;
try {
// extract current thread task executor from luceneManager
- matches = new DatabaseSearcher(query, databaseContext, new CurrentThreadTaskExecutor(), cliPreferences.getFilePreferences()).getMatches();
+ matches =
+ new DatabaseSearcher(
+ query,
+ databaseContext,
+ new CurrentThreadTaskExecutor(),
+ cliPreferences.getFilePreferences())
+ .getMatches();
} catch (IOException e) {
LOGGER.error("Error occurred when searching", e);
return false;
@@ -485,8 +566,12 @@ private boolean exportMatches(List loaded) {
// default exporter: bib file
formatName = "bib";
default -> {
- System.err.println(Localization.lang("Output file missing").concat(". \n \t ")
- .concat(Localization.lang("Usage")).concat(": ") + JabRefCLI.getExportMatchesSyntax());
+ System.err.println(
+ Localization.lang("Output file missing")
+ .concat(". \n \t ")
+ .concat(Localization.lang("Usage"))
+ .concat(": ")
+ + JabRefCLI.getExportMatchesSyntax());
guiNeeded = false;
return false;
}
@@ -499,9 +584,10 @@ private boolean exportMatches(List loaded) {
LOGGER.debug("Finished export");
} else {
// export new database
- ExporterFactory exporterFactory = ExporterFactory.create(
- cliPreferences,
- Injector.instantiateModelOrService(BibEntryTypesManager.class));
+ ExporterFactory exporterFactory =
+ ExporterFactory.create(
+ cliPreferences,
+ Injector.instantiateModelOrService(BibEntryTypesManager.class));
Optional exporter = exporterFactory.getExporterByName(formatName);
if (exporter.isEmpty()) {
System.err.println(Localization.lang("Unknown export format %0", formatName));
@@ -509,14 +595,19 @@ private boolean exportMatches(List loaded) {
// We have an TemplateExporter instance:
try {
System.out.println(Localization.lang("Exporting %0", data[1]));
- exporter.get().export(
- databaseContext,
- Path.of(data[1]),
- matches,
- Collections.emptyList(),
- Injector.instantiateModelOrService(JournalAbbreviationRepository.class));
+ exporter.get()
+ .export(
+ databaseContext,
+ Path.of(data[1]),
+ matches,
+ Collections.emptyList(),
+ Injector.instantiateModelOrService(
+ JournalAbbreviationRepository.class));
} catch (Exception ex) {
- System.err.println(Localization.lang("Could not export file '%0' (reason: %1)", data[1], Throwables.getStackTraceAsString(ex)));
+ System.err.println(
+ Localization.lang(
+ "Could not export file '%0' (reason: %1)",
+ data[1], Throwables.getStackTraceAsString(ex)));
}
}
}
@@ -558,11 +649,14 @@ private List importAndOpenFiles() {
ParserResult pr = new ParserResult();
if (bibExtension) {
try {
- pr = OpenDatabase.loadDatabase(
- Path.of(aLeftOver),
- cliPreferences.getImportFormatPreferences(),
- fileUpdateMonitor);
- // In contrast to org.jabref.gui.LibraryTab.onDatabaseLoadingSucceed, we do not execute OpenDatabaseAction.performPostOpenActions(result, dialogService);
+ pr =
+ OpenDatabase.loadDatabase(
+ Path.of(aLeftOver),
+ cliPreferences.getImportFormatPreferences(),
+ fileUpdateMonitor);
+ // In contrast to org.jabref.gui.LibraryTab.onDatabaseLoadingSucceed, we do
+ // not execute OpenDatabaseAction.performPostOpenActions(result,
+ // dialogService);
} catch (IOException ex) {
pr = ParserResult.fromError(ex);
LOGGER.error("Error opening file '{}'", aLeftOver, ex);
@@ -600,7 +694,9 @@ private List importAndOpenFiles() {
}
if (!cli.isBlank() && cli.isBibtexImport()) {
- importBibtexToOpenBase(cli.getBibtexImport(), cliPreferences.getImportFormatPreferences()).ifPresent(loaded::add);
+ importBibtexToOpenBase(
+ cli.getBibtexImport(), cliPreferences.getImportFormatPreferences())
+ .ifPresent(loaded::add);
}
return loaded;
@@ -633,26 +729,38 @@ private boolean generateAux(List loaded, String[] data) {
private void saveDatabase(BibDatabase newBase, String subName) {
try {
System.out.println(Localization.lang("Saving") + ": " + subName);
- try (AtomicFileWriter fileWriter = new AtomicFileWriter(Path.of(subName), StandardCharsets.UTF_8)) {
+ try (AtomicFileWriter fileWriter =
+ new AtomicFileWriter(Path.of(subName), StandardCharsets.UTF_8)) {
BibWriter bibWriter = new BibWriter(fileWriter, OS.NEWLINE);
- SelfContainedSaveConfiguration saveConfiguration = (SelfContainedSaveConfiguration) new SelfContainedSaveConfiguration()
- .withReformatOnSave(cliPreferences.getLibraryPreferences().shouldAlwaysReformatOnSave());
- BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter(
- bibWriter,
- saveConfiguration,
- cliPreferences.getFieldPreferences(),
- cliPreferences.getCitationKeyPatternPreferences(),
- entryTypesManager);
+ SelfContainedSaveConfiguration saveConfiguration =
+ (SelfContainedSaveConfiguration)
+ new SelfContainedSaveConfiguration()
+ .withReformatOnSave(
+ cliPreferences
+ .getLibraryPreferences()
+ .shouldAlwaysReformatOnSave());
+ BibDatabaseWriter databaseWriter =
+ new BibtexDatabaseWriter(
+ bibWriter,
+ saveConfiguration,
+ cliPreferences.getFieldPreferences(),
+ cliPreferences.getCitationKeyPatternPreferences(),
+ entryTypesManager);
databaseWriter.saveDatabase(new BibDatabaseContext(newBase));
// Show just a warning message if encoding did not work for all characters:
if (fileWriter.hasEncodingProblems()) {
- System.err.println(Localization.lang("Warning") + ": "
- + Localization.lang("UTF-8 could not be used to encode the following characters: %0", fileWriter.getEncodingProblems()));
+ System.err.println(
+ Localization.lang("Warning")
+ + ": "
+ + Localization.lang(
+ "UTF-8 could not be used to encode the following characters: %0",
+ fileWriter.getEncodingProblems()));
}
}
} catch (IOException ex) {
- System.err.println(Localization.lang("Could not save file.") + "\n" + ex.getLocalizedMessage());
+ System.err.println(
+ Localization.lang("Could not save file.") + "\n" + ex.getLocalizedMessage());
}
}
@@ -666,7 +774,8 @@ private void exportFile(List loaded, String[] data) {
saveDatabase(pr.getDatabase(), data[0]);
}
} else {
- System.err.println(Localization.lang("The output option depends on a valid import option."));
+ System.err.println(
+ Localization.lang("The output option depends on a valid import option."));
}
} else if (data.length == 2) {
// This signals that the latest import should be stored in the given
@@ -676,26 +785,32 @@ private void exportFile(List loaded, String[] data) {
Path path = parserResult.getPath().get().toAbsolutePath();
BibDatabaseContext databaseContext = parserResult.getDatabaseContext();
databaseContext.setDatabasePath(path);
- List fileDirForDatabase = databaseContext
- .getFileDirectories(cliPreferences.getFilePreferences());
+ List fileDirForDatabase =
+ databaseContext.getFileDirectories(cliPreferences.getFilePreferences());
System.out.println(Localization.lang("Exporting %0", data[0]));
- ExporterFactory exporterFactory = ExporterFactory.create(
- cliPreferences,
- Injector.instantiateModelOrService(BibEntryTypesManager.class));
+ ExporterFactory exporterFactory =
+ ExporterFactory.create(
+ cliPreferences,
+ Injector.instantiateModelOrService(BibEntryTypesManager.class));
Optional exporter = exporterFactory.getExporterByName(data[1]);
if (exporter.isEmpty()) {
System.err.println(Localization.lang("Unknown export format %0", data[1]));
} else {
// We have an exporter:
try {
- exporter.get().export(
- parserResult.getDatabaseContext(),
- Path.of(data[0]),
- parserResult.getDatabaseContext().getDatabase().getEntries(),
- fileDirForDatabase,
- Injector.instantiateModelOrService(JournalAbbreviationRepository.class));
+ exporter.get()
+ .export(
+ parserResult.getDatabaseContext(),
+ Path.of(data[0]),
+ parserResult.getDatabaseContext().getDatabase().getEntries(),
+ fileDirForDatabase,
+ Injector.instantiateModelOrService(
+ JournalAbbreviationRepository.class));
} catch (Exception ex) {
- System.err.println(Localization.lang("Could not export file '%0' (reason: %1)", data[0], Throwables.getStackTraceAsString(ex)));
+ System.err.println(
+ Localization.lang(
+ "Could not export file '%0' (reason: %1)",
+ data[0], Throwables.getStackTraceAsString(ex)));
}
}
}
@@ -704,7 +819,8 @@ private void exportFile(List loaded, String[] data) {
private void importPreferences() {
try {
cliPreferences.importPreferences(Path.of(cli.getPreferencesImport()));
- Injector.setModelOrService(BibEntryTypesManager.class, cliPreferences.getCustomEntryTypesRepository());
+ Injector.setModelOrService(
+ BibEntryTypesManager.class, cliPreferences.getCustomEntryTypesRepository());
} catch (JabRefException ex) {
LOGGER.error("Cannot import preferences", ex);
}
@@ -725,7 +841,8 @@ private void resetPreferences(String value) {
for (String key : keys) {
try {
cliPreferences.deleteKey(key.trim());
- System.out.println(Localization.lang("Resetting preference key '%0'", key.trim()));
+ System.out.println(
+ Localization.lang("Resetting preference key '%0'", key.trim()));
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
@@ -736,18 +853,24 @@ private void resetPreferences(String value) {
private void automaticallySetFileLinks(List loaded) {
for (ParserResult parserResult : loaded) {
BibDatabase database = parserResult.getDatabase();
- LOGGER.info("Automatically setting file links for {}",
- parserResult.getDatabaseContext().getDatabasePath()
- .map(Path::getFileName)
- .map(Path::toString).orElse("UNKNOWN"));
-
- AutoSetFileLinksUtil util = new AutoSetFileLinksUtil(
- parserResult.getDatabaseContext(),
- guiPreferences.getExternalApplicationsPreferences(),
- cliPreferences.getFilePreferences(),
- cliPreferences.getAutoLinkPreferences());
+ LOGGER.info(
+ "Automatically setting file links for {}",
+ parserResult
+ .getDatabaseContext()
+ .getDatabasePath()
+ .map(Path::getFileName)
+ .map(Path::toString)
+ .orElse("UNKNOWN"));
+
+ AutoSetFileLinksUtil util =
+ new AutoSetFileLinksUtil(
+ parserResult.getDatabaseContext(),
+ guiPreferences.getExternalApplicationsPreferences(),
+ cliPreferences.getFilePreferences(),
+ cliPreferences.getAutoLinkPreferences());
- util.linkAssociatedFiles(database.getEntries(), (linkedFile, bibEntry) -> bibEntry.addFile(linkedFile));
+ util.linkAssociatedFiles(
+ database.getEntries(), (linkedFile, bibEntry) -> bibEntry.addFile(linkedFile));
}
}
@@ -757,9 +880,10 @@ private void regenerateCitationKeys(List loaded) {
LOGGER.info(Localization.lang("Regenerating citation keys according to metadata"));
- CitationKeyGenerator keyGenerator = new CitationKeyGenerator(
- parserResult.getDatabaseContext(),
- cliPreferences.getCitationKeyPatternPreferences());
+ CitationKeyGenerator keyGenerator =
+ new CitationKeyGenerator(
+ parserResult.getDatabaseContext(),
+ cliPreferences.getCitationKeyPatternPreferences());
for (BibEntry entry : database.getEntries()) {
keyGenerator.generateAndSetKey(entry);
}
@@ -774,7 +898,8 @@ private void regenerateCitationKeys(List loaded) {
*/
private Optional fetch(String fetchCommand) {
if ((fetchCommand == null) || !fetchCommand.contains(":")) {
- System.out.println(Localization.lang("Expected syntax for --fetch=':'"));
+ System.out.println(
+ Localization.lang("Expected syntax for --fetch=':'"));
System.out.println(Localization.lang("The following fetchers are available:"));
return Optional.empty();
}
@@ -783,12 +908,14 @@ private Optional fetch(String fetchCommand) {
String engine = split[0];
String query = split[1];
- Set fetchers = WebFetchers.getSearchBasedFetchers(
- cliPreferences.getImportFormatPreferences(),
- cliPreferences.getImporterPreferences());
- Optional selectedFetcher = fetchers.stream()
- .filter(fetcher -> fetcher.getName().equalsIgnoreCase(engine))
- .findFirst();
+ Set fetchers =
+ WebFetchers.getSearchBasedFetchers(
+ cliPreferences.getImportFormatPreferences(),
+ cliPreferences.getImporterPreferences());
+ Optional selectedFetcher =
+ fetchers.stream()
+ .filter(fetcher -> fetcher.getName().equalsIgnoreCase(engine))
+ .findFirst();
if (selectedFetcher.isEmpty()) {
System.out.println(Localization.lang("Could not find fetcher '%0'", engine));
@@ -797,7 +924,8 @@ private Optional fetch(String fetchCommand) {
return Optional.empty();
} else {
- System.out.println(Localization.lang("Running query '%0' with fetcher '%1'.", query, engine));
+ System.out.println(
+ Localization.lang("Running query '%0' with fetcher '%1'.", query, engine));
System.out.print(Localization.lang("Please wait..."));
try {
List matches = selectedFetcher.get().performSearch(query);
@@ -805,7 +933,10 @@ private Optional fetch(String fetchCommand) {
System.out.println("\r" + Localization.lang("No results found."));
return Optional.empty();
} else {
- System.out.println("\r" + Localization.lang("Found %0 results.", String.valueOf(matches.size())));
+ System.out.println(
+ "\r"
+ + Localization.lang(
+ "Found %0 results.", String.valueOf(matches.size())));
return Optional.of(new ParserResult(matches));
}
} catch (FetcherException e) {
diff --git a/src/main/java/org/jabref/cli/AuxCommandLine.java b/src/main/java/org/jabref/cli/AuxCommandLine.java
index 61f4c133008d..fe8d9c02e9ee 100644
--- a/src/main/java/org/jabref/cli/AuxCommandLine.java
+++ b/src/main/java/org/jabref/cli/AuxCommandLine.java
@@ -1,7 +1,5 @@
package org.jabref.cli;
-import java.nio.file.Path;
-
import org.jabref.gui.auximport.AuxParserResultViewModel;
import org.jabref.logic.auxparser.AuxParser;
import org.jabref.logic.auxparser.AuxParserResult;
@@ -9,6 +7,8 @@
import org.jabref.model.database.BibDatabase;
import org.jabref.model.strings.StringUtil;
+import java.nio.file.Path;
+
public class AuxCommandLine {
private final String auxFile;
private final BibDatabase database;
diff --git a/src/main/java/org/jabref/cli/JabRefCLI.java b/src/main/java/org/jabref/cli/JabRefCLI.java
index 0cd74a0bba40..524f4f0d2778 100644
--- a/src/main/java/org/jabref/cli/JabRefCLI.java
+++ b/src/main/java/org/jabref/cli/JabRefCLI.java
@@ -1,10 +1,15 @@
package org.jabref.cli;
-import java.util.List;
-import java.util.Objects;
+import com.airhacks.afterburner.injection.Injector;
import javafx.util.Pair;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
import org.jabref.logic.exporter.ExporterFactory;
import org.jabref.logic.importer.ImportFormatReader;
import org.jabref.logic.l10n.Localization;
@@ -15,17 +20,15 @@
import org.jabref.model.strings.StringUtil;
import org.jabref.model.util.DummyFileUpdateMonitor;
-import com.airhacks.afterburner.injection.Injector;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
+import java.util.List;
+import java.util.Objects;
public class JabRefCLI {
- private static final int WIDTH = 100; // Number of characters per line before a line break must be added.
- private static final String WRAPPED_LINE_PREFIX = ""; // If a line break is added, this prefix will be inserted at the beginning of the next line
+ private static final int WIDTH =
+ 100; // Number of characters per line before a line break must be added.
+ private static final String WRAPPED_LINE_PREFIX =
+ ""; // If a line break is added, this prefix will be inserted at the beginning of the
+ // next line
private static final String STRING_TABLE_DELIMITER = " : ";
private final CommandLine cl;
@@ -38,10 +41,11 @@ public JabRefCLI(String[] args) throws ParseException {
}
public static String getExportMatchesSyntax() {
- return "[%s]searchTerm,outputFile:%s[,%s]".formatted(
- Localization.lang("field"),
- Localization.lang("file"),
- Localization.lang("exportFormat"));
+ return "[%s]searchTerm,outputFile:%s[,%s]"
+ .formatted(
+ Localization.lang("field"),
+ Localization.lang("file"),
+ Localization.lang("exportFormat"));
}
public boolean isHelp() {
@@ -165,9 +169,13 @@ public boolean isWriteMetadataToPdf() {
}
public String getWriteMetadataToPdf() {
- return cl.hasOption("writeMetadatatoPdf") ? cl.getOptionValue("writeMetadataToPdf") :
- cl.hasOption("writeXMPtoPdf") ? cl.getOptionValue("writeXmpToPdf") :
- cl.hasOption("embeddBibfileInPdf") ? cl.getOptionValue("embeddBibfileInPdf") : null;
+ return cl.hasOption("writeMetadatatoPdf")
+ ? cl.getOptionValue("writeMetadataToPdf")
+ : cl.hasOption("writeXMPtoPdf")
+ ? cl.getOptionValue("writeXmpToPdf")
+ : cl.hasOption("embeddBibfileInPdf")
+ ? cl.getOptionValue("embeddBibfileInPdf")
+ : null;
}
public String getJumpToKey() {
@@ -182,125 +190,196 @@ private static Options getOptions() {
Options options = new Options();
// boolean options
- options.addOption("h", "help", false, Localization.lang("Display help on command line options"));
- options.addOption("n", "nogui", false, Localization.lang("No GUI. Only process command line options"));
- options.addOption("asfl", "automaticallySetFileLinks", false, Localization.lang("Automatically set file links"));
- options.addOption("g", "generateCitationKeys", false, Localization.lang("Regenerate all keys for the entries in a BibTeX file"));
- options.addOption("b", "blank", false, Localization.lang("Do not open any files at startup"));
+ options.addOption(
+ "h", "help", false, Localization.lang("Display help on command line options"));
+ options.addOption(
+ "n",
+ "nogui",
+ false,
+ Localization.lang("No GUI. Only process command line options"));
+ options.addOption(
+ "asfl",
+ "automaticallySetFileLinks",
+ false,
+ Localization.lang("Automatically set file links"));
+ options.addOption(
+ "g",
+ "generateCitationKeys",
+ false,
+ Localization.lang("Regenerate all keys for the entries in a BibTeX file"));
+ options.addOption(
+ "b", "blank", false, Localization.lang("Do not open any files at startup"));
options.addOption("v", "version", false, Localization.lang("Display version"));
options.addOption(null, "debug", false, Localization.lang("Show debug level messages"));
- options.addOption(Option
- .builder("i")
- .longOpt("import")
- .desc("%s: '%s'".formatted(Localization.lang("Import file"), "-i library.bib"))
- .hasArg()
- .argName("FILE[,FORMAT]")
- .build());
-
- options.addOption(Option
- .builder()
- .longOpt("importToOpen")
- .desc(Localization.lang("Same as --import, but will be imported to the opened tab"))
- .hasArg()
- .argName("FILE[,FORMAT]")
- .build());
-
- options.addOption(Option
- .builder("ib")
- .longOpt("importBibtex")
- .desc("%s: '%s'".formatted(Localization.lang("Import BibTeX"), "-ib @article{entry}"))
- .hasArg()
- .argName("BIBTEXT_STRING")
- .build());
-
- options.addOption(Option
- .builder("o")
- .longOpt("output")
- .desc("%s: '%s'".formatted(Localization.lang("Export an input to a file"), "-i db.bib -o db.htm,html"))
- .hasArg()
- .argName("FILE[,FORMAT]")
- .build());
-
- options.addOption(Option
- .builder("m")
- .longOpt("exportMatches")
- .desc("%s: '%s'".formatted(Localization.lang("Matching"), "-i db.bib -m author=Newton,search.htm,html"))
- .hasArg()
- .argName("QUERY,FILE[,FORMAT]")
- .build());
-
- options.addOption(Option
- .builder("f")
- .longOpt("fetch")
- .desc("%s: '%s'".formatted(Localization.lang("Run fetcher"), "-f Medline/PubMed:cancer"))
- .hasArg()
- .argName("FETCHER:QUERY")
- .build());
-
- options.addOption(Option
- .builder("a")
- .longOpt("aux")
- .desc("%s: '%s'".formatted(Localization.lang("Sublibrary from AUX to BibTeX"), "-a thesis.aux,new.bib"))
- .hasArg()
- .argName("FILE[.aux],FILE[.bib] FILE")
- .build());
-
- options.addOption(Option
- .builder("x")
- .longOpt("prexp")
- .desc("%s: '%s'".formatted(Localization.lang("Export preferences to a file"), "-x prefs.xml"))
- .hasArg()
- .argName("[FILE]")
- .build());
-
- options.addOption(Option
- .builder("p")
- .longOpt("primp")
- .desc("%s: '%s'".formatted(Localization.lang("Import preferences from a file"), "-p prefs.xml"))
- .hasArg()
- .argName("[FILE]")
- .build());
-
- options.addOption(Option
- .builder("d")
- .longOpt("prdef")
- .desc("%s: '%s'".formatted(Localization.lang("Reset preferences"), "-d mainFontSize,newline' or '-d all"))
- .hasArg()
- .argName("KEY1[,KEY2][,KEYn] | all")
- .build());
-
- options.addOption(Option
- .builder()
- .longOpt("writeXmpToPdf")
- .desc("%s: '%s'".formatted(Localization.lang("Write BibTeX as XMP metadata to PDF."), "-w pathToMyOwnPaper.pdf"))
- .hasArg()
- .argName("CITEKEY1[,CITEKEY2][,CITEKEYn] | PDF1[,PDF2][,PDFn] | all")
- .build());
-
- options.addOption(Option
- .builder()
- .longOpt("embedBibFileInPdf")
- .desc("%s: '%s'".formatted(Localization.lang("Embed BibTeX as attached file in PDF."), "-w pathToMyOwnPaper.pdf"))
- .hasArg()
- .argName("CITEKEY1[,CITEKEY2][,CITEKEYn] | PDF1[,PDF2][,PDFn] | all")
- .build());
-
- options.addOption(Option
- .builder("w")
- .longOpt("writeMetadataToPdf")
- .desc("%s: '%s'".formatted(Localization.lang("Write BibTeX to PDF (XMP and embedded)"), "-w pathToMyOwnPaper.pdf"))
- .hasArg()
- .argName("CITEKEY1[,CITEKEY2][,CITEKEYn] | PDF1[,PDF2][,PDFn] | all")
- .build());
-
- options.addOption(Option
- .builder("j")
- .longOpt("jumpToKey")
- .desc("%s: '%s'".formatted(Localization.lang("Jump to the entry of the given citation key."), "-j key"))
- .hasArg()
- .argName("CITATIONKEY")
- .build());
+ options.addOption(
+ Option.builder("i")
+ .longOpt("import")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Import file"), "-i library.bib"))
+ .hasArg()
+ .argName("FILE[,FORMAT]")
+ .build());
+
+ options.addOption(
+ Option.builder()
+ .longOpt("importToOpen")
+ .desc(
+ Localization.lang(
+ "Same as --import, but will be imported to the opened tab"))
+ .hasArg()
+ .argName("FILE[,FORMAT]")
+ .build());
+
+ options.addOption(
+ Option.builder("ib")
+ .longOpt("importBibtex")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Import BibTeX"),
+ "-ib @article{entry}"))
+ .hasArg()
+ .argName("BIBTEXT_STRING")
+ .build());
+
+ options.addOption(
+ Option.builder("o")
+ .longOpt("output")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Export an input to a file"),
+ "-i db.bib -o db.htm,html"))
+ .hasArg()
+ .argName("FILE[,FORMAT]")
+ .build());
+
+ options.addOption(
+ Option.builder("m")
+ .longOpt("exportMatches")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Matching"),
+ "-i db.bib -m author=Newton,search.htm,html"))
+ .hasArg()
+ .argName("QUERY,FILE[,FORMAT]")
+ .build());
+
+ options.addOption(
+ Option.builder("f")
+ .longOpt("fetch")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Run fetcher"),
+ "-f Medline/PubMed:cancer"))
+ .hasArg()
+ .argName("FETCHER:QUERY")
+ .build());
+
+ options.addOption(
+ Option.builder("a")
+ .longOpt("aux")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Sublibrary from AUX to BibTeX"),
+ "-a thesis.aux,new.bib"))
+ .hasArg()
+ .argName("FILE[.aux],FILE[.bib] FILE")
+ .build());
+
+ options.addOption(
+ Option.builder("x")
+ .longOpt("prexp")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Export preferences to a file"),
+ "-x prefs.xml"))
+ .hasArg()
+ .argName("[FILE]")
+ .build());
+
+ options.addOption(
+ Option.builder("p")
+ .longOpt("primp")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Import preferences from a file"),
+ "-p prefs.xml"))
+ .hasArg()
+ .argName("[FILE]")
+ .build());
+
+ options.addOption(
+ Option.builder("d")
+ .longOpt("prdef")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang("Reset preferences"),
+ "-d mainFontSize,newline' or '-d all"))
+ .hasArg()
+ .argName("KEY1[,KEY2][,KEYn] | all")
+ .build());
+
+ options.addOption(
+ Option.builder()
+ .longOpt("writeXmpToPdf")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang(
+ "Write BibTeX as XMP metadata to PDF."),
+ "-w pathToMyOwnPaper.pdf"))
+ .hasArg()
+ .argName("CITEKEY1[,CITEKEY2][,CITEKEYn] | PDF1[,PDF2][,PDFn] | all")
+ .build());
+
+ options.addOption(
+ Option.builder()
+ .longOpt("embedBibFileInPdf")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang(
+ "Embed BibTeX as attached file in PDF."),
+ "-w pathToMyOwnPaper.pdf"))
+ .hasArg()
+ .argName("CITEKEY1[,CITEKEY2][,CITEKEYn] | PDF1[,PDF2][,PDFn] | all")
+ .build());
+
+ options.addOption(
+ Option.builder("w")
+ .longOpt("writeMetadataToPdf")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang(
+ "Write BibTeX to PDF (XMP and embedded)"),
+ "-w pathToMyOwnPaper.pdf"))
+ .hasArg()
+ .argName("CITEKEY1[,CITEKEY2][,CITEKEYn] | PDF1[,PDF2][,PDFn] | all")
+ .build());
+
+ options.addOption(
+ Option.builder("j")
+ .longOpt("jumpToKey")
+ .desc(
+ "%s: '%s'"
+ .formatted(
+ Localization.lang(
+ "Jump to the entry of the given citation key."),
+ "-j key"))
+ .hasArg()
+ .argName("CITATIONKEY")
+ .build());
return options;
}
@@ -312,33 +391,46 @@ public void displayVersion() {
public static void printUsage(CliPreferences preferences) {
String header = "";
- ImportFormatReader importFormatReader = new ImportFormatReader(
- preferences.getImporterPreferences(),
- preferences.getImportFormatPreferences(),
- preferences.getCitationKeyPatternPreferences(),
- new DummyFileUpdateMonitor()
- );
- List> importFormats = importFormatReader
- .getImportFormats().stream()
- .map(format -> new Pair<>(format.getName(), format.getId()))
- .toList();
+ ImportFormatReader importFormatReader =
+ new ImportFormatReader(
+ preferences.getImporterPreferences(),
+ preferences.getImportFormatPreferences(),
+ preferences.getCitationKeyPatternPreferences(),
+ new DummyFileUpdateMonitor());
+ List> importFormats =
+ importFormatReader.getImportFormats().stream()
+ .map(format -> new Pair<>(format.getName(), format.getId()))
+ .toList();
String importFormatsIntro = Localization.lang("Available import formats");
- String importFormatsList = "%s:%n%s%n".formatted(importFormatsIntro, alignStringTable(importFormats));
-
- ExporterFactory exporterFactory = ExporterFactory.create(
- preferences,
- Injector.instantiateModelOrService(BibEntryTypesManager.class));
- List> exportFormats = exporterFactory
- .getExporters().stream()
- .map(format -> new Pair<>(format.getName(), format.getId()))
- .toList();
+ String importFormatsList =
+ "%s:%n%s%n".formatted(importFormatsIntro, alignStringTable(importFormats));
+
+ ExporterFactory exporterFactory =
+ ExporterFactory.create(
+ preferences,
+ Injector.instantiateModelOrService(BibEntryTypesManager.class));
+ List> exportFormats =
+ exporterFactory.getExporters().stream()
+ .map(format -> new Pair<>(format.getName(), format.getId()))
+ .toList();
String outFormatsIntro = Localization.lang("Available export formats");
- String outFormatsList = "%s:%n%s%n".formatted(outFormatsIntro, alignStringTable(exportFormats));
+ String outFormatsList =
+ "%s:%n%s%n".formatted(outFormatsIntro, alignStringTable(exportFormats));
- String footer = '\n' + importFormatsList + outFormatsList + "\nPlease report issues at https://github.com/JabRef/jabref/issues.";
+ String footer =
+ '\n'
+ + importFormatsList
+ + outFormatsList
+ + "\nPlease report issues at https://github.com/JabRef/jabref/issues.";
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp(WIDTH, "jabref [OPTIONS] [BIBTEX_FILE]\n\nOptions:", header, getOptions(), footer, true);
+ formatter.printHelp(
+ WIDTH,
+ "jabref [OPTIONS] [BIBTEX_FILE]\n\nOptions:",
+ header,
+ getOptions(),
+ footer,
+ true);
}
private String getVersionInfo() {
@@ -353,9 +445,11 @@ public List getLeftOver() {
protected static String alignStringTable(List> table) {
StringBuilder sb = new StringBuilder();
- int maxLength = table.stream()
- .mapToInt(pair -> Objects.requireNonNullElse(pair.getKey(), "").length())
- .max().orElse(0);
+ int maxLength =
+ table.stream()
+ .mapToInt(pair -> Objects.requireNonNullElse(pair.getKey(), "").length())
+ .max()
+ .orElse(0);
for (Pair pair : table) {
int padding = Math.max(0, maxLength - pair.getKey().length());
diff --git a/src/main/java/org/jabref/cli/JournalListMvGenerator.java b/src/main/java/org/jabref/cli/JournalListMvGenerator.java
index dad187dc81a3..779255f7ffee 100644
--- a/src/main/java/org/jabref/cli/JournalListMvGenerator.java
+++ b/src/main/java/org/jabref/cli/JournalListMvGenerator.java
@@ -1,5 +1,11 @@
package org.jabref.cli;
+import org.h2.mvstore.MVMap;
+import org.h2.mvstore.MVStore;
+import org.jabref.logic.journals.Abbreviation;
+import org.jabref.logic.journals.JournalAbbreviationLoader;
+import org.jooq.lambda.Unchecked;
+
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
@@ -9,13 +15,6 @@
import java.util.Set;
import java.util.stream.Collectors;
-import org.jabref.logic.journals.Abbreviation;
-import org.jabref.logic.journals.JournalAbbreviationLoader;
-
-import org.h2.mvstore.MVMap;
-import org.h2.mvstore.MVStore;
-import org.jooq.lambda.Unchecked;
-
public class JournalListMvGenerator {
public static void main(String[] args) throws IOException {
@@ -23,53 +22,66 @@ public static void main(String[] args) throws IOException {
Path abbreviationsDirectory = Path.of("buildres", "abbrv.jabref.org", "journals");
if (!Files.exists(abbreviationsDirectory)) {
- System.out.println("Path " + abbreviationsDirectory.toAbsolutePath() + " does not exist");
+ System.out.println(
+ "Path " + abbreviationsDirectory.toAbsolutePath() + " does not exist");
System.exit(0);
}
- Path journalListMvFile = Path.of("build", "resources", "main", "journals", "journal-list.mv");
+ Path journalListMvFile =
+ Path.of("build", "resources", "main", "journals", "journal-list.mv");
- Set ignoredNames = Set.of(
- // remove all lists without dot in them:
- // we use abbreviation lists containing dots in them only (to be consistent)
- "journal_abbreviations_entrez.csv",
- "journal_abbreviations_medicus.csv",
- "journal_abbreviations_webofscience-dotless.csv",
+ Set ignoredNames =
+ Set.of(
+ // remove all lists without dot in them:
+ // we use abbreviation lists containing dots in them only (to be consistent)
+ "journal_abbreviations_entrez.csv",
+ "journal_abbreviations_medicus.csv",
+ "journal_abbreviations_webofscience-dotless.csv",
- // we currently do not have good support for BibTeX strings
- "journal_abbreviations_ieee_strings.csv"
- );
+ // we currently do not have good support for BibTeX strings
+ "journal_abbreviations_ieee_strings.csv");
Files.createDirectories(journalListMvFile.getParent());
- try (DirectoryStream stream = Files.newDirectoryStream(abbreviationsDirectory, "*.csv");
- MVStore store = new MVStore.Builder().
- fileName(journalListMvFile.toString()).
- compressHigh().
- open()) {
+ try (DirectoryStream stream =
+ Files.newDirectoryStream(abbreviationsDirectory, "*.csv");
+ MVStore store =
+ new MVStore.Builder()
+ .fileName(journalListMvFile.toString())
+ .compressHigh()
+ .open()) {
MVMap fullToAbbreviation = store.openMap("FullToAbbreviation");
- stream.forEach(Unchecked.consumer(path -> {
- String fileName = path.getFileName().toString();
- System.out.print("Checking ");
- System.out.print(fileName);
- if (ignoredNames.contains(fileName)) {
- System.out.println(" ignored");
- } else {
- System.out.println("...");
- Collection abbreviations = JournalAbbreviationLoader.readAbbreviationsFromCsvFile(path);
- Map abbreviationMap = abbreviations
- .stream()
- .collect(Collectors.toMap(
- Abbreviation::getName,
- abbreviation -> abbreviation,
- (abbreviation1, abbreviation2) -> {
- if (verbose) {
- System.out.println("Double entry " + abbreviation1.getName());
- }
- return abbreviation2;
- }));
- fullToAbbreviation.putAll(abbreviationMap);
- }
- }));
+ stream.forEach(
+ Unchecked.consumer(
+ path -> {
+ String fileName = path.getFileName().toString();
+ System.out.print("Checking ");
+ System.out.print(fileName);
+ if (ignoredNames.contains(fileName)) {
+ System.out.println(" ignored");
+ } else {
+ System.out.println("...");
+ Collection abbreviations =
+ JournalAbbreviationLoader.readAbbreviationsFromCsvFile(
+ path);
+ Map abbreviationMap =
+ abbreviations.stream()
+ .collect(
+ Collectors.toMap(
+ Abbreviation::getName,
+ abbreviation -> abbreviation,
+ (abbreviation1,
+ abbreviation2) -> {
+ if (verbose) {
+ System.out.println(
+ "Double entry "
+ + abbreviation1
+ .getName());
+ }
+ return abbreviation2;
+ }));
+ fullToAbbreviation.putAll(abbreviationMap);
+ }
+ }));
}
}
}
diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java
index 3e1455908e05..f1c63af8c38b 100644
--- a/src/main/java/org/jabref/gui/ClipBoardManager.java
+++ b/src/main/java/org/jabref/gui/ClipBoardManager.java
@@ -1,12 +1,6 @@
package org.jabref.gui;
-import java.awt.Toolkit;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.StringSelection;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
-import java.io.IOException;
-import java.util.List;
+import com.airhacks.afterburner.injection.Injector;
import javafx.application.Platform;
import javafx.scene.control.TextInputControl;
@@ -23,11 +17,17 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.entry.BibtexString;
-
-import com.airhacks.afterburner.injection.Injector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.awt.Toolkit;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.List;
+
@AllowedToUseAwt("Requires ava.awt.datatransfer.Clipboard")
public class ClipBoardManager {
@@ -58,19 +58,25 @@ public ClipBoardManager(Clipboard clipboard, java.awt.datatransfer.Clipboard pri
* text over clipboards
*/
public static void addX11Support(TextInputControl input) {
- input.selectedTextProperty().addListener(
- // using InvalidationListener because of https://bugs.openjdk.java.net/browse/JDK-8176270
- observable -> Platform.runLater(() -> {
- String newValue = input.getSelectedText();
- if (!newValue.isEmpty() && (primary != null)) {
- primary.setContents(new StringSelection(newValue), null);
+ input.selectedTextProperty()
+ .addListener(
+ // using InvalidationListener because of
+ // https://bugs.openjdk.java.net/browse/JDK-8176270
+ observable ->
+ Platform.runLater(
+ () -> {
+ String newValue = input.getSelectedText();
+ if (!newValue.isEmpty() && (primary != null)) {
+ primary.setContents(
+ new StringSelection(newValue), null);
+ }
+ }));
+ input.setOnMouseClicked(
+ event -> {
+ if (event.getButton() == MouseButton.MIDDLE) {
+ input.insertText(input.getCaretPosition(), getContentsPrimary());
}
- }));
- input.setOnMouseClicked(event -> {
- if (event.getButton() == MouseButton.MIDDLE) {
- input.insertText(input.getCaretPosition(), getContentsPrimary());
- }
- });
+ });
}
/**
@@ -153,25 +159,39 @@ public void setContent(String string) {
setPrimaryClipboardContent(content);
}
- public void setContent(List entries, BibEntryTypesManager entryTypesManager) throws IOException {
+ public void setContent(List entries, BibEntryTypesManager entryTypesManager)
+ throws IOException {
String serializedEntries = serializeEntries(entries, entryTypesManager);
setContent(serializedEntries);
}
- public void setContent(List entries, BibEntryTypesManager entryTypesManager, List stringConstants) throws IOException {
+ public void setContent(
+ List entries,
+ BibEntryTypesManager entryTypesManager,
+ List stringConstants)
+ throws IOException {
StringBuilder builder = new StringBuilder();
- stringConstants.forEach(strConst -> builder.append(strConst.getParsedSerialization() == null ? "" : strConst.getParsedSerialization()));
+ stringConstants.forEach(
+ strConst ->
+ builder.append(
+ strConst.getParsedSerialization() == null
+ ? ""
+ : strConst.getParsedSerialization()));
String serializedEntries = serializeEntries(entries, entryTypesManager);
builder.append(serializedEntries);
setContent(builder.toString());
}
- private String serializeEntries(List entries, BibEntryTypesManager entryTypesManager) throws IOException {
+ private String serializeEntries(List entries, BibEntryTypesManager entryTypesManager)
+ throws IOException {
CliPreferences preferences = Injector.instantiateModelOrService(CliPreferences.class);
// BibEntry is not Java serializable. Thus, we need to do the serialization manually
- // At reading of the clipboard in JabRef, we parse the plain string in all cases, so we don't need to flag we put BibEntries here
+ // At reading of the clipboard in JabRef, we parse the plain string in all cases, so we
+ // don't need to flag we put BibEntries here
// Furthermore, storing a string also enables other applications to work with the data
- BibEntryWriter writer = new BibEntryWriter(new FieldWriter(preferences.getFieldPreferences()), entryTypesManager);
+ BibEntryWriter writer =
+ new BibEntryWriter(
+ new FieldWriter(preferences.getFieldPreferences()), entryTypesManager);
return writer.serializeAll(entries, BibDatabaseMode.BIBTEX);
}
}
diff --git a/src/main/java/org/jabref/gui/CoreGuiPreferences.java b/src/main/java/org/jabref/gui/CoreGuiPreferences.java
index 23212a62ed19..0c949da63dff 100644
--- a/src/main/java/org/jabref/gui/CoreGuiPreferences.java
+++ b/src/main/java/org/jabref/gui/CoreGuiPreferences.java
@@ -19,13 +19,14 @@ public class CoreGuiPreferences {
private final StringProperty lastSelectedIdBasedFetcher;
- public CoreGuiPreferences(double positionX,
- double positionY,
- double sizeX,
- double sizeY,
- boolean windowMaximised,
- String lastSelectedIdBasedFetcher,
- double sidePaneWidth) {
+ public CoreGuiPreferences(
+ double positionX,
+ double positionY,
+ double sizeX,
+ double sizeY,
+ boolean windowMaximised,
+ String lastSelectedIdBasedFetcher,
+ double sidePaneWidth) {
this.positionX = new SimpleDoubleProperty(positionX);
this.positionY = new SimpleDoubleProperty(positionY);
this.sizeX = new SimpleDoubleProperty(sizeX);
diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java
index 7248be475117..bc08b1fc31fb 100644
--- a/src/main/java/org/jabref/gui/DialogService.java
+++ b/src/main/java/org/jabref/gui/DialogService.java
@@ -1,12 +1,5 @@
package org.jabref.gui;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Consumer;
-
import javafx.concurrent.Task;
import javafx.print.PrinterJob;
import javafx.scene.control.Alert;
@@ -17,6 +10,8 @@
import javafx.scene.control.TextInputDialog;
import javafx.util.StringConverter;
+import org.controlsfx.control.textfield.CustomPasswordField;
+import org.controlsfx.dialog.ProgressDialog;
import org.jabref.gui.util.BaseDialog;
import org.jabref.gui.util.BaseWindow;
import org.jabref.gui.util.DirectoryDialogConfiguration;
@@ -24,8 +19,12 @@
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.util.NotificationService;
-import org.controlsfx.control.textfield.CustomPasswordField;
-import org.controlsfx.dialog.ProgressDialog;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
/**
* This interface provides methods to create dialogs and show them to the user.
@@ -37,19 +36,37 @@ public interface DialogService extends NotificationService {
*
* @implNote The implementation should accept {@code null} for {@code defaultChoice}, but callers should use {@link #showChoiceDialogAndWait(String, String, String, Collection)}.
*/
- Optional showChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices);
+ Optional showChoiceDialogAndWait(
+ String title,
+ String content,
+ String okButtonLabel,
+ T defaultChoice,
+ Collection choices);
/**
* This will create and display new {@link ChoiceDialog} of type T with a collection of possible choices
*/
- default Optional showChoiceDialogAndWait(String title, String content, String okButtonLabel, Collection choices) {
+ default Optional showChoiceDialogAndWait(
+ String title, String content, String okButtonLabel, Collection choices) {
return showChoiceDialogAndWait(title, content, okButtonLabel, null, choices);
}
- Optional showEditableChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices, StringConverter converter);
-
- default Optional showEditableChoiceDialogAndWait(String title, String content, String okButtonLabel, Collection choices, StringConverter converter) {
- return showEditableChoiceDialogAndWait(title, content, okButtonLabel, null, choices, converter);
+ Optional showEditableChoiceDialogAndWait(
+ String title,
+ String content,
+ String okButtonLabel,
+ T defaultChoice,
+ Collection choices,
+ StringConverter converter);
+
+ default Optional showEditableChoiceDialogAndWait(
+ String title,
+ String content,
+ String okButtonLabel,
+ Collection choices,
+ StringConverter converter) {
+ return showEditableChoiceDialogAndWait(
+ title, content, okButtonLabel, null, choices, converter);
}
/**
@@ -60,7 +77,8 @@ default Optional showEditableChoiceDialogAndWait(String title, String con
/**
* This will create and display new {@link TextInputDialog} with a text field with a default value to enter data
*/
- Optional showInputDialogWithDefaultAndWait(String title, String content, String defaultValue);
+ Optional showInputDialogWithDefaultAndWait(
+ String title, String content, String defaultValue);
/**
* This will create and display a new information dialog.
@@ -145,7 +163,8 @@ default Optional showEditableChoiceDialogAndWait(String title, String con
*
* @return true if the use clicked "OK" otherwise false
*/
- boolean showConfirmationDialogAndWait(String title, String content, String okButtonLabel, String cancelButtonLabel);
+ boolean showConfirmationDialogAndWait(
+ String title, String content, String okButtonLabel, String cancelButtonLabel);
/**
* Create and display a new confirmation dialog.
@@ -156,8 +175,8 @@ default Optional showEditableChoiceDialogAndWait(String title, String con
*
* @return true if the use clicked "YES" otherwise false
*/
- boolean showConfirmationDialogWithOptOutAndWait(String title, String content,
- String optOutMessage, Consumer optOutAction);
+ boolean showConfirmationDialogWithOptOutAndWait(
+ String title, String content, String optOutMessage, Consumer optOutAction);
/**
* Create and display a new confirmation dialog.
@@ -168,9 +187,13 @@ boolean showConfirmationDialogWithOptOutAndWait(String title, String content,
*
* @return true if the use clicked "YES" otherwise false
*/
- boolean showConfirmationDialogWithOptOutAndWait(String title, String content,
- String okButtonLabel, String cancelButtonLabel,
- String optOutMessage, Consumer optOutAction);
+ boolean showConfirmationDialogWithOptOutAndWait(
+ String title,
+ String content,
+ String okButtonLabel,
+ String cancelButtonLabel,
+ String optOutMessage,
+ Consumer optOutAction);
/**
* This will create and display new {@link CustomPasswordField} that doesn't show the text, and two buttons
@@ -201,8 +224,8 @@ boolean showConfirmationDialogWithOptOutAndWait(String title, String content,
*
* @return Optional with the pressed Button as ButtonType
*/
- Optional showCustomButtonDialogAndWait(Alert.AlertType type, String title, String content,
- ButtonType... buttonTypes);
+ Optional showCustomButtonDialogAndWait(
+ Alert.AlertType type, String title, String content, ButtonType... buttonTypes);
/**
* This will create and display a new dialog showing a custom {@link DialogPane}
@@ -210,7 +233,8 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String
*
* @return Optional with the pressed Button as ButtonType
*/
- Optional showCustomDialogAndWait(String title, DialogPane contentPane, ButtonType... buttonTypes);
+ Optional showCustomDialogAndWait(
+ String title, DialogPane contentPane, ButtonType... buttonTypes);
/**
* Shows a custom dialog and returns the result.
@@ -250,7 +274,8 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String
* @param content message to show below the list of background tasks
* @param stateManager The {@link StateManager} which contains the background tasks
*/
- Optional showBackgroundProgressDialogAndWait(String title, String content, StateManager stateManager);
+ Optional showBackgroundProgressDialogAndWait(
+ String title, String content, StateManager stateManager);
/**
* Shows a new file save dialog. The method doesn't return until the
@@ -281,7 +306,8 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String
*
* @return the selected files or an empty {@link List} if no file has been selected
*/
- List showFileOpenDialogAndGetMultipleFiles(FileDialogConfiguration fileDialogConfiguration);
+ List showFileOpenDialogAndGetMultipleFiles(
+ FileDialogConfiguration fileDialogConfiguration);
/**
* Shows a new directory selection dialog. The method doesn't return until the
@@ -291,7 +317,8 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String
*
* @return the selected directory or an empty {@link Optional} if no directory has been selected
*/
- Optional showDirectorySelectionDialog(DirectoryDialogConfiguration directoryDialogConfiguration);
+ Optional showDirectorySelectionDialog(
+ DirectoryDialogConfiguration directoryDialogConfiguration);
/**
* Displays a Print Dialog. Allow the user to update job state such as printer and settings. These changes will be
diff --git a/src/main/java/org/jabref/gui/DragAndDropDataFormats.java b/src/main/java/org/jabref/gui/DragAndDropDataFormats.java
index 4ab27396efa0..1fe7f2e9873a 100644
--- a/src/main/java/org/jabref/gui/DragAndDropDataFormats.java
+++ b/src/main/java/org/jabref/gui/DragAndDropDataFormats.java
@@ -1,20 +1,27 @@
package org.jabref.gui;
-import java.util.List;
-
import javafx.scene.input.DataFormat;
import org.jabref.logic.preview.PreviewLayout;
+import java.util.List;
+
/**
* Contains all the different {@link DataFormat}s that may occur in JabRef.
*/
public class DragAndDropDataFormats {
public static final DataFormat FIELD = new DataFormat("dnd/org.jabref.model.entry.field.Field");
- public static final DataFormat GROUP = new DataFormat("dnd/org.jabref.model.groups.GroupTreeNode");
- public static final DataFormat LINKED_FILE = new DataFormat("dnd/org.jabref.model.entry.LinkedFile");
- public static final DataFormat ENTRIES = new DataFormat("dnd/org.jabref.model.entry.BibEntries");
- public static final DataFormat PREVIEWLAYOUTS = new DataFormat("dnd/org.jabref.logic.citationstyle.PreviewLayouts");
- @SuppressWarnings("unchecked") public static final Class> PREVIEWLAYOUT_LIST_CLASS = (Class>) (Class>) List.class;
+ public static final DataFormat GROUP =
+ new DataFormat("dnd/org.jabref.model.groups.GroupTreeNode");
+ public static final DataFormat LINKED_FILE =
+ new DataFormat("dnd/org.jabref.model.entry.LinkedFile");
+ public static final DataFormat ENTRIES =
+ new DataFormat("dnd/org.jabref.model.entry.BibEntries");
+ public static final DataFormat PREVIEWLAYOUTS =
+ new DataFormat("dnd/org.jabref.logic.citationstyle.PreviewLayouts");
+
+ @SuppressWarnings("unchecked")
+ public static final Class> PREVIEWLAYOUT_LIST_CLASS =
+ (Class>) (Class>) List.class;
}
diff --git a/src/main/java/org/jabref/gui/FXDialog.java b/src/main/java/org/jabref/gui/FXDialog.java
index 891eae589f7d..a16ea0d77eb3 100644
--- a/src/main/java/org/jabref/gui/FXDialog.java
+++ b/src/main/java/org/jabref/gui/FXDialog.java
@@ -1,5 +1,7 @@
package org.jabref.gui;
+import com.airhacks.afterburner.injection.Injector;
+
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Alert;
import javafx.scene.control.Dialog;
@@ -12,8 +14,6 @@
import org.jabref.gui.keyboard.KeyBinding;
import org.jabref.gui.keyboard.KeyBindingRepository;
-import com.airhacks.afterburner.injection.Injector;
-
/**
* This class provides a super class for all dialogs implemented in JavaFX.
*
@@ -59,12 +59,17 @@ public FXDialog(AlertType type, boolean isModal) {
initModality(Modality.NONE);
}
- dialogWindow.getScene().setOnKeyPressed(event -> {
- KeyBindingRepository keyBindingRepository = Injector.instantiateModelOrService(KeyBindingRepository.class);
- if (keyBindingRepository.checkKeyCombinationEquality(KeyBinding.CLOSE, event)) {
- dialogWindow.close();
- }
- });
+ dialogWindow
+ .getScene()
+ .setOnKeyPressed(
+ event -> {
+ KeyBindingRepository keyBindingRepository =
+ Injector.instantiateModelOrService(KeyBindingRepository.class);
+ if (keyBindingRepository.checkKeyCombinationEquality(
+ KeyBinding.CLOSE, event)) {
+ dialogWindow.close();
+ }
+ });
}
public FXDialog(AlertType type) {
diff --git a/src/main/java/org/jabref/gui/JabRefDialogService.java b/src/main/java/org/jabref/gui/JabRefDialogService.java
index dccdc17898dd..0e1c39925714 100644
--- a/src/main/java/org/jabref/gui/JabRefDialogService.java
+++ b/src/main/java/org/jabref/gui/JabRefDialogService.java
@@ -1,14 +1,6 @@
package org.jabref.gui;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Consumer;
+import com.tobiasdiez.easybind.EasyBind;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
@@ -37,6 +29,11 @@
import javafx.util.Duration;
import javafx.util.StringConverter;
+import org.controlsfx.control.Notifications;
+import org.controlsfx.control.TaskProgressView;
+import org.controlsfx.control.textfield.CustomPasswordField;
+import org.controlsfx.dialog.ExceptionDialog;
+import org.controlsfx.dialog.ProgressDialog;
import org.jabref.gui.help.ErrorConsoleAction;
import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.theme.ThemeManager;
@@ -51,16 +48,19 @@
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.FetcherServerException;
import org.jabref.logic.l10n.Localization;
-
-import com.tobiasdiez.easybind.EasyBind;
-import org.controlsfx.control.Notifications;
-import org.controlsfx.control.TaskProgressView;
-import org.controlsfx.control.textfield.CustomPasswordField;
-import org.controlsfx.dialog.ExceptionDialog;
-import org.controlsfx.dialog.ProgressDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+
/**
* This class provides methods to create default
* JavaFX dialogs which will also work on top of Swing
@@ -97,26 +97,29 @@ private FXDialog createDialog(AlertType type, String title, String content) {
return alert;
}
- private FXDialog createDialogWithOptOut(String title, String content,
- String optOutMessage, Consumer optOutAction) {
+ private FXDialog createDialogWithOptOut(
+ String title, String content, String optOutMessage, Consumer optOutAction) {
FXDialog alert = new FXDialog(AlertType.CONFIRMATION, title, true);
- // Need to force the alert to layout in order to grab the graphic as we are replacing the dialog pane with a custom pane
+ // Need to force the alert to layout in order to grab the graphic as we are replacing the
+ // dialog pane with a custom pane
alert.getDialogPane().applyCss();
Node graphic = alert.getDialogPane().getGraphic();
// Create a new dialog pane that has a checkbox instead of the hide/show details button
// Use the supplied callback for the action of the checkbox
- alert.setDialogPane(new DialogPane() {
- @Override
- protected Node createDetailsButton() {
- CheckBox optOut = new CheckBox();
- optOut.setText(optOutMessage);
- optOut.setOnAction(e -> optOutAction.accept(optOut.isSelected()));
- return optOut;
- }
- });
-
- // Fool the dialog into thinking there is some expandable content; a group won't take up any space if it has no children
+ alert.setDialogPane(
+ new DialogPane() {
+ @Override
+ protected Node createDetailsButton() {
+ CheckBox optOut = new CheckBox();
+ optOut.setText(optOutMessage);
+ optOut.setOnAction(e -> optOutAction.accept(optOut.isSelected()));
+ return optOut;
+ }
+ });
+
+ // Fool the dialog into thinking there is some expandable content; a group won't take up any
+ // space if it has no children
alert.getDialogPane().setExpandableContent(new Group());
alert.getDialogPane().setExpanded(true);
@@ -136,9 +139,16 @@ public static String shortenDialogMessage(String dialogMessage) {
return (dialogMessage.substring(0, JabRefDialogService.DIALOG_SIZE_LIMIT) + "...").trim();
}
- private ChoiceDialog createChoiceDialog(String title, String content, String okButtonLabel, T defaultChoice, Collection choices) {
+ private ChoiceDialog createChoiceDialog(
+ String title,
+ String content,
+ String okButtonLabel,
+ T defaultChoice,
+ Collection choices) {
ChoiceDialog choiceDialog = new ChoiceDialog<>(defaultChoice, choices);
- ((Stage) choiceDialog.getDialogPane().getScene().getWindow()).getIcons().add(IconTheme.getJabRefImage());
+ ((Stage) choiceDialog.getDialogPane().getScene().getWindow())
+ .getIcons()
+ .add(IconTheme.getJabRefImage());
ButtonType okButtonType = new ButtonType(okButtonLabel, ButtonBar.ButtonData.OK_DONE);
choiceDialog.getDialogPane().getButtonTypes().setAll(ButtonType.CANCEL, okButtonType);
choiceDialog.setHeaderText(title);
@@ -149,17 +159,32 @@ private ChoiceDialog createChoiceDialog(String title, String content, Str
}
@Override
- public Optional showChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices) {
- return createChoiceDialog(title, content, okButtonLabel, defaultChoice, choices).showAndWait();
+ public Optional showChoiceDialogAndWait(
+ String title,
+ String content,
+ String okButtonLabel,
+ T defaultChoice,
+ Collection choices) {
+ return createChoiceDialog(title, content, okButtonLabel, defaultChoice, choices)
+ .showAndWait();
}
@Override
- public Optional showEditableChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices, StringConverter converter) {
- ChoiceDialog choiceDialog = createChoiceDialog(title, content, okButtonLabel, defaultChoice, choices);
+ public Optional showEditableChoiceDialogAndWait(
+ String title,
+ String content,
+ String okButtonLabel,
+ T defaultChoice,
+ Collection choices,
+ StringConverter converter) {
+ ChoiceDialog choiceDialog =
+ createChoiceDialog(title, content, okButtonLabel, defaultChoice, choices);
ComboBox comboBox = (ComboBox) choiceDialog.getDialogPane().lookup(".combo-box");
comboBox.setEditable(true);
comboBox.setConverter(converter);
- EasyBind.subscribe(comboBox.getEditor().textProperty(), text -> comboBox.setValue(converter.fromString(text)));
+ EasyBind.subscribe(
+ comboBox.getEditor().textProperty(),
+ text -> comboBox.setValue(converter.fromString(text)));
return choiceDialog.showAndWait();
}
@@ -173,7 +198,8 @@ public Optional showInputDialogAndWait(String title, String content) {
}
@Override
- public Optional showInputDialogWithDefaultAndWait(String title, String content, String defaultValue) {
+ public Optional showInputDialogWithDefaultAndWait(
+ String title, String content, String defaultValue) {
TextInputDialog inputDialog = new TextInputDialog(defaultValue);
inputDialog.setHeaderText(title);
inputDialog.setContentText(content);
@@ -224,12 +250,23 @@ public void showErrorDialogAndWait(FetcherException fetcherException) {
String localizedMessage = fetcherException.getLocalizedMessage();
Optional httpResponse = fetcherException.getHttpResponse();
if (httpResponse.isPresent()) {
- this.showInformationDialogAndWait(failedTitle, getContentByCode(httpResponse.get().statusCode()) + "\n\n" + localizedMessage);
+ this.showInformationDialogAndWait(
+ failedTitle,
+ getContentByCode(httpResponse.get().statusCode()) + "\n\n" + localizedMessage);
} else if (fetcherException instanceof FetcherClientException) {
- this.showErrorDialogAndWait(failedTitle, Localization.lang("Something is wrong on JabRef side. Please check the URL and try again.") + "\n\n" + localizedMessage);
+ this.showErrorDialogAndWait(
+ failedTitle,
+ Localization.lang(
+ "Something is wrong on JabRef side. Please check the URL and try again.")
+ + "\n\n"
+ + localizedMessage);
} else if (fetcherException instanceof FetcherServerException) {
- this.showInformationDialogAndWait(failedTitle,
- Localization.lang("Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.") + "\n\n" + localizedMessage);
+ this.showInformationDialogAndWait(
+ failedTitle,
+ Localization.lang(
+ "Error downloading from URL. Cause is likely the server side.\nPlease try again later or contact the server administrator.")
+ + "\n\n"
+ + localizedMessage);
} else {
this.showErrorDialogAndWait(failedTitle, localizedMessage);
}
@@ -246,7 +283,8 @@ public void showErrorDialogAndWait(String title, String content, Throwable excep
@Override
public void showErrorDialogAndWait(String message) {
- FXDialog alert = createDialog(AlertType.ERROR, Localization.lang("Error Occurred"), message);
+ FXDialog alert =
+ createDialog(AlertType.ERROR, Localization.lang("Error Occurred"), message);
alert.showAndWait();
}
@@ -257,7 +295,8 @@ public boolean showConfirmationDialogAndWait(String title, String content) {
}
@Override
- public boolean showConfirmationDialogAndWait(String title, String content, String okButtonLabel) {
+ public boolean showConfirmationDialogAndWait(
+ String title, String content, String okButtonLabel) {
FXDialog alert = createDialog(AlertType.CONFIRMATION, title, content);
ButtonType okButtonType = new ButtonType(okButtonLabel, ButtonBar.ButtonData.OK_DONE);
alert.getButtonTypes().setAll(ButtonType.CANCEL, okButtonType);
@@ -265,8 +304,8 @@ public boolean showConfirmationDialogAndWait(String title, String content, Strin
}
@Override
- public boolean showConfirmationDialogAndWait(String title, String content,
- String okButtonLabel, String cancelButtonLabel) {
+ public boolean showConfirmationDialogAndWait(
+ String title, String content, String okButtonLabel, String cancelButtonLabel) {
FXDialog alert = createDialog(AlertType.CONFIRMATION, title, content);
ButtonType okButtonType = new ButtonType(okButtonLabel, ButtonBar.ButtonData.OK_DONE);
ButtonType cancelButtonType = new ButtonType(cancelButtonLabel, ButtonBar.ButtonData.NO);
@@ -275,17 +314,21 @@ public boolean showConfirmationDialogAndWait(String title, String content,
}
@Override
- public boolean showConfirmationDialogWithOptOutAndWait(String title, String content,
- String optOutMessage, Consumer optOutAction) {
+ public boolean showConfirmationDialogWithOptOutAndWait(
+ String title, String content, String optOutMessage, Consumer optOutAction) {
FXDialog alert = createDialogWithOptOut(title, content, optOutMessage, optOutAction);
alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO);
return alert.showAndWait().filter(buttonType -> buttonType == ButtonType.YES).isPresent();
}
@Override
- public boolean showConfirmationDialogWithOptOutAndWait(String title, String content,
- String okButtonLabel, String cancelButtonLabel,
- String optOutMessage, Consumer optOutAction) {
+ public boolean showConfirmationDialogWithOptOutAndWait(
+ String title,
+ String content,
+ String okButtonLabel,
+ String cancelButtonLabel,
+ String optOutMessage,
+ Consumer optOutAction) {
FXDialog alert = createDialogWithOptOut(title, content, optOutMessage, optOutAction);
ButtonType okButtonType = new ButtonType(okButtonLabel, ButtonBar.ButtonData.YES);
ButtonType cancelButtonType = new ButtonType(cancelButtonLabel, ButtonBar.ButtonData.NO);
@@ -294,16 +337,16 @@ public boolean showConfirmationDialogWithOptOutAndWait(String title, String cont
}
@Override
- public Optional showCustomButtonDialogAndWait(AlertType type, String title, String content,
- ButtonType... buttonTypes) {
+ public Optional showCustomButtonDialogAndWait(
+ AlertType type, String title, String content, ButtonType... buttonTypes) {
FXDialog alert = createDialog(type, title, content);
alert.getButtonTypes().setAll(buttonTypes);
return alert.showAndWait();
}
@Override
- public Optional showCustomDialogAndWait(String title, DialogPane contentPane,
- ButtonType... buttonTypes) {
+ public Optional showCustomDialogAndWait(
+ String title, DialogPane contentPane, ButtonType... buttonTypes) {
FXDialog alert = new FXDialog(AlertType.NONE, title);
alert.setDialogPane(contentPane);
alert.getButtonTypes().setAll(buttonTypes);
@@ -336,12 +379,13 @@ public Optional showPasswordDialogAndWait(String title, String header, S
dialog.getDialogPane().setContent(box);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK);
- dialog.setResultConverter(dialogButton -> {
- if (dialogButton == ButtonType.OK) {
- return passwordField.getText();
- }
- return null;
- });
+ dialog.setResultConverter(
+ dialogButton -> {
+ if (dialogButton == ButtonType.OK) {
+ return passwordField.getText();
+ }
+ return null;
+ });
return dialog.showAndWait();
}
@@ -351,15 +395,18 @@ private ProgressDialog createProgressDialog(String title, String content, Ta
progressDialog.setTitle(title);
progressDialog.setContentText(content);
progressDialog.setGraphic(null);
- ((Stage) progressDialog.getDialogPane().getScene().getWindow()).getIcons().add(IconTheme.getJabRefImage());
+ ((Stage) progressDialog.getDialogPane().getScene().getWindow())
+ .getIcons()
+ .add(IconTheme.getJabRefImage());
progressDialog.setOnCloseRequest(evt -> task.cancel());
DialogPane dialogPane = progressDialog.getDialogPane();
dialogPane.getButtonTypes().add(ButtonType.CANCEL);
Button cancelButton = (Button) dialogPane.lookupButton(ButtonType.CANCEL);
- cancelButton.setOnAction(evt -> {
- task.cancel();
- progressDialog.close();
- });
+ cancelButton.setOnAction(
+ evt -> {
+ task.cancel();
+ progressDialog.close();
+ });
progressDialog.initOwner(mainWindow);
return progressDialog;
}
@@ -377,11 +424,13 @@ public void showProgressDialogAndWait(String title, String content, Task
}
@Override
- public Optional showBackgroundProgressDialogAndWait(String title, String content, StateManager stateManager) {
+ public Optional showBackgroundProgressDialogAndWait(
+ String title, String content, StateManager stateManager) {
TaskProgressView> taskProgressView = new TaskProgressView<>();
EasyBind.bindContent(taskProgressView.getTasks(), stateManager.getRunningBackgroundTasks());
taskProgressView.setRetainTasks(false);
- taskProgressView.setGraphicFactory(task -> ThemeManager.getDownloadIconTitleMap.getOrDefault(task.getTitle(), null));
+ taskProgressView.setGraphicFactory(
+ task -> ThemeManager.getDownloadIconTitleMap.getOrDefault(task.getTitle(), null));
Label message = new Label(content);
@@ -397,12 +446,15 @@ public Optional showBackgroundProgressDialogAndWait(String title, St
alert.setResizable(true);
alert.initOwner(mainWindow);
- stateManager.getAnyTasksThatWillNotBeRecoveredRunning().addListener((observable, oldValue, newValue) -> {
- if (!newValue) {
- alert.setResult(ButtonType.YES);
- alert.close();
- }
- });
+ stateManager
+ .getAnyTasksThatWillNotBeRecoveredRunning()
+ .addListener(
+ (observable, oldValue, newValue) -> {
+ if (!newValue) {
+ alert.setResult(ButtonType.YES);
+ alert.close();
+ }
+ });
return alert.showAndWait();
}
@@ -413,31 +465,40 @@ public void notify(String message) {
// The event log is not that user friendly (different purpose).
LOGGER.info(message);
- UiTaskExecutor.runInJavaFXThread(() ->
- Notifications.create()
- .text(message)
- .position(Pos.BOTTOM_CENTER)
- .hideAfter(TOAST_MESSAGE_DISPLAY_TIME)
- .owner(mainWindow)
- .threshold(5,
- Notifications.create()
- .title(Localization.lang("Last notification"))
- .text(
- "(" + Localization.lang("Check the event log to see all notifications") + ")"
- + "\n\n" + message)
- .onAction(e -> {
- ErrorConsoleAction ec = new ErrorConsoleAction();
- ec.execute();
- }))
- .hideCloseButton()
- .show());
+ UiTaskExecutor.runInJavaFXThread(
+ () ->
+ Notifications.create()
+ .text(message)
+ .position(Pos.BOTTOM_CENTER)
+ .hideAfter(TOAST_MESSAGE_DISPLAY_TIME)
+ .owner(mainWindow)
+ .threshold(
+ 5,
+ Notifications.create()
+ .title(Localization.lang("Last notification"))
+ .text(
+ "("
+ + Localization.lang(
+ "Check the event log to see all notifications")
+ + ")"
+ + "\n\n"
+ + message)
+ .onAction(
+ e -> {
+ ErrorConsoleAction ec =
+ new ErrorConsoleAction();
+ ec.execute();
+ }))
+ .hideCloseButton()
+ .show());
}
@Override
public Optional showFileSaveDialog(FileDialogConfiguration fileDialogConfiguration) {
FileChooser chooser = getConfiguredFileChooser(fileDialogConfiguration);
File file = chooser.showSaveDialog(mainWindow);
- Optional.ofNullable(chooser.getSelectedExtensionFilter()).ifPresent(fileDialogConfiguration::setSelectedExtensionFilter);
+ Optional.ofNullable(chooser.getSelectedExtensionFilter())
+ .ifPresent(fileDialogConfiguration::setSelectedExtensionFilter);
return Optional.ofNullable(file).map(File::toPath);
}
@@ -445,27 +506,34 @@ public Optional showFileSaveDialog(FileDialogConfiguration fileDialogConfi
public Optional showFileOpenDialog(FileDialogConfiguration fileDialogConfiguration) {
FileChooser chooser = getConfiguredFileChooser(fileDialogConfiguration);
File file = chooser.showOpenDialog(mainWindow);
- Optional.ofNullable(chooser.getSelectedExtensionFilter()).ifPresent(fileDialogConfiguration::setSelectedExtensionFilter);
+ Optional.ofNullable(chooser.getSelectedExtensionFilter())
+ .ifPresent(fileDialogConfiguration::setSelectedExtensionFilter);
return Optional.ofNullable(file).map(File::toPath);
}
@Override
- public Optional showDirectorySelectionDialog(DirectoryDialogConfiguration directoryDialogConfiguration) {
+ public Optional showDirectorySelectionDialog(
+ DirectoryDialogConfiguration directoryDialogConfiguration) {
DirectoryChooser chooser = getConfiguredDirectoryChooser(directoryDialogConfiguration);
File file = chooser.showDialog(mainWindow);
return Optional.ofNullable(file).map(File::toPath);
}
@Override
- public List showFileOpenDialogAndGetMultipleFiles(FileDialogConfiguration fileDialogConfiguration) {
+ public List showFileOpenDialogAndGetMultipleFiles(
+ FileDialogConfiguration fileDialogConfiguration) {
FileChooser chooser = getConfiguredFileChooser(fileDialogConfiguration);
List files = chooser.showOpenMultipleDialog(mainWindow);
return files != null ? files.stream().map(File::toPath).toList() : List.of();
}
- private DirectoryChooser getConfiguredDirectoryChooser(DirectoryDialogConfiguration directoryDialogConfiguration) {
+ private DirectoryChooser getConfiguredDirectoryChooser(
+ DirectoryDialogConfiguration directoryDialogConfiguration) {
DirectoryChooser chooser = new DirectoryChooser();
- directoryDialogConfiguration.getInitialDirectory().map(Path::toFile).ifPresent(chooser::setInitialDirectory);
+ directoryDialogConfiguration
+ .getInitialDirectory()
+ .map(Path::toFile)
+ .ifPresent(chooser::setInitialDirectory);
return chooser;
}
@@ -474,7 +542,10 @@ private FileChooser getConfiguredFileChooser(FileDialogConfiguration fileDialogC
chooser.getExtensionFilters().addAll(fileDialogConfiguration.getExtensionFilters());
chooser.setSelectedExtensionFilter(fileDialogConfiguration.getDefaultExtension());
chooser.setInitialFileName(fileDialogConfiguration.getInitialFileName());
- fileDialogConfiguration.getInitialDirectory().map(Path::toFile).ifPresent(chooser::setInitialDirectory);
+ fileDialogConfiguration
+ .getInitialDirectory()
+ .map(Path::toFile)
+ .ifPresent(chooser::setInitialDirectory);
return chooser;
}
@@ -512,13 +583,17 @@ public void showCustomWindow(BaseWindow window) {
private String getContentByCode(int statusCode) {
return switch (statusCode) {
case 401 ->
- Localization.lang("Access denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.");
+ Localization.lang(
+ "Access denied. You are not authorized to access this resource. Please check your credentials and try again. If you believe you should have access, please contact the administrator for assistance.");
case 403 ->
- Localization.lang("Access denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.");
+ Localization.lang(
+ "Access denied. You do not have permission to access this resource. Please contact the administrator for assistance or try a different action.");
case 404 ->
- Localization.lang("The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.");
+ Localization.lang(
+ "The requested resource could not be found. It seems that the file you are trying to download is not available or has been moved. Please verify the URL and try again. If you believe this is an error, please contact the administrator for further assistance.");
default ->
- Localization.lang("Something is wrong on JabRef side. Please check the URL and try again.");
+ Localization.lang(
+ "Something is wrong on JabRef side. Please check the URL and try again.");
};
}
}
diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java
index b0c0e1c83f0e..fda21561e73b 100644
--- a/src/main/java/org/jabref/gui/JabRefGUI.java
+++ b/src/main/java/org/jabref/gui/JabRefGUI.java
@@ -1,9 +1,7 @@
package org.jabref.gui;
-import java.util.List;
-import java.util.Optional;
-
-import javax.swing.undo.UndoManager;
+import com.airhacks.afterburner.injection.Injector;
+import com.tobiasdiez.easybind.EasyBind;
import javafx.application.Application;
import javafx.application.Platform;
@@ -14,6 +12,8 @@
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
+import kong.unirest.core.Unirest;
+
import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService;
import org.jabref.gui.frame.JabRefFrame;
import org.jabref.gui.help.VersionWorker;
@@ -41,13 +41,14 @@
import org.jabref.model.strings.StringUtil;
import org.jabref.model.util.DirectoryMonitor;
import org.jabref.model.util.FileUpdateMonitor;
-
-import com.airhacks.afterburner.injection.Injector;
-import com.tobiasdiez.easybind.EasyBind;
-import kong.unirest.core.Unirest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.List;
+import java.util.Optional;
+
+import javax.swing.undo.UndoManager;
+
/**
* Represents the outer stage and the scene of the JabRef window.
*/
@@ -75,9 +76,10 @@ public class JabRefGUI extends Application {
private Stage mainStage;
- public static void setup(List uiCommands,
- GuiPreferences preferences,
- FileUpdateMonitor fileUpdateMonitor) {
+ public static void setup(
+ List uiCommands,
+ GuiPreferences preferences,
+ FileUpdateMonitor fileUpdateMonitor) {
JabRefGUI.uiCommands = uiCommands;
JabRefGUI.preferences = preferences;
JabRefGUI.fileUpdateMonitor = fileUpdateMonitor;
@@ -87,27 +89,32 @@ public static void setup(List uiCommands,
public void start(Stage stage) {
this.mainStage = stage;
- FallbackExceptionHandler.installExceptionHandler((exception, thread) -> {
- UiTaskExecutor.runInJavaFXThread(() -> {
- DialogService dialogService = Injector.instantiateModelOrService(DialogService.class);
- dialogService.showErrorDialogAndWait("Uncaught exception occurred in " + thread, exception);
- });
- });
+ FallbackExceptionHandler.installExceptionHandler(
+ (exception, thread) -> {
+ UiTaskExecutor.runInJavaFXThread(
+ () -> {
+ DialogService dialogService =
+ Injector.instantiateModelOrService(DialogService.class);
+ dialogService.showErrorDialogAndWait(
+ "Uncaught exception occurred in " + thread, exception);
+ });
+ });
initialize();
- JabRefGUI.mainFrame = new JabRefFrame(
- mainStage,
- dialogService,
- fileUpdateMonitor,
- preferences,
- aiService,
- chatHistoryService,
- stateManager,
- countingUndoManager,
- Injector.instantiateModelOrService(BibEntryTypesManager.class),
- clipBoardManager,
- taskExecutor);
+ JabRefGUI.mainFrame =
+ new JabRefFrame(
+ mainStage,
+ dialogService,
+ fileUpdateMonitor,
+ preferences,
+ aiService,
+ chatHistoryService,
+ stateManager,
+ countingUndoManager,
+ Injector.instantiateModelOrService(BibEntryTypesManager.class),
+ clipBoardManager,
+ taskExecutor);
openWindow();
@@ -115,21 +122,22 @@ public void start(Stage stage) {
if (!fileUpdateMonitor.isActive()) {
dialogService.showErrorDialogAndWait(
- Localization.lang("Unable to monitor file changes. Please close files " +
- "and processes and restart. You may encounter errors if you continue " +
- "with this session."));
+ Localization.lang(
+ "Unable to monitor file changes. Please close files "
+ + "and processes and restart. You may encounter errors if you continue "
+ + "with this session."));
}
BuildInfo buildInfo = Injector.instantiateModelOrService(BuildInfo.class);
- EasyBind.subscribe(preferences.getInternalPreferences().versionCheckEnabledProperty(), enabled -> {
- if (enabled) {
- new VersionWorker(buildInfo.version,
- dialogService,
- taskExecutor,
- preferences)
- .checkForNewVersionDelayed();
- }
- });
+ EasyBind.subscribe(
+ preferences.getInternalPreferences().versionCheckEnabledProperty(),
+ enabled -> {
+ if (enabled) {
+ new VersionWorker(
+ buildInfo.version, dialogService, taskExecutor, preferences)
+ .checkForNewVersionDelayed();
+ }
+ });
setupProxy();
}
@@ -143,12 +151,12 @@ public void initialize() {
JabRefGUI.stateManager = new StateManager();
Injector.setModelOrService(StateManager.class, stateManager);
- Injector.setModelOrService(KeyBindingRepository.class, preferences.getKeyBindingRepository());
+ Injector.setModelOrService(
+ KeyBindingRepository.class, preferences.getKeyBindingRepository());
- JabRefGUI.themeManager = new ThemeManager(
- preferences.getWorkspacePreferences(),
- fileUpdateMonitor,
- Runnable::run);
+ JabRefGUI.themeManager =
+ new ThemeManager(
+ preferences.getWorkspacePreferences(), fileUpdateMonitor, Runnable::run);
Injector.setModelOrService(ThemeManager.class, themeManager);
JabRefGUI.countingUndoManager = new CountingUndoManager();
@@ -165,16 +173,17 @@ public void initialize() {
JabRefGUI.clipBoardManager = new ClipBoardManager();
Injector.setModelOrService(ClipBoardManager.class, clipBoardManager);
- JabRefGUI.aiService = new AiService(
- preferences.getAiPreferences(),
- preferences.getFilePreferences(),
- dialogService,
- taskExecutor);
+ JabRefGUI.aiService =
+ new AiService(
+ preferences.getAiPreferences(),
+ preferences.getFilePreferences(),
+ dialogService,
+ taskExecutor);
Injector.setModelOrService(AiService.class, aiService);
- JabRefGUI.chatHistoryService = new ChatHistoryService(
- preferences.getCitationKeyPatternPreferences(),
- dialogService);
+ JabRefGUI.chatHistoryService =
+ new ChatHistoryService(
+ preferences.getCitationKeyPatternPreferences(), dialogService);
Injector.setModelOrService(ChatHistoryService.class, chatHistoryService);
}
@@ -190,10 +199,11 @@ private void setupProxy() {
return;
}
- Optional password = dialogService.showPasswordDialogAndWait(
- Localization.lang("Proxy configuration"),
- Localization.lang("Proxy requires password"),
- Localization.lang("Password"));
+ Optional password =
+ dialogService.showPasswordDialogAndWait(
+ Localization.lang("Proxy configuration"),
+ Localization.lang("Proxy requires password"),
+ Localization.lang("Password"));
if (password.isPresent()) {
preferences.getProxyPreferences().setPassword(password.get());
@@ -212,7 +222,8 @@ private void openWindow() {
mainStage.setMinWidth(580);
mainStage.setMinHeight(330);
- // maximized target state is stored, because "saveWindowState" saves x and y only if not maximized
+ // maximized target state is stored, because "saveWindowState" saves x and y only if not
+ // maximized
boolean windowMaximised = coreGuiPreferences.isWindowMaximised();
LOGGER.debug("Screens: {}", Screen.getScreens());
@@ -226,7 +237,8 @@ private void openWindow() {
mainStage.setHeight(coreGuiPreferences.getSizeY());
LOGGER.debug("NOT saving window positions");
} else {
- LOGGER.info("The JabRef window is outside of screen bounds. Position and size will be corrected to 1024x768. Primary screen will be used.");
+ LOGGER.info(
+ "The JabRef window is outside of screen bounds. Position and size will be corrected to 1024x768. Primary screen will be used.");
Rectangle2D bounds = Screen.getPrimary().getBounds();
mainStage.setX(bounds.getMinX());
mainStage.setY(bounds.getMinY());
@@ -245,10 +257,11 @@ private void openWindow() {
themeManager.installCss(scene);
LOGGER.debug("Handle TextEditor key bindings");
- scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> TextInputKeyBindings.call(
- scene,
- event,
- preferences.getKeyBindingRepository()));
+ scene.addEventFilter(
+ KeyEvent.KEY_PRESSED,
+ event ->
+ TextInputKeyBindings.call(
+ scene, event, preferences.getKeyBindingRepository()));
mainStage.setTitle(JabRefFrame.FRAME_TITLE);
mainStage.getIcons().addAll(IconTheme.getLogoSetFX());
@@ -270,7 +283,7 @@ public void onShowing(WindowEvent event) {
// Open last edited databases
if (uiCommands.stream().noneMatch(UiCommand.BlankWorkspace.class::isInstance)
- && preferences.getWorkspacePreferences().shouldOpenLastEdited()) {
+ && preferences.getWorkspacePreferences().shouldOpenLastEdited()) {
mainFrame.openLastEditedDatabases();
}
}
@@ -305,7 +318,8 @@ private void saveWindowState() {
* @param mainStage JabRef's stage
*/
private void debugLogWindowState(Stage mainStage) {
- LOGGER.debug("""
+ LOGGER.debug(
+ """
screen data:
mainStage.WINDOW_MAXIMISED: {}
mainStage.POS_X: {}
@@ -313,7 +327,11 @@ private void debugLogWindowState(Stage mainStage) {
mainStage.SIZE_X: {}
mainStage.SIZE_Y: {}
""",
- mainStage.isMaximized(), mainStage.getX(), mainStage.getY(), mainStage.getWidth(), mainStage.getHeight());
+ mainStage.isMaximized(),
+ mainStage.getX(),
+ mainStage.getY(),
+ mainStage.getWidth(),
+ mainStage.getHeight());
}
/**
@@ -323,7 +341,8 @@ private boolean isWindowPositionInBounds() {
CoreGuiPreferences coreGuiPreferences = preferences.getGuiPreferences();
if (LOGGER.isDebugEnabled()) {
- Screen.getScreens().forEach(screen -> LOGGER.debug("Screen bounds: {}", screen.getBounds()));
+ Screen.getScreens()
+ .forEach(screen -> LOGGER.debug("Screen bounds: {}", screen.getBounds()));
}
return lowerLeftIsInBounds(coreGuiPreferences) && upperRightIsInBounds(coreGuiPreferences);
@@ -335,19 +354,24 @@ private boolean lowerLeftIsInBounds(CoreGuiPreferences coreGuiPreferences) {
double bottomY = coreGuiPreferences.getPositionY() + coreGuiPreferences.getSizeY();
LOGGER.debug("left x: {}, bottom y: {}", leftX, bottomY);
- boolean inBounds = Screen.getScreens().stream().anyMatch((screen -> screen.getBounds().contains(leftX, bottomY)));
+ boolean inBounds =
+ Screen.getScreens().stream()
+ .anyMatch((screen -> screen.getBounds().contains(leftX, bottomY)));
LOGGER.debug("lower left corner is in bounds: {}", inBounds);
return inBounds;
}
private boolean upperRightIsInBounds(CoreGuiPreferences coreGuiPreferences) {
// The upper right corner is checked as there are most probably the window controls.
- // Windows/PowerToys somehow adds 10 pixels to the right and top of the screen, they are removed
+ // Windows/PowerToys somehow adds 10 pixels to the right and top of the screen, they are
+ // removed
double rightX = coreGuiPreferences.getPositionX() + coreGuiPreferences.getSizeX() - 10.0;
double topY = coreGuiPreferences.getPositionY();
LOGGER.debug("right x: {}, top y: {}", rightX, topY);
- boolean inBounds = Screen.getScreens().stream().anyMatch((screen -> screen.getBounds().contains(rightX, topY)));
+ boolean inBounds =
+ Screen.getScreens().stream()
+ .anyMatch((screen -> screen.getBounds().contains(rightX, topY)));
LOGGER.debug("upper right corner is in bounds: {}", inBounds);
return inBounds;
}
@@ -355,14 +379,12 @@ private boolean upperRightIsInBounds(CoreGuiPreferences coreGuiPreferences) {
// Background tasks
public void startBackgroundTasks() {
RemotePreferences remotePreferences = preferences.getRemotePreferences();
- BibEntryTypesManager bibEntryTypesManager = Injector.instantiateModelOrService(BibEntryTypesManager.class);
+ BibEntryTypesManager bibEntryTypesManager =
+ Injector.instantiateModelOrService(BibEntryTypesManager.class);
if (remotePreferences.useRemoteServer()) {
remoteListenerServerManager.openAndStart(
new CLIMessageHandler(
- mainFrame,
- preferences,
- fileUpdateMonitor,
- bibEntryTypesManager),
+ mainFrame, preferences, fileUpdateMonitor, bibEntryTypesManager),
remotePreferences.getPort());
}
}
@@ -398,7 +420,8 @@ public static void shutdownThreadPools() {
LOGGER.trace("Shutting down fileUpdateMonitor");
fileUpdateMonitor.shutdown();
LOGGER.trace("Shutting down directoryMonitor");
- DirectoryMonitor directoryMonitor = Injector.instantiateModelOrService(DirectoryMonitor.class);
+ DirectoryMonitor directoryMonitor =
+ Injector.instantiateModelOrService(DirectoryMonitor.class);
directoryMonitor.shutdown();
LOGGER.trace("Shutting down HeadlessExecutorService");
HeadlessExecutorService.INSTANCE.shutdownEverything();
diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java
index 791eec0dee12..ca614a428e9f 100644
--- a/src/main/java/org/jabref/gui/LibraryTab.java
+++ b/src/main/java/org/jabref/gui/LibraryTab.java
@@ -1,16 +1,9 @@
package org.jabref.gui;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Random;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-
-import javax.swing.undo.UndoManager;
+import com.airhacks.afterburner.injection.Injector;
+import com.google.common.eventbus.Subscribe;
+import com.tobiasdiez.easybind.EasyBind;
+import com.tobiasdiez.easybind.Subscription;
import javafx.animation.PauseTransition;
import javafx.application.Platform;
@@ -36,6 +29,8 @@
import javafx.scene.layout.BorderPane;
import javafx.util.Duration;
+import org.controlsfx.control.NotificationPane;
+import org.controlsfx.control.action.Action;
import org.jabref.gui.actions.StandardActions;
import org.jabref.gui.autocompleter.AutoCompletePreferences;
import org.jabref.gui.autocompleter.PersonNameSuggestionProvider;
@@ -98,16 +93,21 @@
import org.jabref.model.util.DirectoryMonitor;
import org.jabref.model.util.DirectoryMonitorManager;
import org.jabref.model.util.FileUpdateMonitor;
-
-import com.airhacks.afterburner.injection.Injector;
-import com.google.common.eventbus.Subscribe;
-import com.tobiasdiez.easybind.EasyBind;
-import com.tobiasdiez.easybind.Subscription;
-import org.controlsfx.control.NotificationPane;
-import org.controlsfx.control.action.Action;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Random;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import javax.swing.undo.UndoManager;
+
/**
* Represents the ui area where the notifier pane, the library table and the entry editor are shown.
*/
@@ -115,7 +115,10 @@ public class LibraryTab extends Tab {
/**
* Defines the different modes that the tab can operate in
*/
- private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR }
+ private enum PanelMode {
+ MAIN_TABLE,
+ MAIN_TABLE_AND_ENTRY_EDITOR
+ }
private static final Logger LOGGER = LoggerFactory.getLogger(LibraryTab.class);
private final LibraryTabContainer tabContainer;
@@ -155,7 +158,8 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR }
private Subscription dividerPositionSubscription;
private ListProperty selectedGroupsProperty;
- private final OptionalObjectProperty searchQueryProperty = OptionalObjectProperty.empty();
+ private final OptionalObjectProperty searchQueryProperty =
+ OptionalObjectProperty.empty();
private final IntegerProperty resultSize = new SimpleIntegerProperty(0);
private Optional changeMonitor = Optional.empty();
@@ -175,17 +179,18 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR }
* If the index is created for the dummy context, the actual context will not be able to open the index until it is closed by the dummy context.
* Closing the index takes time and will slow down opening the library.
*/
- private LibraryTab(BibDatabaseContext bibDatabaseContext,
- LibraryTabContainer tabContainer,
- DialogService dialogService,
- GuiPreferences preferences,
- StateManager stateManager,
- FileUpdateMonitor fileUpdateMonitor,
- BibEntryTypesManager entryTypesManager,
- CountingUndoManager undoManager,
- ClipBoardManager clipBoardManager,
- TaskExecutor taskExecutor,
- boolean isDummyContext) {
+ private LibraryTab(
+ BibDatabaseContext bibDatabaseContext,
+ LibraryTabContainer tabContainer,
+ DialogService dialogService,
+ GuiPreferences preferences,
+ StateManager stateManager,
+ FileUpdateMonitor fileUpdateMonitor,
+ BibEntryTypesManager entryTypesManager,
+ CountingUndoManager undoManager,
+ ClipBoardManager clipBoardManager,
+ TaskExecutor taskExecutor,
+ boolean isDummyContext) {
this.tabContainer = Objects.requireNonNull(tabContainer);
this.bibDatabaseContext = Objects.requireNonNull(bibDatabaseContext);
this.undoManager = undoManager;
@@ -196,7 +201,9 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext,
this.entryTypesManager = entryTypesManager;
this.clipBoardManager = clipBoardManager;
this.taskExecutor = taskExecutor;
- this.directoryMonitorManager = new DirectoryMonitorManager(Injector.instantiateModelOrService(DirectoryMonitor.class));
+ this.directoryMonitorManager =
+ new DirectoryMonitorManager(
+ Injector.instantiateModelOrService(DirectoryMonitor.class));
initializeComponentsAndListeners(isDummyContext);
@@ -220,19 +227,31 @@ private void initializeComponentsAndListeners(boolean isDummyContext) {
bibDatabaseContext.getDatabase().registerListener(this);
bibDatabaseContext.getMetaData().registerListener(this);
- this.selectedGroupsProperty = new SimpleListProperty<>(stateManager.getSelectedGroups(bibDatabaseContext));
- this.tableModel = new MainTableDataModel(getBibDatabaseContext(), preferences, taskExecutor, stateManager, getLuceneManager(), selectedGroupsProperty(), searchQueryProperty(), resultSizeProperty());
+ this.selectedGroupsProperty =
+ new SimpleListProperty<>(stateManager.getSelectedGroups(bibDatabaseContext));
+ this.tableModel =
+ new MainTableDataModel(
+ getBibDatabaseContext(),
+ preferences,
+ taskExecutor,
+ stateManager,
+ getLuceneManager(),
+ selectedGroupsProperty(),
+ searchQueryProperty(),
+ resultSizeProperty());
new CitationStyleCache(bibDatabaseContext);
- annotationCache = new FileAnnotationCache(bibDatabaseContext, preferences.getFilePreferences());
- importHandler = new ImportHandler(
- bibDatabaseContext,
- preferences,
- fileUpdateMonitor,
- undoManager,
- stateManager,
- dialogService,
- taskExecutor);
+ annotationCache =
+ new FileAnnotationCache(bibDatabaseContext, preferences.getFilePreferences());
+ importHandler =
+ new ImportHandler(
+ bibDatabaseContext,
+ preferences,
+ fileUpdateMonitor,
+ undoManager,
+ stateManager,
+ dialogService,
+ taskExecutor);
setupMainPanel();
setupAutoCompletion();
@@ -249,17 +268,23 @@ private void initializeComponentsAndListeners(boolean isDummyContext) {
this.entryEditor = createEntryEditor();
- Platform.runLater(() -> {
- EasyBind.subscribe(changedProperty, this::updateTabTitle);
- stateManager.getOpenDatabases().addListener((ListChangeListener) c ->
- updateTabTitle(changedProperty.getValue()));
- });
+ Platform.runLater(
+ () -> {
+ EasyBind.subscribe(changedProperty, this::updateTabTitle);
+ stateManager
+ .getOpenDatabases()
+ .addListener(
+ (ListChangeListener)
+ c -> updateTabTitle(changedProperty.getValue()));
+ });
}
private EntryEditor createEntryEditor() {
Supplier tabSupplier = () -> this;
- return new EntryEditor(this,
- // Actions are recreated here since this avoids passing more parameters and the amount of additional memory consumption is neglegtable.
+ return new EntryEditor(
+ this,
+ // Actions are recreated here since this avoids passing more parameters and the
+ // amount of additional memory consumption is neglegtable.
new UndoAction(tabSupplier, undoManager, dialogService, stateManager),
new RedoAction(tabSupplier, undoManager, dialogService, stateManager));
}
@@ -275,7 +300,8 @@ private static void addModeInfo(StringBuilder text, BibDatabaseContext bibDataba
text.append(modeInfo);
}
- private static void addSharedDbInformation(StringBuilder text, BibDatabaseContext bibDatabaseContext) {
+ private static void addSharedDbInformation(
+ StringBuilder text, BibDatabaseContext bibDatabaseContext) {
text.append(bibDatabaseContext.getDBMSSynchronizer().getDBName());
text.append(" [");
text.append(Localization.lang("shared"));
@@ -291,7 +317,8 @@ private void setDataLoadingTask(BackgroundTask dataLoadingTask) {
* The layout to display in the tab when it is loading
*/
private Node createLoadingAnimationLayout() {
- ProgressIndicator progressIndicator = new ProgressIndicator(ProgressIndicator.INDETERMINATE_PROGRESS);
+ ProgressIndicator progressIndicator =
+ new ProgressIndicator(ProgressIndicator.INDETERMINATE_PROGRESS);
BorderPane pane = new BorderPane();
pane.setCenter(progressIndicator);
return pane;
@@ -316,7 +343,9 @@ private void onDatabaseLoadingSucceed(ParserResult result) {
}
public void createLuceneManager() {
- luceneManager = new LuceneManager(bibDatabaseContext, taskExecutor, preferences.getFilePreferences());
+ luceneManager =
+ new LuceneManager(
+ bibDatabaseContext, taskExecutor, preferences.getFilePreferences());
stateManager.setLuceneManager(bibDatabaseContext, luceneManager);
}
@@ -332,7 +361,10 @@ private void onDatabaseLoadingFailed(Exception ex) {
loading.set(false);
String title = Localization.lang("Connection error");
- String content = "%s\n\n%s".formatted(ex.getMessage(), Localization.lang("A local copy will be opened."));
+ String content =
+ "%s\n\n%s"
+ .formatted(
+ ex.getMessage(), Localization.lang("A local copy will be opened."));
dialogService.showErrorDialogAndWait(title, content, ex);
}
@@ -349,9 +381,14 @@ private void setDatabaseContext(BibDatabaseContext bibDatabaseContext) {
stateManager.activeTabProperty().set(Optional.of(this));
}
- // Remove existing dummy BibDatabaseContext and add correct BibDatabaseContext from ParserResult to trigger changes in the openDatabases list in the stateManager
- Optional foundExistingBibDatabase = stateManager.getOpenDatabases().stream().filter(databaseContext -> databaseContext.equals(this.bibDatabaseContext)).findFirst();
- foundExistingBibDatabase.ifPresent(databaseContext -> stateManager.getOpenDatabases().remove(databaseContext));
+ // Remove existing dummy BibDatabaseContext and add correct BibDatabaseContext from
+ // ParserResult to trigger changes in the openDatabases list in the stateManager
+ Optional foundExistingBibDatabase =
+ stateManager.getOpenDatabases().stream()
+ .filter(databaseContext -> databaseContext.equals(this.bibDatabaseContext))
+ .findFirst();
+ foundExistingBibDatabase.ifPresent(
+ databaseContext -> stateManager.getOpenDatabases().remove(databaseContext));
this.bibDatabaseContext = Objects.requireNonNull(bibDatabaseContext);
@@ -364,22 +401,29 @@ private void setDatabaseContext(BibDatabaseContext bibDatabaseContext) {
public void installAutosaveManagerAndBackupManager() {
if (isDatabaseReadyForAutoSave(bibDatabaseContext)) {
AutosaveManager autosaveManager = AutosaveManager.start(bibDatabaseContext);
- autosaveManager.registerListener(new AutosaveUiManager(this, dialogService, preferences, entryTypesManager));
+ autosaveManager.registerListener(
+ new AutosaveUiManager(this, dialogService, preferences, entryTypesManager));
}
- if (isDatabaseReadyForBackup(bibDatabaseContext) && preferences.getFilePreferences().shouldCreateBackup()) {
- BackupManager.start(this, bibDatabaseContext, Injector.instantiateModelOrService(BibEntryTypesManager.class), preferences);
+ if (isDatabaseReadyForBackup(bibDatabaseContext)
+ && preferences.getFilePreferences().shouldCreateBackup()) {
+ BackupManager.start(
+ this,
+ bibDatabaseContext,
+ Injector.instantiateModelOrService(BibEntryTypesManager.class),
+ preferences);
}
}
private boolean isDatabaseReadyForAutoSave(BibDatabaseContext context) {
return ((context.getLocation() == DatabaseLocation.SHARED)
- || ((context.getLocation() == DatabaseLocation.LOCAL)
- && preferences.getLibraryPreferences().shouldAutoSave()))
+ || ((context.getLocation() == DatabaseLocation.LOCAL)
+ && preferences.getLibraryPreferences().shouldAutoSave()))
&& context.getDatabasePath().isPresent();
}
private boolean isDatabaseReadyForBackup(BibDatabaseContext context) {
- return (context.getLocation() == DatabaseLocation.LOCAL) && context.getDatabasePath().isPresent();
+ return (context.getLocation() == DatabaseLocation.LOCAL)
+ && context.getDatabasePath().isPresent();
}
/**
@@ -426,7 +470,9 @@ public void updateTabTitle(boolean isChanged) {
}
// Unique path fragment
- Optional uniquePathPart = FileUtil.getUniquePathDirectory(stateManager.collectAllDatabasePaths(), databasePath);
+ Optional uniquePathPart =
+ FileUtil.getUniquePathDirectory(
+ stateManager.collectAllDatabasePaths(), databasePath);
uniquePathPart.ifPresent(part -> tabTitle.append(" \u2013 ").append(part));
} else {
if (databaseLocation == DatabaseLocation.LOCAL) {
@@ -437,15 +483,17 @@ public void updateTabTitle(boolean isChanged) {
addSharedDbInformation(toolTipText, bibDatabaseContext);
}
addModeInfo(toolTipText, bibDatabaseContext);
- if ((databaseLocation == DatabaseLocation.LOCAL) && bibDatabaseContext.getDatabase().hasEntries()) {
+ if ((databaseLocation == DatabaseLocation.LOCAL)
+ && bibDatabaseContext.getDatabase().hasEntries()) {
addChangedInformation(toolTipText, Localization.lang("untitled"));
}
}
- UiTaskExecutor.runInJavaFXThread(() -> {
- textProperty().setValue(tabTitle.toString());
- setTooltip(new Tooltip(toolTipText.toString()));
- });
+ UiTaskExecutor.runInJavaFXThread(
+ () -> {
+ textProperty().setValue(tabTitle.toString());
+ setTooltip(new Tooltip(toolTipText.toString()));
+ });
}
@Subscribe
@@ -473,36 +521,44 @@ public void registerUndoableChanges(List changes) {
public void editEntryAndFocusField(BibEntry entry, Field field) {
showAndEdit(entry);
- Platform.runLater(() -> {
- // Focus field and entry in main table (async to give entry editor time to load)
- entryEditor.setFocusToField(field);
- clearAndSelect(entry);
- });
+ Platform.runLater(
+ () -> {
+ // Focus field and entry in main table (async to give entry editor time to load)
+ entryEditor.setFocusToField(field);
+ clearAndSelect(entry);
+ });
}
private void createMainTable() {
- mainTable = new MainTable(tableModel,
- this,
- tabContainer,
- bibDatabaseContext,
- preferences,
- dialogService,
- stateManager,
- preferences.getKeyBindingRepository(),
- clipBoardManager,
- entryTypesManager,
- taskExecutor,
- importHandler);
- // Add the listener that binds selection to state manager (TODO: should be replaced by proper JavaFX binding as soon as table is implemented in JavaFX)
- // content binding between StateManager#getselectedEntries and mainTable#getSelectedEntries does not work here as it does not trigger the ActionHelper#needsEntriesSelected checker for the menubar
- mainTable.addSelectionListener(event -> {
- List entries = event.getList().stream().map(BibEntryTableViewModel::getEntry).toList();
- stateManager.setSelectedEntries(entries);
- if (!entries.isEmpty()) {
- // Update entry editor and preview according to selected entries
- entryEditor.setCurrentlyEditedEntry(entries.getFirst());
- }
- });
+ mainTable =
+ new MainTable(
+ tableModel,
+ this,
+ tabContainer,
+ bibDatabaseContext,
+ preferences,
+ dialogService,
+ stateManager,
+ preferences.getKeyBindingRepository(),
+ clipBoardManager,
+ entryTypesManager,
+ taskExecutor,
+ importHandler);
+ // Add the listener that binds selection to state manager (TODO: should be replaced by
+ // proper JavaFX binding as soon as table is implemented in JavaFX)
+ // content binding between StateManager#getselectedEntries and mainTable#getSelectedEntries
+ // does not work here as it does not trigger the ActionHelper#needsEntriesSelected checker
+ // for the menubar
+ mainTable.addSelectionListener(
+ event -> {
+ List entries =
+ event.getList().stream().map(BibEntryTableViewModel::getEntry).toList();
+ stateManager.setSelectedEntries(entries);
+ if (!entries.isEmpty()) {
+ // Update entry editor and preview according to selected entries
+ entryEditor.setCurrentlyEditedEntry(entries.getFirst());
+ }
+ });
}
public void setupMainPanel() {
@@ -516,10 +572,12 @@ public void setupMainPanel() {
setContent(databaseNotificationPane);
// Saves the divider position as soon as it changes
- // We need to keep a reference to the subscription, otherwise the binding gets garbage collected
- dividerPositionSubscription = EasyBind.valueAt(splitPane.getDividers(), 0)
- .mapObservable(SplitPane.Divider::positionProperty)
- .subscribeToValues(this::saveDividerLocation);
+ // We need to keep a reference to the subscription, otherwise the binding gets garbage
+ // collected
+ dividerPositionSubscription =
+ EasyBind.valueAt(splitPane.getDividers(), 0)
+ .mapObservable(SplitPane.Divider::positionProperty)
+ .subscribeToValues(this::saveDividerLocation);
// Add changePane in case a file is present - otherwise just add the splitPane to the panel
Optional file = bibDatabaseContext.getDatabasePath();
@@ -541,15 +599,17 @@ public void setupMainPanel() {
private void setupAutoCompletion() {
AutoCompletePreferences autoCompletePreferences = preferences.getAutoCompletePreferences();
if (autoCompletePreferences.shouldAutoComplete()) {
- suggestionProviders = new SuggestionProviders(
- getDatabase(),
- Injector.instantiateModelOrService(JournalAbbreviationRepository.class),
- autoCompletePreferences);
+ suggestionProviders =
+ new SuggestionProviders(
+ getDatabase(),
+ Injector.instantiateModelOrService(JournalAbbreviationRepository.class),
+ autoCompletePreferences);
} else {
// Create empty suggestion providers if auto-completion is deactivated
suggestionProviders = new SuggestionProviders();
}
- searchAutoCompleter = new PersonNameSuggestionProvider(FieldFactory.getPersonNameFields(), getDatabase());
+ searchAutoCompleter =
+ new PersonNameSuggestionProvider(FieldFactory.getPersonNameFields(), getDatabase());
}
public SuggestionProvider getAutoCompleter() {
@@ -569,7 +629,8 @@ public void showAndEdit(BibEntry entry) {
if (!splitPane.getItems().contains(entryEditor)) {
splitPane.getItems().addLast(entryEditor);
mode = PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR;
- splitPane.setDividerPositions(preferences.getEntryEditorPreferences().getDividerPosition());
+ splitPane.setDividerPositions(
+ preferences.getEntryEditorPreferences().getDividerPosition());
}
// We use != instead of equals because of performance reasons
@@ -596,11 +657,15 @@ public void clearAndSelect(final BibEntry bibEntry) {
}
public void selectPreviousEntry() {
- mainTable.getSelectionModel().clearAndSelect(mainTable.getSelectionModel().getSelectedIndex() - 1);
+ mainTable
+ .getSelectionModel()
+ .clearAndSelect(mainTable.getSelectionModel().getSelectedIndex() - 1);
}
public void selectNextEntry() {
- mainTable.getSelectionModel().clearAndSelect(mainTable.getSelectionModel().getSelectedIndex() + 1);
+ mainTable
+ .getSelectionModel()
+ .clearAndSelect(mainTable.getSelectionModel().getSelectedIndex() + 1);
}
/**
@@ -617,7 +682,8 @@ public void entryEditorClosing() {
private void ensureNotShowingBottomPanel(List entriesToCheck) {
// This method is not able to close the bottom pane currently
- if ((mode == PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR) && (entriesToCheck.contains(entryEditor.getCurrentlyEditedEntry()))) {
+ if ((mode == PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR)
+ && (entriesToCheck.contains(entryEditor.getCurrentlyEditedEntry()))) {
closeBottomPane();
}
}
@@ -660,7 +726,10 @@ private boolean showDeleteConfirmationDialog(int numberOfEntries) {
String cancelButton = Localization.lang("Keep entry");
if (numberOfEntries > 1) {
title = Localization.lang("Delete multiple entries");
- message = Localization.lang("Really delete the %0 selected entries?", Integer.toString(numberOfEntries));
+ message =
+ Localization.lang(
+ "Really delete the %0 selected entries?",
+ Integer.toString(numberOfEntries));
okButton = Localization.lang("Delete entries");
cancelButton = Localization.lang("Keep entries");
}
@@ -709,20 +778,29 @@ private boolean confirmClose() {
return true;
}
- String filename = getBibDatabaseContext()
- .getDatabasePath()
- .map(Path::toAbsolutePath)
- .map(Path::toString)
- .orElse(Localization.lang("untitled"));
-
- ButtonType saveChanges = new ButtonType(Localization.lang("Save changes"), ButtonBar.ButtonData.YES);
- ButtonType discardChanges = new ButtonType(Localization.lang("Discard changes"), ButtonBar.ButtonData.NO);
- ButtonType returnToLibrary = new ButtonType(Localization.lang("Return to library"), ButtonBar.ButtonData.CANCEL_CLOSE);
-
- Optional response = dialogService.showCustomButtonDialogAndWait(Alert.AlertType.CONFIRMATION,
- Localization.lang("Save before closing"),
- Localization.lang("Library '%0' has changed.", filename),
- saveChanges, discardChanges, returnToLibrary);
+ String filename =
+ getBibDatabaseContext()
+ .getDatabasePath()
+ .map(Path::toAbsolutePath)
+ .map(Path::toString)
+ .orElse(Localization.lang("untitled"));
+
+ ButtonType saveChanges =
+ new ButtonType(Localization.lang("Save changes"), ButtonBar.ButtonData.YES);
+ ButtonType discardChanges =
+ new ButtonType(Localization.lang("Discard changes"), ButtonBar.ButtonData.NO);
+ ButtonType returnToLibrary =
+ new ButtonType(
+ Localization.lang("Return to library"), ButtonBar.ButtonData.CANCEL_CLOSE);
+
+ Optional response =
+ dialogService.showCustomButtonDialogAndWait(
+ Alert.AlertType.CONFIRMATION,
+ Localization.lang("Save before closing"),
+ Localization.lang("Library '%0' has changed.", filename),
+ saveChanges,
+ discardChanges,
+ returnToLibrary);
if (response.isEmpty()) {
return true;
@@ -736,7 +814,12 @@ private boolean confirmClose() {
if (buttonType.equals(saveChanges)) {
try {
- SaveDatabaseAction saveAction = new SaveDatabaseAction(this, dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class));
+ SaveDatabaseAction saveAction =
+ new SaveDatabaseAction(
+ this,
+ dialogService,
+ preferences,
+ Injector.instantiateModelOrService(BibEntryTypesManager.class));
if (saveAction.save()) {
return true;
}
@@ -744,14 +827,18 @@ private boolean confirmClose() {
dialogService.notify(Localization.lang("Unable to save library"));
} catch (Throwable ex) {
LOGGER.error("A problem occurred when trying to save the file", ex);
- dialogService.showErrorDialogAndWait(Localization.lang("Save library"), Localization.lang("Could not save file."), ex);
+ dialogService.showErrorDialogAndWait(
+ Localization.lang("Save library"),
+ Localization.lang("Could not save file."),
+ ex);
}
// Save was cancelled or an error occurred.
return false;
}
if (buttonType.equals(discardChanges)) {
- BackupManager.discardBackup(bibDatabaseContext, preferences.getFilePreferences().getBackupDirectory());
+ BackupManager.discardBackup(
+ bibDatabaseContext, preferences.getFilePreferences().getBackupDirectory());
return true;
}
@@ -799,7 +886,8 @@ private void onClosed(Event event) {
LOGGER.error("Problem when shutting down autosave manager", e);
}
try {
- BackupManager.shutdown(bibDatabaseContext,
+ BackupManager.shutdown(
+ bibDatabaseContext,
preferences.getFilePreferences().getBackupDirectory(),
preferences.getFilePreferences().shouldCreateBackup());
} catch (RuntimeException e) {
@@ -868,14 +956,17 @@ public FileAnnotationCache getAnnotationCache() {
public void resetChangeMonitor() {
changeMonitor.ifPresent(DatabaseChangeMonitor::unregister);
- changeMonitor = Optional.of(new DatabaseChangeMonitor(bibDatabaseContext,
- fileUpdateMonitor,
- taskExecutor,
- dialogService,
- preferences,
- databaseNotificationPane,
- undoManager,
- stateManager));
+ changeMonitor =
+ Optional.of(
+ new DatabaseChangeMonitor(
+ bibDatabaseContext,
+ fileUpdateMonitor,
+ taskExecutor,
+ dialogService,
+ preferences,
+ databaseNotificationPane,
+ undoManager,
+ stateManager));
}
public void insertEntry(final BibEntry bibEntry) {
@@ -887,7 +978,8 @@ public void insertEntries(final List entries) {
importHandler.importCleanedEntries(entries);
// Create an UndoableInsertEntries object.
- getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries));
+ getUndoManager()
+ .addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries));
markBaseChanged();
if (preferences.getEntryEditorPreferences().shouldOpenOnNewEntry()) {
@@ -908,12 +1000,14 @@ public void copyEntry() {
private int doCopyEntry(List selectedEntries) {
if (!selectedEntries.isEmpty()) {
- List stringConstants = bibDatabaseContext.getDatabase().getUsedStrings(selectedEntries);
+ List stringConstants =
+ bibDatabaseContext.getDatabase().getUsedStrings(selectedEntries);
try {
if (stringConstants.isEmpty()) {
clipBoardManager.setContent(selectedEntries, entryTypesManager);
} else {
- clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants);
+ clipBoardManager.setContent(
+ selectedEntries, entryTypesManager, stringConstants);
}
return selectedEntries.size();
} catch (IOException e) {
@@ -942,12 +1036,15 @@ public void pasteEntry() {
private List handleNonBibTeXStringData(String data) {
try {
return this.importHandler.handleStringData(data);
- } catch (
- FetcherException exception) {
+ } catch (FetcherException exception) {
if (exception instanceof FetcherClientException) {
- dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("No data was found for the identifier"));
+ dialogService.showInformationDialogAndWait(
+ Localization.lang("Look up identifier"),
+ Localization.lang("No data was found for the identifier"));
} else if (exception instanceof FetcherServerException) {
- dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("Server not available"));
+ dialogService.showInformationDialogAndWait(
+ Localization.lang("Look up identifier"),
+ Localization.lang("Server not available"));
} else {
dialogService.showErrorDialogAndWait(exception);
}
@@ -976,7 +1073,8 @@ public void cutEntry() {
* Removes the selected entries and files linked to selected entries from the database
*/
public void deleteEntry() {
- int entriesDeleted = doDeleteEntry(StandardActions.DELETE_ENTRY, mainTable.getSelectedEntries());
+ int entriesDeleted =
+ doDeleteEntry(StandardActions.DELETE_ENTRY, mainTable.getSelectedEntries());
dialogService.notify(Localization.lang("Deleted %0 entry(ies)", entriesDeleted));
}
@@ -998,21 +1096,41 @@ private int doDeleteEntry(StandardActions mode, List entries) {
}
// Delete selected entries
- getUndoManager().addEdit(new UndoableRemoveEntries(bibDatabaseContext.getDatabase(), entries, mode == StandardActions.CUT));
+ getUndoManager()
+ .addEdit(
+ new UndoableRemoveEntries(
+ bibDatabaseContext.getDatabase(),
+ entries,
+ mode == StandardActions.CUT));
bibDatabaseContext.getDatabase().removeEntries(entries);
if (mode != StandardActions.CUT) {
- List linkedFileList = entries.stream()
- .flatMap(entry -> entry.getFiles().stream())
- .distinct()
- .toList();
+ List linkedFileList =
+ entries.stream()
+ .flatMap(entry -> entry.getFiles().stream())
+ .distinct()
+ .toList();
if (!linkedFileList.isEmpty()) {
- List viewModels = linkedFileList.stream()
- .map(linkedFile -> LinkedFileViewModel.fromLinkedFile(linkedFile, null, bibDatabaseContext, null, null, preferences))
- .collect(Collectors.toList());
-
- new DeleteFileAction(dialogService, preferences.getFilePreferences(), bibDatabaseContext, viewModels).execute();
+ List viewModels =
+ linkedFileList.stream()
+ .map(
+ linkedFile ->
+ LinkedFileViewModel.fromLinkedFile(
+ linkedFile,
+ null,
+ bibDatabaseContext,
+ null,
+ null,
+ preferences))
+ .collect(Collectors.toList());
+
+ new DeleteFileAction(
+ dialogService,
+ preferences.getFilePreferences(),
+ bibDatabaseContext,
+ viewModels)
+ .execute();
}
}
@@ -1049,52 +1167,56 @@ public void resetChangedProperties() {
* @param dataLoadingTask The task to execute to load the data asynchronously.
* @param file the path to the file (loaded by the dataLoadingTask)
*/
- public static LibraryTab createLibraryTab(BackgroundTask dataLoadingTask,
- Path file,
- DialogService dialogService,
- GuiPreferences preferences,
- StateManager stateManager,
- LibraryTabContainer tabContainer,
- FileUpdateMonitor fileUpdateMonitor,
- BibEntryTypesManager entryTypesManager,
- CountingUndoManager undoManager,
- ClipBoardManager clipBoardManager,
- TaskExecutor taskExecutor) {
+ public static LibraryTab createLibraryTab(
+ BackgroundTask dataLoadingTask,
+ Path file,
+ DialogService dialogService,
+ GuiPreferences preferences,
+ StateManager stateManager,
+ LibraryTabContainer tabContainer,
+ FileUpdateMonitor fileUpdateMonitor,
+ BibEntryTypesManager entryTypesManager,
+ CountingUndoManager undoManager,
+ ClipBoardManager clipBoardManager,
+ TaskExecutor taskExecutor) {
BibDatabaseContext context = new BibDatabaseContext();
context.setDatabasePath(file);
- LibraryTab newTab = new LibraryTab(
- context,
- tabContainer,
- dialogService,
- preferences,
- stateManager,
- fileUpdateMonitor,
- entryTypesManager,
- undoManager,
- clipBoardManager,
- taskExecutor,
- true);
+ LibraryTab newTab =
+ new LibraryTab(
+ context,
+ tabContainer,
+ dialogService,
+ preferences,
+ stateManager,
+ fileUpdateMonitor,
+ entryTypesManager,
+ undoManager,
+ clipBoardManager,
+ taskExecutor,
+ true);
newTab.setDataLoadingTask(dataLoadingTask);
- dataLoadingTask.onRunning(newTab::onDatabaseLoadingStarted)
- .onSuccess(newTab::onDatabaseLoadingSucceed)
- .onFailure(newTab::onDatabaseLoadingFailed)
- .executeWith(taskExecutor);
+ dataLoadingTask
+ .onRunning(newTab::onDatabaseLoadingStarted)
+ .onSuccess(newTab::onDatabaseLoadingSucceed)
+ .onFailure(newTab::onDatabaseLoadingFailed)
+ .executeWith(taskExecutor);
return newTab;
}
- public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext,
- LibraryTabContainer tabContainer,
- DialogService dialogService,
- GuiPreferences preferences,
- StateManager stateManager,
- FileUpdateMonitor fileUpdateMonitor,
- BibEntryTypesManager entryTypesManager,
- UndoManager undoManager,
- ClipBoardManager clipBoardManager,
- TaskExecutor taskExecutor) {
+ public static LibraryTab createLibraryTab(
+ BibDatabaseContext databaseContext,
+ LibraryTabContainer tabContainer,
+ DialogService dialogService,
+ GuiPreferences preferences,
+ StateManager stateManager,
+ FileUpdateMonitor fileUpdateMonitor,
+ BibEntryTypesManager entryTypesManager,
+ UndoManager undoManager,
+ ClipBoardManager clipBoardManager,
+ TaskExecutor taskExecutor) {
Objects.requireNonNull(databaseContext);
return new LibraryTab(
@@ -1122,8 +1244,12 @@ public void listen(EntriesAddedEvent addedEntriesEvent) {
// Automatically add new entries to the selected group (or set of groups)
if (preferences.getGroupsPreferences().shouldAutoAssignGroup()) {
- stateManager.getSelectedGroups(bibDatabaseContext).forEach(
- selectedGroup -> selectedGroup.addEntriesToGroup(addedEntriesEvent.getBibEntries()));
+ stateManager
+ .getSelectedGroups(bibDatabaseContext)
+ .forEach(
+ selectedGroup ->
+ selectedGroup.addEntriesToGroup(
+ addedEntriesEvent.getBibEntries()));
}
}
}
@@ -1150,7 +1276,11 @@ public void listen(EntriesRemovedEvent removedEntriesEvent) {
@Subscribe
public void listen(FieldChangedEvent fieldChangedEvent) {
- luceneManager.updateEntry(fieldChangedEvent.getBibEntry(), fieldChangedEvent.getOldValue(), fieldChangedEvent.getNewValue(), fieldChangedEvent.getField().equals(StandardField.FILE));
+ luceneManager.updateEntry(
+ fieldChangedEvent.getBibEntry(),
+ fieldChangedEvent.getOldValue(),
+ fieldChangedEvent.getNewValue(),
+ fieldChangedEvent.getField().equals(StandardField.FILE));
}
}
@@ -1178,10 +1308,12 @@ public DatabaseNotification getNotificationPane() {
@Override
public String toString() {
- return "LibraryTab{" +
- "bibDatabaseContext=" + bibDatabaseContext +
- ", showing=" + showing +
- '}';
+ return "LibraryTab{"
+ + "bibDatabaseContext="
+ + bibDatabaseContext
+ + ", showing="
+ + showing
+ + '}';
}
public LibraryTabContainer getLibraryTabContainer() {
diff --git a/src/main/java/org/jabref/gui/LibraryTabContainer.java b/src/main/java/org/jabref/gui/LibraryTabContainer.java
index 139653c87caf..1ad7390ade1f 100644
--- a/src/main/java/org/jabref/gui/LibraryTabContainer.java
+++ b/src/main/java/org/jabref/gui/LibraryTabContainer.java
@@ -1,19 +1,17 @@
package org.jabref.gui;
-import java.util.List;
-
import org.jabref.model.database.BibDatabaseContext;
-
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
+import java.util.List;
+
@NullMarked
public interface LibraryTabContainer {
List getLibraryTabs();
- @Nullable
- LibraryTab getCurrentLibraryTab();
+ @Nullable LibraryTab getCurrentLibraryTab();
void showLibraryTab(LibraryTab libraryTab);
diff --git a/src/main/java/org/jabref/gui/StateManager.java b/src/main/java/org/jabref/gui/StateManager.java
index e75ffcdc89e9..77cb3e5f41a4 100644
--- a/src/main/java/org/jabref/gui/StateManager.java
+++ b/src/main/java/org/jabref/gui/StateManager.java
@@ -1,9 +1,7 @@
package org.jabref.gui;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
+import com.tobiasdiez.easybind.EasyBind;
+import com.tobiasdiez.easybind.EasyBinding;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
@@ -33,12 +31,14 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.groups.GroupTreeNode;
import org.jabref.model.search.SearchQuery;
-
-import com.tobiasdiez.easybind.EasyBind;
-import com.tobiasdiez.easybind.EasyBinding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
/**
* This class manages the GUI-state of JabRef, including:
*
@@ -56,26 +56,60 @@ public class StateManager {
private static final Logger LOGGER = LoggerFactory.getLogger(StateManager.class);
private final CustomLocalDragboard localDragboard = new CustomLocalDragboard();
- private final ObservableList openDatabases = FXCollections.observableArrayList();
- private final OptionalObjectProperty activeDatabase = OptionalObjectProperty.empty();
+ private final ObservableList openDatabases =
+ FXCollections.observableArrayList();
+ private final OptionalObjectProperty activeDatabase =
+ OptionalObjectProperty.empty();
private final OptionalObjectProperty activeTab = OptionalObjectProperty.empty();
private final ObservableList selectedEntries = FXCollections.observableArrayList();
- private final ObservableMap> selectedGroups = FXCollections.observableHashMap();
- private final ObservableMap luceneManagers = FXCollections.observableHashMap();
- private final OptionalObjectProperty activeSearchQuery = OptionalObjectProperty.empty();
- private final OptionalObjectProperty activeGlobalSearchQuery = OptionalObjectProperty.empty();
+ private final ObservableMap> selectedGroups =
+ FXCollections.observableHashMap();
+ private final ObservableMap luceneManagers =
+ FXCollections.observableHashMap();
+ private final OptionalObjectProperty activeSearchQuery =
+ OptionalObjectProperty.empty();
+ private final OptionalObjectProperty activeGlobalSearchQuery =
+ OptionalObjectProperty.empty();
private final IntegerProperty searchResultSize = new SimpleIntegerProperty(0);
private final IntegerProperty globalSearchResultSize = new SimpleIntegerProperty(0);
private final OptionalObjectProperty focusOwner = OptionalObjectProperty.empty();
- private final ObservableList, Task>>> backgroundTasksPairs = FXCollections.observableArrayList(task -> new Observable[] {task.getValue().progressProperty(), task.getValue().runningProperty()});
- private final ObservableList> backgroundTasks = EasyBind.map(backgroundTasksPairs, Pair::getValue);
- private final FilteredList> runningBackgroundTasks = new FilteredList<>(backgroundTasks, Task::isRunning);
- private final BooleanBinding anyTaskRunning = Bindings.createBooleanBinding(() -> !runningBackgroundTasks.isEmpty(), runningBackgroundTasks);
- private final EasyBinding