Skip to content

Commit

Permalink
Merge branch 'main' into fix-jump
Browse files Browse the repository at this point in the history
  • Loading branch information
koppor committed Oct 30, 2024
2 parents f597f48 + a2a64f1 commit 3115e68
Show file tree
Hide file tree
Showing 46 changed files with 811 additions and 263 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- ⚠️ We relaxed the escaping requirements for [bracketed patterns](https://docs.jabref.org/setup/citationkeypatterns), which are used for the [citaton key generator](https://docs.jabref.org/advanced/entryeditor#autogenerate-citation-key) and [filename and directory patterns](https://docs.jabref.org/finding-sorting-and-cleaning-entries/filelinks#auto-linking-files). One only needs to write `\"` if a quote sign should be escaped. All other escapings are not necessary (and working) any more. [#11967](https://github.com/JabRef/jabref/pull/11967)
- When importing BibTeX data starging from on a PDF, the XMP metadata takes precedence over Grobid data. [#11992](https://github.com/JabRef/jabref/pull/11992)
- JabRef now uses TLS 1.2 for all HTTPS connections. [#11852](https://github.com/JabRef/jabref/pull/11852)
- We improved the functionality of getting BibTeX data out of PDF files. [#11999](https://github.com/JabRef/jabref/issues/11999)
- We improved the display of long messages in the integrity check dialog. [#11619](https://github.com/JabRef/jabref/pull/11619)
- We improved the undo/redo buttons in the main toolbar and main menu to be disabled when there is nothing to undo/redo. [#8807](https://github.com/JabRef/jabref/issues/8807)
- We improved the DOI detection in PDF imports. [#11782](https://github.com/JabRef/jabref/pull/11782)
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ dependencies {
exclude group: 'org.jetbrains.kotlin'
}


implementation 'org.apache.velocity:velocity-engine-core:2.3'
implementation platform('ai.djl:bom:0.30.0')
implementation 'ai.djl:api'
implementation 'ai.djl.huggingface:tokenizers'
Expand Down
1 change: 1 addition & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
uses ai.djl.repository.RepositoryFactory;
uses ai.djl.repository.zoo.ZooProvider;
uses dev.langchain4j.spi.prompt.PromptTemplateFactory;
requires velocity.engine.core;
// endregion

// region: Lucene
Expand Down
53 changes: 28 additions & 25 deletions src/main/java/org/jabref/gui/LibraryTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ public void editEntryAndFocusField(BibEntry entry, Field field) {
Platform.runLater(() -> {
// Focus field and entry in main table (async to give entry editor time to load)
entryEditor.setFocusToField(field);
clearAndSelect(entry);
});
}

Expand Down Expand Up @@ -567,11 +566,15 @@ public EntryEditor getEntryEditor() {
}

/**
* Sets the entry editor as the bottom component in the split pane. If an entry editor already was shown, makes sure that the divider doesn't move. Updates the mode to SHOWING_EDITOR. Then shows the given entry.
* Sets the entry editor as the bottom component in the split pane. If an entry editor already was shown, makes sure that the divider doesn't move. Updates the mode to {@link PanelMode#MAIN_TABLE_AND_ENTRY_EDITOR}.
* Then shows the given entry.
*
* Additionally, selects the entry in the main table - so that the selected entry in the main table always corresponds to the edited entry.
*
* @param entry The entry to edit.
*/
public void showAndEdit(BibEntry entry) {
this.clearAndSelect(entry);
if (!splitPane.getItems().contains(entryEditor)) {
splitPane.getItems().addLast(entryEditor);
mode = PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR;
Expand Down Expand Up @@ -889,16 +892,16 @@ public void insertEntry(final BibEntry bibEntry) {
}

public void insertEntries(final List<BibEntry> entries) {
if (!entries.isEmpty()) {
importHandler.importCleanedEntries(entries);

// Create an UndoableInsertEntries object.
getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries));
if (entries.isEmpty()) {
return;
}

markBaseChanged();
if (preferences.getEntryEditorPreferences().shouldOpenOnNewEntry()) {
showAndEdit(entries.getFirst());
}
importHandler.importCleanedEntries(entries);
getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries));
markBaseChanged();
if (preferences.getEntryEditorPreferences().shouldOpenOnNewEntry()) {
showAndEdit(entries.getFirst());
} else {
clearAndSelect(entries.getFirst());
}
}
Expand All @@ -913,22 +916,22 @@ public void copyEntry() {
}

private int doCopyEntry(List<BibEntry> selectedEntries) {
if (!selectedEntries.isEmpty()) {
List<BibtexString> stringConstants = bibDatabaseContext.getDatabase().getUsedStrings(selectedEntries);
try {
if (stringConstants.isEmpty()) {
clipBoardManager.setContent(selectedEntries, entryTypesManager);
} else {
clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants);
}
return selectedEntries.size();
} catch (IOException e) {
LOGGER.error("Error while copying selected entries to clipboard.", e);
return -1;
}
if (selectedEntries.isEmpty()) {
return 0;
}

return 0;
List<BibtexString> stringConstants = bibDatabaseContext.getDatabase().getUsedStrings(selectedEntries);
try {
if (stringConstants.isEmpty()) {
clipBoardManager.setContent(selectedEntries, entryTypesManager);
} else {
clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants);
}
return selectedEntries.size();
} catch (IOException e) {
LOGGER.error("Error while copying selected entries to clipboard.", e);
return -1;
}
}

public void pasteEntry() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ private void jumpToEntry(CitationRelationItem entry) {
citingTask.cancel();
citedByTask.cancel();
libraryTab.showAndEdit(entry.localEntry());
libraryTab.clearAndSelect(entry.localEntry());
}

/**
Expand Down Expand Up @@ -527,7 +526,7 @@ private void importEntries(List<CitationRelationItem> entriesToImport, CitationF

citationsRelationsTabViewModel.importEntries(entriesToImport, searchType, existingEntry);

dialogService.notify(Localization.lang("Number of entries successfully imported") + ": " + entriesToImport.size());
dialogService.notify(Localization.lang("%0 entry(s) imported", entriesToImport.size()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package org.jabref.gui.entryeditor.citationrelationtab;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.SequencedSet;

import javax.swing.undo.UndoManager;

Expand All @@ -12,11 +11,10 @@
import org.jabref.gui.externalfiles.ImportHandler;
import org.jabref.gui.preferences.GuiPreferences;
import org.jabref.logic.citationkeypattern.CitationKeyGenerator;
import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.util.FileUpdateMonitor;

public class CitationsRelationsTabViewModel {
Expand All @@ -40,7 +38,11 @@ public CitationsRelationsTabViewModel(BibDatabaseContext databaseContext, GuiPre
}

public void importEntries(List<CitationRelationItem> entriesToImport, CitationFetcher.SearchType searchType, BibEntry existingEntry) {
List<BibEntry> entries = entriesToImport.stream().map(CitationRelationItem::entry).toList();
List<BibEntry> entries = entriesToImport.stream()
.map(CitationRelationItem::entry)
// We need to have a clone of the entry, because we add the entry to the library (and keep it in the citation relation tab, too)
.map(entry -> (BibEntry) entry.clone())
.toList();

ImportHandler importHandler = new ImportHandler(
databaseContext,
Expand All @@ -50,67 +52,51 @@ public void importEntries(List<CitationRelationItem> entriesToImport, CitationFe
stateManager,
dialogService,
taskExecutor);
CitationKeyGenerator generator = new CitationKeyGenerator(databaseContext, preferences.getCitationKeyPatternPreferences());
boolean generateNewKeyOnImport = preferences.getImporterPreferences().generateNewKeyOnImportProperty().get();

switch (searchType) {
case CITES -> importCites(entries, existingEntry, importHandler);
case CITED_BY -> importCitedBy(entries, existingEntry, importHandler);
case CITES -> importCites(entries, existingEntry, importHandler, generator, generateNewKeyOnImport);
case CITED_BY -> importCitedBy(entries, existingEntry, importHandler, generator, generateNewKeyOnImport);
}
}

private void importCites(List<BibEntry> entries, BibEntry existingEntry, ImportHandler importHandler) {
CitationKeyPatternPreferences citationKeyPatternPreferences = preferences.getCitationKeyPatternPreferences();
CitationKeyGenerator generator = new CitationKeyGenerator(databaseContext, citationKeyPatternPreferences);
boolean generateNewKeyOnImport = preferences.getImporterPreferences().generateNewKeyOnImportProperty().get();

List<String> citeKeys = getExistingEntriesFromCiteField(existingEntry);
citeKeys.removeIf(String::isEmpty);
private void importCites(List<BibEntry> entries, BibEntry existingEntry, ImportHandler importHandler, CitationKeyGenerator generator, boolean generateNewKeyOnImport) {
SequencedSet<String> citeKeys = existingEntry.getCites();

for (BibEntry entryToCite : entries) {
if (generateNewKeyOnImport || entryToCite.getCitationKey().isEmpty()) {
String key = generator.generateKey(entryToCite);
entryToCite.setCitationKey(key);
addToKeyToList(citeKeys, key);
} else {
addToKeyToList(citeKeys, entryToCite.getCitationKey().get());
}
citeKeys.add(entryToCite.getCitationKey().get());
}
existingEntry.setField(StandardField.CITES, toCommaSeparatedString(citeKeys));

existingEntry.setCites(citeKeys);
importHandler.importEntries(entries);
}

private void importCitedBy(List<BibEntry> entries, BibEntry existingEntry, ImportHandler importHandler) {
CitationKeyPatternPreferences citationKeyPatternPreferences = preferences.getCitationKeyPatternPreferences();
CitationKeyGenerator generator = new CitationKeyGenerator(databaseContext, citationKeyPatternPreferences);
boolean generateNewKeyOnImport = preferences.getImporterPreferences().generateNewKeyOnImportProperty().get();

for (BibEntry entryThatCitesOurExistingEntry : entries) {
List<String> existingCites = getExistingEntriesFromCiteField(entryThatCitesOurExistingEntry);
existingCites.removeIf(String::isEmpty);
String key;
if (generateNewKeyOnImport || entryThatCitesOurExistingEntry.getCitationKey().isEmpty()) {
key = generator.generateKey(entryThatCitesOurExistingEntry);
entryThatCitesOurExistingEntry.setCitationKey(key);
} else {
key = existingEntry.getCitationKey().get();
/**
* "cited by" is the opposite of "cites", but not stored in field `CITED_BY`, but in the `CITES` field of the citing entry.
* <p>
* Therefore, some special handling is needed
*/
private void importCitedBy(List<BibEntry> entries, BibEntry existingEntry, ImportHandler importHandler, CitationKeyGenerator generator, boolean generateNewKeyOnImport) {
if (existingEntry.getCitationKey().isEmpty()) {
if (!generateNewKeyOnImport) {
dialogService.notify(Localization.lang("No citation key for %0", existingEntry.getAuthorTitleYear()));
return;
}
addToKeyToList(existingCites, key);
entryThatCitesOurExistingEntry.setField(StandardField.CITES, toCommaSeparatedString(existingCites));
existingEntry.setCitationKey(generator.generateKey(existingEntry));
}
String citationKey = existingEntry.getCitationKey().get();

importHandler.importEntries(entries);
}

private void addToKeyToList(List<String> list, String key) {
if (!list.contains(key)) {
list.add(key);
for (BibEntry citingEntry : entries) {
SequencedSet<String> existingCites = citingEntry.getCites();
existingCites.add(citationKey);
citingEntry.setCites(existingCites);
}
}

private List<String> getExistingEntriesFromCiteField(BibEntry entry) {
return Arrays.stream(entry.getField(StandardField.CITES).orElse("").split(",")).collect(Collectors.toList());
}

private String toCommaSeparatedString(List<String> citeentries) {
return String.join(",", citeentries);
importHandler.importEntries(entries);
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/gui/importer/ImportCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ private void importSingleFile(Path file, SortedSet<Importer> importers, FileChoo
if (importMethod == ImportMethod.AS_NEW) {
task.onSuccess(parserResult -> {
tabContainer.addTab(parserResult.getDatabaseContext(), true);
dialogService.notify(Localization.lang("Imported entries") + ": " + parserResult.getDatabase().getEntries().size());
dialogService.notify(Localization.lang("%0 entry(s) imported", parserResult.getDatabase().getEntries().size()));
})
.onFailure(ex -> {
LOGGER.error("Error importing", ex);
Expand Down
5 changes: 1 addition & 4 deletions src/main/java/org/jabref/gui/maintable/MainTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,10 +482,7 @@ public List<BibEntry> getSelectedEntries() {
}

private Optional<BibEntryTableViewModel> findEntry(BibEntry entry) {
return model.getEntriesFilteredAndSorted()
.stream()
.filter(viewModel -> viewModel.getEntry().equals(entry))
.findFirst();
return model.getViewModelByIndex(database.getDatabase().indexOf(entry));
}

public void setCitationMergeMode(boolean citationMerge) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/jabref/gui/maintable/MainTableDataModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@
import com.tobiasdiez.easybind.EasyBind;
import com.tobiasdiez.easybind.Subscription;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.jabref.model.search.PostgreConstants.ENTRY_ID;

public class MainTableDataModel {
private final Logger LOGGER = LoggerFactory.getLogger(MainTableDataModel.class);

private final ObservableList<BibEntryTableViewModel> entriesViewModel;
private final FilteredList<BibEntryTableViewModel> entriesFiltered;
Expand Down Expand Up @@ -195,6 +198,14 @@ public SortedList<BibEntryTableViewModel> getEntriesFilteredAndSorted() {
return entriesFilteredAndSorted;
}

public Optional<BibEntryTableViewModel> getViewModelByIndex(int index) {
if (index < 0 || index >= entriesViewModel.size()) {
LOGGER.warn("Tried to access out of bounds index {} in entriesViewModel", index);
return Optional.empty();
}
return Optional.of(entriesViewModel.get(index));
}

public void resetFieldFormatter() {
this.fieldValueFormatter.setValue(new MainTableFieldValueFormatter(nameDisplayPreferences, bibDatabaseContext));
}
Expand Down
39 changes: 35 additions & 4 deletions src/main/java/org/jabref/gui/preferences/ai/AiTab.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<?import com.dlsc.unitfx.IntegerInputField?>
<?import org.controlsfx.control.SearchableComboBox?>
<?import org.controlsfx.control.textfield.CustomPasswordField?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TextArea?>
<fx:root
spacing="10.0"
type="VBox"
Expand Down Expand Up @@ -162,10 +165,6 @@
</children>
</HBox>

<ResizableTextArea
fx:id="instructionTextArea"
wrapText="true"/>

<GridPane hgap="10" vgap="10">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" percentWidth="50" />
Expand Down Expand Up @@ -235,5 +234,37 @@
glyph="REFRESH"/>
</graphic>
</Button>

<HBox alignment="BASELINE_CENTER">
<Label styleClass="sectionHeader"
text="%Templates"
maxWidth="Infinity"
HBox.hgrow="ALWAYS"/>
<Button fx:id="templatesHelp"
prefWidth="20.0"/>
</HBox>

<TabPane>
<Tab text="%System message for chatting" closable="false">
<TextArea fx:id="systemMessageTextArea"/>
</Tab>
<Tab text="User message for chatting" closable="false">
<TextArea fx:id="userMessageTextArea"/>
</Tab>
<Tab text="Completion text for summarization of a chunk" closable="false">
<TextArea fx:id="summarizationChunkTextArea"/>
</Tab>
<Tab text="Completion text for summarization of several chunks" closable="false">
<TextArea fx:id="summarizationCombineTextArea"/>
</Tab>
</TabPane>

<Button onAction="#onResetTemplatesButtonClick"
text="%Reset templates to default">
<graphic>
<JabRefIconView
glyph="REFRESH"/>
</graphic>
</Button>
</children>
</fx:root>
Loading

0 comments on commit 3115e68

Please sign in to comment.