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

Export pdf/linked files #3147

merged 36 commits into from
Nov 1, 2017

Conversation

Siedlerchr
Copy link
Member

@Siedlerchr Siedlerchr commented Aug 22, 2017

Fixes #2539

Followup from #2706 because somehow my new changes did not update the PR correctly.

grafik

  • Change in CHANGELOG.md described
  • Tests created for changes
  • Screenshots added (for bigger UI changes)
  • Manually tested changed features in running JabRef
  • Check documentation status (Issue created for outdated help page at help.jabref.org?)
  • If you changed the localization: Did you run gradle localizationUpdate?

@Siedlerchr Siedlerchr added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Aug 22, 2017
Copy link
Member

@lenhard lenhard left a comment

Choose a reason for hiding this comment

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

I've tested it locally and it works in principle.

There's one thing I would like you to add, though: logging: When I do the export, I would like to have a log statement that says where I exported to, or alternatively if I tried to export and it failed. This will make error diagnosis later much easier. And you can expect to get issue reports, because this is something that works with the file system, so there are users who will use it in weird circumstances.


public class ExportLinkedFilesAction extends AbstractAction {

private final BiFunction<Path, Path, Path> resolvePathFilename = (p, f) -> {
Copy link
Member

Choose a reason for hiding this comment

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

Please use meaningful names (not p, f) even in lambdas

private final BiFunction<Path, Path, Path> resolvePathFilename = (p, f) -> {
return p.resolve(f.getFileName());
};
private final DialogService ds = new FXDialogService();
Copy link
Member

Choose a reason for hiding this comment

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

Same here, better name please.

Copy link
Member

Choose a reason for hiding this comment

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

Not fixed.


long totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count();

Service<Void> service = new Service<Void>() {
Copy link
Member

Choose a reason for hiding this comment

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

The enclosing actionPerformed() is a really big method. Please do some refactoring and make it smaller. The first thing would be to extract this class, at least to an inner class instead of an anonymous one.

service.start();

DefaultTaskExecutor.runInJavaFXThread(() -> {
ProgressDialog dlg = new ProgressDialog(service);
Copy link
Member

Choose a reason for hiding this comment

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

And again, more meaningful names please :-)

@LinusDietz LinusDietz added this to the v4.1 milestone Aug 28, 2017
@koppor
Copy link
Member

koppor commented Aug 31, 2017

Is it possible to add this to the context menu? I once added "Send as email" to the menu as I also needed a similar functionality for sending entries as email:

grafik

@koppor koppor mentioned this pull request Aug 31, 2017
6 tasks
@koppor
Copy link
Member

koppor commented Aug 31, 2017

@Siedlerchr Your PR did not update as you named the branches differently: exportPdf vs. exportPDF. The letters D and F are cased differently. Thus, these are different branches. 🎉

@koppor
Copy link
Member

koppor commented Aug 31, 2017

Current accessibility:

grafik

Reading #2706 (comment) and the following comments, I do not like the word "Export" in the Tools menu. It took me 5 minutes to find the functionality.

  1. Context menu: No entry for that
  2. File menu: No entry for that
  3. File -> Export: Cannot select "PDFs" somehow.

Suggestion:

Rename to "Copy attached files to folder..."

Further minor issues

  • progress always shows "exporting file 0 of x"
    grafik
  • Last chosen folder is not remembered. The browse-dialog always starts in %HOME
  • Pressing "Cancel" when choosing the folder also triggers the export.

@LinusDietz
Copy link
Member

Added devcall label to discuss milestone

@koppor
Copy link
Member

koppor commented Aug 31, 2017

Stays at v4.1 milestone as v4.1 will be our PDF feature release.

@koppor koppor added on-hold and removed status: devcall status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers labels Aug 31, 2017
Remove code that produces NPE
Remove code that produces NPE

Export linked files
Don't replace existings

Create new Action for exporting files
TODO: Add to menu

Move to Tools entry

try around with some background task stuf

remove compile errro

Add Progessbar dialog
Add localization

Fix checkstyle

extract to inner class
Add some more output messages
renamed variables

Fix gui display
Fix localization to copy files
@Siedlerchr Siedlerchr added status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers and removed on-hold labels Oct 7, 2017
@Siedlerchr
Copy link
Member Author

I think I fixed all issues raised by @koppor and I also create a log file in the export dir.

Copy link
Member

@lenhard lenhard left a comment

Choose a reason for hiding this comment

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

Overall, the code looks fine. I just have a few suggestions for quality improvements. It would be cool if you could have a go at these, but it wouldn't block this PR if you don't.

The only real blocker is the missing changelog entry :)

@@ -51,6 +51,7 @@ public static void main(String[] args) {
public void start(Stage mainStage) throws Exception {
Platform.setImplicitExit(false);
SwingUtilities.invokeLater(() -> start(arguments));

Copy link
Member

Choose a reason for hiding this comment

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

Why is there a blank line here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops.

});
}

private class ExportService extends Service<Void> {
Copy link
Member

Choose a reason for hiding this comment

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

This is rather nitpicky, but what about extracting this into a separate class file in the same package with default visibility? You could also extract parts of call() into separate private methods. All this wouldn't change anything about the functionality, but it would make the code a little less chunky and more readable.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see no reason why I should extract that in a new class. It's just a single Service for one purpose.
But I think I can surely extract some private methods

Copy link
Member

Choose a reason for hiding this comment

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

One reason is that you could (and should) write tests for the ExportService.

Avoid code duplicaiton
DefaultTaskExecutor.runInJavaFXThread(() -> {
service.start();

ProgressDialog progressDialog = new ProgressDialog(service);
Copy link
Member

Choose a reason for hiding this comment

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

Can you please extract the "show progress dialog" part of this method to the DialogService class.

List<LinkedFile> files = entries.get(i).getFiles();

for (int j = 0; j < files.size(); j++) {
updateMessage(Localization.lang("Copying file %0 of BibEntry %1", Integer.toString(j + 1), Integer.toString(i + 1)));
Copy link
Member

Choose a reason for hiding this comment

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

I think we never used BibEntry before in the user interface (it is the class name...). What about only "entry" or "item"?


for (int j = 0; j < files.size(); j++) {
updateMessage(Localization.lang("Copying file %0 of BibEntry %1", Integer.toString(j + 1), Integer.toString(i + 1)));
Thread.sleep(500); //TODO: Adjust/leave/any other idea?
Copy link
Member

Choose a reason for hiding this comment

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

This sleep makes the whole progress of copying files really slow. I would remove it even through then the user has no chance to actually read the message for small files (but that is ok in my opinion).

Thread.sleep(500); //TODO: Adjust/leave/any other idea?

String fileName = files.get(j).getLink();
Optional<Path> fileToExport = FileHelper.expandFilenameAsPath(fileName,
Copy link
Member

Choose a reason for hiding this comment

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

Use

public Optional<Path> findIn(BibDatabaseContext databaseContext, FileDirectoryPreferences fileDirectoryPreferences) {

updateMessage(Localization.lang("Copying files..."));
updateProgress(0, totalFilesCount);

try (BufferedWriter bw = Files.newBufferedWriter(exportPath.get().resolve(LOGFILE), StandardCharsets.UTF_8)) {
Copy link
Member

Choose a reason for hiding this comment

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

In my opinion, a log file is an inconvenient solution for the user. Why don't log all the errors to an internal list and display this list at the end in a new dialog?

@@ -313,12 +313,6 @@ public void performExport(final BibDatabaseContext databaseContext, final String

}

@Override
public void performExport(final BibDatabaseContext databaseContext, Path file, final Charset encoding,
Copy link
Member

Choose a reason for hiding this comment

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

Please don't delete this path based methods. I know they are not yet used but they are actually preferable to the string or file-based methods (these should actually be deprecated).

Copy link
Member Author

Choose a reason for hiding this comment

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

I deleted it on purpose because it is not working at all as I explained in my other PR or earlier.
It always lead to an exception.

Copy link
Member

Choose a reason for hiding this comment

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

ok...

@@ -102,6 +103,7 @@ public RightClickMenu(JabRefFrame frame, BasePanel panel) {

add(new GeneralAction(Actions.SEND_AS_EMAIL, Localization.lang("Send as email"), IconTheme.JabRefIcon.EMAIL.getSmallIcon()));
addSeparator();
add(new ExportLinkedFilesAction());
Copy link
Member

Choose a reason for hiding this comment

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

Do you really think that this export functionality is used that often that we should add it to the right click menu?

Copy link
Member Author

Choose a reason for hiding this comment

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

It was requested by @koppor And I think it makes sense to have it in the context menu

* upstream/master:
  Set WM_CLASS to org-jabref-JabRefMain (#3273)
  Terminate JavaFX thread when running with "nogui" option (#3274)
* upstream/master:
  Update gradle to 4.2.1 (#3322)
  Avoid recreation of the EntryEditor (#3187)
  Fix #3133 telemetry by locking azure to 1.0.9
  German translation for missing properties (#3312)
  Improvement for Java FX font rendering on Linux (#3305)
  Add also conversion for em dash
  Add \textendash to the html conversion table
  Update latex2tunicode from 0.2.1 -> 0.2.2
  Added note about updating controlsfx
  Fix exception/freezing on EntryChangedEvent in Entry Editor (#3299)
  Update libs (#3300)
  update guava from 23.0 -> 23.2
  update mvvmfx-validation from 1.6.0 -> 1.7.0
  Resolves #3255 file open dialog should have "supported formates" filetype
  Fix #3235: remote metadata is updated instead of delete + insert (#3282)
  Change OO paths to Libre Office in preferences (#3287)
  Fix #2471: remove line breaks from abstracts in ADS fetcher (#3285)
  Resolves #3280 Empty String instead of N/A (#3288)
</TableView>
<ButtonBar prefHeight="40.0" prefWidth="200.0">
<buttons>
<Button defaultButton="true" mnemonicParsing="false" onAction="#close" text="OK" />
Copy link
Member

Choose a reason for hiding this comment

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

you should always annotate buttons in a button bar with a proper "button data", which lets JavaFX position these buttons appropriately according to the style guidelines of the current os.

* upstream/master:
  Change integrity message for names depending on database mode (#3330)
  Fix location bundle with fast access (#3327)
  Small code cleanup
  Fix "path not found" exception

# Conflicts:
#	src/main/java/org/jabref/logic/l10n/Localization.java
import java.util.ArrayList;
import java.util.List;

public class CopyFilesResultListDependency {
Copy link
Member Author

Choose a reason for hiding this comment

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

@tobiasdiez I have created this wrapper class to inject it

Copy link
Member Author

Choose a reason for hiding this comment

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

If I dont' intilaize the ArrayList with Empty, it will give an NPE in my View Model which leads to the conclusion that this are somehow different objects. I remember having similair problems wit the Sharelatex Integration and ended up making it static. But maybe there is another solution?

Copy link
Member

Choose a reason for hiding this comment

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

Oh damn...thats ugly. It is not possible to directly inject the list of results?
You also hit this bug here: AdamBien/afterburner.fx#71 this is why you need the no-arg constructor.

Copy link
Member

Choose a reason for hiding this comment

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

I'll have a look at it later.

Copy link
Member Author

Choose a reason for hiding this comment

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

The list can not be directly injected, because List is an interface which of course can not be instantiated...that's where our default injector throws an error
I tried to add handling for list but then generics are a problem...

Copy link
Member Author

Choose a reason for hiding this comment

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

@tobiasdiez I found the issue. The "key" of the Hashmap and the name of the with inject annotated variable differed! That's why the data was not passed correct

Copy link
Member

Choose a reason for hiding this comment

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

With #3334 you should be able to use @Inject List<whatever> toBeInjected or other complex types (they do not need to have a no-args constructor anymore). Of course the names of the "key" and the "field" have to coincide to make this work.

@@ -76,7 +71,11 @@ private void startServiceAndshowProgessDialog(Task<List<CopyFilesResultItemViewM
}

private void showDialog(List<CopyFilesResultItemViewModel> data) {
Dialog<ButtonType> dlg = new Dialog<>();

CopyFilesDialogView dlg = new CopyFilesDialogView(databaseContext, new CopyFilesResultListDependency(data));
Copy link
Member Author

Choose a reason for hiding this comment

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

@tobiasdiez Here I am passing the instance of the object, but it doesn't display any data.

Switch gui to border pane
add tooltip to factory
* upstream/master:
  Initializing EntryEditor Tabs on focus (#3331)
  Fix #3292: annotations are now automatically refreshed (#3325)

# Conflicts:
#	CHANGELOG.md
* upstream/master:
  Fix NPE when calling with bib file as cmd argument (#3343)
  update mockito-core from 2.10.0 -> 2.11.0 (#3338)
  Remove underscore in Localized messages (#3336)
  Localisation: French: new entries translated (#3337)
  Refactoring: Lazy init of all editor tabs (#3333)
@LinusDietz
Copy link
Member

The result dialog is displayed way too small on my display.

screen shot 2017-10-25 at 18 24 34

When I try to resize it, a magical fourth column appears.
screen shot 2017-10-25 at 18 29 19

Copy link
Member

@LinusDietz LinusDietz left a comment

Choose a reason for hiding this comment

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

Just some minor remarks which are not really blockers.

public class CopyFilesTask extends Task<List<CopyFilesResultItemViewModel>> {

private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class);
private static final String LOGFILE = "exportLog.log";
Copy link
Member

Choose a reason for hiding this comment

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

I am unsure if this logfile is needed.

If it is, I would encode a timestamp into the filename to be able to distinguish several exports into the same folder.

private List<BibEntry> entries;

public ExportLinkedFilesAction() {
super(Localization.lang("Copy attached files to folder..."));
Copy link
Member

Choose a reason for hiding this comment

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

The terminology should be consistent. I suggest "Copy linked files to folder.."

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) ?

Add timestamp
Improve GUI
@Siedlerchr
Copy link
Member Author

@lynyus I changed the column size and there is also a tooltip for the file column

* upstream/master:
  Rework AutoSetFileLinks (#3368)
  revert wrongly commited changes
  Refactorings (#3370)
  Fix freezing when running cleanup file operations like rename (#3315)
  This additional style setting for IDEA (#3355)
  Fix checkstyle
  Add proper equals to content selector
  Source tab entry duplication (#3360)
  Use CITE_COMMENT not only for external latex editors but also for cop… (#3351)
  Updating with new translations (#3348)
  Upgrade error-prone (#3350)
  Jabref_pt_BR partially updated (#3349)
  Delete unused code
  Extract difference finder from gui to logic
  Used late initialization for context menus (#3340)
  Remove unnecessary EntrySorter
  Move existing code to gui and rename change classes to view model
  Small code improvements
Copy link
Member

@lenhard lenhard left a comment

Choose a reason for hiding this comment

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

I had another look at the code, which seems fine. I think you have addressed all the other reviewers comments, so I"ll merge this now.

@lenhard lenhard merged commit d5f0b69 into master Nov 1, 2017
@lenhard lenhard deleted the exportPdf branch November 1, 2017 15:28
Siedlerchr added a commit that referenced this pull request Nov 3, 2017
* upstream/master: (22 commits)
  Improve SyncLang.py (#3184)
  Config intellj code style to adhere to empty lines checkstyle rule (#3365)
  Don't list same look and feels more than once (#3393)
  progessdialog and result table are now shown correclty on copy files
  Export pdf/linked files  (#3147)
  Added checking integrity dialog (#3388)
  Update richtext and flowless (#3386)
  Source tab: hide notification pane when code is correct again (#3387)
  Titles are optional at crossref (#3378)
  Update entry for every change in the source panel (#3366)
  Rework AutoSetFileLinks (#3368)
  revert wrongly commited changes
  Refactorings (#3370)
  Fix freezing when running cleanup file operations like rename (#3315)
  This additional style setting for IDEA (#3355)
  Fix checkstyle
  Add proper equals to content selector
  Delete unused code
  Extract difference finder from gui to logic
  Remove unnecessary EntrySorter
  ...

# Conflicts:
#	src/main/java/org/jabref/gui/entryeditor/SourceTab.java
Siedlerchr added a commit that referenced this pull request Nov 4, 2017
* upstream/master: (26 commits)
  Fix static localized text (#3400)
  Fix problems in source editor (#3398)
  Fix MathSciNet fetcher (#3402)
  Fix NPE when saving new file
  Improve SyncLang.py (#3184)
  Config intellj code style to adhere to empty lines checkstyle rule (#3365)
  Don't list same look and feels more than once (#3393)
  progessdialog and result table are now shown correclty on copy files
  Export pdf/linked files  (#3147)
  Added checking integrity dialog (#3388)
  Update richtext and flowless (#3386)
  Source tab: hide notification pane when code is correct again (#3387)
  Titles are optional at crossref (#3378)
  Update entry for every change in the source panel (#3366)
  Rework AutoSetFileLinks (#3368)
  revert wrongly commited changes
  Refactorings (#3370)
  Fix freezing when running cleanup file operations like rename (#3315)
  This additional style setting for IDEA (#3355)
  Fix checkstyle
  ...

# Conflicts:
#	CHANGELOG.md
Siedlerchr added a commit that referenced this pull request Nov 19, 2017
* upstream/master:
  Improve SyncLang.py (#3184)
  Config intellj code style to adhere to empty lines checkstyle rule (#3365)
  Don't list same look and feels more than once (#3393)
  progessdialog and result table are now shown correclty on copy files
  Export pdf/linked files  (#3147)
  Added checking integrity dialog (#3388)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants