From 77b1bcf5451757787eda8aa5c8ffb9d064ca3d70 Mon Sep 17 00:00:00 2001
From: Tobias Diez
Date: Thu, 24 Jan 2019 01:15:23 +0100
Subject: [PATCH 1/2] Convert "Customize importer" dialog to JavaFX
---
.../java/org/jabref/gui/DialogService.java | 9 +
.../java/org/jabref/gui/FXDialogService.java | 12 +
src/main/java/org/jabref/gui/JabRefFrame.java | 2 +-
.../actions/ManageCustomImportsAction.java | 10 +-
.../ExportCustomizationDialogView.java | 30 +-
.../importer/ImportCustomizationDialog.fxml | 22 ++
.../importer/ImportCustomizationDialog.java | 368 +++---------------
.../ImportCustomizationDialogViewModel.java | 134 +++++++
.../jabref/gui/importer/ZipFileChooser.java | 241 ------------
.../gui/util/ViewModelTableRowFactory.java | 16 +
.../org/jabref/gui/util/ZipFileChooser.java | 84 ++++
11 files changed, 348 insertions(+), 580 deletions(-)
create mode 100644 src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.fxml
create mode 100644 src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java
delete mode 100644 src/main/java/org/jabref/gui/importer/ZipFileChooser.java
create mode 100644 src/main/java/org/jabref/gui/util/ZipFileChooser.java
diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java
index f776d192671..d1da9b44c4c 100644
--- a/src/main/java/org/jabref/gui/DialogService.java
+++ b/src/main/java/org/jabref/gui/DialogService.java
@@ -1,5 +1,6 @@
package org.jabref.gui;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@@ -247,4 +248,12 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String
*/
boolean showPrintDialog(PrinterJob job);
+ /**
+ * Shows a new dialog that list all files contained in the given archive and which lets the user select one of these
+ * files. The method doesn't return until the displayed open dialog is dismissed. The return value specifies the
+ * file chosen by the user or an empty {@link Optional} if no selection has been made.
+ *
+ * @return the selected file or an empty {@link Optional} if no file has been selected
+ */
+ Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException;
}
diff --git a/src/main/java/org/jabref/gui/FXDialogService.java b/src/main/java/org/jabref/gui/FXDialogService.java
index 60593d1edf9..59283b7b200 100644
--- a/src/main/java/org/jabref/gui/FXDialogService.java
+++ b/src/main/java/org/jabref/gui/FXDialogService.java
@@ -1,6 +1,7 @@
package org.jabref.gui;
import java.io.File;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
@@ -8,6 +9,7 @@
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
+import java.util.zip.ZipFile;
import javafx.concurrent.Task;
import javafx.print.PrinterJob;
@@ -31,6 +33,7 @@
import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.util.DirectoryDialogConfiguration;
import org.jabref.gui.util.FileDialogConfiguration;
+import org.jabref.gui.util.ZipFileChooser;
import org.jabref.logic.l10n.Localization;
import org.controlsfx.dialog.ExceptionDialog;
@@ -300,4 +303,13 @@ private FileChooser getConfiguredFileChooser(FileDialogConfiguration fileDialogC
public boolean showPrintDialog(PrinterJob job) {
return job.showPrintDialog(mainWindow);
}
+
+ @Override
+ public Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException {
+ try (ZipFile zipFile = new ZipFile(archivePath.toFile(), ZipFile.OPEN_READ)) {
+ return new ZipFileChooser(zipFile).showAndWait();
+ } catch (NoClassDefFoundError exc) {
+ throw new IOException("Could not instantiate ZIP-archive reader.", exc);
+ }
+ }
}
diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java
index 66e4643e1d2..d8fd07cb6f2 100644
--- a/src/main/java/org/jabref/gui/JabRefFrame.java
+++ b/src/main/java/org/jabref/gui/JabRefFrame.java
@@ -928,7 +928,7 @@ private MenuBar createMenu() {
new SeparatorMenuItem(),
factory.createMenuItem(StandardActions.SETUP_GENERAL_FIELDS, new SetupGeneralFieldsAction()),
- factory.createMenuItem(StandardActions.MANAGE_CUSTOM_IMPORTS, new ManageCustomImportsAction(this)),
+ factory.createMenuItem(StandardActions.MANAGE_CUSTOM_IMPORTS, new ManageCustomImportsAction()),
factory.createMenuItem(StandardActions.MANAGE_CUSTOM_EXPORTS, new ManageCustomExportsAction()),
factory.createMenuItem(StandardActions.MANAGE_EXTERNAL_FILETYPES, new EditExternalFileTypesAction()),
factory.createMenuItem(StandardActions.MANAGE_JOURNALS, new ManageJournalsAction()),
diff --git a/src/main/java/org/jabref/gui/actions/ManageCustomImportsAction.java b/src/main/java/org/jabref/gui/actions/ManageCustomImportsAction.java
index 5359168805c..e36ea7ac07c 100644
--- a/src/main/java/org/jabref/gui/actions/ManageCustomImportsAction.java
+++ b/src/main/java/org/jabref/gui/actions/ManageCustomImportsAction.java
@@ -1,21 +1,15 @@
package org.jabref.gui.actions;
-import org.jabref.gui.JabRefFrame;
import org.jabref.gui.importer.ImportCustomizationDialog;
public class ManageCustomImportsAction extends SimpleCommand {
- private final JabRefFrame jabRefFrame;
-
- public ManageCustomImportsAction(JabRefFrame jabRefFrame) {
- this.jabRefFrame = jabRefFrame;
+ public ManageCustomImportsAction() {
}
@Override
public void execute() {
- ImportCustomizationDialog ecd = new ImportCustomizationDialog(jabRefFrame);
- ecd.setVisible(true);
-
+ new ImportCustomizationDialog().showAndWait();
}
}
diff --git a/src/main/java/org/jabref/gui/exporter/ExportCustomizationDialogView.java b/src/main/java/org/jabref/gui/exporter/ExportCustomizationDialogView.java
index 0ca7d26c5ee..506f829ad66 100644
--- a/src/main/java/org/jabref/gui/exporter/ExportCustomizationDialogView.java
+++ b/src/main/java/org/jabref/gui/exporter/ExportCustomizationDialogView.java
@@ -41,22 +41,13 @@ public ExportCustomizationDialogView() {
.load()
.setAsDialogPane(this);
- ControlHelper.setAction(addButton, getDialogPane(), event -> addExporter());
- ControlHelper.setAction(modifyButton, getDialogPane(), event -> modifyExporter());
- ControlHelper.setAction(removeButton, getDialogPane(), event -> removeExporter());
- ControlHelper.setAction(closeButton, getDialogPane(), event -> saveAndClose());
- }
-
- private void addExporter() {
- viewModel.addExporter();
- }
-
- private void modifyExporter() {
- viewModel.modifyExporter();
- }
-
- private void removeExporter() {
- viewModel.removeExporters();
+ ControlHelper.setAction(addButton, getDialogPane(), event -> viewModel.addExporter());
+ ControlHelper.setAction(modifyButton, getDialogPane(), event -> viewModel.modifyExporter());
+ ControlHelper.setAction(removeButton, getDialogPane(), event -> viewModel.removeExporters());
+ ControlHelper.setAction(closeButton, getDialogPane(), event -> {
+ viewModel.saveToPrefs();
+ close();
+ });
}
@FXML
@@ -69,9 +60,4 @@ private void initialize() {
layoutColumn.setCellValueFactory(cellData -> cellData.getValue().layoutFileName());
extensionColumn.setCellValueFactory(cellData -> cellData.getValue().extension());
}
-
- private void saveAndClose() {
- viewModel.saveToPrefs();
- close();
- }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.fxml b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.fxml
new file mode 100644
index 00000000000..ef7ac89babb
--- /dev/null
+++ b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.fxml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.java b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.java
index 3cbfa285a47..7dd005727e5 100644
--- a/src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.java
+++ b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialog.java
@@ -1,320 +1,72 @@
package org.jabref.gui.importer;
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.event.ActionEvent;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.zip.ZipFile;
+import javax.inject.Inject;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import javax.swing.ActionMap;
-import javax.swing.BorderFactory;
-import javax.swing.InputMap;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.ScrollPaneConstants;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumnModel;
+import javafx.beans.property.ReadOnlyStringWrapper;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.ButtonType;
+import javafx.scene.control.SelectionMode;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.Tooltip;
-import org.jabref.Globals;
import org.jabref.gui.DialogService;
-import org.jabref.gui.JabRefDialog;
-import org.jabref.gui.JabRefFrame;
-import org.jabref.gui.help.HelpAction;
-import org.jabref.gui.keyboard.KeyBinding;
-import org.jabref.gui.util.DefaultTaskExecutor;
-import org.jabref.gui.util.FileDialogConfiguration;
-import org.jabref.logic.help.HelpFile;
+import org.jabref.gui.util.BaseDialog;
+import org.jabref.gui.util.ControlHelper;
+import org.jabref.gui.util.ViewModelTableRowFactory;
import org.jabref.logic.importer.fileformat.CustomImporter;
+import org.jabref.logic.journals.JournalAbbreviationLoader;
import org.jabref.logic.l10n.Localization;
-import org.jabref.logic.util.StandardFileType;
-import org.jabref.preferences.JabRefPreferences;
-
-import com.jgoodies.forms.builder.ButtonBarBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Dialog to manage custom importers.
- */
-public class ImportCustomizationDialog extends JabRefDialog {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(ImportCustomizationDialog.class);
-
- // Column widths for import customization dialog table:
- private static final int COL_0_WIDTH = 200;
- private static final int COL_1_WIDTH = 80;
- private static final int COL_2_WIDTH = 200;
-
- private static final int COL_3_WIDTH = 200;
-
- private final JTable customImporterTable;
-
- public ImportCustomizationDialog(final JabRefFrame frame) {
- super(Localization.lang("Manage custom imports"), false, ImportCustomizationDialog.class);
-
- DialogService dialogService = frame.getDialogService();
-
- ImportTableModel tableModel = new ImportTableModel();
- customImporterTable = new JTable(tableModel);
- TableColumnModel cm = customImporterTable.getColumnModel();
- cm.getColumn(0).setPreferredWidth(COL_0_WIDTH);
- cm.getColumn(1).setPreferredWidth(COL_1_WIDTH);
- cm.getColumn(2).setPreferredWidth(COL_2_WIDTH);
- cm.getColumn(3).setPreferredWidth(COL_3_WIDTH);
- JScrollPane sp = new JScrollPane(customImporterTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
- ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
- customImporterTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- customImporterTable.setPreferredScrollableViewportSize(getSize());
- if (customImporterTable.getRowCount() > 0) {
- customImporterTable.setRowSelectionInterval(0, 0);
- }
-
- JButton addFromFolderButton = new JButton(Localization.lang("Add from folder"));
- addFromFolderButton.addActionListener(e -> {
-
- FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder()
- .addExtensionFilter(StandardFileType.CLASS, StandardFileType.JAR)
- .withDefaultExtension(StandardFileType.JAR)
- .withInitialDirectory(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)).build();
-
- Optional selectedFile = DefaultTaskExecutor
- .runInJavaFXThread(() -> dialogService.showFileOpenDialog(fileDialogConfiguration));
-
- if (selectedFile.isPresent() && (selectedFile.get().getParent() != null)) {
- String chosenFileStr = selectedFile.get().toString();
-
- try {
- String basePath = selectedFile.get().getParent().toString();
- String className = pathToClass(basePath, new File(chosenFileStr));
- CustomImporter importer = new CustomImporter(basePath, className);
-
- addOrReplaceImporter(importer);
- customImporterTable.revalidate();
- customImporterTable.repaint();
- } catch (Exception exc) {
- dialogService.showErrorDialogAndWait(Localization.lang("Could not instantiate %0", chosenFileStr), exc);
- } catch (NoClassDefFoundError exc) {
- dialogService.showErrorDialogAndWait(
- Localization.lang("Could not instantiate %0. Have you chosen the correct package path?", chosenFileStr),
- exc);
- }
-
- }
- });
- addFromFolderButton
- .setToolTipText(Localization.lang("Add a (compiled) custom Importer class from a class path.")
- + "\n" + Localization.lang("The path need not be on the classpath of JabRef."));
-
- JButton addFromJarButton = new JButton(Localization.lang("Add from JAR"));
- addFromJarButton.addActionListener(e -> {
- FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder()
- .addExtensionFilter(StandardFileType.JAR, StandardFileType.ZIP)
- .withDefaultExtension(StandardFileType.JAR)
- .withInitialDirectory(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)).build();
-
- Optional jarZipFile = DefaultTaskExecutor
- .runInJavaFXThread(() -> dialogService.showFileOpenDialog(fileDialogConfiguration));
-
- if (jarZipFile.isPresent()) {
- try (ZipFile zipFile = new ZipFile(jarZipFile.get().toFile(), ZipFile.OPEN_READ)) {
- ZipFileChooser zipFileChooser = new ZipFileChooser(this, zipFile);
- zipFileChooser.setVisible(true);
- customImporterTable.revalidate();
- customImporterTable.repaint(10);
- } catch (IOException exc) {
- LOGGER.info("Could not open ZIP-archive.", exc);
- dialogService.showErrorDialogAndWait(
- Localization.lang("Could not open %0", jarZipFile.get().toString()) + "\n"
- + Localization.lang("Have you chosen the correct package path?"),
- exc);
- } catch (NoClassDefFoundError exc) {
- LOGGER.info("Could not instantiate ZIP-archive reader.", exc);
- dialogService.showErrorDialogAndWait(
- Localization.lang("Could not instantiate %0", jarZipFile.get().toString()) + "\n"
- + Localization.lang("Have you chosen the correct package path?"),
- exc);
- }
- }
- });
- addFromJarButton
- .setToolTipText(Localization.lang("Add a (compiled) custom Importer class from a ZIP-archive.")
- + "\n" + Localization.lang("The ZIP-archive need not be on the classpath of JabRef."));
-
- JButton showDescButton = new JButton(Localization.lang("Show description"));
- showDescButton.addActionListener(e -> {
- int row = customImporterTable.getSelectedRow();
- if (row == -1) {
- dialogService.showWarningDialogAndWait(
- Localization.lang("Manage custom imports"),
- Localization.lang("Please select an importer."));
- } else {
- CustomImporter importer = ((ImportTableModel) customImporterTable.getModel()).getImporter(row);
- dialogService.showWarningDialogAndWait(
- Localization.lang("Manage custom imports"),
- importer.getDescription());
- }
+import org.jabref.preferences.PreferencesService;
+
+import com.airhacks.afterburner.views.ViewLoader;
+import org.fxmisc.easybind.EasyBind;
+
+public class ImportCustomizationDialog extends BaseDialog {
+
+ @FXML private ButtonType addButton;
+ @FXML private ButtonType removeButton;
+ @FXML private ButtonType closeButton;
+ @FXML private TableView importerTable;
+ @FXML private TableColumn nameColumn;
+ @FXML private TableColumn classColumn;
+ @FXML private TableColumn basePathColumn;
+
+ @Inject private DialogService dialogService;
+ @Inject private PreferencesService preferences;
+ @Inject private JournalAbbreviationLoader loader;
+ private ImportCustomizationDialogViewModel viewModel;
+
+ public ImportCustomizationDialog() {
+ this.setTitle(Localization.lang("Manage custom imports"));
+
+ ViewLoader.view(this)
+ .load()
+ .setAsDialogPane(this);
+
+ ((Button) getDialogPane().lookupButton(addButton)).setTooltip(new Tooltip(
+ Localization.lang("Add a (compiled) custom Importer class from a class path.")
+ + "\n" + Localization.lang("The path need not be on the classpath of JabRef.")));
+ ControlHelper.setAction(addButton, getDialogPane(), event -> viewModel.addImporter());
+ ControlHelper.setAction(removeButton, getDialogPane(), event -> viewModel.removeSelectedImporter());
+ ControlHelper.setAction(closeButton, getDialogPane(), event -> {
+ viewModel.saveToPrefs();
+ close();
});
-
- JButton removeButton = new JButton(Localization.lang("Remove"));
- removeButton.addActionListener(e -> {
- int row = customImporterTable.getSelectedRow();
- if (row == -1) {
- dialogService.showWarningDialogAndWait(
- Localization.lang("Manage custom imports"),
- Localization.lang("Please select an importer."));
- } else {
- customImporterTable.removeRowSelectionInterval(row, row);
- Globals.prefs.customImports
- .remove(((ImportTableModel) customImporterTable.getModel()).getImporter(row));
- Globals.IMPORT_FORMAT_READER.resetImportFormats(Globals.prefs.getImportFormatPreferences(),
- Globals.prefs.getXMPPreferences(), Globals.getFileUpdateMonitor());
- customImporterTable.revalidate();
- customImporterTable.repaint();
- }
- });
-
- Action closeAction = new AbstractAction() {
-
- @Override
- public void actionPerformed(ActionEvent e) {
- dispose();
- }
- };
-
- JButton closeButton = new JButton(Localization.lang("Close"));
- closeButton.addActionListener(closeAction);
-
- JButton helpButton = new HelpAction(HelpFile.CUSTOM_IMPORTS).getHelpButton();
-
- // Key bindings:
- JPanel mainPanel = new JPanel();
- ActionMap am = mainPanel.getActionMap();
- InputMap im = mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
- im.put(Globals.getKeyPrefs().getKey(KeyBinding.CLOSE), "close");
- am.put("close", closeAction);
- mainPanel.setLayout(new BorderLayout());
- mainPanel.add(sp, BorderLayout.CENTER);
- JPanel buttons = new JPanel();
- ButtonBarBuilder bb = new ButtonBarBuilder(buttons);
- buttons.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
- bb.addGlue();
- bb.addButton(addFromFolderButton);
- bb.addButton(addFromJarButton);
- bb.addButton(showDescButton);
- bb.addButton(removeButton);
- bb.addButton(closeButton);
- bb.addUnrelatedGap();
- bb.addButton(helpButton);
- bb.addGlue();
-
- getContentPane().add(mainPanel, BorderLayout.CENTER);
- getContentPane().add(buttons, BorderLayout.SOUTH);
- this.setSize(getSize());
- pack();
- customImporterTable.requestFocus();
}
- /*
- * (non-Javadoc)
- * @see java.awt.Component#getSize()
- */
- @Override
- public Dimension getSize() {
- int width = COL_0_WIDTH + COL_1_WIDTH + COL_2_WIDTH + COL_3_WIDTH;
- return new Dimension(width, width / 2);
+ @FXML
+ private void initialize() {
+ viewModel = new ImportCustomizationDialogViewModel(preferences, dialogService);
+ importerTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
+ importerTable.itemsProperty().bind(viewModel.importersProperty());
+ EasyBind.listBind(viewModel.selectedImportersProperty(), importerTable.getSelectionModel().getSelectedItems());
+ nameColumn.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getName()));
+ classColumn.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getClassName()));
+ basePathColumn.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getBasePath().toString()));
+ new ViewModelTableRowFactory()
+ .withTooltip(CustomImporter::getDescription)
+ .install(importerTable);
}
-
- /**
- * Converts a path relative to a base-path into a class name.
- *
- * @param basePath base path
- * @param path path that includes base-path as a prefix
- * @return class name
- */
- private static String pathToClass(String basePath, File path) {
- String className = null;
- File actualPath = path;
- // remove leading basepath from path
- while (!actualPath.equals(new File(basePath))) {
- className = actualPath.getName() + (className == null ? "" : "." + className);
- actualPath = actualPath.getParentFile();
- }
- if (className != null) {
- int lastDot = className.lastIndexOf('.');
- if (lastDot < 0) {
- return className;
- }
- className = className.substring(0, lastDot);
- }
- return className;
- }
-
- /**
- * Adds an importer to the model that underlies the custom importers.
- *
- * @param importer importer
- */
- public void addOrReplaceImporter(CustomImporter importer) {
- Globals.prefs.customImports.replaceImporter(importer);
- Globals.IMPORT_FORMAT_READER.resetImportFormats(Globals.prefs.getImportFormatPreferences(),
- Globals.prefs.getXMPPreferences(), Globals.getFileUpdateMonitor());
- ((ImportTableModel) customImporterTable.getModel()).fireTableDataChanged();
- }
-
- /**
- * Table model for the custom importer table.
- */
- private class ImportTableModel extends AbstractTableModel {
-
- private final String[] columnNames = new String[] {Localization.lang("Import name"),
- Localization.lang("Command line id"), Localization.lang("Importer class"),
- Localization.lang("Contained in")};
-
- @Override
- public Object getValueAt(int rowIndex, int columnIndex) {
- Object value = null;
- CustomImporter importer = getImporter(rowIndex);
- if (columnIndex == 0) {
- value = importer.getName();
- } else if (columnIndex == 1) {
- value = importer.getName();
- } else if (columnIndex == 2) {
- value = importer.getClassName();
- } else if (columnIndex == 3) {
- value = importer.getBasePath();
- }
- return value;
- }
-
- @Override
- public int getColumnCount() {
- return columnNames.length;
- }
-
- @Override
- public int getRowCount() {
- return Globals.prefs.customImports.size();
- }
-
- @Override
- public String getColumnName(int col) {
- return columnNames[col];
- }
-
- public CustomImporter getImporter(int rowIndex) {
- CustomImporter[] importers = Globals.prefs.customImports
- .toArray(new CustomImporter[Globals.prefs.customImports.size()]);
- return importers[rowIndex];
- }
- }
-
}
diff --git a/src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java
new file mode 100644
index 00000000000..ef204f9c4fb
--- /dev/null
+++ b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java
@@ -0,0 +1,134 @@
+package org.jabref.gui.importer;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Optional;
+
+import javafx.beans.property.ListProperty;
+import javafx.beans.property.SimpleListProperty;
+import javafx.collections.FXCollections;
+
+import org.jabref.Globals;
+import org.jabref.gui.AbstractViewModel;
+import org.jabref.gui.DialogService;
+import org.jabref.gui.util.FileDialogConfiguration;
+import org.jabref.logic.importer.fileformat.CustomImporter;
+import org.jabref.logic.l10n.Localization;
+import org.jabref.logic.util.StandardFileType;
+import org.jabref.logic.util.io.FileUtil;
+import org.jabref.preferences.JabRefPreferences;
+import org.jabref.preferences.PreferencesService;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ImportCustomizationDialogViewModel extends AbstractViewModel {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ImportCustomizationDialogViewModel.class);
+
+ private final ListProperty importers;
+ private final ListProperty selectedImporters = new SimpleListProperty<>(FXCollections.observableArrayList());
+
+ private final PreferencesService preferences;
+ private final DialogService dialogService;
+
+ public ImportCustomizationDialogViewModel(PreferencesService preferences, DialogService dialogService) {
+ this.preferences = preferences;
+ this.dialogService = dialogService;
+ this.importers = new SimpleListProperty<>(FXCollections.observableArrayList(Globals.prefs.customImports));
+ }
+
+ /**
+ * Converts a path relative to a base-path into a class name.
+ *
+ * @param basePath base path
+ * @param path path that includes base-path as a prefix
+ * @return class name
+ */
+ private static String pathToClass(String basePath, Path path) {
+ String className = FileUtil.relativize(path, Collections.singletonList(Paths.get(basePath))).toString();
+ if (className != null) {
+ int lastDot = className.lastIndexOf('.');
+ if (lastDot < 0) {
+ return className;
+ }
+ className = className.substring(0, lastDot);
+ }
+ return className;
+ }
+
+ public void addImporter() {
+ FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder()
+ .addExtensionFilter(StandardFileType.CLASS, StandardFileType.JAR, StandardFileType.ZIP)
+ .withDefaultExtension(StandardFileType.CLASS)
+ .withInitialDirectory(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY))
+ .build();
+
+ Optional selectedFile = dialogService.showFileOpenDialog(fileDialogConfiguration);
+
+ if (selectedFile.isPresent() && (selectedFile.get().getParent() != null)) {
+ boolean isArchive = FileUtil.getFileExtension(selectedFile.get())
+ .filter(extension -> extension.equalsIgnoreCase("jar") || extension.equalsIgnoreCase("zip"))
+ .isPresent();
+
+ if (isArchive) {
+ try {
+ Optional selectedFileInArchive = dialogService.showFileOpenFromArchiveDialog(selectedFile.get());
+ if (selectedFileInArchive.isPresent()) {
+ String className = selectedFileInArchive.get().substring(0, selectedFileInArchive.get().lastIndexOf('.')).replace(
+ "/", ".");
+ CustomImporter importer = new CustomImporter(selectedFile.get().toAbsolutePath().toString(), className);
+ importers.add(importer);
+ }
+ } catch (IOException exc) {
+ LOGGER.error("Could not open ZIP-archive.", exc);
+ dialogService.showErrorDialogAndWait(
+ Localization.lang("Could not open %0", selectedFile.get().toString()) + "\n"
+ + Localization.lang("Have you chosen the correct package path?"),
+ exc);
+ } catch (ClassNotFoundException exc) {
+ LOGGER.error("Could not instantiate importer", exc);
+ dialogService.showErrorDialogAndWait(
+ Localization.lang("Could not instantiate %0 %1", "importer"),
+ exc);
+ }
+ } else {
+ try {
+ String basePath = selectedFile.get().getParent().toString();
+ String className = pathToClass(basePath, selectedFile.get());
+ CustomImporter importer = new CustomImporter(basePath, className);
+
+ importers.add(importer);
+ } catch (Exception exc) {
+ LOGGER.error("Could not instantiate importer", exc);
+ dialogService.showErrorDialogAndWait(Localization.lang("Could not instantiate %0", selectedFile.get().toString()), exc);
+ } catch (NoClassDefFoundError exc) {
+ LOGGER.error("Could not find class while instantiating importer", exc);
+ dialogService.showErrorDialogAndWait(
+ Localization.lang("Could not instantiate %0. Have you chosen the correct package path?", selectedFile.get().toString()),
+ exc);
+ }
+ }
+ }
+ }
+
+ public void removeSelectedImporter() {
+ importers.removeAll(selectedImporters);
+ }
+
+ public void saveToPrefs() {
+ Globals.prefs.customImports.clear();
+ Globals.prefs.customImports.addAll(importers);
+ Globals.IMPORT_FORMAT_READER.resetImportFormats(Globals.prefs.getImportFormatPreferences(), Globals.prefs.getXMPPreferences(), Globals.getFileUpdateMonitor());
+ }
+
+ public ListProperty selectedImportersProperty() {
+ return selectedImporters;
+ }
+
+ public ListProperty importersProperty() {
+ return importers;
+ }
+}
diff --git a/src/main/java/org/jabref/gui/importer/ZipFileChooser.java b/src/main/java/org/jabref/gui/importer/ZipFileChooser.java
deleted file mode 100644
index f4a1f78f5dd..00000000000
--- a/src/main/java/org/jabref/gui/importer/ZipFileChooser.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package org.jabref.gui.importer;
-
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.FormatStyle;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import javax.swing.Box;
-import javax.swing.JButton;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.ScrollPaneConstants;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumnModel;
-
-import org.jabref.gui.JabRefDialog;
-import org.jabref.logic.importer.fileformat.CustomImporter;
-import org.jabref.logic.l10n.Localization;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Dialog to allow users to choose a file contained in a ZIP file.
- */
-class ZipFileChooser extends JabRefDialog {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(ZipFileChooser.class);
-
-
- /**
- * New ZIP file chooser.
- *
- * @param importCustomizationDialog Owner of the file chooser
- * @param zipFile ZIP-Fle to choose from, must be readable
- */
- public ZipFileChooser(ImportCustomizationDialog importCustomizationDialog, ZipFile zipFile) {
- super(importCustomizationDialog, Localization.lang("Select file from ZIP-archive"), false, ZipFileChooser.class);
-
-
- ZipFileChooserTableModel tableModel = new ZipFileChooserTableModel(zipFile, getSelectableZipEntries(zipFile));
- JTable table = new JTable(tableModel);
- TableColumnModel cm = table.getColumnModel();
- cm.getColumn(0).setPreferredWidth(200);
- cm.getColumn(1).setPreferredWidth(150);
- cm.getColumn(2).setPreferredWidth(100);
- JScrollPane sp = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
- ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
- table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- table.setPreferredScrollableViewportSize(new Dimension(500, 150));
- if (table.getRowCount() > 0) {
- table.setRowSelectionInterval(0, 0);
- }
-
- // cancel: no entry is selected
- JButton cancelButton = new JButton(Localization.lang("Cancel"));
- cancelButton.addActionListener(e -> dispose());
- // ok: get selected class and check if it is instantiable as an importer
- JButton okButton = new JButton(Localization.lang("OK"));
- okButton.addActionListener(e -> {
- int row = table.getSelectedRow();
- if (row == -1) {
- JOptionPane.showMessageDialog(this, Localization.lang("Please select an importer."));
- } else {
- ZipFileChooserTableModel model = (ZipFileChooserTableModel) table.getModel();
- ZipEntry tempZipEntry = model.getZipEntry(row);
- String className = tempZipEntry.getName().substring(0, tempZipEntry.getName().lastIndexOf('.')).replace(
- "/", ".");
-
- try {
- CustomImporter importer = new CustomImporter(model.getZipFile().getName(), className);
- importCustomizationDialog.addOrReplaceImporter(importer);
- dispose();
- } catch (ClassNotFoundException exc) {
- LOGGER.warn("Could not instantiate importer: " + className, exc);
- JOptionPane.showMessageDialog(this, Localization.lang("Could not instantiate %0 %1",
- className + ":\n", exc.getMessage()));
- }
- }
- });
-
-
- // Key bindings:
- JPanel mainPanel = new JPanel();
- //ActionMap am = mainPanel.getActionMap();
- //InputMap im = mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
- //im.put(Globals.getKeyPrefs().getKey(KeyBinds.CLOSE_DIALOG), "close");
- //am.put("close", closeAction);
- mainPanel.setLayout(new BorderLayout());
- mainPanel.add(sp, BorderLayout.CENTER);
-
- JPanel optionsPanel = new JPanel();
- optionsPanel.add(okButton);
- optionsPanel.add(cancelButton);
- optionsPanel.add(Box.createHorizontalStrut(5));
-
- getContentPane().add(mainPanel, BorderLayout.CENTER);
- getContentPane().add(optionsPanel, BorderLayout.SOUTH);
- this.setSize(getSize());
- pack();
- this.setLocationRelativeTo(importCustomizationDialog);
- table.requestFocus();
- }
-
- /**
- * Entries that can be selected with this dialog.
- *
- * @param zipFile ZIP-File
- * @return entries that can be selected
- */
- private static List getSelectableZipEntries(ZipFile zipFile) {
- List entries = new ArrayList<>();
- Enumeration extends ZipEntry> e = zipFile.entries();
- for (ZipEntry entry : Collections.list(e)) {
- if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
- entries.add(entry);
- }
- }
- return entries;
- }
-
- /*
- * (non-Javadoc)
- * @see java.awt.Component#getSize()
- */
- @Override
- public Dimension getSize() {
- return new Dimension(400, 300);
- }
-
-
- /**
- * Table model for the ZIP archive contents.
- *
- * Contains one row for each entry.
- * Does not contain rows for directory entries.
- *
- * The columns contain information about ZIP file entries:
- *
-
- * name {@link String}
- *
-
- * time of last modification {@link Date}
- *
-
- * size (uncompressed) {@link Long}
- *
- */
- private static class ZipFileChooserTableModel extends AbstractTableModel {
-
- private final List columnNames = Arrays.asList(Localization.lang("Name"),
- Localization.lang("Last modified"), Localization.lang("Size"));
- private final List rows;
- private final ZipFile zipFile;
-
-
- ZipFileChooserTableModel(ZipFile zipFile, List rows) {
- super();
- this.rows = rows;
- this.zipFile = zipFile;
- }
-
- /*
- * (non-Javadoc)
- * @see javax.swing.table.TableModel#getColumnCount()
- */
- @Override
- public int getColumnCount() {
- return columnNames.size();
- }
-
- /*
- * (non-Javadoc)
- * @see javax.swing.table.TableModel#getRowCount()
- */
- @Override
- public int getRowCount() {
- return this.rows.size();
- }
-
- /*
- * (non-Javadoc)
- * @see javax.swing.table.TableModel#getColumnName(int)
- */
- @Override
- public String getColumnName(int col) {
- return columnNames.get(col);
- }
-
- /**
- * ZIP-File entry at the given row index.
- *
- * @param rowIndex row index
- * @return ZIP file entry
- */
- public ZipEntry getZipEntry(int rowIndex) {
- return this.rows.get(rowIndex);
- }
-
- /**
- * ZIP file which contains all entries of this model.
- *
- * @return zip file
- */
- public ZipFile getZipFile() {
- return this.zipFile;
- }
-
- /*
- * (non-Javadoc)
- * @see javax.swing.table.TableModel#getValueAt(int, int)
- */
- @Override
- public Object getValueAt(int rowIndex, int columnIndex) {
- Object value = null;
- ZipEntry entry = getZipEntry(rowIndex);
- if (columnIndex == 0) {
- value = entry.getName();
- } else if (columnIndex == 1) {
- value = ZonedDateTime.ofInstant(new Date(entry.getTime()).toInstant(),
- ZoneId.systemDefault())
- .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM));
- } else if (columnIndex == 2) {
- value = entry.getSize();
- }
- return value;
- }
- }
-
-}
diff --git a/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java b/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java
index 6e053fc3a40..78d50765935 100644
--- a/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java
+++ b/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java
@@ -8,6 +8,7 @@
import javafx.scene.control.ContextMenu;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
+import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeTableCell;
import javafx.scene.input.DragEvent;
import javafx.scene.input.KeyCode;
@@ -16,6 +17,8 @@
import javafx.scene.input.MouseEvent;
import javafx.util.Callback;
+import org.jabref.model.strings.StringUtil;
+
import org.reactfx.util.TriConsumer;
/**
@@ -33,6 +36,7 @@ public class ViewModelTableRowFactory implements Callback, Table
private BiConsumer toOnDragExited;
private BiConsumer toOnDragOver;
private TriConsumer, S, ? super MouseDragEvent> toOnMouseDragEntered;
+ private Callback toTooltip;
public ViewModelTableRowFactory withOnMouseClickedEvent(BiConsumer onMouseClickedEvent) {
this.onMouseClickedEvent = onMouseClickedEvent;
@@ -84,10 +88,22 @@ public ViewModelTableRowFactory setOnDragOver(BiConsumer withTooltip(Callback toTooltip) {
+ this.toTooltip = toTooltip;
+ return this;
+ }
+
@Override
public TableRow call(TableView tableView) {
TableRow row = new TableRow<>();
+ if (toTooltip != null) {
+ String tooltipText = toTooltip.call(row.getItem());
+ if (StringUtil.isNotBlank(tooltipText)) {
+ row.setTooltip(new Tooltip(tooltipText));
+ }
+ }
+
if (onMouseClickedEvent != null) {
row.setOnMouseClicked(event -> {
if (!row.isEmpty()) {
diff --git a/src/main/java/org/jabref/gui/util/ZipFileChooser.java b/src/main/java/org/jabref/gui/util/ZipFileChooser.java
new file mode 100644
index 00000000000..3335dcaaea6
--- /dev/null
+++ b/src/main/java/org/jabref/gui/util/ZipFileChooser.java
@@ -0,0 +1,84 @@
+package org.jabref.gui.util;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javafx.beans.property.ReadOnlyLongWrapper;
+import javafx.beans.property.ReadOnlyStringWrapper;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.scene.control.ButtonType;
+import javafx.scene.control.SelectionMode;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+
+import org.jabref.logic.l10n.Localization;
+
+/**
+ * Dialog to allow users to choose a file contained in a ZIP file.
+ */
+public class ZipFileChooser extends BaseDialog {
+
+ /**
+ * New ZIP file chooser.
+ *
+ * @param zipFile ZIP-Fle to choose from, must be readable
+ */
+ public ZipFileChooser(ZipFile zipFile) {
+ setTitle(Localization.lang("Select file from ZIP-archive"));
+
+ TableView table = new TableView<>(getSelectableZipEntries(zipFile));
+ TableColumn nameColumn = new TableColumn<>(Localization.lang("Name"));
+ TableColumn modifiedColumn = new TableColumn<>(Localization.lang("Last modified"));
+ TableColumn sizeColumn = new TableColumn<>(Localization.lang("Size"));
+ table.getColumns().add(nameColumn);
+ table.getColumns().add(modifiedColumn);
+ table.getColumns().add(sizeColumn);
+ nameColumn.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().getName()));
+ modifiedColumn.setCellValueFactory(data -> new ReadOnlyStringWrapper(
+ ZonedDateTime.ofInstant(new Date(data.getValue().getTime()).toInstant(),
+ ZoneId.systemDefault())
+ .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))));
+ sizeColumn.setCellValueFactory(data -> new ReadOnlyLongWrapper(data.getValue().getSize()));
+ table.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
+
+ getDialogPane().setContent(table);
+
+ getDialogPane().getButtonTypes().setAll(
+ ButtonType.OK,
+ ButtonType.CANCEL
+ );
+
+ setResultConverter(button -> {
+ if (button == ButtonType.OK) {
+ return table.getSelectionModel().getSelectedItem().getName();
+ } else {
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Entries that can be selected with this dialog.
+ *
+ * @param zipFile ZIP-File
+ * @return entries that can be selected
+ */
+ private static ObservableList getSelectableZipEntries(ZipFile zipFile) {
+ ObservableList entries = FXCollections.observableArrayList();
+ Enumeration extends ZipEntry> e = zipFile.entries();
+ for (ZipEntry entry : Collections.list(e)) {
+ if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
+ entries.add(entry);
+ }
+ }
+ return entries;
+ }
+}
From 0903eb1b97bcc0b9de139d036909074f7023e9ed Mon Sep 17 00:00:00 2001
From: Tobias Diez
Date: Thu, 24 Jan 2019 21:26:56 +0100
Subject: [PATCH 2/2] Use nio methods to access contents of zip files
---
.../java/org/jabref/gui/DialogService.java | 2 +-
.../java/org/jabref/gui/FXDialogService.java | 7 +-
.../ImportCustomizationDialogViewModel.java | 4 +-
.../org/jabref/gui/util/ZipFileChooser.java | 66 +++++++++++--------
src/main/resources/l10n/JabRef_en.properties | 14 ----
5 files changed, 46 insertions(+), 47 deletions(-)
diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java
index d1da9b44c4c..947fa1c66a0 100644
--- a/src/main/java/org/jabref/gui/DialogService.java
+++ b/src/main/java/org/jabref/gui/DialogService.java
@@ -255,5 +255,5 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String
*
* @return the selected file or an empty {@link Optional} if no file has been selected
*/
- Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException;
+ Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException;
}
diff --git a/src/main/java/org/jabref/gui/FXDialogService.java b/src/main/java/org/jabref/gui/FXDialogService.java
index 59283b7b200..93470689c79 100644
--- a/src/main/java/org/jabref/gui/FXDialogService.java
+++ b/src/main/java/org/jabref/gui/FXDialogService.java
@@ -2,6 +2,8 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
@@ -9,7 +11,6 @@
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
-import java.util.zip.ZipFile;
import javafx.concurrent.Task;
import javafx.print.PrinterJob;
@@ -305,8 +306,8 @@ public boolean showPrintDialog(PrinterJob job) {
}
@Override
- public Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException {
- try (ZipFile zipFile = new ZipFile(archivePath.toFile(), ZipFile.OPEN_READ)) {
+ public Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException {
+ try (FileSystem zipFile = FileSystems.newFileSystem(archivePath, null)) {
return new ZipFileChooser(zipFile).showAndWait();
} catch (NoClassDefFoundError exc) {
throw new IOException("Could not instantiate ZIP-archive reader.", exc);
diff --git a/src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java
index ef204f9c4fb..8ab6ba58277 100644
--- a/src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java
+++ b/src/main/java/org/jabref/gui/importer/ImportCustomizationDialogViewModel.java
@@ -75,9 +75,9 @@ public void addImporter() {
if (isArchive) {
try {
- Optional selectedFileInArchive = dialogService.showFileOpenFromArchiveDialog(selectedFile.get());
+ Optional selectedFileInArchive = dialogService.showFileOpenFromArchiveDialog(selectedFile.get());
if (selectedFileInArchive.isPresent()) {
- String className = selectedFileInArchive.get().substring(0, selectedFileInArchive.get().lastIndexOf('.')).replace(
+ String className = selectedFileInArchive.get().toString().substring(0, selectedFileInArchive.get().toString().lastIndexOf('.')).replace(
"/", ".");
CustomImporter importer = new CustomImporter(selectedFile.get().toAbsolutePath().toString(), className);
importers.add(importer);
diff --git a/src/main/java/org/jabref/gui/util/ZipFileChooser.java b/src/main/java/org/jabref/gui/util/ZipFileChooser.java
index 3335dcaaea6..74049324e9d 100644
--- a/src/main/java/org/jabref/gui/util/ZipFileChooser.java
+++ b/src/main/java/org/jabref/gui/util/ZipFileChooser.java
@@ -1,14 +1,14 @@
package org.jabref.gui.util;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+import java.util.stream.Collectors;
import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.beans.property.ReadOnlyStringWrapper;
@@ -24,29 +24,43 @@
/**
* Dialog to allow users to choose a file contained in a ZIP file.
*/
-public class ZipFileChooser extends BaseDialog {
+public class ZipFileChooser extends BaseDialog {
/**
* New ZIP file chooser.
*
* @param zipFile ZIP-Fle to choose from, must be readable
*/
- public ZipFileChooser(ZipFile zipFile) {
+ public ZipFileChooser(FileSystem zipFile) throws IOException {
setTitle(Localization.lang("Select file from ZIP-archive"));
- TableView table = new TableView<>(getSelectableZipEntries(zipFile));
- TableColumn nameColumn = new TableColumn<>(Localization.lang("Name"));
- TableColumn modifiedColumn = new TableColumn<>(Localization.lang("Last modified"));
- TableColumn sizeColumn = new TableColumn<>(Localization.lang("Size"));
+ TableView table = new TableView<>(getSelectableZipEntries(zipFile));
+ TableColumn nameColumn = new TableColumn<>(Localization.lang("Name"));
+ TableColumn modifiedColumn = new TableColumn<>(Localization.lang("Last modified"));
+ TableColumn sizeColumn = new TableColumn<>(Localization.lang("Size"));
table.getColumns().add(nameColumn);
table.getColumns().add(modifiedColumn);
table.getColumns().add(sizeColumn);
- nameColumn.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().getName()));
- modifiedColumn.setCellValueFactory(data -> new ReadOnlyStringWrapper(
- ZonedDateTime.ofInstant(new Date(data.getValue().getTime()).toInstant(),
- ZoneId.systemDefault())
- .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))));
- sizeColumn.setCellValueFactory(data -> new ReadOnlyLongWrapper(data.getValue().getSize()));
+ nameColumn.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().toString()));
+ modifiedColumn.setCellValueFactory(data -> {
+ try {
+ return new ReadOnlyStringWrapper(
+ ZonedDateTime.ofInstant(Files.getLastModifiedTime(data.getValue()).toInstant(),
+ ZoneId.systemDefault())
+ .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)));
+ } catch (IOException e) {
+ // Ignore
+ return new ReadOnlyStringWrapper("");
+ }
+ });
+ sizeColumn.setCellValueFactory(data -> {
+ try {
+ return new ReadOnlyLongWrapper(Files.size(data.getValue()));
+ } catch (IOException e) {
+ // Ignore
+ return new ReadOnlyLongWrapper(0);
+ }
+ });
table.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
getDialogPane().setContent(table);
@@ -58,7 +72,7 @@ public ZipFileChooser(ZipFile zipFile) {
setResultConverter(button -> {
if (button == ButtonType.OK) {
- return table.getSelectionModel().getSelectedItem().getName();
+ return table.getSelectionModel().getSelectedItem();
} else {
return null;
}
@@ -71,14 +85,12 @@ public ZipFileChooser(ZipFile zipFile) {
* @param zipFile ZIP-File
* @return entries that can be selected
*/
- private static ObservableList getSelectableZipEntries(ZipFile zipFile) {
- ObservableList entries = FXCollections.observableArrayList();
- Enumeration extends ZipEntry> e = zipFile.entries();
- for (ZipEntry entry : Collections.list(e)) {
- if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
- entries.add(entry);
- }
- }
- return entries;
+ private static ObservableList getSelectableZipEntries(FileSystem zipFile) throws IOException {
+ Path rootDir = zipFile.getRootDirectories().iterator().next();
+
+ return FXCollections.observableArrayList(
+ Files.walk(rootDir)
+ .filter(file -> file.endsWith(".class"))
+ .collect(Collectors.toList()));
}
}
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index d451fa524d2..121851eeae8 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -40,17 +40,10 @@ Add=Add
Add\ a\ (compiled)\ custom\ Importer\ class\ from\ a\ class\ path.=Add a (compiled) custom Importer class from a class path.
The\ path\ need\ not\ be\ on\ the\ classpath\ of\ JabRef.=The path need not be on the classpath of JabRef.
-Add\ a\ (compiled)\ custom\ Importer\ class\ from\ a\ ZIP-archive.=Add a (compiled) custom Importer class from a ZIP-archive.
-The\ ZIP-archive\ need\ not\ be\ on\ the\ classpath\ of\ JabRef.=The ZIP-archive need not be on the classpath of JabRef.
-
Add\ a\ regular\ expression\ for\ the\ key\ pattern.=Add a regular expression for the key pattern.
Add\ selected\ entries\ to\ this\ group=Add selected entries to this group
-Add\ from\ folder=Add from folder
-
-Add\ from\ JAR=Add from JAR
-
Add\ subgroup=Add subgroup
Add\ to\ group=Add to group
@@ -155,8 +148,6 @@ Clear=Clear
Clear\ fields=Clear fields
-Close=Close
-
Close\ entry=Close entry
Close\ dialog=Close dialog
@@ -167,7 +158,6 @@ Close\ window=Close window
Closed\ library=Closed library
-Command\ line\ id=Command line id
Comments=Comments
Contained\ in=Contained in
@@ -787,8 +777,6 @@ Please\ enter\ the\ field\ to\ search\ (e.g.\ keywords)\ and\ the\ keywor
Please\ enter\ the\ string's\ label=Please enter the string's label
-Please\ select\ an\ importer.=Please select an importer.
-
Please\ restart\ JabRef\ for\ preferences\ to\ take\ effect.=Please restart JabRef for preferences to take effect.
Possible\ duplicate\ entries=Possible duplicate entries
@@ -972,8 +960,6 @@ Show\ BibTeX\ source\ by\ default=Show BibTeX source by default
Show\ confirmation\ dialog\ when\ deleting\ entries=Show confirmation dialog when deleting entries
-Show\ description=Show description
-
Show\ file\ column=Show file column
Show\ last\ names\ only=Show last names only