Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into jabrefonline
Browse files Browse the repository at this point in the history
* upstream/main:
  New Crowdin updates (#7843)
  Refactoring and addition of unit tests (#7597)
  CLI option to write XMP metadata to pdfs (#7814)
  Add query validation for web search (#7809)
  change eclipse default output dir (#7842)
  Bump lucene-queryparser from 8.8.2 to 8.9.0 (#7835)
  Bump libreoffice from 7.1.3 to 7.1.4 (#7836)
  Bump postgresql from 42.2.21 to 42.2.22 (#7839)
  Bump org.eclipse.jgit (#7838)
  Bump byte-buddy-parent from 1.11.2 to 1.11.5 (#7837)
  Bump unoloader from 7.1.3 to 7.1.4 (#7841)
  Ms Office Export patent author as inventor (#7831)
  Abbreviation toggle within the JournalEditorViewModel now ignores curly braces (issue #7773) (#7807)
  • Loading branch information
Siedlerchr committed Jun 22, 2021
2 parents b79bf7e + b6697fe commit bd5ab5b
Show file tree
Hide file tree
Showing 54 changed files with 1,645 additions and 1,137 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We added a select all button for the library import function. [#7786](https://github.com/JabRef/jabref/issues/7786)
- We added a search feature for journal abbreviations. [#7804](https://github.com/JabRef/jabref/pull/7804)
- We added auto-key-generation progress to the background task list. [#7267](https://github.com/JabRef/jabref/issues/72)
- We added the option to write XMP metadata to pdfs from the CLI. [7814](https://github.com/JabRef/jabref/pull/7814)

### Changed

- The export to MS Office XML now exports the author field as `Inventor` if the bibtex entry type is `patent` [#7830](https://github.com/JabRef/jabref/issues/7830)
- We changed the EndNote importer to import the field `label` to the corresponding bibtex field `endnote-label` [forum#2734](https://discourse.jabref.org/t/importing-endnote-label-field-to-jabref-from-xml-file/2734)
- The keywords added via "Manage content selectors" are now displayed in alphabetical order. [#3791](https://github.com/JabRef/jabref/issues/3791)
- We improved the "Find unlinked files" dialog to show import results for each file. [#7209](https://github.com/JabRef/jabref/pull/7209)
Expand All @@ -49,6 +51,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- The tooltip of the search field explaining the search is always shown. [#7279](https://github.com/JabRef/jabref/pull/7279)
- We rewrote the ACM fetcher to adapt to the new interface. [#5804](https://github.com/JabRef/jabref/issues/5804)
- We moved the select/collapse buttons in the unlinked files dialog into a context menu. [#7383](https://github.com/JabRef/jabref/issues/7383)
- We fixed an issue where journal abbreviations containing curly braces were not recognized [#7773](https://github.com/JabRef/jabref/issues/7773)

### Fixed

Expand Down
12 changes: 6 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ dependencies {

implementation 'commons-cli:commons-cli:1.4'

implementation 'org.libreoffice:libreoffice:7.1.3'
implementation 'org.libreoffice:unoloader:7.1.3'
implementation 'org.libreoffice:libreoffice:7.1.4'
implementation 'org.libreoffice:unoloader:7.1.4'

implementation 'io.github.java-diff-utils:java-diff-utils:4.10'
implementation 'info.debatty:java-string-similarity:2.0.0'
Expand All @@ -145,18 +145,18 @@ dependencies {
antlr4 'org.antlr:antlr4:4.9.2'
implementation 'org.antlr:antlr4-runtime:4.9.2'

implementation (group: 'org.apache.lucene', name: 'lucene-queryparser', version: '8.8.2') {
implementation (group: 'org.apache.lucene', name: 'lucene-queryparser', version: '8.9.0') {
exclude group: 'org.apache.lucene', module: 'lucene-sandbox'
}

implementation group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '5.11.1.202105131744-r'
implementation group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '5.12.0.202106070339-r'

implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.12.3'
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.12.3'

implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.7.3'

implementation 'org.postgresql:postgresql:42.2.21'
implementation 'org.postgresql:postgresql:42.2.22'

implementation ('com.oracle.ojdbc:ojdbc10:19.3.0.0') {
// causing module issues
Expand Down Expand Up @@ -217,7 +217,7 @@ dependencies {
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.7.2'
testImplementation 'org.junit.platform:junit-platform-launcher:1.7.2'

testImplementation 'net.bytebuddy:byte-buddy-parent:1.11.2'
testImplementation 'net.bytebuddy:byte-buddy-parent:1.11.5'
testRuntimeOnly group: 'org.apache.logging.log4j', name: 'log4j-core', version: '3.0.0-SNAPSHOT'
testRuntimeOnly group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '3.0.0-SNAPSHOT'
testImplementation 'org.mockito:mockito-core:3.11.1'
Expand Down
95 changes: 95 additions & 0 deletions src/main/java/org/jabref/cli/ArgumentProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.Vector;
import java.util.prefs.BackingStoreException;

import org.jabref.gui.Globals;
Expand All @@ -24,6 +28,7 @@
import org.jabref.logic.exporter.ExporterFactory;
import org.jabref.logic.exporter.SavePreferences;
import org.jabref.logic.exporter.TemplateExporter;
import org.jabref.logic.exporter.XmpPdfExporter;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ImportException;
import org.jabref.logic.importer.ImportFormatReader;
Expand All @@ -49,6 +54,8 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.strings.StringUtil;
import org.jabref.model.util.DummyFileUpdateMonitor;
import org.jabref.model.util.FileHelper;
import org.jabref.preferences.FilePreferences;
import org.jabref.preferences.SearchPreferences;

import com.google.common.base.Throwables;
Expand Down Expand Up @@ -215,6 +222,12 @@ private List<ParserResult> processArguments() {
automaticallySetFileLinks(loaded);
}

if (cli.isWriteXMPtoPdf()) {
if (!loaded.isEmpty()) {
writeXMPtoPdf(loaded, cli.getWriteXMPtoPdf(), Globals.prefs.getDefaultEncoding(), Globals.prefs.getXmpPreferences(), Globals.prefs.getFilePreferences());
}
}

if (cli.isFileExport()) {
if (!loaded.isEmpty()) {
exportFile(loaded, cli.getFileExport().split(","));
Expand All @@ -239,6 +252,88 @@ private List<ParserResult> processArguments() {
return loaded;
}

private void writeXMPtoPdf(List<ParserResult> loaded, String filesAndCitekeys, Charset encoding, XmpPreferences xmpPreferences, FilePreferences filePreferences) {
if (loaded.isEmpty()) {
LOGGER.error("The write xmp option depends on a valid import option.");
return;
}
ParserResult pr = loaded.get(loaded.size() - 1);
BibDatabaseContext databaseContext = pr.getDatabaseContext();
BibDatabase dataBase = pr.getDatabase();

XmpPdfExporter xmpPdfExporter = new XmpPdfExporter(xmpPreferences);

if ("all".equals(filesAndCitekeys)) {
for (BibEntry entry : dataBase.getEntries()) {
writeXMPtoPDFsOfEntry(databaseContext, entry.getCitationKey().orElse("<no cite key defined>"), entry, encoding, filePreferences, xmpPdfExporter);
}
return;
}

Vector<String> citeKeys = new Vector<>();
Vector<String> pdfs = new Vector<>();
for (String fileOrCiteKey : filesAndCitekeys.split(",")) {
if (fileOrCiteKey.toLowerCase(Locale.ROOT).endsWith(".pdf")) {
pdfs.add(fileOrCiteKey);
} else {
citeKeys.add(fileOrCiteKey);
}
}

writeXMPtoPdfByCitekey(databaseContext, dataBase, citeKeys, encoding, filePreferences, xmpPdfExporter);
writeXMPtoPdfByFileNames(databaseContext, dataBase, pdfs, encoding, filePreferences, xmpPdfExporter);

}

private void writeXMPtoPDFsOfEntry(BibDatabaseContext databaseContext, String citeKey, BibEntry entry, Charset encoding, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter) {
try {
if (xmpPdfExporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, entry, Arrays.asList(entry))) {
LOGGER.info(String.format("Successfully written XMP metadata on at least one linked file of %s", citeKey));
} else {
LOGGER.error(String.format("Cannot write XMP metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.", citeKey));
}
} catch (Exception e) {
LOGGER.error(String.format("Failed writing XMP metadata on a linked file of %s.", citeKey));
}
}

private void writeXMPtoPdfByCitekey(BibDatabaseContext databaseContext, BibDatabase dataBase, Vector<String> citeKeys, Charset encoding, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter) {
for (String citeKey : citeKeys) {
List<BibEntry> bibEntryList = dataBase.getEntriesByCitationKey(citeKey);
if (bibEntryList.isEmpty()) {
LOGGER.error(String.format("Skipped - Cannot find %s in library.", citeKey));
continue;
}
for (BibEntry entry : bibEntryList) {
writeXMPtoPDFsOfEntry(databaseContext, citeKey, entry, encoding, filePreferences, xmpPdfExporter);
}
}
}

private void writeXMPtoPdfByFileNames(BibDatabaseContext databaseContext, BibDatabase dataBase, Vector<String> fileNames, Charset encoding, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter) {
for (String fileName : fileNames) {
Path filePath = Path.of(fileName);
if (!filePath.isAbsolute()) {
filePath = FileHelper.find(fileName, databaseContext.getFileDirectories(filePreferences)).orElse(FileHelper.find(fileName, Arrays.asList(Path.of("").toAbsolutePath())).orElse(filePath));
}
if (Files.exists(filePath)) {
try {
if (xmpPdfExporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, filePath)) {
LOGGER.info(String.format("Successfully written XMP metadata of at least one entry to %s", fileName));
} else {
LOGGER.error(String.format("File %s is not linked to any entry in database.", fileName));
}
} catch (IOException e) {
LOGGER.error("Error accessing files.", fileName);
} catch (Exception e) {
LOGGER.error(String.format("Error writing entry to %s.", fileName));
}
} else {
LOGGER.error(String.format("Skipped - PDF %s does not exist", fileName));
}
}
}

private boolean exportMatches(List<ParserResult> loaded) {
String[] data = cli.getExportMatches().split(",");
String searchTerm = data[0].replace("\\$", " "); // enables blanks within the search term:
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/org/jabref/cli/JabRefCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ public boolean isAutomaticallySetFileLinks() {
return cl.hasOption("automaticallySetFileLinks");
}

public boolean isWriteXMPtoPdf() {
return cl.hasOption("writeXMPtoPdf");
}

public String getWriteXMPtoPdf() {
return cl.getOptionValue("writeXMPtoPdf");
}

private static Options getOptions() {
Options options = new Options();

Expand Down Expand Up @@ -242,6 +250,14 @@ private static Options getOptions() {
.argName("KEY1[,KEY2][,KEYn] | all")
.build());

options.addOption(Option
.builder("w")
.longOpt("writeXMPtoPdf")
.desc(String.format("%s: '%s'", Localization.lang("Write BibTeXEntry as XMP metadata to PDF."), "-w pathToMyOwnPaper.pdf"))
.hasArg()
.argName("CITEKEY1[,CITEKEY2][,CITEKEYn] | PDF1[,PDF2][,PDFn] | all")
.build());

return options;
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/jabref/gui/Base.css
Original file line number Diff line number Diff line change
Expand Up @@ -1236,3 +1236,7 @@ TextFlow * {
.fontsizeSpinner{
-fx-pref-width: 5em;
}

.text-field:invalid {
-fx-background-color: rgba(240, 128, 128, 0.5);
}
10 changes: 4 additions & 6 deletions src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -1040,11 +1039,10 @@ public void addTab(LibraryTab libraryTab, boolean raisePanel) {
}

private void trackOpenNewDatabase(LibraryTab libraryTab) {
Map<String, String> properties = new HashMap<>();
Map<String, Double> measurements = new HashMap<>();
measurements.put("NumberOfEntries", (double) libraryTab.getBibDatabaseContext().getDatabase().getEntryCount());

Globals.getTelemetryClient().ifPresent(client -> client.trackEvent("OpenNewDatabase", properties, measurements));
Globals.getTelemetryClient().ifPresent(client -> client.trackEvent(
"OpenNewDatabase",
Map.of(),
Map.of("NumberOfEntries", (double) libraryTab.getBibDatabaseContext().getDatabase().getEntryCount())));
}

public LibraryTab addTab(BibDatabaseContext databaseContext, boolean raisePanel) {
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/org/jabref/gui/actions/JabRefAction.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.jabref.gui.actions;

import java.util.HashMap;
import java.util.Map;

import javafx.beans.binding.Bindings;
Expand Down Expand Up @@ -77,10 +76,9 @@ private void trackExecute(String actionName) {
}

private void trackUserActionSource(String actionName, Sources source) {
Map<String, String> properties = new HashMap<>();
Map<String, Double> measurements = new HashMap<>();
properties.put("Source", source.toString());

Globals.getTelemetryClient().ifPresent(telemetryClient -> telemetryClient.trackEvent(actionName, properties, measurements));
Globals.getTelemetryClient().ifPresent(telemetryClient -> telemetryClient.trackEvent(
actionName,
Map.of("Source", source.toString()),
Map.of()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ public SuggestionProviders() {
}

public SuggestionProvider<?> getForField(Field field) {

if (isEmpty || !autoCompletePreferences.getCompleteFields().contains(field)) {
return new EmptySuggestionProvider();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ public void toggleAbbreviation() {
return;
}

if (journalAbbreviationRepository.isKnownName(text.get())) {
Optional<String> nextAbbreviation = journalAbbreviationRepository.getNextAbbreviation(text.get());
// Ignore brackets when matching abbreviations.
final String name = StringUtil.ignoreCurlyBracket(text.get());

if (journalAbbreviationRepository.isKnownName(name)) {
Optional<String> nextAbbreviation = journalAbbreviationRepository.getNextAbbreviation(name);

if (nextAbbreviation.isPresent()) {
text.set(nextAbbreviation.get());
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/jabref/gui/importer/fetcher/WebSearchPane.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package org.jabref.gui.importer.fetcher;

import javafx.css.PseudoClass;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
Expand All @@ -31,6 +33,8 @@

public class WebSearchPane extends SidePaneComponent {

private static final PseudoClass QUERY_INVALID = PseudoClass.getPseudoClass("invalid");

private final PreferencesService preferences;
private final WebSearchPaneViewModel viewModel;

Expand Down Expand Up @@ -75,6 +79,16 @@ protected Node createContentPane() {
query.getStyleClass().add("searchBar");

viewModel.queryProperty().bind(query.textProperty());
EasyBind.subscribe(viewModel.queryValidationStatus().validProperty(),
valid -> {
if (!valid && viewModel.queryValidationStatus().getHighestMessage().isPresent()) {
query.setTooltip(new Tooltip(viewModel.queryValidationStatus().getHighestMessage().get().getMessage()));
query.pseudoClassStateChanged(QUERY_INVALID, true);
} else {
query.setTooltip(null);
query.pseudoClassStateChanged(QUERY_INVALID, false);
}
});

// Allows to trigger search on pressing enter
query.setOnKeyPressed(event -> {
Expand Down
Loading

0 comments on commit bd5ab5b

Please sign in to comment.