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

Export pdf/linked files #3147

Merged
merged 36 commits into from
Nov 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9d38d12
First approach for implementing PDF Exporter
Siedlerchr Apr 2, 2017
00eccc7
First approach for implementing PDF Exporter
Siedlerchr Oct 7, 2017
50e9716
Add to File menu and context menu
Siedlerchr Oct 7, 2017
26a7e1f
Remove separator from tools menu
Siedlerchr Oct 7, 2017
ec7c44b
fix fileUtil and localzation from rebase
Siedlerchr Oct 7, 2017
68e1562
Remove empty line
Siedlerchr Oct 7, 2017
d1b53eb
Move service to new class
Siedlerchr Oct 8, 2017
7021371
Fix translation
Siedlerchr Oct 8, 2017
6b02e9c
Add idea for list view dialog
Siedlerchr Oct 8, 2017
edec73d
Merge remote-tracking branch 'upstream/master' into exportPdf
Siedlerchr Oct 11, 2017
95474ea
Merge remote-tracking branch 'upstream/master' into exportPdf
Siedlerchr Oct 19, 2017
bed0a54
Add TableView to show log message
Siedlerchr Oct 19, 2017
e347bc9
Add class for table view data
Siedlerchr Oct 19, 2017
090a4cd
Add Green/Red icons for status
Siedlerchr Oct 19, 2017
93f72b2
fix checkstyle and make cancel button close button
Siedlerchr Oct 19, 2017
353e9ad
fix codacy
Siedlerchr Oct 20, 2017
f29066c
Merge remote-tracking branch 'upstream/master' into exportPdf
Siedlerchr Oct 20, 2017
aa10731
Renamings
Siedlerchr Oct 20, 2017
9e6cffc
Remove setter
Siedlerchr Oct 20, 2017
b61082c
Add fxml and move to package
Siedlerchr Oct 20, 2017
713ecec
fix controller
Siedlerchr Oct 20, 2017
cfa74e5
Merge remote-tracking branch 'upstream/master' into exportPdf
Siedlerchr Oct 21, 2017
4c01181
add button data
Siedlerchr Oct 21, 2017
cc30b98
Add new wrapper class for injection
Siedlerchr Oct 21, 2017
a67cd4e
Add todos hinting at empty
Siedlerchr Oct 21, 2017
5d96526
Fix injection of data
Siedlerchr Oct 21, 2017
8011e6e
rebame and fix checkstyle
Siedlerchr Oct 21, 2017
bb1a304
Make variables private
Siedlerchr Oct 21, 2017
5e1117a
Merge remote-tracking branch 'upstream/master' into exportPdf
Siedlerchr Oct 22, 2017
8dabe6d
Merge remote-tracking branch 'upstream/master' into exportPdf
Siedlerchr Oct 25, 2017
fc7a2a1
fix merge error in lang files
Siedlerchr Oct 25, 2017
ba35360
Fix some coday warnings
Siedlerchr Oct 25, 2017
88faa7c
Rename l10n
Siedlerchr Oct 26, 2017
658d97e
Merge remote-tracking branch 'upstream/master' into exportPdf
Siedlerchr Oct 31, 2017
8f14cc7
fix showing of progress bar
Siedlerchr Oct 31, 2017
07ee6ea
Merge branch 'exportPdf' of https://github.com/JabRef/jabref into exp…
Siedlerchr Oct 31, 2017
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- We now set the WM_CLASS of the UI to org-jabref-JabRefMain to allow certain Un*x window managers to properly identify its windows
- We changed the default paths for the OpenOffice/LibreOffice binaries to the default path for LibreOffice
- We no longer create a new entry editor when selecting a new entry to increase performance. [#3187](https://github.com/JabRef/jabref/pull/3187)
- We added the possibility to copy linked files from entries to a single output folder [#2539](https://github.com/JabRef/jabref/pull/2593)
- We increased performance and decreased the memory footprint of the entry editor drastically. [#3331](https://github.com/JabRef/jabref/pull/3331)
- Late initialization of the context menus in the entry editor. This improves performance and memory footprint further [#3340](https://github.com/JabRef/jabref/pull/3340)

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/jabref/gui/AbstractDialogView.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package org.jabref.gui;

import java.util.function.Function;

public abstract class AbstractDialogView extends AbstractView {

public AbstractDialogView() {
super();
}

public AbstractDialogView(Function<String, Object> injectionContext) {
super(injectionContext);
}

public abstract void show();
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/jabref/gui/DialogService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.List;
import java.util.Optional;

import javafx.concurrent.Task;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.DialogPane;
Expand All @@ -13,6 +14,8 @@
import org.jabref.gui.util.FileDialogConfiguration;
import org.jabref.logic.l10n.Localization;

import org.controlsfx.dialog.ProgressDialog;

/**
* This interface provides methods to create dialogs and show them to the user.
*/
Expand Down Expand Up @@ -121,6 +124,12 @@ Optional<ButtonType> showCustomButtonDialogAndWait(Alert.AlertType type, String
*/
<R> Optional<R> showCustomDialogAndWait(Dialog<R> dialog);

/**
* Constructs and shows a canceable {@link ProgressDialog}. Clicking cancel will cancel the underlying service and close the dialog
* @param task The {@link Task} which executes the work and for which to show the dialog
*/
<V> void showCanceableProgressDialogAndWait(Task<V> task);

/**
* Notify the user in an non-blocking way (i.e., update status message instead of showing a dialog).
* @param message the message to show.
Expand Down Expand Up @@ -173,4 +182,5 @@ Optional<ButtonType> showCustomButtonDialogAndWait(Alert.AlertType type, String
* @return A configured instance of the {@link FileChooser}
*/
FileChooser getConfiguredFileChooser(FileDialogConfiguration fileDialogConfiguration);

}
18 changes: 18 additions & 0 deletions src/main/java/org/jabref/gui/FXDialogService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import java.util.Optional;
import java.util.stream.Collectors;

import javafx.concurrent.Task;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.DialogPane;
Expand All @@ -22,6 +24,7 @@
import org.jabref.logic.l10n.Localization;

import org.controlsfx.dialog.ExceptionDialog;
import org.controlsfx.dialog.ProgressDialog;

/**
* This class provides methods to create default
Expand Down Expand Up @@ -127,6 +130,21 @@ public <R> Optional<R> showCustomDialogAndWait(Dialog<R> dialog) {
return dialog.showAndWait();
}

@Override
public <V> void showCanceableProgressDialogAndWait(Task<V> task) {
ProgressDialog progressDialog = new ProgressDialog(task);
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();
});
progressDialog.showAndWait();

}

@Override
public void notify(String message) {
JabRefGUI.getMainFrame().output(message);
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import org.jabref.gui.actions.SortTabsAction;
import org.jabref.gui.autosaveandbackup.AutosaveUIManager;
import org.jabref.gui.bibtexkeypattern.BibtexKeyPatternDialog;
import org.jabref.gui.copyfiles.CopyFilesAction;
import org.jabref.gui.customentrytypes.EntryCustomizationDialog;
import org.jabref.gui.dbproperties.DatabasePropertiesDialog;
import org.jabref.gui.documentviewer.ShowDocumentViewerAction;
Expand Down Expand Up @@ -389,6 +390,7 @@ public void actionPerformed(ActionEvent e) {
Localization.menuTitle("Unabbreviate journal names"),
Localization.lang("Unabbreviate journal names of the selected entries"),
Globals.getKeyPrefs().getKey(KeyBinding.UNABBREVIATE));
private final AbstractAction exportLinkedFiles = new CopyFilesAction();
private final AbstractAction manageJournals = new ManageJournalsAction();
private final AbstractAction databaseProperties = new DatabasePropertiesAction();
private final AbstractAction bibtexKeyPattern = new BibtexKeyPatternAction();
Expand Down Expand Up @@ -1059,6 +1061,7 @@ private void fillMenu() {
file.add(importCurrent);
file.add(exportAll);
file.add(exportSelected);
file.add(exportLinkedFiles);
file.addSeparator();
file.add(connectToSharedDatabaseAction);
file.add(pullChangesFromSharedDatabase);
Expand Down Expand Up @@ -1440,7 +1443,7 @@ dupliCheck, autoSetFile, newEntryAction, newSpec, customizeAction, plainTextImpo
twoEntriesOnlyActions.addAll(Arrays.asList(mergeEntries));

atLeastOneEntryActions.clear();
atLeastOneEntryActions.addAll(Arrays.asList(downloadFullText, lookupIdentifiers));
atLeastOneEntryActions.addAll(Arrays.asList(downloadFullText, lookupIdentifiers, exportLinkedFiles));

tabbedPane.addChangeListener(event -> updateEnabledState());

Expand Down
70 changes: 70 additions & 0 deletions src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.jabref.gui.copyfiles;

import java.awt.event.ActionEvent;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Optional;

import javax.swing.AbstractAction;

import javafx.concurrent.Task;

import org.jabref.Globals;
import org.jabref.JabRefExecutorService;
import org.jabref.JabRefGUI;
import org.jabref.gui.DialogService;
import org.jabref.gui.FXDialogService;
import org.jabref.gui.util.DefaultTaskExecutor;
import org.jabref.gui.util.DirectoryDialogConfiguration;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.preferences.JabRefPreferences;

public class CopyFilesAction extends AbstractAction {

private final DialogService dialogService = new FXDialogService();
private BibDatabaseContext databaseContext;
private List<BibEntry> entries;

public CopyFilesAction() {
super(Localization.lang("Copy linked files to folder..."));
}

@Override
public void actionPerformed(ActionEvent e) {

DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder()
.withInitialDirectory(Paths.get(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY)))
.build();
entries = JabRefGUI.getMainFrame().getCurrentBasePanel().getSelectedEntries();

Optional<Path> exportPath = DefaultTaskExecutor
.runInJavaFXThread(() -> dialogService.showDirectorySelectionDialog(dirDialogConfiguration));

exportPath.ifPresent(path -> {
databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext();

Task<List<CopyFilesResultItemViewModel>> exportTask = new CopyFilesTask(databaseContext, entries, path);
startServiceAndshowProgessDialog(exportTask);
});
}

private void startServiceAndshowProgessDialog(Task<List<CopyFilesResultItemViewModel>> exportService) {
DefaultTaskExecutor.runInJavaFXThread(() -> {
exportService.setOnSucceeded(value -> {
DefaultTaskExecutor.runInJavaFXThread(() -> showDialog(exportService.getValue()));

});
JabRefExecutorService.INSTANCE.executeInterruptableTask(exportService);
dialogService.showCanceableProgressDialogAndWait(exportService);

});
}

private void showDialog(List<CopyFilesResultItemViewModel> data) {
CopyFilesDialogView dlg = new CopyFilesDialogView(databaseContext, new CopyFilesResultListDependency(data));
dlg.show();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.jabref.gui.copyfiles;

import javax.inject.Inject;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;

import org.jabref.gui.AbstractController;
import org.jabref.gui.util.ValueTableCellFactory;

import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
import de.jensd.fx.glyphs.materialdesignicons.utils.MaterialDesignIconFactory;

public class CopyFilesDialogController extends AbstractController<CopyFilesDialogViewModel> {

@FXML private TableView<CopyFilesResultItemViewModel> tvResult;
@FXML private TableColumn<CopyFilesResultItemViewModel, MaterialDesignIcon> colStatus;
@FXML private TableColumn<CopyFilesResultItemViewModel, String> colMessage;
@FXML private TableColumn<CopyFilesResultItemViewModel, String> colFile;

@Inject private CopyFilesResultListDependency copyfilesresultlistDependency; //This var must have the same name as the key in the View

@FXML
private void close(@SuppressWarnings("unused") ActionEvent event) {
getStage().close();
}

@FXML
private void initialize() {
viewModel = new CopyFilesDialogViewModel(copyfilesresultlistDependency);
setupTable();
}

private void setupTable() {
colFile.setCellValueFactory(cellData -> cellData.getValue().getFile());
colMessage.setCellValueFactory(cellData -> cellData.getValue().getMessage());
colStatus.setCellValueFactory(cellData -> cellData.getValue().getIcon());

colFile.setCellFactory(new ValueTableCellFactory<CopyFilesResultItemViewModel, String>().withText(item -> item).withTooltip(item -> item));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to prevent that fourth column appearing #3147 (comment) ?

colStatus.setCellFactory(new ValueTableCellFactory<CopyFilesResultItemViewModel, MaterialDesignIcon>().withGraphic(item -> {

Text icon = MaterialDesignIconFactory.get().createIcon(item);
if (item == MaterialDesignIcon.CHECK) {
icon.setFill(Color.GREEN);
}
if (item == MaterialDesignIcon.ALERT) {
icon.setFill(Color.RED);
}
return icon;
}));

tvResult.setItems(viewModel.copyFilesResultListProperty());
tvResult.setColumnResizePolicy((param) -> true);
}
}
36 changes: 36 additions & 0 deletions src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.jabref.gui.copyfiles;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.DialogPane;

import org.jabref.gui.AbstractDialogView;
import org.jabref.gui.FXDialog;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;

public class CopyFilesDialogView extends AbstractDialogView {

public CopyFilesDialogView(BibDatabaseContext bibDatabaseContext, CopyFilesResultListDependency results) {
super(createContext(bibDatabaseContext, results));
}

@Override
public void show() {
FXDialog copyFilesResultDlg = new FXDialog(AlertType.INFORMATION, Localization.lang("Result"));
copyFilesResultDlg.setResizable(true);
copyFilesResultDlg.setDialogPane((DialogPane) this.getView());
copyFilesResultDlg.show();
}

private static Function<String, Object> createContext(BibDatabaseContext bibDatabaseContext, CopyFilesResultListDependency copyfilesresultlistDependency) {
Map<String, Object> context = new HashMap<>();
//The "keys" of the HashMap must have the same name as the with @inject annotated field in the controller
context.put("bibdatabasecontext", bibDatabaseContext);
context.put("copyfilesresultlistDependency", copyfilesresultlistDependency);
return context::get;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.jabref.gui.copyfiles;

import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;

import org.jabref.gui.AbstractViewModel;

public class CopyFilesDialogViewModel extends AbstractViewModel {

private final SimpleListProperty<CopyFilesResultItemViewModel> copyFilesResultItems = new SimpleListProperty<>(
FXCollections.observableArrayList());

public CopyFilesDialogViewModel(CopyFilesResultListDependency results) {
copyFilesResultItems.addAll(results.getResults());
}

public SimpleListProperty<CopyFilesResultItemViewModel> copyFilesResultListProperty() {
return this.copyFilesResultItems;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.jabref.gui.copyfiles;

import java.nio.file.Path;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;

public class CopyFilesResultItemViewModel {

private final StringProperty file = new SimpleStringProperty("");
private final ObjectProperty<MaterialDesignIcon> icon = new SimpleObjectProperty<>(MaterialDesignIcon.ALERT);
private final StringProperty message = new SimpleStringProperty("");

public CopyFilesResultItemViewModel(Path file, boolean success, String message) {
this.file.setValue(file.toString());
this.message.setValue(message);
if (success) {
this.icon.setValue(MaterialDesignIcon.CHECK);
}
}

public StringProperty getFile() {
return file;
}

public StringProperty getMessage() {
return message;
}

public ObjectProperty<MaterialDesignIcon> getIcon() {
return icon;
}

@Override
public String toString() {
return "CopyFilesResultItemViewModel [file=" + file.get() + ", message=" + message.get() + "]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.jabref.gui.copyfiles;

import java.util.ArrayList;
import java.util.List;

/**
* This class is a wrapper class for the containing list as it is currently not possible to inject complex object types into FXML controller
*
*/
public class CopyFilesResultListDependency {

private List<CopyFilesResultItemViewModel> results = new ArrayList<>();

public CopyFilesResultListDependency() {
//empty, workaround for injection into FXML controller
}

public CopyFilesResultListDependency(List<CopyFilesResultItemViewModel> results) {
this.results = results;
}

public List<CopyFilesResultItemViewModel> getResults() {
return results;
}

@Override
public String toString() {
return "CopyFilesResultListDependency [results=" + results + "]";
}

}
Loading