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 user interface for the TEX parser tool #5103

Merged
merged 32 commits into from
Jul 12, 2019
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
203b9ff
Add user interface for the TEX parser tool
davidemdot Jun 12, 2019
1ca4c50
Fix some issues discussed in the PR
davidemdot Jun 19, 2019
75b6b35
Update TexFileCrawler for using Path instead of File
davidemdot Jun 20, 2019
45dadd5
Update ReferenceWrapper for using Collection and fix minor issue
davidemdot Jun 20, 2019
e7a6523
Adapt ParseTexDialog to MVVM and update to a better crawler
davidemdot Jun 26, 2019
9274481
Fix a few issues of the last commit
davidemdot Jun 26, 2019
3ade18a
Add temp implementation for jumpToFile()
davidemdot Jun 27, 2019
08eac13
Update WalkFileTreeTask and fix minor issues (getDisplayText, increas…
davidemdot Jun 27, 2019
aca6f1a
Fix issues (grouping properties, showTreeView, EasyBind, Logger)
davidemdot Jun 28, 2019
77893bc
Update for fixing the last few issues and revert WalkFileTreeTask
davidemdot Jul 1, 2019
de9ea2a
Separate file node class into FileNode and FileNodeViewModel
davidemdot Jul 2, 2019
d0cdb5c
Merge branch 'latexintegration' of https://github.com/JabRef/jabref i…
davidemdot Jul 2, 2019
d741835
Update ReferenceWrapper and related classes
davidemdot Jul 2, 2019
beca782
Remove JumpToFile feature until it is ready
davidemdot Jul 4, 2019
bd8315f
Fix a few issues explained in #5103
davidemdot Jul 5, 2019
fd986b2
Fix a few issues explained in #5103 (2)
davidemdot Jul 6, 2019
19c2f0c
Remove WalkFileTreeTask and move searchDirectory() to ParseTexDialogV…
davidemdot Jul 6, 2019
8f213f4
Update for running parse() in a BackgroundTask
davidemdot Jul 6, 2019
89b371d
Update for parsing TEX files in a BackgroundTask
davidemdot Jul 7, 2019
0feb22b
Add validation checker for texDirectory
davidemdot Jul 7, 2019
2cc4bff
Update for disabling search button until there is a valid path
davidemdot Jul 7, 2019
bb4eb5d
Update for fixing minor issues
davidemdot Jul 7, 2019
dacbb1e
Update for disabling parse button while there are no items checked
davidemdot Jul 7, 2019
6ea93e3
Fix minor issues
davidemdot Jul 7, 2019
9098519
Add progress indicator
davidemdot Jul 7, 2019
d9b2e50
Update for small fixes
davidemdot Jul 7, 2019
0924b8d
Add a few comments and fix small issues
davidemdot Jul 10, 2019
0683d85
Update CHANGELOG.md
davidemdot Jul 10, 2019
10d90b2
Update for improving the searchDirectory method
davidemdot Jul 11, 2019
277ab94
Fix minor issues from last commit
davidemdot Jul 11, 2019
0495b51
Add more improvements
davidemdot Jul 11, 2019
21c33d5
Update for opening results in a new dialog
davidemdot Jul 12, 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: 2 additions & 0 deletions src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
import org.jabref.gui.search.GlobalSearchBar;
import org.jabref.gui.shared.ConnectToSharedDatabaseCommand;
import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory;
import org.jabref.gui.texparser.ParseTexAction;
import org.jabref.gui.undo.CountingUndoManager;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.DefaultTaskExecutor;
Expand Down Expand Up @@ -768,6 +769,7 @@ private MenuBar createMenu() {
pushToApplicationsManager.setMenuItem(pushToApplicationMenuItem);

tools.getItems().addAll(
factory.createMenuItem(StandardActions.PARSE_TEX, new ParseTexAction(stateManager)),
factory.createMenuItem(StandardActions.NEW_SUB_LIBRARY_FROM_AUX, new NewSubLibraryAction(this, stateManager)),
factory.createMenuItem(StandardActions.FIND_UNLINKED_FILES, new FindUnlinkedFilesAction(this, stateManager)),
factory.createMenuItem(StandardActions.WRITE_XMP, new OldDatabaseCommandWrapper(Actions.WRITE_XMP, this, stateManager)),
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jabref/gui/actions/StandardActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public enum StandardActions implements Action {
TOOGLE_OO(Localization.lang("OpenOffice/LibreOffice"), IconTheme.JabRefIcons.FILE_OPENOFFICE, KeyBinding.OPEN_OPEN_OFFICE_LIBRE_OFFICE_CONNECTION),
TOGGLE_WEB_SEARCH(Localization.lang("Web search"), Localization.lang("Toggle web search interface"), IconTheme.JabRefIcons.WWW, KeyBinding.WEB_SEARCH),

PARSE_TEX(Localization.lang("LaTeX references search"), IconTheme.JabRefIcons.APPLICATION_TEXSTUDIO),
NEW_SUB_LIBRARY_FROM_AUX(Localization.lang("New sublibrary based on AUX file") + "...", Localization.lang("New BibTeX sublibrary") + Localization.lang("This feature generates a new library based on which entries are needed in an existing LaTeX document."), IconTheme.JabRefIcons.NEW),
WRITE_XMP(Localization.lang("Write XMP-metadata to PDFs"), Localization.lang("Will write XMP-metadata to the PDFs linked from selected entries."), KeyBinding.WRITE_XMP),
OPEN_FOLDER(Localization.lang("Open folder"), Localization.lang("Open folder"), KeyBinding.OPEN_FOLDER),
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/org/jabref/gui/texparser/FileNodeViewModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.jabref.gui.texparser;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.StringJoiner;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import org.jabref.logic.l10n.Localization;

public class FileNodeViewModel {
davidemdot marked this conversation as resolved.
Show resolved Hide resolved

private Path path;
private int fileCount;
private final ObservableList<FileNodeViewModel> children;

public FileNodeViewModel(Path path) {
this.path = path;
this.fileCount = 0;
this.children = FXCollections.observableArrayList();
}

public Path getPath() {
return path;
}

public void setPath(Path path) {
this.path = path;
}

public int getFileCount() {
return fileCount;
}

public void setFileCount(int fileCount) {
this.fileCount = fileCount;
}

public ObservableList<FileNodeViewModel> getChildren() {
return children;
}

public String getDisplayText() {
if (Files.isDirectory(this.path)) {
return String.format("%s (%s %s)", path.getFileName(), fileCount,
fileCount == 1 ? Localization.lang("file") : Localization.lang("files"));
}
return path.getFileName().toString();
}

@Override
public String toString() {
return new StringJoiner(", ", FileNodeViewModel.class.getSimpleName() + "[", "]")
.add("path=" + path)
.add("fileCount=" + fileCount)
.add("children=" + children)
.toString();
}
}
25 changes: 25 additions & 0 deletions src/main/java/org/jabref/gui/texparser/ParseTexAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.jabref.gui.texparser;

import org.jabref.gui.StateManager;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.model.database.BibDatabaseContext;

import static org.jabref.gui.actions.ActionHelper.needsDatabase;

public class ParseTexAction extends SimpleCommand {

private final StateManager stateManager;

public ParseTexAction(StateManager stateManager) {
this.stateManager = stateManager;
this.executable.bind(needsDatabase(stateManager));
}

@Override
public void execute() {
BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(NullPointerException::new);
ParseTexDialogView dialog = new ParseTexDialogView(database);

dialog.showAndWait();
}
}
40 changes: 40 additions & 0 deletions src/main/java/org/jabref/gui/texparser/ParseTexDialog.fxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonType?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import org.controlsfx.control.CheckTreeView?>

<DialogPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="org.jabref.gui.texparser.ParseTexDialogView"
prefWidth="500.0" prefHeight="650.0">
<content>
<VBox spacing="10.0">
<VBox spacing="5.0">
<Label text="%LaTeX files directory:"/>
<HBox spacing="10.0">
<TextField fx:id="texDirectoryField" HBox.hgrow="ALWAYS"/>
<Button fx:id="browseButton" onAction="#browseButtonClicked" text="%Browse"/>
<Button fx:id="searchButton" defaultButton="true" onAction="#searchButtonClicked" text="%Search"/>
</HBox>
</VBox>
<VBox spacing="5.0">
<Label text="%LaTeX files found:"/>
<CheckTreeView fx:id="fileTreeView" prefHeight="500.0" VBox.vgrow="ALWAYS"/>
</VBox>
<VBox spacing="5.0">
<HBox spacing="10.0">
<Button fx:id="selectAllButton" text="%Select all" styleClass="text-button" onAction="#selectAll"/>
<Button fx:id="unselectAllButton" text="%Unselect all" styleClass="text-button"
onAction="#unselectAll"/>
</HBox>
</VBox>
</VBox>
</content>
<ButtonType fx:constant="CLOSE"/>
<ButtonType fx:id="parseButtonType" text="%Parse"/>
</DialogPane>
107 changes: 107 additions & 0 deletions src/main/java/org/jabref/gui/texparser/ParseTexDialogView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.jabref.gui.texparser;

import javax.inject.Inject;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TextField;

import org.jabref.gui.DialogService;
import org.jabref.gui.util.BaseDialog;
import org.jabref.gui.util.RecursiveTreeItem;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.gui.util.ViewModelTreeCellFactory;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.preferences.PreferencesService;

import com.airhacks.afterburner.views.ViewLoader;
import org.controlsfx.control.CheckTreeView;
import org.fxmisc.easybind.EasyBind;

public class ParseTexDialogView extends BaseDialog<Void> {

private final BibDatabaseContext databaseContext;
@FXML private TextField texDirectoryField;
@FXML private Button browseButton;
@FXML private Button searchButton;
@FXML private CheckTreeView<FileNodeViewModel> fileTreeView;
@FXML private Button selectAllButton;
@FXML private Button unselectAllButton;
@FXML private ButtonType parseButtonType;
@Inject private DialogService dialogService;
@Inject private TaskExecutor taskExecutor;
@Inject private PreferencesService preferencesService;
private ParseTexDialogViewModel viewModel;

public ParseTexDialogView(BibDatabaseContext databaseContext) {
this.databaseContext = databaseContext;

this.setTitle(Localization.lang("LaTeX references search"));

ViewLoader.view(this)
.load()
.setAsDialogPane(this);

Button parseButton = (Button) this.getDialogPane().lookupButton(parseButtonType);
parseButton.disableProperty().bindBidirectional(viewModel.noFilesFoundProperty());
davidemdot marked this conversation as resolved.
Show resolved Hide resolved

setResultConverter(button -> {
if (button == parseButtonType) {
viewModel.parse();
}
return null;
});
}

@FXML
private void initialize() {
viewModel = new ParseTexDialogViewModel(databaseContext, dialogService, taskExecutor, preferencesService);

fileTreeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
fileTreeView.showRootProperty().bindBidirectional(viewModel.successfulSearchProperty());
fileTreeView.rootProperty().bind(EasyBind.map(viewModel.rootProperty(), fileNode ->
new RecursiveTreeItem<>(fileNode, FileNodeViewModel::getChildren)));

EasyBind.subscribe(fileTreeView.rootProperty(), root -> {
if (root != null) {
((CheckBoxTreeItem<FileNodeViewModel>) root).setSelected(true);
root.setExpanded(true);
EasyBind.listBind(viewModel.getCheckedFileList(), fileTreeView.getCheckModel().getCheckedItems());
davidemdot marked this conversation as resolved.
Show resolved Hide resolved
}
});

new ViewModelTreeCellFactory<FileNodeViewModel>()
.withText(FileNodeViewModel::getDisplayText)
.install(fileTreeView);

texDirectoryField.textProperty().bindBidirectional(viewModel.texDirectoryProperty());
browseButton.disableProperty().bindBidirectional(viewModel.searchInProgressProperty());
searchButton.disableProperty().bindBidirectional(viewModel.searchInProgressProperty());
selectAllButton.disableProperty().bindBidirectional(viewModel.noFilesFoundProperty());
unselectAllButton.disableProperty().bindBidirectional(viewModel.noFilesFoundProperty());
}

@FXML
private void browseButtonClicked() {
viewModel.browseButtonClicked();
}

@FXML
private void searchButtonClicked() {
viewModel.searchButtonClicked();
}

@FXML
private void selectAll() {
fileTreeView.getCheckModel().checkAll();
}

@FXML
private void unselectAll() {
fileTreeView.getCheckModel().clearChecks();
}
}
Loading