Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LaTeX citations tab to the entry editor #5137

Merged
merged 34 commits into from
Jul 29, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a13e3b2
Update EntryEditor for using PreferencesService
davidemdot Jul 18, 2019
fedda55
Add LaTeX references tab option to entry editor preferences
davidemdot Jul 18, 2019
4214103
Add getCitationsByKey(BibEntry) method in TexParserResult
davidemdot Jul 18, 2019
4ba7f0d
Add LaTeX references tab to the entry editor
davidemdot Jul 18, 2019
d1fc7b3
Add missing localization keys
davidemdot Jul 19, 2019
145b631
Fix bug related to the display of results
davidemdot Jul 19, 2019
cba1949
Replace Boolean with boolean type in preferences
davidemdot Jul 20, 2019
47deee4
Rename feature-related stuff (references -> citations)
davidemdot Jul 20, 2019
4d7256d
Update CHANGELOG.md
davidemdot Jul 20, 2019
04d1a5f
Improve exception handling and add search cancellation
davidemdot Jul 20, 2019
0d41f30
Update DefaultTexParser for avoiding ClosedByInterruptException when …
davidemdot Jul 20, 2019
0095bed
Update EntryEditor for adding @Inject uses
davidemdot Jul 20, 2019
de0db44
Fix bug in EntryEditor (setOnDragDropped event)
davidemdot Jul 20, 2019
e6722ee
Merge remote-tracking branch 'origin/master' into latexintegration-en…
davidemdot Jul 20, 2019
b1c7cb6
Update logger messages in cancelSearch()
davidemdot Jul 20, 2019
824ba0d
Update LaTeX citations tab for using a enum status property
davidemdot Jul 20, 2019
1fd6d4e
Merge branch 'master' into latexintegration-entryeditortab
davidemdot Jul 24, 2019
ce4f925
Improve performance in the entry editor tab by searching for only the…
davidemdot Jul 24, 2019
00287d8
Add default case to bindToEntry() in LatexCitationsTab
davidemdot Jul 24, 2019
b2c75cb
Update for adding small improvements
davidemdot Jul 25, 2019
2db46d2
Improve performance and exception handling
davidemdot Jul 25, 2019
2b700f1
Update error message for entries without BibTeX key
davidemdot Jul 25, 2019
3fd9c36
Update GUI classes for public access
davidemdot Jul 25, 2019
4c88528
Fix minor issues
davidemdot Jul 26, 2019
0dbd084
Update for improving code
davidemdot Jul 26, 2019
2a3f4ac
Update for adding the last improvements
davidemdot Jul 26, 2019
e4c0e14
Update for code refining
davidemdot Jul 26, 2019
de5d705
Set the search pane in LatexCitationsTab just once
davidemdot Jul 28, 2019
3bb24a6
Update LatexCitationsTabViewModel for avoiding 'orElse(null)'
davidemdot Jul 28, 2019
ee1501e
Update TexParserResult for avoiding 'orElse(null)'
davidemdot Jul 28, 2019
5cc4622
Update DefaultTexParser for explaining when and why it skips the cita…
davidemdot Jul 28, 2019
3d019db
Change toString() methods
davidemdot Jul 28, 2019
7adf03a
Add a new JabRefIcons.LATEX_CITATIONS
davidemdot Jul 28, 2019
34713f5
Fix all issues from reviews of #5137
davidemdot Jul 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/gui/BasePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ public BasePanel(JabRefFrame frame, BasePanelPreferences preferences, BibDatabas

this.getDatabase().registerListener(new UpdateTimestampListener(Globals.prefs));

this.entryEditor = new EntryEditor(this, preferences.getEntryEditorPreferences(), Globals.getFileUpdateMonitor(), dialogService, externalFileTypes, Globals.TASK_EXECUTOR, Globals.stateManager);
this.entryEditor = new EntryEditor(this, Globals.prefs, Globals.getFileUpdateMonitor(), dialogService, externalFileTypes, Globals.TASK_EXECUTOR, Globals.stateManager);

this.preview = new PreviewPanel(getBibDatabaseContext(), this, dialogService, externalFileTypes, Globals.getKeyPrefs(), preferences.getPreviewPreferences());
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/org/jabref/gui/entryeditor/EntryEditor.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,31 @@
.bibtexSourceCodeArea .text {
-fx-fill: -fx-text-background-color;
}

.latexReferences-tab {
-fx-background-color: -fx-control-inner-background;
-fx-padding: 20px;
}

.latexReferences-title {
-fx-font-size: 130%;
-fx-font-weight: bold;
}

.latexReferences-description {
-fx-font-style: italic;
-fx-padding: 20px;
}

.latexReferences-contextBox {
-fx-border-color: grey;
-fx-border-style: dashed;
-fx-border-width: 2px;
-fx-font-size: 110%;
-fx-font-style: italic;
-fx-padding: 15px;
}

.latexReferences-fileData {
-fx-font-family: 'Courier New', Courier, monospace;
}
135 changes: 71 additions & 64 deletions src/main/java/org/jabref/gui/entryeditor/EntryEditor.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ public class EntryEditorPreferences {
private boolean showSourceTabByDefault;
private final KeyBindingRepository keyBindings;
private boolean avoidOverwritingCiteKey;
private final boolean shouldShowLatexReferencesTab;

public EntryEditorPreferences(Map<String, List<String>> entryEditorTabList, LatexFieldFormatterPreferences latexFieldFormatterPreferences, ImportFormatPreferences importFormatPreferences, List<String> customTabFieldNames, boolean shouldShowRecommendationsTab, boolean isMrdlibAccepted, boolean showSourceTabByDefault, BibtexKeyPatternPreferences bibtexKeyPatternPreferences, KeyBindingRepository keyBindings, boolean avoidOverwritingCiteKey) {
public EntryEditorPreferences(Map<String, List<String>> entryEditorTabList, LatexFieldFormatterPreferences latexFieldFormatterPreferences, ImportFormatPreferences importFormatPreferences, List<String> customTabFieldNames, boolean shouldShowRecommendationsTab, boolean isMrdlibAccepted, boolean shouldShowLatexReferencesTab, boolean showSourceTabByDefault, BibtexKeyPatternPreferences bibtexKeyPatternPreferences, KeyBindingRepository keyBindings, boolean avoidOverwritingCiteKey) {
this.entryEditorTabList = entryEditorTabList;
this.latexFieldFormatterPreferences = latexFieldFormatterPreferences;
this.importFormatPreferences = importFormatPreferences;
Expand All @@ -32,6 +33,7 @@ public EntryEditorPreferences(Map<String, List<String>> entryEditorTabList, Late
this.bibtexKeyPatternPreferences = bibtexKeyPatternPreferences;
this.keyBindings = keyBindings;
this.avoidOverwritingCiteKey = avoidOverwritingCiteKey;
this.shouldShowLatexReferencesTab = shouldShowLatexReferencesTab;
}

public Map<String, List<String>> getEntryEditorTabList() {
Expand Down Expand Up @@ -78,6 +80,10 @@ public void setShowSourceTabByDefault(boolean showSourceTabByDefault) {
this.showSourceTabByDefault = showSourceTabByDefault;
}

public boolean shouldShowLatexReferencesTab() {
return shouldShowLatexReferencesTab;
}

public boolean avoidOverwritingCiteKey() {
return avoidOverwritingCiteKey;
}
Expand Down
109 changes: 109 additions & 0 deletions src/main/java/org/jabref/gui/entryeditor/LatexReferencesTab.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package org.jabref.gui.entryeditor;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;

import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.strings.LatexToUnicodeAdapter;
import org.jabref.model.texparser.Citation;
import org.jabref.preferences.PreferencesService;

import org.fxmisc.easybind.EasyBind;

public class LatexReferencesTab extends EntryEditorTab {

private final LatexReferencesTabViewModel viewModel;
private ProgressIndicator progressIndicator;
private ObservableList<VBox> formattedCitationList;
private StackPane searchPane;

public LatexReferencesTab(BibDatabaseContext databaseContext, PreferencesService preferencesService,
TaskExecutor taskExecutor) {
this.viewModel = new LatexReferencesTabViewModel(databaseContext, preferencesService, taskExecutor);

setText(Localization.lang("LaTeX references"));
setTooltip(new Tooltip(Localization.lang("Search this reference in the LaTeX file directory")));
setGraphic(IconTheme.JabRefIcons.APPLICATION_TEXSTUDIO.getGraphicNode());
}

private void setupSearchPane() {
progressIndicator = new ProgressIndicator();
progressIndicator.setMaxSize(100.0, 100.0);

formattedCitationList = FXCollections.observableArrayList();

searchPane = new StackPane();
searchPane.getStyleClass().add("latexReferences-tab");
searchPane.getChildren().add(progressIndicator);

setContent(searchPane);
}

@Override
protected void bindToEntry(BibEntry entry) {
setupSearchPane();

viewModel.setEntry(entry);
viewModel.initSearch();
davidemdot marked this conversation as resolved.
Show resolved Hide resolved

EasyBind.subscribe(viewModel.searchInProgressProperty(), stillWorking -> {
if (!stillWorking) {
formattedCitationList = EasyBind.map(viewModel.getCitationList(), this::citationToGraphic);
searchPane.getChildren().setAll(
viewModel.successfulSearchProperty().get()
? getCitationsPane()
: getNotFoundPane());
}
});
}

private VBox citationToGraphic(Citation citation) {
HBox contextBox = new HBox(new Text(LatexToUnicodeAdapter.format(citation.getLineText())));
contextBox.getStyleClass().add("latexReferences-contextBox");

Text fileData = new Text(String.format("%n%s (%s:%s-%s)", citation.getPath().toAbsolutePath(),
citation.getLine(), citation.getColStart(), citation.getColEnd()));
fileData.getStyleClass().add("latexReferences-fileData");

return new VBox(contextBox, fileData);
}

private ScrollPane getCitationsPane() {
Text titleText = new Text(Localization.lang("References found:"));
titleText.getStyleClass().add("latexReferences-title");

VBox vBox = new VBox(20.0, titleText);
vBox.getChildren().setAll(formattedCitationList);

ScrollPane citationsPane = new ScrollPane();
citationsPane.setContent(vBox);

return citationsPane;
}

private ScrollPane getNotFoundPane() {
Text descriptionText = new Text(Localization.lang("No references found for this entry."));
descriptionText.getStyleClass().add("latexReferences-description");

ScrollPane notFoundPane = new ScrollPane();
notFoundPane.setContent(descriptionText);

return notFoundPane;
}

@Override
public boolean shouldShow(BibEntry entry) {
return viewModel.shouldShow();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.jabref.gui.entryeditor;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyListWrapper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import org.jabref.gui.AbstractViewModel;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.texparser.DefaultTexParser;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.texparser.Citation;
import org.jabref.model.texparser.TexParserResult;
import org.jabref.preferences.PreferencesService;

public class LatexReferencesTabViewModel extends AbstractViewModel {

private static final String TEX_EXT = ".tex";
private final BibDatabaseContext databaseContext;
private final PreferencesService preferencesService;
private final TaskExecutor taskExecutor;
private final ObjectProperty<BibEntry> entry;
private final ObservableList<Citation> citationList;
private final BooleanProperty searchInProgress;
private final BooleanProperty successfulSearch;

public LatexReferencesTabViewModel(BibDatabaseContext databaseContext, PreferencesService preferencesService,
TaskExecutor taskExecutor) {
this.databaseContext = databaseContext;
this.preferencesService = preferencesService;
this.taskExecutor = taskExecutor;
this.entry = new SimpleObjectProperty<>();
this.citationList = FXCollections.observableArrayList();
this.searchInProgress = new SimpleBooleanProperty(true);
this.successfulSearch = new SimpleBooleanProperty(false);
}

public void setEntry(BibEntry entry) {
this.entry.set(entry);
}

public ObservableList<Citation> getCitationList() {
return new ReadOnlyListWrapper<>(citationList);
}

public BooleanProperty searchInProgressProperty() {
return searchInProgress;
}

public BooleanProperty successfulSearchProperty() {
return successfulSearch;
}

public void initSearch() {
BackgroundTask.wrap(this::searchAndParse)
.onRunning(() -> {
searchInProgress.set(true);
successfulSearch.set(false);
})
.onSuccess(resultsFound -> {
successfulSearch.set(resultsFound);
searchInProgress.set(false);
})
.executeWith(taskExecutor);
}

private boolean searchAndParse() throws IOException {
Path directory = databaseContext.getMetaData().getLaTexFileDirectory(preferencesService.getUser())
.orElse(preferencesService.getWorkingDir());

List<Path> texFiles;
davidemdot marked this conversation as resolved.
Show resolved Hide resolved
try (Stream<Path> filesStream = Files.walk(directory)) {
texFiles = filesStream.filter(path -> path.toFile().isFile() && path.toString().endsWith(TEX_EXT))
.collect(Collectors.toList());
} catch (IOException e) {
throw new IOException("An error occurred while searching files: ", e);
}

TexParserResult texParserResult = new DefaultTexParser().parse(texFiles);
Collection<Citation> citationCollection = texParserResult.getCitationsByKey(entry.get());
citationList.setAll(citationCollection);

return !citationCollection.isEmpty();
}

public boolean shouldShow() {
return preferencesService.getEntryEditorPreferences().shouldShowLatexReferencesTab();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class EntryEditorPrefsTab extends Pane implements PrefsTab {
private final CheckBox autoComplete;
private final CheckBox recommendations;
private final CheckBox acceptRecommendations;
private final CheckBox latexReferences;
private final CheckBox validation;
private final RadioButton autoCompBoth;
private final RadioButton autoCompFF;
Expand Down Expand Up @@ -60,6 +61,7 @@ public EntryEditorPrefsTab(JabRefPreferences prefs) {
autoComplete = new CheckBox(Localization.lang("Enable word/name autocompletion"));
recommendations = new CheckBox(Localization.lang("Show 'Related Articles' tab"));
acceptRecommendations = new CheckBox(Localization.lang("Accept recommendations from Mr. DLib"));
latexReferences = new CheckBox(Localization.lang("Show 'LaTeX references' tab"));
validation = new CheckBox(Localization.lang("Show validation messages"));

// allowed name formats
Expand Down Expand Up @@ -96,8 +98,9 @@ public EntryEditorPrefsTab(JabRefPreferences prefs) {
builder.add(emacsRebindCtrlF, 1, 6);
builder.add(recommendations, 1, 7);
builder.add(acceptRecommendations, 1, 8);
builder.add(validation, 1, 9);
builder.add(new Label(""), 1, 10);
builder.add(latexReferences, 1, 9);
builder.add(validation, 1, 10);
builder.add(new Label(""), 1, 11);

builder.add(new Separator(), 1, 13);

Expand Down Expand Up @@ -189,6 +192,7 @@ public void setValues() {
emacsRebindCtrlF.setSelected(prefs.getBoolean(JabRefPreferences.EDITOR_EMACS_KEYBINDINGS_REBIND_CF));
recommendations.setSelected(prefs.getBoolean(JabRefPreferences.SHOW_RECOMMENDATIONS));
acceptRecommendations.setSelected(prefs.getBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS));
latexReferences.setSelected(prefs.getBoolean(JabRefPreferences.SHOW_LATEX_REFERENCES));
autoComplete.setSelected(autoCompletePreferences.shouldAutoComplete());
autoCompFields.setText(autoCompletePreferences.getCompleteNamesAsString());

Expand Down Expand Up @@ -235,6 +239,7 @@ public void storeSettings() {
prefs.putBoolean(JabRefPreferences.DEFAULT_SHOW_SOURCE, defSource.isSelected());
prefs.putBoolean(JabRefPreferences.SHOW_RECOMMENDATIONS, recommendations.isSelected());
prefs.putBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS, acceptRecommendations.isSelected());
prefs.putBoolean(JabRefPreferences.SHOW_LATEX_REFERENCES, latexReferences.isSelected());
prefs.putBoolean(JabRefPreferences.VALIDATE_IN_ENTRY_EDITOR, validation.isSelected());
boolean emacsModeChanged = prefs.getBoolean(JabRefPreferences.EDITOR_EMACS_KEYBINDINGS) != emacsMode.isSelected();
boolean emacsRebindCtrlAChanged = prefs.getBoolean(JabRefPreferences.EDITOR_EMACS_KEYBINDINGS_REBIND_CA) != emacsRebindCtrlA.isSelected();
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/org/jabref/model/texparser/TexParserResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.util.Set;
import java.util.StringJoiner;

import org.jabref.model.entry.BibEntry;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

Expand Down Expand Up @@ -49,6 +51,13 @@ public Collection<Citation> getCitationsByKey(String key) {
return citations.get(key);
}

/**
* Return a collection of citations using a BibEntry as reference.
*/
public Collection<Citation> getCitationsByKey(BibEntry entry) {
return getCitationsByKey(entry.getCiteKeyOptional().orElse(null));
}

/**
* Add a list of files to fileList or nestedFiles, depending on whether this is the first list.
*/
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/jabref/preferences/JabRefPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ public class JabRefPreferences implements PreferencesService {
public static final String PUSH_TO_APPLICATION = "pushToApplication";
public static final String SHOW_RECOMMENDATIONS = "showRecommendations";
public static final String ACCEPT_RECOMMENDATIONS = "acceptRecommendations";
public static final String SHOW_LATEX_REFERENCES = "showLatexReferences";
public static final String SEND_LANGUAGE_DATA = "sendLanguageData";
public static final String SEND_OS_DATA = "sendOSData";
public static final String SEND_TIMEZONE_DATA = "sendTimezoneData";
Expand Down Expand Up @@ -574,6 +575,7 @@ private JabRefPreferences() {

defaults.put(SHOW_RECOMMENDATIONS, Boolean.TRUE);
defaults.put(ACCEPT_RECOMMENDATIONS, Boolean.FALSE);
defaults.put(SHOW_LATEX_REFERENCES, Boolean.TRUE);
defaults.put(SEND_LANGUAGE_DATA, Boolean.FALSE);
defaults.put(SEND_OS_DATA, Boolean.FALSE);
defaults.put(SEND_TIMEZONE_DATA, Boolean.FALSE);
Expand Down Expand Up @@ -901,6 +903,7 @@ public EntryEditorPreferences getEntryEditorPreferences() {
getCustomTabFieldNames(),
getBoolean(SHOW_RECOMMENDATIONS),
getBoolean(ACCEPT_RECOMMENDATIONS),
getBoolean(SHOW_LATEX_REFERENCES),
getBoolean(DEFAULT_SHOW_SOURCE),
getBibtexKeyPatternPreferences(),
Globals.getKeyPrefs(),
Expand Down
Loading