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

Fix custom exporter not displayed in file chooser #4015

Merged
merged 24 commits into from
Jun 3, 2018

Conversation

Siedlerchr
Copy link
Member

@Siedlerchr Siedlerchr commented May 6, 2018

Fixes #4013

Fixed several issues with the Custom Exporter.

  • Filename check for layout files was wrong
  • Commandline name for custom exports was the filename and not the name, opposed to what our help says
  • Custom exports could not be added due to our hardcoded enum
  • Expanded the enum with Mixins

  • Change in CHANGELOG.md described
  • Tests created for changes
  • Manually tested changed features in running JabRef
  • Screenshots added in PR description (for bigger UI changes)
  • Ensured that the git commit message is a good one
  • Check documentation status (Issue created for outdated help page at help.jabref.org?)

@Siedlerchr Siedlerchr added status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers and removed status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers labels May 6, 2018
Siedlerchr added 2 commits May 6, 2018 21:50
Rename FileType -> BasicFileType
Fix error with layout file in custom export
Fix problem with custom export and file types
Remove old ExportFileFilter
Importer still uses BasicFileType
@Siedlerchr Siedlerchr added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label May 6, 2018
Copy link
Member

@tobiasdiez tobiasdiez left a comment

Choose a reason for hiding this comment

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

I just had a quick look but I'm a bit confused. The problem that custom export formats are not displayed correctly sounds like a gui problem to me. However, the solution involves redefining / changing a lot of logic code. Thus I think there should be an easier solution.

The exporter are displayed using the FileChooser.ExtensionFilter. Thus I suspect that one only needs to change the way how an exporter is converted to an ExtensionFilter. For the "All import formats" option, this is done in

public static FileChooser.ExtensionFilter forAllImporters(SortedSet<Importer> importers) {
return convertImporter(Localization.lang("Available import formats"), importers);
}

and I don't see why such an approach shouldn't work also for custom exporters.

But as I said, I only had a quick look and so probably missed something obvious.

allfileTypes.add(fileType);
}

public static FileType parse(String description) {
Copy link
Member

Choose a reason for hiding this comment

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

It appears to me that the parse method is no longer needed and I suspect that hence the allFileTypes list can be removed. Right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes missed that.

@Siedlerchr
Copy link
Member Author

The core problem is not the gui but that each exporter has a file type and this file type was also added for the custom exporter. These file type used the parse method to find a file type based on the extension. The file type class is used for the file filter chooser. And an exporter is matched on the file type description.
But as this is an enum, it did not work for custom export as always one of the enum values was used, e.g the default HTML Export.

The core changes are in the enum which now implemented an interface.
In fact it's just a rename of the old enum and a simple interface which has the name of the old one

To avoid code duplicates in the anonymous class and the enum I moved them to private static methods.

@tobiasdiez
Copy link
Member

ok, thanks for the explanation. I thought a bit more about this problem and came to the conclusion that the cleanest solution is probably to split the description from the "file type". If the later is only a list of extensions (xml, bib, txt, ...) and the importer/exporter itself contains the description, then you can easily create a ExtensionFilter for an importer/exporter (and don't need to pay special attention to custom exporters). What do you think?

@Siedlerchr
Copy link
Member Author

Siedlerchr commented May 12, 2018

This would only work if the custom export follows the standard file types. If I want my exporter to have filetype xyz then this would not be possible.
What I did is to provide a set of standard file types and their descriptions which can be extended to support custom one. The standard file types are also used for the importer.

Another thing which just came to my mind was that we with this approach could also resuse the functionality for the ExternalFileType stuff. Than we could get rid of that completely.

@tobiasdiez
Copy link
Member

ok, good point. Do you want to improve the code around ExternalFileType as part of this PR or is this a follow-up?

I would still separate the file extension from the description text.

@Siedlerchr
Copy link
Member Author

I would rather do this in a follow up on the maintable directly

CHANGELOG.md Outdated
@@ -16,6 +16,10 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- We changed the implementation of the `[shorttitle]` key pattern. It now removes small words like `a`, `an`, `on`, `the` etc. Refer to the help page for a complete overview. [Feature request in the forum](http://discourse.jabref.org/t/jabref-differences-in-shorttitle-between-versions-3-8-1-and-4-not-discounting-the-a-an-of-in-titles/1147)

### Fixed
We fixed an issue where the export to clipboard functionality could not be invoked [#3994](https://github.com/JabRef/jabref/issues/3994)
We fixed an issue with the migration of invalid Look and Feels [#3995, comment](https://github.com/JabRef/jabref/issues/3995#issuecomment-385649448)
Copy link
Member

Choose a reason for hiding this comment

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

This looks like a duplication (probably due to a problem while merging).

@@ -101,7 +102,7 @@ public Builder withInitialDirectory(String directory) {
return this;
}

public Builder withDefaultExtension(FileType fileType) {
public Builder withDefaultExtension(BasicFileType fileType) {
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 this method should still accept FileType

return toExtensionFilter(description, fileTypes);
}

private static FileChooser.ExtensionFilter toExtensionFilter(String description, List<FileType> fileTypes) {
private static FileChooser.ExtensionFilter toExtensionFilter(String description, List<BasicFileType> fileTypes) {
Copy link
Member

Choose a reason for hiding this comment

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

Here also FileType

@@ -117,7 +118,7 @@ public TemplateExporter(String consoleName, String lfFileName, String directory,
* @param savePreferences Preferences for saving
* @param deleteBlankLines If blank lines should be remove (default: false)
*/
public TemplateExporter(String consoleName, String lfFileName, String directory, FileType extension, LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, boolean deleteBlankLines) {
public TemplateExporter(String consoleName, String lfFileName, String directory, BasicFileType extension, LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, boolean deleteBlankLines) {
Copy link
Member

Choose a reason for hiding this comment

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

here too

*/
public abstract FileType getFileType();
public abstract BasicFileType getFileType();
Copy link
Member

Choose a reason for hiding this comment

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

here as well...

import org.jabref.logic.l10n.Localization;

/**
* This enum contains a list of file types used in open and save dialogs.
Copy link
Member

Choose a reason for hiding this comment

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

We shouldn't reference dialogs here (as we are in the logic package).

DEFAULT(Localization.lang("%0 file", "DEFAULT"), "default");

private static Set<FileType> allfileTypes = new HashSet<>(EnumSet.allOf(BasicFileType.class));
private final String[] extensions;
Copy link
Member

Choose a reason for hiding this comment

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

It probably makes the code below a bit easier to read if you simply store the extensions as a List. Moreover, the comment below can probably be removed.

public String getFirstExtensionWithDot() {
return "." + extensions[0].trim();
}
String getFirstExtensionWithDot();
Copy link
Member

Choose a reason for hiding this comment

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

For these two method you can provide a default implementation.

}

public static FileType addnewFileType(String description, String... extensions) {
FileType fileType = new FileType() {
Copy link
Member

Choose a reason for hiding this comment

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

It is probably better to extract this anonymous class to a separate class since it looks to be the standard implementation that can be reused in custom importers

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 have created a factory method for this. So the caller does not need to create it's own file type objects
public static FileType addnewFileType(String description, String... extensions) {

}
return sj.toString();
}
String getDescription();
Copy link
Member

Choose a reason for hiding this comment

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

Also on a second look, I'm strongly in favor of removing the description from the file type. It is actually the description of the exporter/importer that we should show in the dialog...if you want to reuse the strings you can extract the descriptions in BasicFileType to a new class, but its also ok if you just repeat the description in the importer and exporter.

Copy link
Member Author

Choose a reason for hiding this comment

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

This would not solve the underlying problem and in fact would result in the same problem I intend to fix here.
As we have multiple file types with the same extension e.g. html. We already have Html Table, Html LIst etc. Only with the added description, the file type is unique

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 your example is a good illustration why the current mix of file extensions and description is misleading. The file type is html in both examples, but the exporter used is different (tables vs list). You don't get these kind of problems if the FileType is only an abstraction of the extension and the description comes from the exporter...

Copy link
Member Author

Choose a reason for hiding this comment

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

At least we need the description in the extension filter. Otherwise we can't map it. I will think about this. I will look and see how this would affect the importer

…leType

* upstream/master: (33 commits)
  Import inspection uses now same font size setttings as maintable (#4062)
  Add date checker (#4007)
  Enable tests
  macOs push to application fix
  Fix #4041 to make Push to Application work again on OSX. (#4057)
  Add NormalizeEnDashesFormatter (#4045)
  Package private for tests
  Shutdown duplicate code
  Move migrations to PreferencesMigrations
  Structure startup
  Extract migrations
  A first solution for the cli problem #4038 (#4047)
  New translations JabRef_en.properties (French) (#4052)
  Update CHANGELOG.md
  Fix checkstyle
  Make test more informative in the failing case
  New translations JabRef_en.properties (French) (#4051)
  New translations JabRef_en.properties (Vietnamese) (#4050)
  Make Formatter an abstract class (and remove AbstractFormatter)
  New Crowdin translations (#4048)
  ...

# Conflicts:
#	CHANGELOG.md
remove list of custom file types as it's not needed
use list instead of varargs params
…abref into fixCustomExportFileType

* 'fixCustomExportFileType' of https://github.com/JabRef/jabref:

# Conflicts:
#	CHANGELOG.md
…leType

* upstream/master:
  New Crowdin translations (#4065)
  New translations Menu_en.properties (Vietnamese) (#4063)
@Siedlerchr Siedlerchr mentioned this pull request May 29, 2018
@stefan-kolb stefan-kolb added this to the v4.3 milestone May 30, 2018
@Siedlerchr
Copy link
Member Author

@tobiasdiez I now removed the exporter stuff from the FileTypes. So currently it's only used for the importers. The key problem with the importers is, that we have an "All available import formats" plus all the extensions. In this case I see no way to filter the importer without having a description in the extension format.

@tobiasdiez
Copy link
Member

A shot in the blue: Instead of

private static FileChooser.ExtensionFilter convertImporter(String description, Collection<Importer> formats) {
List<FileType> fileTypes = formats.stream().map(Importer::getFileType).collect(Collectors.toList());
return toExtensionFilter(description, fileTypes);
}

try

 private static FileChooser.ExtensionFilter convertImporter(Importer importer) { 
     return toExtensionFilter(importer.getDisplayName(), Collections.singletonList(importer.getFileType)); 
}

and at the same time change

public static Optional<Importer> getImporter(FileChooser.ExtensionFilter extensionFilter, Collection<Importer> importers) {
return importers.stream().filter(importer -> importer.getFileType().getDescription().equals(extensionFilter.getDescription())).findFirst();
}

to

 public static Optional<Importer> getImporter(FileChooser.ExtensionFilter extensionFilter, Collection<Importer> importers) { 
     return importers.stream().filter(importer -> importer.getDisplayName().equals(extensionFilter.getDescription())).findFirst(); 
} 

If getImporter returns an empty optional, you know that there is no specific importer, i.e. the user selected "any file" or "any import format".

@tobiasdiez tobiasdiez removed the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label May 31, 2018
only keep those with multiple extensions
TODO: convert each importer
group extensions
@Siedlerchr
Copy link
Member Author

@tobiasdiez I noticed that it was already possible. I just needed to create the Map with Description/Name and FileType like I did for export. It is now analogous to export. I removed the not needed FileTypes.
However, there are still some import formats left which have more than one extension. However, I think it's not worth changing them, too. Would make things a lot more complicated.
We already have a good base for future expansions and for using this in combination with ExternalFileTypes.

Copy link
Member

@tobiasdiez tobiasdiez left a comment

Choose a reason for hiding this comment

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

Very good! There are still some unimplemented comments from previous reviews (the only big one being that the description part should now be removed from the filetype interface).

@@ -152,7 +155,7 @@ public void update() {
}

private static FileDialogConfiguration createExportFileChooser(ExporterFactory exportFactory, String currentDir) {
List<FileType> fileTypes = exportFactory.getExporters().stream().map(Exporter::getFileType).collect(Collectors.toList());
Map<String, FileType> fileTypes = exportFactory.getExporters().stream().collect(Collectors.toMap(Exporter::getDisplayName, Exporter::getFileType));
Copy link
Member

Choose a reason for hiding this comment

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

The logic to convert an exporter (and importer below) to a FileExtensionFilter should reside in FileFilterConverter.

Copy link
Member Author

Choose a reason for hiding this comment

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

No, in this case it would not have any additional benefit. It would still return a map. The map is internally handled in the file dialog configuration and there handled.

…leType

* upstream/master:
  Show development information
  Release v4.3
  Remove invalid test and fix another
  CPU leak #3943 (#4058)

# Conflicts:
#	CHANGELOG.md
@Siedlerchr Siedlerchr added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Jun 3, 2018
@koppor
Copy link
Member

koppor commented Jun 3, 2018

If I understand correctly, this should go into master before merging #3621.

@Siedlerchr
Copy link
Member Author

Yes definitely.

@koppor koppor mentioned this pull request Jun 3, 2018
35 tasks
@tobiasdiez
Copy link
Member

I've refactored a bit more (it was easier to hijack this PR than describe the refactorings in detail -sorry). If you are happy with these changes, feel free to merge; otherwise just revert my commits...

@Siedlerchr
Copy link
Member Author

Looks good so far. If someone can merge this with co authoring ( i got this wrong last time)

@koppor koppor merged commit 2f5f2e5 into master Jun 3, 2018
@koppor koppor deleted the fixCustomExportFileType branch June 3, 2018 19:02
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.

4 participants