From 9d38d12392f70cea2bf7301d487008973f2dd27d Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 2 Apr 2017 17:28:39 +0200 Subject: [PATCH 01/28] First approach for implementing PDF Exporter Remove code that produces NPE --- .../jabref/logic/exporter/ExportFormat.java | 6 --- .../jabref/logic/exporter/ExportFormats.java | 1 + .../jabref/logic/exporter/IExportFormat.java | 15 ------- .../logic/exporter/PdfFileExporter.java | 39 +++++++++++++++++++ 4 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 src/main/java/org/jabref/logic/exporter/PdfFileExporter.java diff --git a/src/main/java/org/jabref/logic/exporter/ExportFormat.java b/src/main/java/org/jabref/logic/exporter/ExportFormat.java index 871d3509136..031b315d5c6 100644 --- a/src/main/java/org/jabref/logic/exporter/ExportFormat.java +++ b/src/main/java/org/jabref/logic/exporter/ExportFormat.java @@ -313,12 +313,6 @@ public void performExport(final BibDatabaseContext databaseContext, final String } - @Override - public void performExport(final BibDatabaseContext databaseContext, Path file, final Charset encoding, - List entries) throws Exception { - performExport(databaseContext, file.getFileName().toString(), encoding, entries); - } - /** * See if there is a name formatter file bundled with this export format. If so, read * all the name formatters so they can be used by the filter layouts. diff --git a/src/main/java/org/jabref/logic/exporter/ExportFormats.java b/src/main/java/org/jabref/logic/exporter/ExportFormats.java index c24a165c694..a74fe5302b5 100644 --- a/src/main/java/org/jabref/logic/exporter/ExportFormats.java +++ b/src/main/java/org/jabref/logic/exporter/ExportFormats.java @@ -61,6 +61,7 @@ public static void initAllExports(Map customFormats, ExportFormats.putFormat(new OpenDocumentSpreadsheetCreator()); ExportFormats.putFormat(new MSBibExportFormat()); ExportFormats.putFormat(new ModsExportFormat()); + ExportFormats.putFormat(new PdfFileExporter()); // Now add custom export formats for (IExportFormat format : customFormats.values()) { diff --git a/src/main/java/org/jabref/logic/exporter/IExportFormat.java b/src/main/java/org/jabref/logic/exporter/IExportFormat.java index 0b176a6c9c8..b2f5a9b781a 100644 --- a/src/main/java/org/jabref/logic/exporter/IExportFormat.java +++ b/src/main/java/org/jabref/logic/exporter/IExportFormat.java @@ -1,7 +1,6 @@ package org.jabref.logic.exporter; import java.nio.charset.Charset; -import java.nio.file.Path; import java.util.List; import org.jabref.model.database.BibDatabaseContext; @@ -38,18 +37,4 @@ public interface IExportFormat { void performExport(BibDatabaseContext databaseContext, String file, Charset encoding, List entries) throws Exception; - /** - * Perform the Export. - * Gets the path as a java.nio.path instead of a string. - * - * @param databaseContext the database to export from. - * @param file the Path to the file to write to.The path should be an java.nio.Path - * @param encoding The encoding to use. - * @param entries A list containing all entries that - * should be exported. The list of entries must be non null - * @throws Exception - */ - void performExport(BibDatabaseContext databaseContext, Path file, Charset encoding, List entries) - throws Exception; - } diff --git a/src/main/java/org/jabref/logic/exporter/PdfFileExporter.java b/src/main/java/org/jabref/logic/exporter/PdfFileExporter.java new file mode 100644 index 00000000000..fd29db4691d --- /dev/null +++ b/src/main/java/org/jabref/logic/exporter/PdfFileExporter.java @@ -0,0 +1,39 @@ +package org.jabref.logic.exporter; + +import java.nio.charset.Charset; +import java.util.List; +import org.jabref.logic.TypedBibEntry; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.ParsedFileField; + +public class PdfFileExporter extends ExportFormat { + + public PdfFileExporter() { + super("PDF files", "PDF", null, null, ".pdf"); + } + @Override + public void performExport(final BibDatabaseContext databaseContext, String file, final Charset encoding, + List entries) throws Exception { + + for (BibEntry entry : entries) { + TypedBibEntry typedEntry = new TypedBibEntry(entry, databaseContext); + + List files = typedEntry.getFiles(); + for (ParsedFileField fileEntry : files) { + String fileName = fileEntry.getLink(); + + // databaseContext.getFileDirectories(preferences) + // Optional oldFile = FileUtil.expandFilename(fileName, + // databaseContext.getFileDirectories(Globals.prefs.getFileDirectoryPreferences())); + + System.out.println("Export pdfs"); + // FileUtil.copyFile(oldFile.get().toPath(), file, false); + + } + + } + + } + +} From 00eccc7225ecfbb9c194b932a04201bb5e42659e Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 7 Oct 2017 16:05:35 +0200 Subject: [PATCH 02/28] First approach for implementing PDF Exporter 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 --- src/main/java/org/jabref/gui/JabRefFrame.java | 6 +- .../gui/actions/ExportLinkedFilesAction.java | 133 +++++++ .../jabref/logic/exporter/ExportFormats.java | 1 - .../logic/exporter/PdfFileExporter.java | 39 -- .../org/jabref/logic/l10n/Localization.java | 2 +- .../org/jabref/logic/util/io/FileUtil.java | 352 ++++++++++++------ src/main/resources/l10n/JabRef_da.properties | 7 + src/main/resources/l10n/JabRef_de.properties | 17 + src/main/resources/l10n/JabRef_el.properties | 7 + src/main/resources/l10n/JabRef_en.properties | 7 + src/main/resources/l10n/JabRef_es.properties | 7 + src/main/resources/l10n/JabRef_fa.properties | 7 + src/main/resources/l10n/JabRef_fr.properties | 7 + src/main/resources/l10n/JabRef_in.properties | 7 + src/main/resources/l10n/JabRef_it.properties | 9 + src/main/resources/l10n/JabRef_ja.properties | 9 + src/main/resources/l10n/JabRef_nl.properties | 7 + src/main/resources/l10n/JabRef_no.properties | 7 + .../resources/l10n/JabRef_pt_BR.properties | 7 + src/main/resources/l10n/JabRef_ru.properties | 7 + src/main/resources/l10n/JabRef_sv.properties | 7 + src/main/resources/l10n/JabRef_tr.properties | 13 + src/main/resources/l10n/JabRef_vi.properties | 7 + src/main/resources/l10n/JabRef_zh.properties | 7 + 24 files changed, 523 insertions(+), 156 deletions(-) create mode 100644 src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java delete mode 100644 src/main/java/org/jabref/logic/exporter/PdfFileExporter.java diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 62465bdc147..0ded1265ee1 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -67,6 +67,7 @@ import org.jabref.gui.actions.AutoLinkFilesAction; import org.jabref.gui.actions.ConnectToSharedDatabaseAction; import org.jabref.gui.actions.ErrorConsoleAction; +import org.jabref.gui.actions.ExportLinkedFilesAction; import org.jabref.gui.actions.IntegrityCheckAction; import org.jabref.gui.actions.LookupIdentifierAction; import org.jabref.gui.actions.ManageKeywordsAction; @@ -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 ExportLinkedFilesAction(); private final AbstractAction manageJournals = new ManageJournalsAction(); private final AbstractAction databaseProperties = new DatabasePropertiesAction(); private final AbstractAction bibtexKeyPattern = new BibtexKeyPatternAction(); @@ -1240,6 +1242,8 @@ private void fillMenu() { tools.add(abbreviateIso); tools.add(abbreviateMedline); tools.add(unabbreviate); + tools.addSeparator(); + tools.add(exportLinkedFiles); mb.add(tools); options.add(showPrefs); @@ -1440,7 +1444,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()); diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java new file mode 100644 index 00000000000..a41fe276803 --- /dev/null +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -0,0 +1,133 @@ +package org.jabref.gui.actions; + +import java.awt.event.ActionEvent; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; + +import javax.swing.AbstractAction; + +import javafx.concurrent.Service; +import javafx.concurrent.Task; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.DialogPane; + +import org.jabref.Globals; +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.logic.util.io.FileUtil; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.LinkedFile; +import org.jabref.model.util.FileHelper; +import org.jabref.model.util.OptionalUtil; +import org.jabref.preferences.JabRefPreferences; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.controlsfx.dialog.ProgressDialog; + +public class ExportLinkedFilesAction extends AbstractAction { + + private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class); + private final BiFunction resolvePathFilename = (path, file) -> { + return path.resolve(file.getFileName()); + }; + private final DialogService ds = new FXDialogService(); + private long totalFilesCount; + private BibDatabaseContext databaseContext; + private Optional exportPath; + private List entries; + + public ExportLinkedFilesAction() { + super(Localization.lang("Export linked files")); + } + + @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(); + exportPath = DefaultTaskExecutor + .runInJavaFXThread(() -> ds.showDirectorySelectionDialog(dirDialogConfiguration)); + databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext(); + totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count(); + + Service exportService = new ExportService(); + startServiceAndshowProgessDialog(exportService); + } + + private void startServiceAndshowProgessDialog(Service service) { + DefaultTaskExecutor.runInJavaFXThread(() -> { + service.start(); + + ProgressDialog progressDialog = new ProgressDialog(service); + progressDialog.setOnCloseRequest(evt -> service.cancel()); + DialogPane dialogPane = progressDialog.getDialogPane(); + dialogPane.getButtonTypes().add(ButtonType.CANCEL); + Button cancelButton = (Button) dialogPane.lookupButton(ButtonType.CANCEL); + cancelButton.setOnAction(evt -> { + service.cancel(); + progressDialog.close(); + }); + progressDialog.showAndWait(); + }); + } + + private class ExportService extends Service { + + @Override + protected Task createTask() { + return new Task() { + + int totalFilesCounter; + Optional newPath; + + @Override + protected Void call() + throws InterruptedException { + updateMessage(Localization.lang("Exporting files...")); + updateProgress(0, totalFilesCount); + + for (int i = 0; i < entries.size(); i++) { + + List files = entries.get(i).getFiles(); + + for (int j = 0; j < files.size(); j++) { + updateMessage(Localization.lang("Exporting file %0 of BibEntry %1", Integer.toString(j + 1), Integer.toString(i + 1))); + Thread.sleep(500); //TODO: Adjust/leave/any other idea? + + String fileName = files.get(j).getLink(); + Optional fileToExport = FileHelper.expandFilenameAsPath(fileName, + databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences())); + + newPath = OptionalUtil.combine(exportPath, fileToExport, resolvePathFilename); + + newPath.ifPresent(newFile -> { + boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); + updateProgress(totalFilesCounter++, totalFilesCount); + if (success) { + updateMessage(Localization.lang("Exported file successfully")); + } else { + updateMessage(Localization.lang("Could not export file") + " " + Localization.lang("File exists")); + } + }); + } + } + updateMessage(Localization.lang("Finished exporting")); + updateMessage(Localization.lang("Exported %0 files sucessfully to %1", Integer.toString(totalFilesCounter), newPath.map(Path::toString).orElse(""))); + return null; + } + }; + } + } +} diff --git a/src/main/java/org/jabref/logic/exporter/ExportFormats.java b/src/main/java/org/jabref/logic/exporter/ExportFormats.java index a74fe5302b5..c24a165c694 100644 --- a/src/main/java/org/jabref/logic/exporter/ExportFormats.java +++ b/src/main/java/org/jabref/logic/exporter/ExportFormats.java @@ -61,7 +61,6 @@ public static void initAllExports(Map customFormats, ExportFormats.putFormat(new OpenDocumentSpreadsheetCreator()); ExportFormats.putFormat(new MSBibExportFormat()); ExportFormats.putFormat(new ModsExportFormat()); - ExportFormats.putFormat(new PdfFileExporter()); // Now add custom export formats for (IExportFormat format : customFormats.values()) { diff --git a/src/main/java/org/jabref/logic/exporter/PdfFileExporter.java b/src/main/java/org/jabref/logic/exporter/PdfFileExporter.java deleted file mode 100644 index fd29db4691d..00000000000 --- a/src/main/java/org/jabref/logic/exporter/PdfFileExporter.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.jabref.logic.exporter; - -import java.nio.charset.Charset; -import java.util.List; -import org.jabref.logic.TypedBibEntry; -import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.ParsedFileField; - -public class PdfFileExporter extends ExportFormat { - - public PdfFileExporter() { - super("PDF files", "PDF", null, null, ".pdf"); - } - @Override - public void performExport(final BibDatabaseContext databaseContext, String file, final Charset encoding, - List entries) throws Exception { - - for (BibEntry entry : entries) { - TypedBibEntry typedEntry = new TypedBibEntry(entry, databaseContext); - - List files = typedEntry.getFiles(); - for (ParsedFileField fileEntry : files) { - String fileName = fileEntry.getLink(); - - // databaseContext.getFileDirectories(preferences) - // Optional oldFile = FileUtil.expandFilename(fileName, - // databaseContext.getFileDirectories(Globals.prefs.getFileDirectoryPreferences())); - - System.out.println("Export pdfs"); - // FileUtil.copyFile(oldFile.get().toPath(), file, false); - - } - - } - - } - -} diff --git a/src/main/java/org/jabref/logic/l10n/Localization.java b/src/main/java/org/jabref/logic/l10n/Localization.java index 8fafc13b3ae..87ceb701616 100644 --- a/src/main/java/org/jabref/logic/l10n/Localization.java +++ b/src/main/java/org/jabref/logic/l10n/Localization.java @@ -11,6 +11,7 @@ import org.apache.commons.logging.LogFactory; public class Localization { + public static final String RESOURCE_PREFIX = "l10n/JabRef"; public static final String MENU_RESOURCE_PREFIX = "l10n/Menu"; public static final String BIBTEX = "BibTeX"; @@ -98,4 +99,3 @@ public static String menuTitle(String key, String... params) { } } - diff --git a/src/main/java/org/jabref/logic/util/io/FileUtil.java b/src/main/java/org/jabref/logic/util/io/FileUtil.java index 3386aebdcc5..c1718ff164d 100644 --- a/src/main/java/org/jabref/logic/util/io/FileUtil.java +++ b/src/main/java/org/jabref/logic/util/io/FileUtil.java @@ -10,37 +10,59 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.Stack; import java.util.Vector; import java.util.regex.Pattern; -import java.util.stream.Collectors; import org.jabref.logic.layout.Layout; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.layout.LayoutHelper; -import org.jabref.logic.util.BracketedPattern; +import org.jabref.logic.util.OS; import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.util.OptionalUtil; +import org.jabref.model.entry.FieldName; +import org.jabref.model.entry.FileField; +import org.jabref.model.entry.ParsedFileField; +import org.jabref.model.metadata.FileDirectoryPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class FileUtil { - public static final boolean IS_POSIX_COMPILANT = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); - public static final int MAXIMUM_FILE_NAME_LENGTH = 255; + private static final Log LOGGER = LogFactory.getLog(FileUtil.class); + private static final Pattern SLASH = Pattern.compile("/"); + private static final Pattern BACKSLASH = Pattern.compile("\\\\"); + + public static final boolean isPosixCompilant = FileSystems.getDefault().supportedFileAttributeViews() + .contains("posix"); + private FileUtil() { } + /** + * Returns the extension of a file or Optional.empty() if the file does not have one (no . in name). + * + * @param file + * @return The extension, trimmed and in lowercase. + */ + public static Optional getFileExtension(File file) { + return getFileExtension(file.getName()); + } + /** * Returns the extension of a file name or Optional.empty() if the file does not have one (no "." in name). * + * @param fileName * @return The extension (without leading dot), trimmed and in lowercase. */ public static Optional getFileExtension(String fileName) { @@ -52,15 +74,6 @@ public static Optional getFileExtension(String fileName) { } } - /** - * Returns the extension of a file or Optional.empty() if the file does not have one (no . in name). - * - * @return The extension, trimmed and in lowercase. - */ - public static Optional getFileExtension(File file) { - return getFileExtension(file.getName()); - } - /** * Returns the name part of a file name (i.e., everything in front of last "."). */ @@ -74,28 +87,10 @@ public static String getFileName(String fileNameWithExtension) { } /** - * Returns a valid filename for most operating systems. + * Adds an extension to the given file name. The original extension is not replaced. That means, + * "demo.bib", ".sav" gets "demo.bib.sav" and not "demo.sav" * - * Currently, only the length is restricted to 255 chars, see MAXIMUM_FILE_NAME_LENGTH. - */ - public static String getValidFileName(String fileName) { - String nameWithoutExtension = getFileName(fileName); - - if (nameWithoutExtension.length() > MAXIMUM_FILE_NAME_LENGTH) { - Optional extension = getFileExtension(fileName); - String shortName = nameWithoutExtension.substring(0, MAXIMUM_FILE_NAME_LENGTH); - LOGGER.info(String.format("Truncated the too long filename '%s' (%d characters) to '%s'.", fileName, fileName.length(), shortName)); - return extension.map(s -> shortName + "." + s).orElse(shortName); - } - - return fileName; - } - - /** - * Adds an extension to the given file name. The original extension is not replaced. That means, "demo.bib", ".sav" - * gets "demo.bib.sav" and not "demo.sav" - * - * @param path the path to add the extension to + * @param path the path to add the extension to * @param extension the extension to add * @return the with the modified file name */ @@ -152,6 +147,7 @@ public static List uniquePathSubstrings(List paths) { * @param pathToDestinationFile Path Destination file * @param replaceExisting boolean Determines whether the copy goes on even if the file exists. * @return boolean Whether the copy succeeded, or was stopped due to the file already existing. + * @throws IOException */ public static boolean copyFile(Path pathToSourceFile, Path pathToDestinationFile, boolean replaceExisting) { // Check if the file already exists. @@ -160,7 +156,7 @@ public static boolean copyFile(Path pathToSourceFile, Path pathToDestinationFile return false; } if (Files.exists(pathToDestinationFile) && !replaceExisting) { - LOGGER.error("Path to the destination file is not exists and the file shouldn't be replace."); + LOGGER.error("Path to the destination file exists and the file shouldn't be replaced."); return false; } try { @@ -185,66 +181,239 @@ public static boolean renameFile(Path fromFile, Path toFile) { /** * Renames a given file * - * @param fromFile The source filename to rename - * @param toFile The target fileName + * @param fromFile The source filename to rename + * @param toFile The target fileName * @param replaceExisting Wether to replace existing files or not * @return True if the rename was successful, false if an exception occurred + * */ public static boolean renameFile(Path fromFile, Path toFile, boolean replaceExisting) { try { - return renameFileWithException(fromFile, toFile, replaceExisting); + if (replaceExisting) { + return Files.move(fromFile, fromFile.resolveSibling(toFile), + StandardCopyOption.REPLACE_EXISTING) != null; + } else { + return Files.move(fromFile, fromFile.resolveSibling(toFile)) != null; + } } catch (IOException e) { LOGGER.error("Renaming Files failed", e); return false; } } - public static boolean renameFileWithException(Path fromFile, Path toFile, boolean replaceExisting) throws IOException { - if (replaceExisting) { - return Files.move(fromFile, fromFile.resolveSibling(toFile), - StandardCopyOption.REPLACE_EXISTING) != null; + /** + * Converts a relative filename to an absolute one, if necessary. Returns an empty optional if the file does not + * exist.
+ *

+ * Uses

    + *
  • the default directory associated with the extension of the file
  • + *
  • the standard file directory
  • + *
  • the directory of the BIB file
  • + *
+ * + * @param databaseContext The database this file belongs to. + * @param name The filename, may also be a relative path to the file + */ + public static Optional expandFilename(final BibDatabaseContext databaseContext, String name, + FileDirectoryPreferences fileDirectoryPreferences) { + Optional extension = getFileExtension(name); + // Find the default directory for this field type, if any: + List directories = databaseContext.getFileDirectories(extension.orElse(null), fileDirectoryPreferences); + // Include the standard "file" directory: + List fileDir = databaseContext.getFileDirectories(fileDirectoryPreferences); + // Include the directory of the BIB file: + List al = new ArrayList<>(); + for (String dir : directories) { + if (!al.contains(dir)) { + al.add(dir); + } + } + for (String aFileDir : fileDir) { + if (!al.contains(aFileDir)) { + al.add(aFileDir); + } + } + + return expandFilename(name, al); + } + + /** + * Converts a relative filename to an absolute one, if necessary. Returns + * null if the file does not exist. + *

+ * Will look in each of the given dirs starting from the beginning and + * returning the first found file to match if any. + */ + public static Optional expandFilename(String name, List directories) { + for (String dir : directories) { + if (dir != null) { + Optional result = expandFilename(name, dir); + if (result.isPresent()) { + return result; + } + } + } + + return Optional.empty(); + } + + /** + * Converts a relative filename to an absolute one, if necessary. Returns + * an empty optional if the file does not exist. + */ + private static Optional expandFilename(String filename, String dir) { + + if ((filename == null) || filename.isEmpty()) { + return Optional.empty(); + } + + String name = filename; + + File file = new File(name); + if (file.exists() || (dir == null)) { + return Optional.of(file); + } + + if (dir.endsWith(OS.FILE_SEPARATOR)) { + name = dir + name; + } else { + name = dir + OS.FILE_SEPARATOR + name; + } + + // fix / and \ problems: + if (OS.WINDOWS) { + name = SLASH.matcher(name).replaceAll("\\\\"); } else { - return Files.move(fromFile, fromFile.resolveSibling(toFile)) != null; + name = BACKSLASH.matcher(name).replaceAll("/"); + } + + File fileInDir = new File(name); + if (fileInDir.exists()) { + return Optional.of(fileInDir); + } else { + return Optional.empty(); } } /** - * Converts an absolute file to a relative one, if possible. Returns the parameter file itself if no shortening is - * possible. + * Converts an absolute filename to a relative one, if necessary. + * Returns the parameter fileName itself if no shortening is possible *

- * This method works correctly only if dirs are sorted decent in their length i.e. /home/user/literature/important before /home/user/literature. + * This method works correctly only if dirs are sorted decent in their length + * i.e. /home/user/literature/important before /home/user/literature * - * @param file the file to be shortened - * @param dirs directories to check + * @param fileName the filename to be shortened + * @param dirs directories to check. */ - public static Path shortenFileName(Path file, List dirs) { - if (!file.isAbsolute()) { - return file; + public static File shortenFileName(File fileName, List dirs) { + if ((fileName == null) || !fileName.isAbsolute() || (dirs == null)) { + return fileName; } - for (Path dir : dirs) { - if (file.startsWith(dir)) { - return dir.relativize(file); + for (String dir : dirs) { + if (dir != null) { + File result = shortenFileName(fileName, dir); + if ((result != null) && !result.equals(fileName)) { + return result; + } } } - return file; + return fileName; + } + + private static File shortenFileName(File fileName, String directory) { + if ((fileName == null) || !fileName.isAbsolute() || (directory == null)) { + return fileName; + } + + String dir = directory; + String longName; + if (OS.WINDOWS) { + // case-insensitive matching on Windows + longName = fileName.toString().toLowerCase(Locale.ROOT); + dir = dir.toLowerCase(Locale.ROOT); + } else { + longName = fileName.toString(); + } + + if (!dir.endsWith(OS.FILE_SEPARATOR)) { + dir = dir.concat(OS.FILE_SEPARATOR); + } + + if (longName.startsWith(dir)) { + // result is based on original name, not on lower-cased name + String newName = fileName.toString().substring(dir.length()); + return new File(newName); + } else { + return fileName; + } + } + + public static Map> findAssociatedFiles(List entries, List extensions, + List directories, boolean autolinkExactKeyOnly) { + Map> result = new HashMap<>(); + + // First scan directories + Set filesWithExtension = FileFinder.findFiles(extensions, directories); + + // Initialize Result-Set + for (BibEntry entry : entries) { + result.put(entry, new ArrayList<>()); + } + + // Now look for keys + nextFile: for (Path file : filesWithExtension) { + + String name = file.getFileName().toString(); + int dot = name.lastIndexOf('.'); + // First, look for exact matches: + for (BibEntry entry : entries) { + Optional citeKey = entry.getCiteKeyOptional(); + if ((citeKey.isPresent()) && !citeKey.get().isEmpty() && (dot > 0) + && name.substring(0, dot).equals(citeKey.get())) { + result.get(entry).add(file.toFile()); + continue nextFile; + } + } + // If we get here, we did not find any exact matches. If non-exact + // matches are allowed, try to find one: + if (!autolinkExactKeyOnly) { + for (BibEntry entry : entries) { + Optional citeKey = entry.getCiteKeyOptional(); + if ((citeKey.isPresent()) && !citeKey.get().isEmpty() && name.startsWith(citeKey.get())) { + result.get(entry).add(file.toFile()); + continue nextFile; + } + } + } + } + + return result; } /** * Returns the list of linked files. The files have the absolute filename * - * @param bes list of BibTeX entries + * @param bes list of BibTeX entries * @param fileDirs list of directories to try for expansion + * * @return list of files. May be empty */ - public static List getListOfLinkedFiles(List bes, List fileDirs) { + public static List getListOfLinkedFiles(List bes, List fileDirs) { Objects.requireNonNull(bes); Objects.requireNonNull(fileDirs); - return bes.stream() - .flatMap(entry -> entry.getFiles().stream()) - .flatMap(file -> OptionalUtil.toStream(file.findIn(fileDirs))) - .collect(Collectors.toList()); + List result = new ArrayList<>(); + for (BibEntry entry : bes) { + entry.getField(FieldName.FILE).ifPresent(fileField -> { + List fileList = FileField.parse(fileField); + for (ParsedFileField file : fileList) { + expandFilename(file.getLink(), fileDirs).ifPresent(result::add); + } + }); + } + + return result; } /** @@ -255,12 +424,9 @@ public static List getListOfLinkedFiles(List bes, List fil * @param fileNamePattern the filename pattern * @param prefs the layout preferences * @return a suggested fileName - * - * @Deprecated use String createFileNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern ) instead. */ - @Deprecated public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern, - LayoutFormatterPreferences prefs) { + LayoutFormatterPreferences prefs) { String targetName = null; StringReader sr = new StringReader(fileNamePattern); @@ -283,53 +449,10 @@ public static String createFileNameFromPattern(BibDatabase database, BibEntry en } /** - * Determines filename provided by an entry in a database - * - * @param database the database, where the entry is located - * @param entry the entry to which the file should be linked to - * @param fileNamePattern the filename pattern - * @return a suggested fileName - */ - public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern) { - String targetName = null; - - targetName = BracketedPattern.expandBrackets(fileNamePattern, ';', entry, database); - - if ((targetName == null) || targetName.isEmpty()) { - targetName = entry.getCiteKeyOptional().orElse("default"); - } - - //Removes illegal characters from filename - targetName = FileNameCleaner.cleanFileName(targetName); - return targetName; - } - - /** - * Determines filename provided by an entry in a database - * - * @param database the database, where the entry is located - * @param entry the entry to which the file should be linked to - * @param fileNamePattern the filename pattern - * @return a suggested fileName - */ - public static String createDirNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern) { - String targetName = null; - - targetName = BracketedPattern.expandBrackets(fileNamePattern, ';', entry, database); - - if ((targetName == null) || targetName.isEmpty()) { - targetName = entry.getCiteKeyOptional().orElse("default"); - } - - //Removes illegal characters from filename - targetName = FileNameCleaner.cleanDirectoryName(targetName); - return targetName; - } - - /** - * Finds a file inside a directory structure. Will also look for the file inside nested directories. + * Finds a file inside a directory structure. + * Will also look for the file inside nested directories. * - * @param filename the name of the file that should be found + * @param filename the name of the file that should be found * @param rootDirectory the rootDirectory that will be searched * @return the path to the first file that matches the defined conditions */ @@ -346,9 +469,10 @@ public static Optional find(String filename, Path rootDirectory) { } /** - * Finds a file inside a list of directory structures. Will also look for the file inside nested directories. + * Finds a file inside a list of directory structures. + * Will also look for the file inside nested directories. * - * @param filename the name of the file that should be found + * @param filename the name of the file that should be found * @param directories the directories that will be searched * @return a list including all found paths to files that match the defined conditions */ diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index b4b46f453fc..1d4faca5fd9 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 7300163cad8..d3bc952ec6e 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2345,3 +2345,20 @@ There_exists_already_a_group_with_the_same_name.=Es_existiert_bereits_eine_Grupp Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= +To_improve_the_user_experience,_we_would_like_to_collect_anonymous_statistics_on_the_features_you_use._We_will_only_record_what_features_you_access_and_how_often_you_do_it._We_will_neither_collect_any_personal_data_nor_the_content_of_bibliographic_items._If_you_choose_to_allow_data_collection,_you_can_later_disable_it_via_Options_->_Preferences_->_General.=Zur_Verbesserung_der_Benutzererfahrung_würden_wir_gerne_anonyme_Statistiken_über_die_Features_sammeln,_die_Sie_benutzen._Wir_zeichnen_nur_auf,_welche_Features_Sie_nutzen_und_wie_oft_Sie_diese_benutzen._Es_werden_keinerlei_persönliche_Informationen_über_Sie_oder_den_Inhalt_Ihrer_Bibliografieeinträge_gesammelt._Die_einmal_erlaubte_Datenaufzeichnnung_kann_jederzeit_unter_Optionen->Einstellungen->Allgemein_deaktiviert werden. +This_file_was_found_automatically._Do_you_want_to_link_it_to_this_entry?= +Names_are_not_in_the_standard_BibTeX_format.= + +Delete_the_selected_file_permanently_from_disk,_or_just_remove_the_file_from_the_entry?_Pressing_Delete_will_delete_the_file_permanently_from_disk.= +Delete_'%0'= +Delete_from_disk= +Remove_from_entry= +The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= +There_exists_already_a_group_with_the_same_name.= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index 43f2df4e552..a6d233aa914 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 31d23cd50df..a814f51be00 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.=There_exists_already_a_group_wi Rename_failed=Rename_failed JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process. Show_console_output_(only_necessary_when_the_launcher_is_used)=Show_console_output_(only_necessary_when_the_launcher_is_used) + +Export_linked_files=Export_linked_files +Exported_file_successfully=Exported_file_successfully +Exporting_file_%0_of_BibEntry_%1=Exporting_file_%0_of_BibEntry_%1 +Exporting_files...=Exporting_files... +Finished_exporting=Finished_exporting +Exported_%0_files_sucessfully_to_%1=Exported_%0_files_sucessfully_to_%1 diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index af491a4146e..cc74cd6c380 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 102b3a8c4b9..d355f2c8d3f 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 21e0e48c030..ea2f6d0992b 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.=Un_groupe_portant_ce_nom_existe Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 5d03c3a5047..bc200a291d2 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 1069fc75664..f337e80767b 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -2345,3 +2345,12 @@ There_exists_already_a_group_with_the_same_name.=Esiste_già_almeno_un_gruppo_co Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= +The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= +There_exists_already_a_group_with_the_same_name.= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 3c03cfa76e5..c3c58e02a02 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2345,3 +2345,12 @@ There_exists_already_a_group_with_the_same_name.=同じ名称のグループが Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= +The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=グループ名にキーワード区切りの「%0」が含まれているので、想定通りにはおそらく動作しません。 +There_exists_already_a_group_with_the_same_name.=同じ名称のグループがすでに存在します。 + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index e8accdffdb6..73e6582c5bc 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 8f70543c1fd..2e9ad05258b 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index a9079256681..66b2d8615e4 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 0b210c11eab..d3a4ba79a04 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 7ea1f95cdba..470dd3c2522 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 68058161875..5d944662e6e 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -2345,3 +2345,16 @@ There_exists_already_a_group_with_the_same_name.=Aynı_isimli_bir_grup_zaten_var Rename_failed=Yeniden_adlandırma_başarısız_oldu JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_dosyaya_erişemiyor_çünkü_dosya_başka_bir_süreç_tarafından_kullanılıyor. Show_console_output_(only_necessary_when_the_launcher_is_used)=Consol_çıktısını_göster_(sadece_başlatıcı_kullanıldığında_gereklidir) +Delete_the_selected_file_permanently_from_disk,_or_just_remove_the_file_from_the_entry?_Pressing_Delete_will_delete_the_file_permanently_from_disk.= +Delete_'%0'= +Delete_from_disk= +Remove_from_entry= +The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= +There_exists_already_a_group_with_the_same_name.= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index e45adaebef0..6c765f1c9f2 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index d1396aa2c53..e853fbf8491 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -2345,3 +2345,10 @@ There_exists_already_a_group_with_the_same_name.= Rename_failed= JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= Show_console_output_(only_necessary_when_the_launcher_is_used)= + +Export_linked_files= +Exported_file_successfully= +Exporting_file_%0_of_BibEntry_%1= +Exporting_files...= +Finished_exporting= +Exported_%0_files_sucessfully_to_%1= From 50e9716f8872f44465831e42f73881421340c3e3 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 7 Oct 2017 15:33:33 +0200 Subject: [PATCH 03/28] Add to File menu and context menu Fix localization to copy files --- src/main/java/org/jabref/gui/JabRefFrame.java | 2 +- .../gui/actions/ExportLinkedFilesAction.java | 99 ++++++++++++------- .../org/jabref/gui/menus/RightClickMenu.java | 2 + src/main/resources/l10n/JabRef_da.properties | 10 ++ src/main/resources/l10n/JabRef_de.properties | 21 ++++ src/main/resources/l10n/JabRef_el.properties | 10 ++ src/main/resources/l10n/JabRef_en.properties | 10 ++ src/main/resources/l10n/JabRef_es.properties | 10 ++ src/main/resources/l10n/JabRef_fa.properties | 10 ++ src/main/resources/l10n/JabRef_fr.properties | 10 ++ src/main/resources/l10n/JabRef_in.properties | 10 ++ src/main/resources/l10n/JabRef_it.properties | 11 +++ src/main/resources/l10n/JabRef_ja.properties | 10 ++ src/main/resources/l10n/JabRef_nl.properties | 10 ++ src/main/resources/l10n/JabRef_no.properties | 10 ++ .../resources/l10n/JabRef_pt_BR.properties | 10 ++ src/main/resources/l10n/JabRef_ru.properties | 10 ++ src/main/resources/l10n/JabRef_sv.properties | 10 ++ src/main/resources/l10n/JabRef_tr.properties | 11 +++ src/main/resources/l10n/JabRef_vi.properties | 10 ++ src/main/resources/l10n/JabRef_zh.properties | 10 ++ 21 files changed, 261 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 0ded1265ee1..dadf0d914b4 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -1061,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); @@ -1243,7 +1244,6 @@ private void fillMenu() { tools.add(abbreviateMedline); tools.add(unabbreviate); tools.addSeparator(); - tools.add(exportLinkedFiles); mb.add(tools); options.add(showPrefs); diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index a41fe276803..2382bf364ac 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -1,6 +1,10 @@ package org.jabref.gui.actions; import java.awt.event.ActionEvent; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; @@ -22,6 +26,7 @@ import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.OS; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -43,11 +48,11 @@ public class ExportLinkedFilesAction extends AbstractAction { private final DialogService ds = new FXDialogService(); private long totalFilesCount; private BibDatabaseContext databaseContext; - private Optional exportPath; + private Optional exportPath = Optional.empty(); private List entries; public ExportLinkedFilesAction() { - super(Localization.lang("Export linked files")); + super(Localization.lang("Copy attached files to folder...")); } @Override @@ -59,11 +64,14 @@ public void actionPerformed(ActionEvent e) { entries = JabRefGUI.getMainFrame().getCurrentBasePanel().getSelectedEntries(); exportPath = DefaultTaskExecutor .runInJavaFXThread(() -> ds.showDirectorySelectionDialog(dirDialogConfiguration)); - databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext(); - totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count(); - Service exportService = new ExportService(); - startServiceAndshowProgessDialog(exportService); + exportPath.ifPresent(path -> { + databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext(); + totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count(); + + Service exportService = new ExportService(); + startServiceAndshowProgessDialog(exportService); + }); } private void startServiceAndshowProgessDialog(Service service) { @@ -85,49 +93,72 @@ private void startServiceAndshowProgessDialog(Service service) { private class ExportService extends Service { + private static final String LOGFILE = "exportLog.log"; + @Override protected Task createTask() { return new Task() { int totalFilesCounter; + int numberSucessful; + int numberError; Optional newPath; @Override protected Void call() - throws InterruptedException { - updateMessage(Localization.lang("Exporting files...")); + throws InterruptedException, IOException { + updateMessage(Localization.lang("Copying files...")); updateProgress(0, totalFilesCount); - for (int i = 0; i < entries.size(); i++) { - - List files = entries.get(i).getFiles(); - - for (int j = 0; j < files.size(); j++) { - updateMessage(Localization.lang("Exporting file %0 of BibEntry %1", Integer.toString(j + 1), Integer.toString(i + 1))); - Thread.sleep(500); //TODO: Adjust/leave/any other idea? - - String fileName = files.get(j).getLink(); - Optional fileToExport = FileHelper.expandFilenameAsPath(fileName, - databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences())); - - newPath = OptionalUtil.combine(exportPath, fileToExport, resolvePathFilename); - - newPath.ifPresent(newFile -> { - boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); - updateProgress(totalFilesCounter++, totalFilesCount); - if (success) { - updateMessage(Localization.lang("Exported file successfully")); - } else { - updateMessage(Localization.lang("Could not export file") + " " + Localization.lang("File exists")); - } - }); + try (BufferedWriter bw = Files.newBufferedWriter(exportPath.get().resolve(LOGFILE), StandardCharsets.UTF_8)) { + + for (int i = 0; i < entries.size(); i++) { + + List 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))); + Thread.sleep(500); //TODO: Adjust/leave/any other idea? + + String fileName = files.get(j).getLink(); + Optional fileToExport = FileHelper.expandFilenameAsPath(fileName, + databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences())); + + newPath = OptionalUtil.combine(exportPath, fileToExport, resolvePathFilename); + + newPath.ifPresent(newFile -> { + boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); + updateProgress(totalFilesCounter++, totalFilesCount); + if (success) { + updateMessage(Localization.lang("Copied file successfully")); + numberSucessful++; + try { + bw.write(Localization.lang("Copied file successfully") + ": " + newFile); + bw.write(OS.NEWLINE); + } catch (IOException e) { + LOGGER.error("error writing log file", e); + } + } else { + updateMessage(Localization.lang("Could not copy file") + ": " + Localization.lang("File exists")); + numberError++; + try { + bw.write(Localization.lang("Could not copy file") + ": " + Localization.lang("File exists") + ":" + newFile); + bw.write(OS.NEWLINE); + } catch (IOException e) { + LOGGER.error("error writing log file", e); + } + } + }); + } } + updateMessage(Localization.lang("Finished copying")); + updateMessage(Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse(""))); + bw.write(Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse(""))); + return null; } - updateMessage(Localization.lang("Finished exporting")); - updateMessage(Localization.lang("Exported %0 files sucessfully to %1", Integer.toString(totalFilesCounter), newPath.map(Path::toString).orElse(""))); - return null; } }; } } + } diff --git a/src/main/java/org/jabref/gui/menus/RightClickMenu.java b/src/main/java/org/jabref/gui/menus/RightClickMenu.java index 845bbef351e..6c784b77df0 100644 --- a/src/main/java/org/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/menus/RightClickMenu.java @@ -22,6 +22,7 @@ import org.jabref.gui.IconTheme; import org.jabref.gui.JabRefFrame; import org.jabref.gui.actions.Actions; +import org.jabref.gui.actions.ExportLinkedFilesAction; import org.jabref.gui.filelist.FileListTableModel; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.mergeentries.FetchAndMergeEntry; @@ -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()); JMenu markSpecific = JabRefFrame.subMenu(Localization.menuTitle("Mark specific color")); markSpecific.setIcon(IconTheme.JabRefIcon.MARK_ENTRIES.getSmallIcon()); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 1d4faca5fd9..642c9415531 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index d3bc952ec6e..11d92688be6 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2362,3 +2362,24 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +This_file_was_found_automatically._Do_you_want_to_link_it_to_this_entry?= +Names_are_not_in_the_standard_BibTeX_format.= + +Delete_the_selected_file_permanently_from_disk,_or_just_remove_the_file_from_the_entry?_Pressing_Delete_will_delete_the_file_permanently_from_disk.=Die_ausgewählte_Datei_unwiderruflich_löschen_oder_nur_vom_Eintrag_entfernen?_Drücken_sie_Entfernen,_um_die_Datei_von_der_Festplatte_zu_löschen. +Delete_'%0'=Lösche_Datei_'%0' +Delete_from_disk=Auf_der_Festplatte_löschen +Remove_from_entry=Vom_Eintrag_entfernen +The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=Der_Gruppename_enthält_das_Trennzeichen_"%0"_und_wird_deswegen_möglicherweise_nicht_wie_erwartet_funktionieren. +There_exists_already_a_group_with_the_same_name.=Es_existiert_bereits_eine_Gruppe_mit_demselben_Namen. + + +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...=Copying_files... +Finished_copying=Finished_copying +Could_not_copy_file=Could_not_copy_file +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index a6d233aa914..176b1bfac3b 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index a814f51be00..f3dcfb5a673 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1=Exporting_file_%0_of_BibEntry_%1 Exporting_files...=Exporting_files... Finished_exporting=Finished_exporting Exported_%0_files_sucessfully_to_%1=Exported_%0_files_sucessfully_to_%1 +Copy_attached_files_to_folder...=Copy_attached_files_to_folder... +Copied_file_successfully=Copied_file_successfully +Copying_file_%0_of_BibEntry_%1=Copying_file_%0_of_BibEntry_%1 +Copying_files...=Copying_files... +Finished_copying=Finished_copying +Could_not_copy_file=Could_not_copy_file +Copied_%0_files_of_%1_sucessfully_to_%2=Copied_%0_files_of_%1_sucessfully_to_%2 +Rename_failed=Rename_failed +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process. +Show_console_output_(only_necessary_when_the_launcher_is_used)=Show_console_output_(only_necessary_when_the_launcher_is_used) diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index cc74cd6c380..bda4acc6a74 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index d355f2c8d3f..11e7db006f3 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index ea2f6d0992b..3e414dd76d8 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index bc200a291d2..4bc5532eee9 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index f337e80767b..ebba1ea0b86 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -2354,3 +2354,14 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= + +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index c3c58e02a02..fc0cf877e34 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2354,3 +2354,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...=Copying_files... +Finished_copying=Finished_copying +Could_not_copy_file=Could_not_copy_file +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 73e6582c5bc..329bd8535d4 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 2e9ad05258b..2269e9c446b 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 66b2d8615e4..a1645fb0449 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index d3a4ba79a04..7f0c48ca724 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 470dd3c2522..f5a2e741fad 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 5d944662e6e..7f46dc9ec60 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -2358,3 +2358,14 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= + +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed=Yeniden_adlandırma_başarısız_oldu +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_dosyaya_erişemiyor_çünkü_dosya_başka_bir_süreç_tarafından_kullanılıyor. +Show_console_output_(only_necessary_when_the_launcher_is_used)=Consol_çıktısını_göster_(sadece_başlatıcı_kullanıldığında_gereklidir) diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 6c765f1c9f2..59b5b617eb0 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index e853fbf8491..a33048559d4 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -2352,3 +2352,13 @@ Exporting_file_%0_of_BibEntry_%1= Exporting_files...= Finished_exporting= Exported_%0_files_sucessfully_to_%1= +Copy_attached_files_to_folder...= +Copied_file_successfully= +Copying_file_%0_of_BibEntry_%1= +Copying_files...= +Finished_copying= +Could_not_copy_file= +Copied_%0_files_of_%1_sucessfully_to_%2= +Rename_failed= +JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= +Show_console_output_(only_necessary_when_the_launcher_is_used)= From 26a7e1ff06d4d623a86df232b42c513b98ca73b6 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 7 Oct 2017 15:36:00 +0200 Subject: [PATCH 04/28] Remove separator from tools menu --- src/main/java/org/jabref/gui/JabRefFrame.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index dadf0d914b4..f0cf505d794 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -1243,7 +1243,6 @@ private void fillMenu() { tools.add(abbreviateIso); tools.add(abbreviateMedline); tools.add(unabbreviate); - tools.addSeparator(); mb.add(tools); options.add(showPrefs); From ec7c44b604967df025f444cf95e3a4a51189a90e Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 7 Oct 2017 16:15:09 +0200 Subject: [PATCH 05/28] fix fileUtil and localzation from rebase --- src/main/java/org/jabref/JabRefMain.java | 1 + .../org/jabref/logic/util/io/FileUtil.java | 349 ++++++------------ src/main/resources/l10n/JabRef_da.properties | 9 - src/main/resources/l10n/JabRef_de.properties | 30 -- src/main/resources/l10n/JabRef_el.properties | 9 - src/main/resources/l10n/JabRef_en.properties | 9 - src/main/resources/l10n/JabRef_es.properties | 9 - src/main/resources/l10n/JabRef_fa.properties | 9 - src/main/resources/l10n/JabRef_fr.properties | 9 - src/main/resources/l10n/JabRef_in.properties | 9 - src/main/resources/l10n/JabRef_it.properties | 12 - src/main/resources/l10n/JabRef_ja.properties | 13 +- src/main/resources/l10n/JabRef_nl.properties | 9 - src/main/resources/l10n/JabRef_no.properties | 9 - .../resources/l10n/JabRef_pt_BR.properties | 9 - src/main/resources/l10n/JabRef_ru.properties | 9 - src/main/resources/l10n/JabRef_sv.properties | 9 - src/main/resources/l10n/JabRef_tr.properties | 16 - src/main/resources/l10n/JabRef_vi.properties | 9 - src/main/resources/l10n/JabRef_zh.properties | 9 - 20 files changed, 115 insertions(+), 432 deletions(-) diff --git a/src/main/java/org/jabref/JabRefMain.java b/src/main/java/org/jabref/JabRefMain.java index b278ecd94a8..238da29a32c 100644 --- a/src/main/java/org/jabref/JabRefMain.java +++ b/src/main/java/org/jabref/JabRefMain.java @@ -51,6 +51,7 @@ public static void main(String[] args) { public void start(Stage mainStage) throws Exception { Platform.setImplicitExit(false); SwingUtilities.invokeLater(() -> start(arguments)); + } private static void start(String[] args) { diff --git a/src/main/java/org/jabref/logic/util/io/FileUtil.java b/src/main/java/org/jabref/logic/util/io/FileUtil.java index c1718ff164d..5a734fd47ff 100644 --- a/src/main/java/org/jabref/logic/util/io/FileUtil.java +++ b/src/main/java/org/jabref/logic/util/io/FileUtil.java @@ -10,59 +10,38 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.Stack; import java.util.Vector; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.jabref.logic.layout.Layout; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.layout.LayoutHelper; -import org.jabref.logic.util.OS; +import org.jabref.logic.util.BracketedPattern; import org.jabref.model.database.BibDatabase; -import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.FieldName; -import org.jabref.model.entry.FileField; -import org.jabref.model.entry.ParsedFileField; -import org.jabref.model.metadata.FileDirectoryPreferences; +import org.jabref.model.util.OptionalUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class FileUtil { + public static final boolean IS_POSIX_COMPILANT = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); + public static final int MAXIMUM_FILE_NAME_LENGTH = 255; private static final Log LOGGER = LogFactory.getLog(FileUtil.class); - private static final Pattern SLASH = Pattern.compile("/"); - private static final Pattern BACKSLASH = Pattern.compile("\\\\"); - - public static final boolean isPosixCompilant = FileSystems.getDefault().supportedFileAttributeViews() - .contains("posix"); - private FileUtil() { } - /** - * Returns the extension of a file or Optional.empty() if the file does not have one (no . in name). - * - * @param file - * @return The extension, trimmed and in lowercase. - */ - public static Optional getFileExtension(File file) { - return getFileExtension(file.getName()); - } - /** * Returns the extension of a file name or Optional.empty() if the file does not have one (no "." in name). * - * @param fileName * @return The extension (without leading dot), trimmed and in lowercase. */ public static Optional getFileExtension(String fileName) { @@ -74,6 +53,15 @@ public static Optional getFileExtension(String fileName) { } } + /** + * Returns the extension of a file or Optional.empty() if the file does not have one (no . in name). + * + * @return The extension, trimmed and in lowercase. + */ + public static Optional getFileExtension(File file) { + return getFileExtension(file.getName()); + } + /** * Returns the name part of a file name (i.e., everything in front of last "."). */ @@ -87,10 +75,28 @@ public static String getFileName(String fileNameWithExtension) { } /** - * Adds an extension to the given file name. The original extension is not replaced. That means, - * "demo.bib", ".sav" gets "demo.bib.sav" and not "demo.sav" + * Returns a valid filename for most operating systems. * - * @param path the path to add the extension to + * Currently, only the length is restricted to 255 chars, see MAXIMUM_FILE_NAME_LENGTH. + */ + public static String getValidFileName(String fileName) { + String nameWithoutExtension = getFileName(fileName); + + if (nameWithoutExtension.length() > MAXIMUM_FILE_NAME_LENGTH) { + Optional extension = getFileExtension(fileName); + String shortName = nameWithoutExtension.substring(0, MAXIMUM_FILE_NAME_LENGTH); + LOGGER.info(String.format("Truncated the too long filename '%s' (%d characters) to '%s'.", fileName, fileName.length(), shortName)); + return extension.map(s -> shortName + "." + s).orElse(shortName); + } + + return fileName; + } + + /** + * Adds an extension to the given file name. The original extension is not replaced. That means, "demo.bib", ".sav" + * gets "demo.bib.sav" and not "demo.sav" + * + * @param path the path to add the extension to * @param extension the extension to add * @return the with the modified file name */ @@ -147,7 +153,6 @@ public static List uniquePathSubstrings(List paths) { * @param pathToDestinationFile Path Destination file * @param replaceExisting boolean Determines whether the copy goes on even if the file exists. * @return boolean Whether the copy succeeded, or was stopped due to the file already existing. - * @throws IOException */ public static boolean copyFile(Path pathToSourceFile, Path pathToDestinationFile, boolean replaceExisting) { // Check if the file already exists. @@ -156,7 +161,7 @@ public static boolean copyFile(Path pathToSourceFile, Path pathToDestinationFile return false; } if (Files.exists(pathToDestinationFile) && !replaceExisting) { - LOGGER.error("Path to the destination file exists and the file shouldn't be replaced."); + LOGGER.error("Path to the destination file is not exists and the file shouldn't be replace."); return false; } try { @@ -181,239 +186,66 @@ public static boolean renameFile(Path fromFile, Path toFile) { /** * Renames a given file * - * @param fromFile The source filename to rename - * @param toFile The target fileName + * @param fromFile The source filename to rename + * @param toFile The target fileName * @param replaceExisting Wether to replace existing files or not * @return True if the rename was successful, false if an exception occurred - * */ public static boolean renameFile(Path fromFile, Path toFile, boolean replaceExisting) { try { - if (replaceExisting) { - return Files.move(fromFile, fromFile.resolveSibling(toFile), - StandardCopyOption.REPLACE_EXISTING) != null; - } else { - return Files.move(fromFile, fromFile.resolveSibling(toFile)) != null; - } + return renameFileWithException(fromFile, toFile, replaceExisting); } catch (IOException e) { LOGGER.error("Renaming Files failed", e); return false; } } - /** - * Converts a relative filename to an absolute one, if necessary. Returns an empty optional if the file does not - * exist.
- *

- * Uses

    - *
  • the default directory associated with the extension of the file
  • - *
  • the standard file directory
  • - *
  • the directory of the BIB file
  • - *
- * - * @param databaseContext The database this file belongs to. - * @param name The filename, may also be a relative path to the file - */ - public static Optional expandFilename(final BibDatabaseContext databaseContext, String name, - FileDirectoryPreferences fileDirectoryPreferences) { - Optional extension = getFileExtension(name); - // Find the default directory for this field type, if any: - List directories = databaseContext.getFileDirectories(extension.orElse(null), fileDirectoryPreferences); - // Include the standard "file" directory: - List fileDir = databaseContext.getFileDirectories(fileDirectoryPreferences); - // Include the directory of the BIB file: - List al = new ArrayList<>(); - for (String dir : directories) { - if (!al.contains(dir)) { - al.add(dir); - } - } - for (String aFileDir : fileDir) { - if (!al.contains(aFileDir)) { - al.add(aFileDir); - } - } - - return expandFilename(name, al); - } - - /** - * Converts a relative filename to an absolute one, if necessary. Returns - * null if the file does not exist. - *

- * Will look in each of the given dirs starting from the beginning and - * returning the first found file to match if any. - */ - public static Optional expandFilename(String name, List directories) { - for (String dir : directories) { - if (dir != null) { - Optional result = expandFilename(name, dir); - if (result.isPresent()) { - return result; - } - } - } - - return Optional.empty(); - } - - /** - * Converts a relative filename to an absolute one, if necessary. Returns - * an empty optional if the file does not exist. - */ - private static Optional expandFilename(String filename, String dir) { - - if ((filename == null) || filename.isEmpty()) { - return Optional.empty(); - } - - String name = filename; - - File file = new File(name); - if (file.exists() || (dir == null)) { - return Optional.of(file); - } - - if (dir.endsWith(OS.FILE_SEPARATOR)) { - name = dir + name; - } else { - name = dir + OS.FILE_SEPARATOR + name; - } - - // fix / and \ problems: - if (OS.WINDOWS) { - name = SLASH.matcher(name).replaceAll("\\\\"); + public static boolean renameFileWithException(Path fromFile, Path toFile, boolean replaceExisting) throws IOException { + if (replaceExisting) { + return Files.move(fromFile, fromFile.resolveSibling(toFile), + StandardCopyOption.REPLACE_EXISTING) != null; } else { - name = BACKSLASH.matcher(name).replaceAll("/"); - } - - File fileInDir = new File(name); - if (fileInDir.exists()) { - return Optional.of(fileInDir); - } else { - return Optional.empty(); + return Files.move(fromFile, fromFile.resolveSibling(toFile)) != null; } } /** - * Converts an absolute filename to a relative one, if necessary. - * Returns the parameter fileName itself if no shortening is possible + * Converts an absolute file to a relative one, if possible. Returns the parameter file itself if no shortening is + * possible. *

- * This method works correctly only if dirs are sorted decent in their length - * i.e. /home/user/literature/important before /home/user/literature + * This method works correctly only if dirs are sorted decent in their length i.e. /home/user/literature/important before /home/user/literature. * - * @param fileName the filename to be shortened - * @param dirs directories to check. + * @param file the file to be shortened + * @param dirs directories to check */ - public static File shortenFileName(File fileName, List dirs) { - if ((fileName == null) || !fileName.isAbsolute() || (dirs == null)) { - return fileName; + public static Path shortenFileName(Path file, List dirs) { + if (!file.isAbsolute()) { + return file; } - for (String dir : dirs) { - if (dir != null) { - File result = shortenFileName(fileName, dir); - if ((result != null) && !result.equals(fileName)) { - return result; - } + for (Path dir : dirs) { + if (file.startsWith(dir)) { + return dir.relativize(file); } } - return fileName; - } - - private static File shortenFileName(File fileName, String directory) { - if ((fileName == null) || !fileName.isAbsolute() || (directory == null)) { - return fileName; - } - - String dir = directory; - String longName; - if (OS.WINDOWS) { - // case-insensitive matching on Windows - longName = fileName.toString().toLowerCase(Locale.ROOT); - dir = dir.toLowerCase(Locale.ROOT); - } else { - longName = fileName.toString(); - } - - if (!dir.endsWith(OS.FILE_SEPARATOR)) { - dir = dir.concat(OS.FILE_SEPARATOR); - } - - if (longName.startsWith(dir)) { - // result is based on original name, not on lower-cased name - String newName = fileName.toString().substring(dir.length()); - return new File(newName); - } else { - return fileName; - } - } - - public static Map> findAssociatedFiles(List entries, List extensions, - List directories, boolean autolinkExactKeyOnly) { - Map> result = new HashMap<>(); - - // First scan directories - Set filesWithExtension = FileFinder.findFiles(extensions, directories); - - // Initialize Result-Set - for (BibEntry entry : entries) { - result.put(entry, new ArrayList<>()); - } - - // Now look for keys - nextFile: for (Path file : filesWithExtension) { - - String name = file.getFileName().toString(); - int dot = name.lastIndexOf('.'); - // First, look for exact matches: - for (BibEntry entry : entries) { - Optional citeKey = entry.getCiteKeyOptional(); - if ((citeKey.isPresent()) && !citeKey.get().isEmpty() && (dot > 0) - && name.substring(0, dot).equals(citeKey.get())) { - result.get(entry).add(file.toFile()); - continue nextFile; - } - } - // If we get here, we did not find any exact matches. If non-exact - // matches are allowed, try to find one: - if (!autolinkExactKeyOnly) { - for (BibEntry entry : entries) { - Optional citeKey = entry.getCiteKeyOptional(); - if ((citeKey.isPresent()) && !citeKey.get().isEmpty() && name.startsWith(citeKey.get())) { - result.get(entry).add(file.toFile()); - continue nextFile; - } - } - } - } - - return result; + return file; } /** * Returns the list of linked files. The files have the absolute filename * - * @param bes list of BibTeX entries + * @param bes list of BibTeX entries * @param fileDirs list of directories to try for expansion - * * @return list of files. May be empty */ - public static List getListOfLinkedFiles(List bes, List fileDirs) { + public static List getListOfLinkedFiles(List bes, List fileDirs) { Objects.requireNonNull(bes); Objects.requireNonNull(fileDirs); - List result = new ArrayList<>(); - for (BibEntry entry : bes) { - entry.getField(FieldName.FILE).ifPresent(fileField -> { - List fileList = FileField.parse(fileField); - for (ParsedFileField file : fileList) { - expandFilename(file.getLink(), fileDirs).ifPresent(result::add); - } - }); - } - - return result; + return bes.stream() + .flatMap(entry -> entry.getFiles().stream()) + .flatMap(file -> OptionalUtil.toStream(file.findIn(fileDirs))) + .collect(Collectors.toList()); } /** @@ -424,7 +256,10 @@ public static List getListOfLinkedFiles(List bes, List f * @param fileNamePattern the filename pattern * @param prefs the layout preferences * @return a suggested fileName + * + * @Deprecated use String createFileNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern ) instead. */ + @Deprecated public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern, LayoutFormatterPreferences prefs) { String targetName = null; @@ -449,10 +284,53 @@ public static String createFileNameFromPattern(BibDatabase database, BibEntry en } /** - * Finds a file inside a directory structure. - * Will also look for the file inside nested directories. + * Determines filename provided by an entry in a database + * + * @param database the database, where the entry is located + * @param entry the entry to which the file should be linked to + * @param fileNamePattern the filename pattern + * @return a suggested fileName + */ + public static String createFileNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern) { + String targetName = null; + + targetName = BracketedPattern.expandBrackets(fileNamePattern, ';', entry, database); + + if ((targetName == null) || targetName.isEmpty()) { + targetName = entry.getCiteKeyOptional().orElse("default"); + } + + //Removes illegal characters from filename + targetName = FileNameCleaner.cleanFileName(targetName); + return targetName; + } + + /** + * Determines filename provided by an entry in a database + * + * @param database the database, where the entry is located + * @param entry the entry to which the file should be linked to + * @param fileNamePattern the filename pattern + * @return a suggested fileName + */ + public static String createDirNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern) { + String targetName = null; + + targetName = BracketedPattern.expandBrackets(fileNamePattern, ';', entry, database); + + if ((targetName == null) || targetName.isEmpty()) { + targetName = entry.getCiteKeyOptional().orElse("default"); + } + + //Removes illegal characters from filename + targetName = FileNameCleaner.cleanDirectoryName(targetName); + return targetName; + } + + /** + * Finds a file inside a directory structure. Will also look for the file inside nested directories. * - * @param filename the name of the file that should be found + * @param filename the name of the file that should be found * @param rootDirectory the rootDirectory that will be searched * @return the path to the first file that matches the defined conditions */ @@ -469,10 +347,9 @@ public static Optional find(String filename, Path rootDirectory) { } /** - * Finds a file inside a list of directory structures. - * Will also look for the file inside nested directories. + * Finds a file inside a list of directory structures. Will also look for the file inside nested directories. * - * @param filename the name of the file that should be found + * @param filename the name of the file that should be found * @param directories the directories that will be searched * @return a list including all found paths to files that match the defined conditions */ diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 642c9415531..5860c7df9a1 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 11d92688be6..21094bfee56 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2342,36 +2342,6 @@ Delete_from_disk=Auf_der_Festplatte_löschen Remove_from_entry=Vom_Eintrag_entfernen The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=Der_Gruppename_enthält_das_Trennzeichen_"%0"_und_wird_deswegen_möglicherweise_nicht_wie_erwartet_funktionieren. There_exists_already_a_group_with_the_same_name.=Es_existiert_bereits_eine_Gruppe_mit_demselben_Namen. -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -To_improve_the_user_experience,_we_would_like_to_collect_anonymous_statistics_on_the_features_you_use._We_will_only_record_what_features_you_access_and_how_often_you_do_it._We_will_neither_collect_any_personal_data_nor_the_content_of_bibliographic_items._If_you_choose_to_allow_data_collection,_you_can_later_disable_it_via_Options_->_Preferences_->_General.=Zur_Verbesserung_der_Benutzererfahrung_würden_wir_gerne_anonyme_Statistiken_über_die_Features_sammeln,_die_Sie_benutzen._Wir_zeichnen_nur_auf,_welche_Features_Sie_nutzen_und_wie_oft_Sie_diese_benutzen._Es_werden_keinerlei_persönliche_Informationen_über_Sie_oder_den_Inhalt_Ihrer_Bibliografieeinträge_gesammelt._Die_einmal_erlaubte_Datenaufzeichnnung_kann_jederzeit_unter_Optionen->Einstellungen->Allgemein_deaktiviert werden. -This_file_was_found_automatically._Do_you_want_to_link_it_to_this_entry?= -Names_are_not_in_the_standard_BibTeX_format.= - -Delete_the_selected_file_permanently_from_disk,_or_just_remove_the_file_from_the_entry?_Pressing_Delete_will_delete_the_file_permanently_from_disk.= -Delete_'%0'= -Delete_from_disk= -Remove_from_entry= -The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= -There_exists_already_a_group_with_the_same_name.= - -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= -This_file_was_found_automatically._Do_you_want_to_link_it_to_this_entry?= -Names_are_not_in_the_standard_BibTeX_format.= - -Delete_the_selected_file_permanently_from_disk,_or_just_remove_the_file_from_the_entry?_Pressing_Delete_will_delete_the_file_permanently_from_disk.=Die_ausgewählte_Datei_unwiderruflich_löschen_oder_nur_vom_Eintrag_entfernen?_Drücken_sie_Entfernen,_um_die_Datei_von_der_Festplatte_zu_löschen. -Delete_'%0'=Lösche_Datei_'%0' -Delete_from_disk=Auf_der_Festplatte_löschen -Remove_from_entry=Vom_Eintrag_entfernen -The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=Der_Gruppename_enthält_das_Trennzeichen_"%0"_und_wird_deswegen_möglicherweise_nicht_wie_erwartet_funktionieren. -There_exists_already_a_group_with_the_same_name.=Es_existiert_bereits_eine_Gruppe_mit_demselben_Namen. - Copy_attached_files_to_folder...= Copied_file_successfully= diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index 176b1bfac3b..000908a2ef4 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index f3dcfb5a673..dc18dd5045b 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2342,16 +2342,7 @@ Delete_from_disk=Delete_from_disk Remove_from_entry=Remove_from_entry The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected. There_exists_already_a_group_with_the_same_name.=There_exists_already_a_group_with_the_same_name. -Rename_failed=Rename_failed -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process. -Show_console_output_(only_necessary_when_the_launcher_is_used)=Show_console_output_(only_necessary_when_the_launcher_is_used) -Export_linked_files=Export_linked_files -Exported_file_successfully=Exported_file_successfully -Exporting_file_%0_of_BibEntry_%1=Exporting_file_%0_of_BibEntry_%1 -Exporting_files...=Exporting_files... -Finished_exporting=Finished_exporting -Exported_%0_files_sucessfully_to_%1=Exported_%0_files_sucessfully_to_%1 Copy_attached_files_to_folder...=Copy_attached_files_to_folder... Copied_file_successfully=Copied_file_successfully Copying_file_%0_of_BibEntry_%1=Copying_file_%0_of_BibEntry_%1 diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index bda4acc6a74..f8603a11d15 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 11e7db006f3..842b7195026 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 3e414dd76d8..3fd81795b56 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -2342,16 +2342,7 @@ Delete_from_disk=Supprimer_du_disque Remove_from_entry=Effacer_de_l'entrée The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=Le_nom_du_groupe_contient_le_séparateur_de_mot-clef_"%0"_et_ne_fonctionnera_probablement_donc_pas_comme_attendu. There_exists_already_a_group_with_the_same_name.=Un_groupe_portant_ce_nom_existe_déjà. -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 4bc5532eee9..ca05109ada5 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index ebba1ea0b86..57d85ad6bda 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -2342,18 +2342,6 @@ Delete_from_disk=Cancella_dal_disco Remove_from_entry=Rimuovi_dalla_voce The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=Il_nome_di_gruppo_contiene_il_separatore_di_keyword_"%0"_e_quindi_probabilmente_non_funziona_come_ci_si_aspetta. There_exists_already_a_group_with_the_same_name.=Esiste_già_almeno_un_gruppo_con_lo_stesso_nome. -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= -There_exists_already_a_group_with_the_same_name.= - -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index fc0cf877e34..c832fac2820 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2342,18 +2342,7 @@ Delete_from_disk=ディスクから削除 Remove_from_entry=項目から除去 The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=グループ名にキーワード区切りの「%0」が含まれているので,想定通りにはおそらく動作しません. There_exists_already_a_group_with_the_same_name.=同じ名称のグループがすでに存在します. -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=グループ名にキーワード区切りの「%0」が含まれているので、想定通りにはおそらく動作しません。 -There_exists_already_a_group_with_the_same_name.=同じ名称のグループがすでに存在します。 - -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= + Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 329bd8535d4..66ad27b6740 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 2269e9c446b..d64ceb0e76d 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index a1645fb0449..9992591a349 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 7f0c48ca724..32f38aa2f58 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index f5a2e741fad..8f487164c6b 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 7f46dc9ec60..89534b5b422 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -2342,22 +2342,6 @@ Delete_from_disk=Diskten_sil Remove_from_entry=Girdiden_sil The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.=Grup_adı_anahtar_sözcük_ayracı_olan_"%0"_içeriyor_ve_bu_sebeple_muhtemelen_beklendiğini_gibi_çalışmayacak. There_exists_already_a_group_with_the_same_name.=Aynı_isimli_bir_grup_zaten_var. -Rename_failed=Yeniden_adlandırma_başarısız_oldu -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_dosyaya_erişemiyor_çünkü_dosya_başka_bir_süreç_tarafından_kullanılıyor. -Show_console_output_(only_necessary_when_the_launcher_is_used)=Consol_çıktısını_göster_(sadece_başlatıcı_kullanıldığında_gereklidir) -Delete_the_selected_file_permanently_from_disk,_or_just_remove_the_file_from_the_entry?_Pressing_Delete_will_delete_the_file_permanently_from_disk.= -Delete_'%0'= -Delete_from_disk= -Remove_from_entry= -The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= -There_exists_already_a_group_with_the_same_name.= - -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 59b5b617eb0..f81cc87abd5 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index a33048559d4..c6c99cc4836 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -2342,16 +2342,7 @@ Delete_from_disk= Remove_from_entry= The_group_name_contains_the_keyword_separator_"%0"_and_thus_probably_does_not_work_as_expected.= There_exists_already_a_group_with_the_same_name.= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= -Export_linked_files= -Exported_file_successfully= -Exporting_file_%0_of_BibEntry_%1= -Exporting_files...= -Finished_exporting= -Exported_%0_files_sucessfully_to_%1= Copy_attached_files_to_folder...= Copied_file_successfully= Copying_file_%0_of_BibEntry_%1= From 68e15625257468b8161c14e6d43aa708158be690 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 7 Oct 2017 22:51:35 +0200 Subject: [PATCH 06/28] Remove empty line Avoid code duplicaiton --- src/main/java/org/jabref/JabRefMain.java | 1 - .../gui/actions/ExportLinkedFilesAction.java | 37 +++++++++++-------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/jabref/JabRefMain.java b/src/main/java/org/jabref/JabRefMain.java index 238da29a32c..b278ecd94a8 100644 --- a/src/main/java/org/jabref/JabRefMain.java +++ b/src/main/java/org/jabref/JabRefMain.java @@ -51,7 +51,6 @@ public static void main(String[] args) { public void start(Stage mainStage) throws Exception { Platform.setImplicitExit(false); SwingUtilities.invokeLater(() -> start(arguments)); - } private static void start(String[] args) { diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index 2382bf364ac..9558eadf444 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -94,6 +94,8 @@ private void startServiceAndshowProgessDialog(Service service) { private class ExportService extends Service { private static final String LOGFILE = "exportLog.log"; + private final String localizedSucessMessage = Localization.lang("Copied file successfully"); + private final String localizedErrorMessage = Localization.lang("Could not copy file") + ": " + Localization.lang("File exists"); @Override protected Task createTask() { @@ -130,35 +132,38 @@ protected Void call() boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); updateProgress(totalFilesCounter++, totalFilesCount); if (success) { - updateMessage(Localization.lang("Copied file successfully")); + updateMessage(localizedSucessMessage); numberSucessful++; - try { - bw.write(Localization.lang("Copied file successfully") + ": " + newFile); - bw.write(OS.NEWLINE); - } catch (IOException e) { - LOGGER.error("error writing log file", e); - } + writeLogMessage(newFile, bw, localizedSucessMessage); + } else { - updateMessage(Localization.lang("Could not copy file") + ": " + Localization.lang("File exists")); + + updateMessage(localizedErrorMessage); numberError++; - try { - bw.write(Localization.lang("Could not copy file") + ": " + Localization.lang("File exists") + ":" + newFile); - bw.write(OS.NEWLINE); - } catch (IOException e) { - LOGGER.error("error writing log file", e); - } + writeLogMessage(newFile, bw, localizedErrorMessage); } }); } } updateMessage(Localization.lang("Finished copying")); - updateMessage(Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse(""))); - bw.write(Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse(""))); + String sucessMessage = Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse("")); + updateMessage(sucessMessage); + bw.write(sucessMessage); return null; } } }; } + + private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) { + try { + bw.write(logMessage + ": " + newFile); + bw.write(OS.NEWLINE); + } catch (IOException e) { + LOGGER.error("error writing log file", e); + } + } + } } From d1b53eb94321b74c4647a09461704d05667523a8 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 8 Oct 2017 11:35:30 +0200 Subject: [PATCH 07/28] Move service to new class --- .../java/org/jabref/gui/DialogService.java | 10 ++ .../java/org/jabref/gui/FXDialogService.java | 18 +++ .../gui/actions/ExportLinkedFilesAction.java | 116 +----------------- .../gui/actions/ExportLinkedFilesService.java | 116 ++++++++++++++++++ 4 files changed, 149 insertions(+), 111 deletions(-) create mode 100644 src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java index 2475365ae13..1bf7fee4e22 100644 --- a/src/main/java/org/jabref/gui/DialogService.java +++ b/src/main/java/org/jabref/gui/DialogService.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Optional; +import javafx.concurrent.Service; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.DialogPane; @@ -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. */ @@ -121,6 +124,12 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String */ Optional showCustomDialogAndWait(Dialog dialog); + /** + * Constructs and shows a canceable {@link ProgressDialog}. Clicking cancel will cancel the underlying service and close the dialog + * @param service The {@link Service} which executes the work and for which to show the dialog + */ + void showCanceableProgressDialogAndWait(Service service); + /** * Notify the user in an non-blocking way (i.e., update status message instead of showing a dialog). * @param message the message to show. @@ -173,4 +182,5 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String * @return A configured instance of the {@link FileChooser} */ FileChooser getConfiguredFileChooser(FileDialogConfiguration fileDialogConfiguration); + } diff --git a/src/main/java/org/jabref/gui/FXDialogService.java b/src/main/java/org/jabref/gui/FXDialogService.java index 6b474d13a2c..6cd7cbf3fbf 100644 --- a/src/main/java/org/jabref/gui/FXDialogService.java +++ b/src/main/java/org/jabref/gui/FXDialogService.java @@ -8,6 +8,8 @@ import java.util.stream.Collectors; import javafx.scene.control.Alert.AlertType; +import javafx.concurrent.Service; +import javafx.scene.control.Button; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; import javafx.scene.control.DialogPane; @@ -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 @@ -127,6 +130,21 @@ public Optional showCustomDialogAndWait(Dialog dialog) { return dialog.showAndWait(); } + @Override + public void showCanceableProgressDialogAndWait(Service service) { + ProgressDialog progressDialog = new ProgressDialog(service); + progressDialog.setOnCloseRequest(evt -> service.cancel()); + DialogPane dialogPane = progressDialog.getDialogPane(); + dialogPane.getButtonTypes().add(ButtonType.CANCEL); + Button cancelButton = (Button) dialogPane.lookupButton(ButtonType.CANCEL); + cancelButton.setOnAction(evt -> { + service.cancel(); + progressDialog.close(); + }); + progressDialog.showAndWait(); + + } + @Override public void notify(String message) { JabRefGUI.getMainFrame().output(message); diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index 9558eadf444..1950c7264c0 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -1,24 +1,13 @@ package org.jabref.gui.actions; import java.awt.event.ActionEvent; -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Optional; -import java.util.function.BiFunction; - import javax.swing.AbstractAction; import javafx.concurrent.Service; -import javafx.concurrent.Task; -import javafx.scene.control.Button; -import javafx.scene.control.ButtonType; -import javafx.scene.control.DialogPane; - import org.jabref.Globals; import org.jabref.JabRefGUI; import org.jabref.gui.DialogService; @@ -26,25 +15,13 @@ import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.OS; -import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.LinkedFile; -import org.jabref.model.util.FileHelper; -import org.jabref.model.util.OptionalUtil; import org.jabref.preferences.JabRefPreferences; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.controlsfx.dialog.ProgressDialog; - public class ExportLinkedFilesAction extends AbstractAction { - private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class); - private final BiFunction resolvePathFilename = (path, file) -> { - return path.resolve(file.getFileName()); - }; + private final DialogService ds = new FXDialogService(); private long totalFilesCount; private BibDatabaseContext databaseContext; @@ -67,9 +44,8 @@ public void actionPerformed(ActionEvent e) { exportPath.ifPresent(path -> { databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext(); - totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count(); - Service exportService = new ExportService(); + Service exportService = new ExportLinkedFilesService(databaseContext, entries, path); startServiceAndshowProgessDialog(exportService); }); } @@ -78,92 +54,10 @@ private void startServiceAndshowProgessDialog(Service service) { DefaultTaskExecutor.runInJavaFXThread(() -> { service.start(); - ProgressDialog progressDialog = new ProgressDialog(service); - progressDialog.setOnCloseRequest(evt -> service.cancel()); - DialogPane dialogPane = progressDialog.getDialogPane(); - dialogPane.getButtonTypes().add(ButtonType.CANCEL); - Button cancelButton = (Button) dialogPane.lookupButton(ButtonType.CANCEL); - cancelButton.setOnAction(evt -> { - service.cancel(); - progressDialog.close(); - }); - progressDialog.showAndWait(); - }); - } - - private class ExportService extends Service { - - private static final String LOGFILE = "exportLog.log"; - private final String localizedSucessMessage = Localization.lang("Copied file successfully"); - private final String localizedErrorMessage = Localization.lang("Could not copy file") + ": " + Localization.lang("File exists"); - - @Override - protected Task createTask() { - return new Task() { - - int totalFilesCounter; - int numberSucessful; - int numberError; - Optional newPath; - - @Override - protected Void call() - throws InterruptedException, IOException { - updateMessage(Localization.lang("Copying files...")); - updateProgress(0, totalFilesCount); - - try (BufferedWriter bw = Files.newBufferedWriter(exportPath.get().resolve(LOGFILE), StandardCharsets.UTF_8)) { - - for (int i = 0; i < entries.size(); i++) { - - List 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))); - Thread.sleep(500); //TODO: Adjust/leave/any other idea? - - String fileName = files.get(j).getLink(); - Optional fileToExport = FileHelper.expandFilenameAsPath(fileName, - databaseContext.getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences())); - - newPath = OptionalUtil.combine(exportPath, fileToExport, resolvePathFilename); - - newPath.ifPresent(newFile -> { - boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); - updateProgress(totalFilesCounter++, totalFilesCount); - if (success) { - updateMessage(localizedSucessMessage); - numberSucessful++; - writeLogMessage(newFile, bw, localizedSucessMessage); - - } else { - - updateMessage(localizedErrorMessage); - numberError++; - writeLogMessage(newFile, bw, localizedErrorMessage); - } - }); - } - } - updateMessage(Localization.lang("Finished copying")); - String sucessMessage = Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse("")); - updateMessage(sucessMessage); - bw.write(sucessMessage); - return null; - } - } - }; - } - - private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) { - try { - bw.write(logMessage + ": " + newFile); - bw.write(OS.NEWLINE); - } catch (IOException e) { - LOGGER.error("error writing log file", e); - } - } + DialogService dlgService = new FXDialogService(); + dlgService.showCanceableProgressDialogAndWait(service); + }); } } diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java new file mode 100644 index 00000000000..4e2e42874a3 --- /dev/null +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java @@ -0,0 +1,116 @@ +package org.jabref.gui.actions; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; + +import javafx.concurrent.Service; +import javafx.concurrent.Task; + +import org.jabref.Globals; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.OS; +import org.jabref.logic.util.io.FileUtil; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.LinkedFile; +import org.jabref.model.util.OptionalUtil; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ExportLinkedFilesService extends Service { + + private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class); + private static final String LOGFILE = "exportLog.log"; + private final String localizedSucessMessage = Localization.lang("Copied file successfully"); + private final String localizedErrorMessage = Localization.lang("Could not copy file") + ": " + Localization.lang("File exists"); + private final long totalFilesCount; + private final BibDatabaseContext databaseContext; + private final List entries; + private final Path exportPath; + + private final BiFunction resolvePathFilename = (path, file) -> { + return path.resolve(file.getFileName()); + }; + + public ExportLinkedFilesService(BibDatabaseContext databaseContext, List entries, Path path) { + this.databaseContext = databaseContext; + this.entries = entries; + this.exportPath = path; + totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count(); + + } + + @Override + protected Task createTask() { + return new Task() { + + int totalFilesCounter; + int numberSucessful; + int numberError; + Optional newPath; + + @Override + protected Void call() + throws InterruptedException, IOException { + updateMessage(Localization.lang("Copying files...")); + updateProgress(0, totalFilesCount); + + try (BufferedWriter bw = Files.newBufferedWriter(exportPath.resolve(LOGFILE), StandardCharsets.UTF_8)) { + + for (int i = 0; i < entries.size(); i++) { + + List files = entries.get(i).getFiles(); + + for (int j = 0; j < files.size(); j++) { + updateMessage(Localization.lang("Copying file %0 of entry %1", Integer.toString(j + 1), Integer.toString(i + 1))); + + LinkedFile fileName = files.get(j); + + Optional fileToExport = fileName.findIn(databaseContext, Globals.prefs.getFileDirectoryPreferences()); + + newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename); + + newPath.ifPresent(newFile -> { + boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); + updateProgress(totalFilesCounter++, totalFilesCount); + if (success) { + updateMessage(localizedSucessMessage); + numberSucessful++; + writeLogMessage(newFile, bw, localizedSucessMessage); + + } else { + + updateMessage(localizedErrorMessage); + numberError++; + writeLogMessage(newFile, bw, localizedErrorMessage); + } + }); + } + } + updateMessage(Localization.lang("Finished copying")); + String sucessMessage = Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse("")); + updateMessage(sucessMessage); + bw.write(sucessMessage); + return null; + } + } + }; + } + + private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) { + try { + bw.write(logMessage + ": " + newFile); + bw.write(OS.NEWLINE); + } catch (IOException e) { + LOGGER.error("error writing log file", e); + } + } + +} From 702137150ca0f962ab9f2423d26980fffebd60e7 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 8 Oct 2017 17:14:57 +0200 Subject: [PATCH 08/28] Fix translation --- src/main/resources/l10n/JabRef_da.properties | 2 +- src/main/resources/l10n/JabRef_de.properties | 2 +- src/main/resources/l10n/JabRef_el.properties | 2 +- src/main/resources/l10n/JabRef_en.properties | 2 +- src/main/resources/l10n/JabRef_es.properties | 2 +- src/main/resources/l10n/JabRef_fa.properties | 2 +- src/main/resources/l10n/JabRef_fr.properties | 2 +- src/main/resources/l10n/JabRef_in.properties | 2 +- src/main/resources/l10n/JabRef_it.properties | 2 +- src/main/resources/l10n/JabRef_ja.properties | 2 +- src/main/resources/l10n/JabRef_nl.properties | 2 +- src/main/resources/l10n/JabRef_no.properties | 2 +- src/main/resources/l10n/JabRef_pt_BR.properties | 2 +- src/main/resources/l10n/JabRef_ru.properties | 2 +- src/main/resources/l10n/JabRef_sv.properties | 2 +- src/main/resources/l10n/JabRef_tr.properties | 2 +- src/main/resources/l10n/JabRef_vi.properties | 2 +- src/main/resources/l10n/JabRef_zh.properties | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 5860c7df9a1..081ae2aa984 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 21094bfee56..77d7b70e7f1 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.=Es_existiert_bereits_eine_Grupp Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...=Copying_files... +Copying_file_%0_of_entry_%1= Finished_copying=Finished_copying Could_not_copy_file=Could_not_copy_file Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index 000908a2ef4..bf13e71987d 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index dc18dd5045b..4330ac36ccb 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.=There_exists_already_a_group_wi Copy_attached_files_to_folder...=Copy_attached_files_to_folder... Copied_file_successfully=Copied_file_successfully -Copying_file_%0_of_BibEntry_%1=Copying_file_%0_of_BibEntry_%1 Copying_files...=Copying_files... +Copying_file_%0_of_entry_%1=Copying_file_%0_of_entry_%1 Finished_copying=Finished_copying Could_not_copy_file=Could_not_copy_file Copied_%0_files_of_%1_sucessfully_to_%2=Copied_%0_files_of_%1_sucessfully_to_%2 diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index f8603a11d15..10c6470c936 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 842b7195026..b231d6323c7 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 3fd81795b56..99c689cb0df 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.=Un_groupe_portant_ce_nom_existe Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index ca05109ada5..e11afdcdf79 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 57d85ad6bda..473348a0072 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.=Esiste_già_almeno_un_gruppo_co Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index c832fac2820..0041d2ff611 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.=同じ名称のグループが Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...=Copying_files... +Copying_file_%0_of_entry_%1= Finished_copying=Finished_copying Could_not_copy_file=Could_not_copy_file Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 66ad27b6740..8bd964c7204 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index d64ceb0e76d..50963574f65 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 9992591a349..28998b0ff28 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 32f38aa2f58..0838102402b 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 8f487164c6b..85e3b9245ac 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 89534b5b422..2cf4e8c13c3 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.=Aynı_isimli_bir_grup_zaten_var Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index f81cc87abd5..7aeffab1aaf 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index c6c99cc4836..d5247dccf85 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -2345,8 +2345,8 @@ There_exists_already_a_group_with_the_same_name.= Copy_attached_files_to_folder...= Copied_file_successfully= -Copying_file_%0_of_BibEntry_%1= Copying_files...= +Copying_file_%0_of_entry_%1= Finished_copying= Could_not_copy_file= Copied_%0_files_of_%1_sucessfully_to_%2= From 6b02e9cb83e444cd44776b28cfd259da6e007284 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 8 Oct 2017 23:28:20 +0200 Subject: [PATCH 09/28] Add idea for list view dialog --- .../org/jabref/gui/actions/ExportLinkedFilesService.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java index 4e2e42874a3..dc4f56a4528 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java @@ -11,6 +11,8 @@ import javafx.concurrent.Service; import javafx.concurrent.Task; +import javafx.scene.control.Dialog; +import javafx.scene.control.ListView; import org.jabref.Globals; import org.jabref.logic.l10n.Localization; @@ -98,6 +100,7 @@ protected Void call() String sucessMessage = Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse("")); updateMessage(sucessMessage); bw.write(sucessMessage); + showDialog(); return null; } } @@ -113,4 +116,10 @@ private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) } } + private void showDialog() { + Dialog dlg = new Dialog<>(); + dlg.setTitle("Results"); + ListView lv = new ListView<>(); + dlg.getDialogPane().setContent(lv); + } } From bed0a54cd3df00c3d53711b8a333310b9f41a39b Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 19 Oct 2017 11:46:15 +0200 Subject: [PATCH 10/28] Add TableView to show log message --- .../gui/actions/ExportLinkedFilesAction.java | 62 +++++++++++++++++-- .../gui/actions/ExportLinkedFilesService.java | 27 ++++---- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index 1950c7264c0..0063ca14ea2 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -5,9 +5,18 @@ import java.nio.file.Paths; import java.util.List; import java.util.Optional; + import javax.swing.AbstractAction; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.concurrent.Service; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; + import org.jabref.Globals; import org.jabref.JabRefGUI; import org.jabref.gui.DialogService; @@ -21,7 +30,6 @@ public class ExportLinkedFilesAction extends AbstractAction { - private final DialogService ds = new FXDialogService(); private long totalFilesCount; private BibDatabaseContext databaseContext; @@ -45,19 +53,63 @@ public void actionPerformed(ActionEvent e) { exportPath.ifPresent(path -> { databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext(); - Service exportService = new ExportLinkedFilesService(databaseContext, entries, path); + Service> exportService = new ExportLinkedFilesService(databaseContext, entries, path); startServiceAndshowProgessDialog(exportService); }); } - private void startServiceAndshowProgessDialog(Service service) { + private void startServiceAndshowProgessDialog(Service> exportService) { DefaultTaskExecutor.runInJavaFXThread(() -> { - service.start(); + exportService.setOnSucceeded(value -> { + System.out.println(exportService.getValue()); + + System.out.println("Service succeeded"); + DefaultTaskExecutor.runInJavaFXThread(() -> showDialog(exportService.getValue())); + }); + exportService.start(); DialogService dlgService = new FXDialogService(); - dlgService.showCanceableProgressDialogAndWait(service); + dlgService.showCanceableProgressDialogAndWait(exportService); }); } + private void showDialog(List data) { + Dialog dlg = new Dialog<>(); + dlg.setTitle("Results"); + ObservableList tableData = FXCollections.observableArrayList(data); + + TableView tv = createTable(); + ScrollPane sp = new ScrollPane(); + sp.setContent(tv); + + dlg.getDialogPane().setContent(sp); + tv.setItems(tableData); + + sp.setFitToHeight(true); + sp.setFitToWidth(true); + + dlg.getDialogPane().getButtonTypes().add(ButtonType.CANCEL); + dlg.setResizable(true); + dlg.showAndWait(); + } + + private static TableView createTable() { + TableView tv = new TableView<>(); + + TableColumn colFile = new TableColumn<>("File"); + TableColumn colSuccess = new TableColumn<>("Success"); + TableColumn colMessage = new TableColumn<>("Log message"); + + colFile.setCellValueFactory(cellData -> cellData.getValue().getFile()); + colSuccess.setCellValueFactory(cellData -> cellData.getValue().getSucess()); + colMessage.setCellValueFactory(cellData -> cellData.getValue().getMessage()); + + tv.getColumns().add(colFile); + tv.getColumns().add(colSuccess); + tv.getColumns().add(colMessage); + + return tv; + } + } diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java index dc4f56a4528..effd736a2ba 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java @@ -5,15 +5,13 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.BiFunction; import javafx.concurrent.Service; import javafx.concurrent.Task; -import javafx.scene.control.Dialog; -import javafx.scene.control.ListView; - import org.jabref.Globals; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; @@ -26,7 +24,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -public class ExportLinkedFilesService extends Service { +public class ExportLinkedFilesService extends Service> { private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class); private static final String LOGFILE = "exportLog.log"; @@ -36,6 +34,7 @@ public class ExportLinkedFilesService extends Service { private final BibDatabaseContext databaseContext; private final List entries; private final Path exportPath; + private final List results = new ArrayList<>(); private final BiFunction resolvePathFilename = (path, file) -> { return path.resolve(file.getFileName()); @@ -50,8 +49,8 @@ public ExportLinkedFilesService(BibDatabaseContext databaseContext, List createTask() { - return new Task() { + protected Task> createTask() { + return new Task>() { int totalFilesCounter; int numberSucessful; @@ -59,7 +58,7 @@ protected Task createTask() { Optional newPath; @Override - protected Void call() + protected List call() throws InterruptedException, IOException { updateMessage(Localization.lang("Copying files...")); updateProgress(0, totalFilesCount); @@ -86,12 +85,14 @@ protected Void call() updateMessage(localizedSucessMessage); numberSucessful++; writeLogMessage(newFile, bw, localizedSucessMessage); + addResultToList(newFile, success, localizedSucessMessage); } else { updateMessage(localizedErrorMessage); numberError++; writeLogMessage(newFile, bw, localizedErrorMessage); + addResultToList(newFile, success, localizedSucessMessage); } }); } @@ -100,8 +101,7 @@ protected Void call() String sucessMessage = Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse("")); updateMessage(sucessMessage); bw.write(sucessMessage); - showDialog(); - return null; + return results; } } }; @@ -116,10 +116,9 @@ private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) } } - private void showDialog() { - Dialog dlg = new Dialog<>(); - dlg.setTitle("Results"); - ListView lv = new ListView<>(); - dlg.getDialogPane().setContent(lv); + private void addResultToList(Path newFile, boolean success, String logMessage) { + CopyFilesResult result = new CopyFilesResult(newFile.toString(), success, logMessage); + results.add(result); } + } From e347bc938b8fca9519273fd69e567a0beb07e855 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 19 Oct 2017 11:46:44 +0200 Subject: [PATCH 11/28] Add class for table view data --- .../jabref/gui/actions/CopyFilesResult.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/main/java/org/jabref/gui/actions/CopyFilesResult.java diff --git a/src/main/java/org/jabref/gui/actions/CopyFilesResult.java b/src/main/java/org/jabref/gui/actions/CopyFilesResult.java new file mode 100644 index 00000000000..f6a997fea2d --- /dev/null +++ b/src/main/java/org/jabref/gui/actions/CopyFilesResult.java @@ -0,0 +1,49 @@ +package org.jabref.gui.actions; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +public class CopyFilesResult { + + private final StringProperty file = new SimpleStringProperty(""); + private final BooleanProperty success = new SimpleBooleanProperty(false); + private final StringProperty message = new SimpleStringProperty(""); + + public CopyFilesResult(String file, boolean success, String message) + { + this.file.setValue(file); + this.success.setValue(success); + this.message.setValue(message); + } + + public StringProperty getFile() { + return file; + } + + public void setFile(String file) { + this.file.setValue(file); + } + + public BooleanProperty getSucess() { + return success; + } + + public void setSucess(Boolean sucess) { + this.success.setValue(sucess); + } + + public StringProperty getMessage() { + return message; + } + + public void setMessage(String message) { + this.message.setValue(message); + } + + @Override + public String toString() { + return "CopyFilesResult [file=" + file.get() + ", success=" + success.get() + ", message=" + message.get() + "]"; + } +} From 090a4cdc75cedb8453d6052b08b7402e5c62a12f Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 19 Oct 2017 15:52:59 +0200 Subject: [PATCH 12/28] Add Green/Red icons for status Reorder columns Fix translation error --- CHANGELOG.md | 1 + .../jabref/gui/actions/CopyFilesResult.java | 31 ++++++------ .../gui/actions/ExportLinkedFilesAction.java | 49 ++++++++++++++++--- .../gui/actions/ExportLinkedFilesService.java | 3 +- src/main/resources/l10n/JabRef_de.properties | 3 -- 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a5b8c89c03..4f401685cd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,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) ### Fixed - We fixed the translation of \textendash in the entry preview [#3307](https://github.com/JabRef/jabref/issues/3307) diff --git a/src/main/java/org/jabref/gui/actions/CopyFilesResult.java b/src/main/java/org/jabref/gui/actions/CopyFilesResult.java index f6a997fea2d..88d618e528d 100644 --- a/src/main/java/org/jabref/gui/actions/CopyFilesResult.java +++ b/src/main/java/org/jabref/gui/actions/CopyFilesResult.java @@ -1,21 +1,26 @@ package org.jabref.gui.actions; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; +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 CopyFilesResult { private final StringProperty file = new SimpleStringProperty(""); - private final BooleanProperty success = new SimpleBooleanProperty(false); + private final ObjectProperty icon = new SimpleObjectProperty<>(MaterialDesignIcon.ALERT); + private final StringProperty message = new SimpleStringProperty(""); - public CopyFilesResult(String file, boolean success, String message) - { + public CopyFilesResult(String file, boolean success, String message) { this.file.setValue(file); - this.success.setValue(success); this.message.setValue(message); + if (success) { + this.icon.setValue(MaterialDesignIcon.CHECK); + } + } public StringProperty getFile() { @@ -26,14 +31,6 @@ public void setFile(String file) { this.file.setValue(file); } - public BooleanProperty getSucess() { - return success; - } - - public void setSucess(Boolean sucess) { - this.success.setValue(sucess); - } - public StringProperty getMessage() { return message; } @@ -42,8 +39,12 @@ public void setMessage(String message) { this.message.setValue(message); } + public ObjectProperty getIcon() { + return icon; + } + @Override public String toString() { - return "CopyFilesResult [file=" + file.get() + ", success=" + success.get() + ", message=" + message.get() + "]"; + return "CopyFilesResult [file=" + file.get() + ", message=" + message.get() + "]"; } } diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index 0063ca14ea2..4ffd39ac48a 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -14,8 +14,11 @@ import javafx.scene.control.ButtonType; import javafx.scene.control.Dialog; import javafx.scene.control.ScrollPane; +import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; +import javafx.scene.paint.Color; +import javafx.scene.text.Text; import org.jabref.Globals; import org.jabref.JabRefGUI; @@ -28,6 +31,9 @@ import org.jabref.model.entry.BibEntry; import org.jabref.preferences.JabRefPreferences; +import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; +import de.jensd.fx.glyphs.materialdesignicons.utils.MaterialDesignIconFactory; + public class ExportLinkedFilesAction extends AbstractAction { private final DialogService ds = new FXDialogService(); @@ -97,19 +103,46 @@ private void showDialog(List data) { private static TableView createTable() { TableView tv = new TableView<>(); - TableColumn colFile = new TableColumn<>("File"); - TableColumn colSuccess = new TableColumn<>("Success"); - TableColumn colMessage = new TableColumn<>("Log message"); + TableColumn colFile = new TableColumn<>(Localization.lang("File")); + TableColumn colIcon = new TableColumn<>(Localization.lang("Status")); + TableColumn colMessage = new TableColumn<>(Localization.lang("Message")); colFile.setCellValueFactory(cellData -> cellData.getValue().getFile()); - colSuccess.setCellValueFactory(cellData -> cellData.getValue().getSucess()); colMessage.setCellValueFactory(cellData -> cellData.getValue().getMessage()); - - tv.getColumns().add(colFile); - tv.getColumns().add(colSuccess); + colIcon.setCellValueFactory(cellData -> cellData.getValue().getIcon()); + + colIcon.setCellFactory(column -> { + return new TableCell() { + + @Override + protected void updateItem(MaterialDesignIcon item, boolean empty) { + super.updateItem(item, empty); + + if ((item == null) || empty) { + setText(null); + setStyle(""); + } else { + Text icon = MaterialDesignIconFactory.get().createIcon(item); + + //Green checkmark + if (item == MaterialDesignIcon.CHECK) { + icon.setFill(Color.GREEN); + } + //Red Alert symbol + if (item == MaterialDesignIcon.ALERT) { + icon.setFill(Color.RED); + } + setGraphic(icon); + + } + } + }; + }); + tv.getColumns().add(colIcon); tv.getColumns().add(colMessage); + tv.getColumns().add(colFile); return tv; } -} +} \ No newline at end of file diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java index effd736a2ba..0c4aabb1223 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java @@ -12,6 +12,7 @@ import javafx.concurrent.Service; import javafx.concurrent.Task; + import org.jabref.Globals; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; @@ -92,7 +93,7 @@ protected List call() updateMessage(localizedErrorMessage); numberError++; writeLogMessage(newFile, bw, localizedErrorMessage); - addResultToList(newFile, success, localizedSucessMessage); + addResultToList(newFile, success, localizedErrorMessage); } }); } diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index d8f84eddec8..b297931ff00 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2345,9 +2345,6 @@ Copying_file_%0_of_entry_%1= Finished_copying=Finished_copying Could_not_copy_file=Could_not_copy_file Copied_%0_files_of_%1_sucessfully_to_%2= -Rename_failed= -JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.= -Show_console_output_(only_necessary_when_the_launcher_is_used)= Rename_failed=Umbenennen_fehlgeschlagen JabRef_cannot_access_the_file_because_it_is_being_used_by_another_process.=JabRef_kann_nicht_auf_die_Datei_zugreifen,_da_sie_von_einem_anderen_Prozess_verwendet_wird. Show_console_output_(only_necessary_when_the_launcher_is_used)=Anzeigen_der_Konsolen-Ausgabe_(Nur_notwendig_wenn_der_Launcher_benutzt_wird) From 93f72b24d67d60cfcc86e0c26c18762673853120 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 19 Oct 2017 18:14:42 +0200 Subject: [PATCH 13/28] fix checkstyle and make cancel button close button remove sys out --- src/main/java/org/jabref/gui/FXDialogService.java | 2 +- .../org/jabref/gui/actions/ExportLinkedFilesAction.java | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/gui/FXDialogService.java b/src/main/java/org/jabref/gui/FXDialogService.java index 6cd7cbf3fbf..d7542b58fe8 100644 --- a/src/main/java/org/jabref/gui/FXDialogService.java +++ b/src/main/java/org/jabref/gui/FXDialogService.java @@ -7,8 +7,8 @@ import java.util.Optional; import java.util.stream.Collectors; -import javafx.scene.control.Alert.AlertType; import javafx.concurrent.Service; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index 4ffd39ac48a..b4c61d21e89 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -67,11 +67,7 @@ public void actionPerformed(ActionEvent e) { private void startServiceAndshowProgessDialog(Service> exportService) { DefaultTaskExecutor.runInJavaFXThread(() -> { exportService.setOnSucceeded(value -> { - System.out.println(exportService.getValue()); - - System.out.println("Service succeeded"); DefaultTaskExecutor.runInJavaFXThread(() -> showDialog(exportService.getValue())); - }); exportService.start(); DialogService dlgService = new FXDialogService(); @@ -82,7 +78,7 @@ private void startServiceAndshowProgessDialog(Service> exp private void showDialog(List data) { Dialog dlg = new Dialog<>(); - dlg.setTitle("Results"); + dlg.setTitle(Localization.lang("Result")); ObservableList tableData = FXCollections.observableArrayList(data); TableView tv = createTable(); @@ -95,7 +91,7 @@ private void showDialog(List data) { sp.setFitToHeight(true); sp.setFitToWidth(true); - dlg.getDialogPane().getButtonTypes().add(ButtonType.CANCEL); + dlg.getDialogPane().getButtonTypes().add(ButtonType.CLOSE); dlg.setResizable(true); dlg.showAndWait(); } From 353e9ad4e57b7ad302a20b6661d4f692f094c38b Mon Sep 17 00:00:00 2001 From: siedlerchr Date: Fri, 20 Oct 2017 11:20:42 +0200 Subject: [PATCH 14/28] fix codacy --- .../java/org/jabref/gui/actions/ExportLinkedFilesAction.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index b4c61d21e89..7ba8b20d266 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -37,9 +37,7 @@ public class ExportLinkedFilesAction extends AbstractAction { private final DialogService ds = new FXDialogService(); - private long totalFilesCount; private BibDatabaseContext databaseContext; - private Optional exportPath = Optional.empty(); private List entries; public ExportLinkedFilesAction() { @@ -53,7 +51,8 @@ public void actionPerformed(ActionEvent e) { .withInitialDirectory(Paths.get(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY))) .build(); entries = JabRefGUI.getMainFrame().getCurrentBasePanel().getSelectedEntries(); - exportPath = DefaultTaskExecutor + + Optional exportPath = DefaultTaskExecutor .runInJavaFXThread(() -> ds.showDirectorySelectionDialog(dirDialogConfiguration)); exportPath.ifPresent(path -> { From aa1073137d827d0794c2fec98817cff49de9ec39 Mon Sep 17 00:00:00 2001 From: siedlerchr Date: Fri, 20 Oct 2017 11:38:27 +0200 Subject: [PATCH 15/28] Renamings --- ...ult.java => CopyFilesResultViewModel.java} | 6 ++-- .../gui/actions/ExportLinkedFilesAction.java | 34 +++++++++---------- .../gui/actions/ExportLinkedFilesService.java | 12 +++---- 3 files changed, 26 insertions(+), 26 deletions(-) rename src/main/java/org/jabref/gui/actions/{CopyFilesResult.java => CopyFilesResultViewModel.java} (83%) diff --git a/src/main/java/org/jabref/gui/actions/CopyFilesResult.java b/src/main/java/org/jabref/gui/actions/CopyFilesResultViewModel.java similarity index 83% rename from src/main/java/org/jabref/gui/actions/CopyFilesResult.java rename to src/main/java/org/jabref/gui/actions/CopyFilesResultViewModel.java index 88d618e528d..583948a41f5 100644 --- a/src/main/java/org/jabref/gui/actions/CopyFilesResult.java +++ b/src/main/java/org/jabref/gui/actions/CopyFilesResultViewModel.java @@ -7,14 +7,14 @@ import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; -public class CopyFilesResult { +public class CopyFilesResultViewModel { private final StringProperty file = new SimpleStringProperty(""); private final ObjectProperty icon = new SimpleObjectProperty<>(MaterialDesignIcon.ALERT); private final StringProperty message = new SimpleStringProperty(""); - public CopyFilesResult(String file, boolean success, String message) { + public CopyFilesResultViewModel(String file, boolean success, String message) { this.file.setValue(file); this.message.setValue(message); if (success) { @@ -45,6 +45,6 @@ public ObjectProperty getIcon() { @Override public String toString() { - return "CopyFilesResult [file=" + file.get() + ", message=" + message.get() + "]"; + return "CopyFilesResultViewModel [file=" + file.get() + ", message=" + message.get() + "]"; } } diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index 7ba8b20d266..c0e41cbc1b5 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -36,7 +36,7 @@ public class ExportLinkedFilesAction extends AbstractAction { - private final DialogService ds = new FXDialogService(); + private final DialogService dialogService = new FXDialogService(); private BibDatabaseContext databaseContext; private List entries; @@ -53,17 +53,17 @@ public void actionPerformed(ActionEvent e) { entries = JabRefGUI.getMainFrame().getCurrentBasePanel().getSelectedEntries(); Optional exportPath = DefaultTaskExecutor - .runInJavaFXThread(() -> ds.showDirectorySelectionDialog(dirDialogConfiguration)); + .runInJavaFXThread(() -> dialogService.showDirectorySelectionDialog(dirDialogConfiguration)); exportPath.ifPresent(path -> { databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext(); - Service> exportService = new ExportLinkedFilesService(databaseContext, entries, path); + Service> exportService = new ExportLinkedFilesService(databaseContext, entries, path); startServiceAndshowProgessDialog(exportService); }); } - private void startServiceAndshowProgessDialog(Service> exportService) { + private void startServiceAndshowProgessDialog(Service> exportService) { DefaultTaskExecutor.runInJavaFXThread(() -> { exportService.setOnSucceeded(value -> { DefaultTaskExecutor.runInJavaFXThread(() -> showDialog(exportService.getValue())); @@ -75,12 +75,12 @@ private void startServiceAndshowProgessDialog(Service> exp }); } - private void showDialog(List data) { + private void showDialog(List data) { Dialog dlg = new Dialog<>(); dlg.setTitle(Localization.lang("Result")); - ObservableList tableData = FXCollections.observableArrayList(data); + ObservableList tableData = FXCollections.observableArrayList(data); - TableView tv = createTable(); + TableView tv = createTable(); ScrollPane sp = new ScrollPane(); sp.setContent(tv); @@ -95,19 +95,19 @@ private void showDialog(List data) { dlg.showAndWait(); } - private static TableView createTable() { - TableView tv = new TableView<>(); + private static TableView createTable() { + TableView tableResult = new TableView<>(); - TableColumn colFile = new TableColumn<>(Localization.lang("File")); - TableColumn colIcon = new TableColumn<>(Localization.lang("Status")); - TableColumn colMessage = new TableColumn<>(Localization.lang("Message")); + TableColumn colFile = new TableColumn<>(Localization.lang("File")); + TableColumn colIcon = new TableColumn<>(Localization.lang("Status")); + TableColumn colMessage = new TableColumn<>(Localization.lang("Message")); colFile.setCellValueFactory(cellData -> cellData.getValue().getFile()); colMessage.setCellValueFactory(cellData -> cellData.getValue().getMessage()); colIcon.setCellValueFactory(cellData -> cellData.getValue().getIcon()); colIcon.setCellFactory(column -> { - return new TableCell() { + return new TableCell() { @Override protected void updateItem(MaterialDesignIcon item, boolean empty) { @@ -133,11 +133,11 @@ protected void updateItem(MaterialDesignIcon item, boolean empty) { } }; }); - tv.getColumns().add(colIcon); - tv.getColumns().add(colMessage); - tv.getColumns().add(colFile); + tableResult.getColumns().add(colIcon); + tableResult.getColumns().add(colMessage); + tableResult.getColumns().add(colFile); - return tv; + return tableResult; } } \ No newline at end of file diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java index 0c4aabb1223..bc3a496dd94 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java @@ -25,7 +25,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -public class ExportLinkedFilesService extends Service> { +public class ExportLinkedFilesService extends Service> { private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class); private static final String LOGFILE = "exportLog.log"; @@ -35,7 +35,7 @@ public class ExportLinkedFilesService extends Service> { private final BibDatabaseContext databaseContext; private final List entries; private final Path exportPath; - private final List results = new ArrayList<>(); + private final List results = new ArrayList<>(); private final BiFunction resolvePathFilename = (path, file) -> { return path.resolve(file.getFileName()); @@ -50,8 +50,8 @@ public ExportLinkedFilesService(BibDatabaseContext databaseContext, List> createTask() { - return new Task>() { + protected Task> createTask() { + return new Task>() { int totalFilesCounter; int numberSucessful; @@ -59,7 +59,7 @@ protected Task> createTask() { Optional newPath; @Override - protected List call() + protected List call() throws InterruptedException, IOException { updateMessage(Localization.lang("Copying files...")); updateProgress(0, totalFilesCount); @@ -118,7 +118,7 @@ private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) } private void addResultToList(Path newFile, boolean success, String logMessage) { - CopyFilesResult result = new CopyFilesResult(newFile.toString(), success, logMessage); + CopyFilesResultViewModel result = new CopyFilesResultViewModel(newFile.toString(), success, logMessage); results.add(result); } From 9e6cffc3c80a70238693a7452c9df5007e269b9d Mon Sep 17 00:00:00 2001 From: siedlerchr Date: Fri, 20 Oct 2017 14:05:42 +0200 Subject: [PATCH 16/28] Remove setter Use Task instead of Service Use CellValueFactory --- .../java/org/jabref/gui/DialogService.java | 6 +- .../java/org/jabref/gui/FXDialogService.java | 10 +- ...java => CopyFilesResultItemViewModel.java} | 19 +-- .../gui/actions/ExportLinkedFilesAction.java | 70 ++++------ .../gui/actions/ExportLinkedFilesService.java | 125 ------------------ .../gui/actions/ExportLinkedFilesTask.java | 118 +++++++++++++++++ 6 files changed, 159 insertions(+), 189 deletions(-) rename src/main/java/org/jabref/gui/actions/{CopyFilesResultViewModel.java => CopyFilesResultItemViewModel.java} (69%) delete mode 100644 src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java create mode 100644 src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java index 1bf7fee4e22..482ca23243e 100644 --- a/src/main/java/org/jabref/gui/DialogService.java +++ b/src/main/java/org/jabref/gui/DialogService.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.Optional; -import javafx.concurrent.Service; +import javafx.concurrent.Task; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.DialogPane; @@ -126,9 +126,9 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String /** * Constructs and shows a canceable {@link ProgressDialog}. Clicking cancel will cancel the underlying service and close the dialog - * @param service The {@link Service} which executes the work and for which to show the dialog + * @param task The {@link Task} which executes the work and for which to show the dialog */ - void showCanceableProgressDialogAndWait(Service service); + void showCanceableProgressDialogAndWait(Task task); /** * Notify the user in an non-blocking way (i.e., update status message instead of showing a dialog). diff --git a/src/main/java/org/jabref/gui/FXDialogService.java b/src/main/java/org/jabref/gui/FXDialogService.java index d7542b58fe8..3beb1c4b416 100644 --- a/src/main/java/org/jabref/gui/FXDialogService.java +++ b/src/main/java/org/jabref/gui/FXDialogService.java @@ -7,7 +7,7 @@ import java.util.Optional; import java.util.stream.Collectors; -import javafx.concurrent.Service; +import javafx.concurrent.Task; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; import javafx.scene.control.ButtonBar; @@ -131,14 +131,14 @@ public Optional showCustomDialogAndWait(Dialog dialog) { } @Override - public void showCanceableProgressDialogAndWait(Service service) { - ProgressDialog progressDialog = new ProgressDialog(service); - progressDialog.setOnCloseRequest(evt -> service.cancel()); + public void showCanceableProgressDialogAndWait(Task 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 -> { - service.cancel(); + task.cancel(); progressDialog.close(); }); progressDialog.showAndWait(); diff --git a/src/main/java/org/jabref/gui/actions/CopyFilesResultViewModel.java b/src/main/java/org/jabref/gui/actions/CopyFilesResultItemViewModel.java similarity index 69% rename from src/main/java/org/jabref/gui/actions/CopyFilesResultViewModel.java rename to src/main/java/org/jabref/gui/actions/CopyFilesResultItemViewModel.java index 583948a41f5..95d59394e2e 100644 --- a/src/main/java/org/jabref/gui/actions/CopyFilesResultViewModel.java +++ b/src/main/java/org/jabref/gui/actions/CopyFilesResultItemViewModel.java @@ -1,5 +1,7 @@ package org.jabref.gui.actions; +import java.nio.file.Path; + import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; @@ -7,44 +9,35 @@ import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; -public class CopyFilesResultViewModel { +public class CopyFilesResultItemViewModel { private final StringProperty file = new SimpleStringProperty(""); private final ObjectProperty icon = new SimpleObjectProperty<>(MaterialDesignIcon.ALERT); private final StringProperty message = new SimpleStringProperty(""); - public CopyFilesResultViewModel(String file, boolean success, String message) { - this.file.setValue(file); + 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 void setFile(String file) { - this.file.setValue(file); - } - public StringProperty getMessage() { return message; } - public void setMessage(String message) { - this.message.setValue(message); - } - public ObjectProperty getIcon() { return icon; } @Override public String toString() { - return "CopyFilesResultViewModel [file=" + file.get() + ", message=" + message.get() + "]"; + return "CopyFilesResultItemViewModel [file=" + file.get() + ", message=" + message.get() + "]"; } } diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java index c0e41cbc1b5..25406a3cb29 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java @@ -10,11 +10,10 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.concurrent.Service; +import javafx.concurrent.Task; import javafx.scene.control.ButtonType; import javafx.scene.control.Dialog; import javafx.scene.control.ScrollPane; -import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.paint.Color; @@ -26,6 +25,7 @@ import org.jabref.gui.FXDialogService; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.DirectoryDialogConfiguration; +import org.jabref.gui.util.ValueTableCellFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -58,29 +58,28 @@ public void actionPerformed(ActionEvent e) { exportPath.ifPresent(path -> { databaseContext = JabRefGUI.getMainFrame().getCurrentBasePanel().getDatabaseContext(); - Service> exportService = new ExportLinkedFilesService(databaseContext, entries, path); - startServiceAndshowProgessDialog(exportService); + Task> exportTask = new ExportLinkedFilesTask(databaseContext, entries, path); + startServiceAndshowProgessDialog(exportTask); }); } - private void startServiceAndshowProgessDialog(Service> exportService) { + private void startServiceAndshowProgessDialog(Task> exportService) { DefaultTaskExecutor.runInJavaFXThread(() -> { exportService.setOnSucceeded(value -> { DefaultTaskExecutor.runInJavaFXThread(() -> showDialog(exportService.getValue())); }); - exportService.start(); - DialogService dlgService = new FXDialogService(); - dlgService.showCanceableProgressDialogAndWait(exportService); + exportService.run(); + dialogService.showCanceableProgressDialogAndWait(exportService); }); } - private void showDialog(List data) { + private void showDialog(List data) { Dialog dlg = new Dialog<>(); dlg.setTitle(Localization.lang("Result")); - ObservableList tableData = FXCollections.observableArrayList(data); + ObservableList tableData = FXCollections.observableArrayList(data); - TableView tv = createTable(); + TableView tv = createTable(); ScrollPane sp = new ScrollPane(); sp.setContent(tv); @@ -95,44 +94,29 @@ private void showDialog(List data) { dlg.showAndWait(); } - private static TableView createTable() { - TableView tableResult = new TableView<>(); + private static TableView createTable() { + TableView tableResult = new TableView<>(); - TableColumn colFile = new TableColumn<>(Localization.lang("File")); - TableColumn colIcon = new TableColumn<>(Localization.lang("Status")); - TableColumn colMessage = new TableColumn<>(Localization.lang("Message")); + TableColumn colFile = new TableColumn<>(Localization.lang("File")); + TableColumn colIcon = new TableColumn<>(Localization.lang("Status")); + TableColumn colMessage = new TableColumn<>(Localization.lang("Message")); colFile.setCellValueFactory(cellData -> cellData.getValue().getFile()); colMessage.setCellValueFactory(cellData -> cellData.getValue().getMessage()); colIcon.setCellValueFactory(cellData -> cellData.getValue().getIcon()); - colIcon.setCellFactory(column -> { - return new TableCell() { - - @Override - protected void updateItem(MaterialDesignIcon item, boolean empty) { - super.updateItem(item, empty); - - if ((item == null) || empty) { - setText(null); - setStyle(""); - } else { - Text icon = MaterialDesignIconFactory.get().createIcon(item); - - //Green checkmark - if (item == MaterialDesignIcon.CHECK) { - icon.setFill(Color.GREEN); - } - //Red Alert symbol - if (item == MaterialDesignIcon.ALERT) { - icon.setFill(Color.RED); - } - setGraphic(icon); - - } - } - }; - }); + colIcon.setCellFactory(new ValueTableCellFactory().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; + })); + tableResult.getColumns().add(colIcon); tableResult.getColumns().add(colMessage); tableResult.getColumns().add(colFile); diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java deleted file mode 100644 index bc3a496dd94..00000000000 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesService.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.jabref.gui.actions; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.BiFunction; - -import javafx.concurrent.Service; -import javafx.concurrent.Task; - -import org.jabref.Globals; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.util.OS; -import org.jabref.logic.util.io.FileUtil; -import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.LinkedFile; -import org.jabref.model.util.OptionalUtil; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class ExportLinkedFilesService extends Service> { - - private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class); - private static final String LOGFILE = "exportLog.log"; - private final String localizedSucessMessage = Localization.lang("Copied file successfully"); - private final String localizedErrorMessage = Localization.lang("Could not copy file") + ": " + Localization.lang("File exists"); - private final long totalFilesCount; - private final BibDatabaseContext databaseContext; - private final List entries; - private final Path exportPath; - private final List results = new ArrayList<>(); - - private final BiFunction resolvePathFilename = (path, file) -> { - return path.resolve(file.getFileName()); - }; - - public ExportLinkedFilesService(BibDatabaseContext databaseContext, List entries, Path path) { - this.databaseContext = databaseContext; - this.entries = entries; - this.exportPath = path; - totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count(); - - } - - @Override - protected Task> createTask() { - return new Task>() { - - int totalFilesCounter; - int numberSucessful; - int numberError; - Optional newPath; - - @Override - protected List call() - throws InterruptedException, IOException { - updateMessage(Localization.lang("Copying files...")); - updateProgress(0, totalFilesCount); - - try (BufferedWriter bw = Files.newBufferedWriter(exportPath.resolve(LOGFILE), StandardCharsets.UTF_8)) { - - for (int i = 0; i < entries.size(); i++) { - - List files = entries.get(i).getFiles(); - - for (int j = 0; j < files.size(); j++) { - updateMessage(Localization.lang("Copying file %0 of entry %1", Integer.toString(j + 1), Integer.toString(i + 1))); - - LinkedFile fileName = files.get(j); - - Optional fileToExport = fileName.findIn(databaseContext, Globals.prefs.getFileDirectoryPreferences()); - - newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename); - - newPath.ifPresent(newFile -> { - boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); - updateProgress(totalFilesCounter++, totalFilesCount); - if (success) { - updateMessage(localizedSucessMessage); - numberSucessful++; - writeLogMessage(newFile, bw, localizedSucessMessage); - addResultToList(newFile, success, localizedSucessMessage); - - } else { - - updateMessage(localizedErrorMessage); - numberError++; - writeLogMessage(newFile, bw, localizedErrorMessage); - addResultToList(newFile, success, localizedErrorMessage); - } - }); - } - } - updateMessage(Localization.lang("Finished copying")); - String sucessMessage = Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse("")); - updateMessage(sucessMessage); - bw.write(sucessMessage); - return results; - } - } - }; - } - - private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) { - try { - bw.write(logMessage + ": " + newFile); - bw.write(OS.NEWLINE); - } catch (IOException e) { - LOGGER.error("error writing log file", e); - } - } - - private void addResultToList(Path newFile, boolean success, String logMessage) { - CopyFilesResultViewModel result = new CopyFilesResultViewModel(newFile.toString(), success, logMessage); - results.add(result); - } - -} diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java new file mode 100644 index 00000000000..231983cb451 --- /dev/null +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java @@ -0,0 +1,118 @@ +package org.jabref.gui.actions; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; + +import javafx.concurrent.Task; + +import org.jabref.Globals; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.OS; +import org.jabref.logic.util.io.FileUtil; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.LinkedFile; +import org.jabref.model.util.OptionalUtil; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ExportLinkedFilesTask extends Task> { + + private static final Log LOGGER = LogFactory.getLog(ExportLinkedFilesAction.class); + private static final String LOGFILE = "exportLog.log"; + private final String localizedSucessMessage = Localization.lang("Copied file successfully"); + private final String localizedErrorMessage = Localization.lang("Could not copy file") + ": " + Localization.lang("File exists"); + private final long totalFilesCount; + private final BibDatabaseContext databaseContext; + private final List entries; + private final Path exportPath; + private final List results = new ArrayList<>(); + + private final BiFunction resolvePathFilename = (path, file) -> { + return path.resolve(file.getFileName()); + }; + + public ExportLinkedFilesTask(BibDatabaseContext databaseContext, List entries, Path path) { + this.databaseContext = databaseContext; + this.entries = entries; + this.exportPath = path; + totalFilesCount = entries.stream().flatMap(entry -> entry.getFiles().stream()).count(); + + } + + int totalFilesCounter; + int numberSucessful; + int numberError; + Optional newPath; + + @Override + protected List call() + throws InterruptedException, IOException { + updateMessage(Localization.lang("Copying files...")); + updateProgress(0, totalFilesCount); + + try (BufferedWriter bw = Files.newBufferedWriter(exportPath.resolve(LOGFILE), StandardCharsets.UTF_8)) { + + for (int i = 0; i < entries.size(); i++) { + + List files = entries.get(i).getFiles(); + + for (int j = 0; j < files.size(); j++) { + updateMessage(Localization.lang("Copying file %0 of entry %1", Integer.toString(j + 1), Integer.toString(i + 1))); + + LinkedFile fileName = files.get(j); + + Optional fileToExport = fileName.findIn(databaseContext, Globals.prefs.getFileDirectoryPreferences()); + + newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename); + + newPath.ifPresent(newFile -> { + boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); + updateProgress(totalFilesCounter++, totalFilesCount); + if (success) { + updateMessage(localizedSucessMessage); + numberSucessful++; + writeLogMessage(newFile, bw, localizedSucessMessage); + addResultToList(newFile, success, localizedSucessMessage); + + } else { + + updateMessage(localizedErrorMessage); + numberError++; + writeLogMessage(newFile, bw, localizedErrorMessage); + addResultToList(newFile, success, localizedErrorMessage); + } + }); + } + } + updateMessage(Localization.lang("Finished copying")); + String sucessMessage = Localization.lang("Copied %0 files of %1 sucessfully to %2", Integer.toString(numberSucessful), Integer.toString(totalFilesCounter), newPath.map(Path::getParent).map(Path::toString).orElse("")); + updateMessage(sucessMessage); + bw.write(sucessMessage); + return results; + } + } + + private void writeLogMessage(Path newFile, BufferedWriter bw, String logMessage) { + try { + bw.write(logMessage + ": " + newFile); + bw.write(OS.NEWLINE); + } catch (IOException e) { + LOGGER.error("error writing log file", e); + } + } + + private void addResultToList(Path newFile, boolean success, String logMessage) { + CopyFilesResultItemViewModel result = new CopyFilesResultItemViewModel(newFile, success, logMessage); + results.add(result); + } + +} From b61082ccf5a3adeb59ab8e7893ce48c90240f9ed Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Fri, 20 Oct 2017 18:12:42 +0200 Subject: [PATCH 17/28] Add fxml and move to package --- src/main/java/org/jabref/gui/JabRefFrame.java | 2 +- .../gui/actions/ExportLinkedFilesTask.java | 2 ++ .../copyfiles/CopyFilesDialogController.java | 30 +++++++++++++++++++ .../gui/copyfiles/CopyFilesDialogView.java | 20 +++++++++++++ .../copyfiles/CopyFilesDialogViewModel.java | 28 +++++++++++++++++ .../CopyFilesResultItemViewModel.java | 2 +- .../ExportLinkedFilesAction.java | 3 +- .../org/jabref/gui/menus/RightClickMenu.java | 2 +- .../gui/copyfiles/CopyResultsDialog.fxml | 30 +++++++++++++++++++ .../CopyResultsDialogController.java | 26 ++++++++++++++++ 10 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogController.java create mode 100644 src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java create mode 100644 src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogViewModel.java rename src/main/java/org/jabref/gui/{actions => copyfiles}/CopyFilesResultItemViewModel.java (97%) rename src/main/java/org/jabref/gui/{actions => copyfiles}/ExportLinkedFilesAction.java (98%) create mode 100644 src/main/resources/org/jabref/gui/copyfiles/CopyResultsDialog.fxml create mode 100644 src/main/resources/org/jabref/gui/copyfiles/CopyResultsDialogController.java diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index f0cf505d794..4a2de382443 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -67,7 +67,6 @@ import org.jabref.gui.actions.AutoLinkFilesAction; import org.jabref.gui.actions.ConnectToSharedDatabaseAction; import org.jabref.gui.actions.ErrorConsoleAction; -import org.jabref.gui.actions.ExportLinkedFilesAction; import org.jabref.gui.actions.IntegrityCheckAction; import org.jabref.gui.actions.LookupIdentifierAction; import org.jabref.gui.actions.ManageKeywordsAction; @@ -81,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.ExportLinkedFilesAction; import org.jabref.gui.customentrytypes.EntryCustomizationDialog; import org.jabref.gui.dbproperties.DatabasePropertiesDialog; import org.jabref.gui.documentviewer.ShowDocumentViewerAction; diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java index 231983cb451..da85b83b0b6 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java +++ b/src/main/java/org/jabref/gui/actions/ExportLinkedFilesTask.java @@ -13,6 +13,8 @@ import javafx.concurrent.Task; import org.jabref.Globals; +import org.jabref.gui.copyfiles.CopyFilesResultItemViewModel; +import org.jabref.gui.copyfiles.ExportLinkedFilesAction; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; import org.jabref.logic.util.io.FileUtil; diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogController.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogController.java new file mode 100644 index 00000000000..771c4e93d40 --- /dev/null +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogController.java @@ -0,0 +1,30 @@ +package org.jabref.gui.copyfiles; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; + +import org.jabref.gui.AbstractController; +import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; + +public class CopyFilesDialogController extends AbstractController { + + @FXML private TableView tvResult; + + @FXML private TableColumn colStatus; + + @FXML private TableColumn colMessage; + + @FXML private TableColumn colFile; + + @FXML + void close(ActionEvent event) { + getStage().close(); + } + + @FXML + private void initialize() { + viewModel = new CopyFilesDialogViewModel(); + } +} diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java new file mode 100644 index 00000000000..a475ee6b80c --- /dev/null +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java @@ -0,0 +1,20 @@ +package org.jabref.gui.copyfiles; + +import javafx.scene.control.DialogPane; +import javafx.scene.control.Alert.AlertType; + +import org.jabref.gui.AbstractDialogView; +import org.jabref.gui.FXDialog; +import org.jabref.logic.l10n.Localization; + +public class CopyFilesDialogView extends AbstractDialogView { + + @Override + public void show() { + FXDialog copyFilesResultDlg = new FXDialog(AlertType.INFORMATION, Localization.lang("Result")); + copyFilesResultDlg.setResizable(true); + copyFilesResultDlg.setDialogPane((DialogPane) this.getView()); + copyFilesResultDlg.show(); + } + +} diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogViewModel.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogViewModel.java new file mode 100644 index 00000000000..f5832278bc6 --- /dev/null +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogViewModel.java @@ -0,0 +1,28 @@ +package org.jabref.gui.copyfiles; + +import java.util.List; + +import javafx.beans.property.SimpleListProperty; +import javafx.collections.FXCollections; + +import org.jabref.gui.AbstractViewModel; + +public class CopyFilesDialogViewModel extends AbstractViewModel { + + private final SimpleListProperty copyFilesResultItems = new SimpleListProperty<>( + FXCollections.observableArrayList()); + + //TODO: How do I add the data here? + public CopyFilesDialogViewModel(List items) { + + this.copyFilesResultItems.addAll(items); + } + + public CopyFilesDialogViewModel() { + // TODO Auto-generated constructor stub + } + + public SimpleListProperty abbreviationsProperty() { + return this.copyFilesResultItems; + } +} diff --git a/src/main/java/org/jabref/gui/actions/CopyFilesResultItemViewModel.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesResultItemViewModel.java similarity index 97% rename from src/main/java/org/jabref/gui/actions/CopyFilesResultItemViewModel.java rename to src/main/java/org/jabref/gui/copyfiles/CopyFilesResultItemViewModel.java index 95d59394e2e..5d95d5c993c 100644 --- a/src/main/java/org/jabref/gui/actions/CopyFilesResultItemViewModel.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesResultItemViewModel.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.copyfiles; import java.nio.file.Path; diff --git a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java b/src/main/java/org/jabref/gui/copyfiles/ExportLinkedFilesAction.java similarity index 98% rename from src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java rename to src/main/java/org/jabref/gui/copyfiles/ExportLinkedFilesAction.java index 25406a3cb29..9a9eb7a873f 100644 --- a/src/main/java/org/jabref/gui/actions/ExportLinkedFilesAction.java +++ b/src/main/java/org/jabref/gui/copyfiles/ExportLinkedFilesAction.java @@ -1,4 +1,4 @@ -package org.jabref.gui.actions; +package org.jabref.gui.copyfiles; import java.awt.event.ActionEvent; import java.nio.file.Path; @@ -23,6 +23,7 @@ import org.jabref.JabRefGUI; import org.jabref.gui.DialogService; import org.jabref.gui.FXDialogService; +import org.jabref.gui.actions.ExportLinkedFilesTask; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.ValueTableCellFactory; diff --git a/src/main/java/org/jabref/gui/menus/RightClickMenu.java b/src/main/java/org/jabref/gui/menus/RightClickMenu.java index 6c784b77df0..e303edf5d27 100644 --- a/src/main/java/org/jabref/gui/menus/RightClickMenu.java +++ b/src/main/java/org/jabref/gui/menus/RightClickMenu.java @@ -22,7 +22,7 @@ import org.jabref.gui.IconTheme; import org.jabref.gui.JabRefFrame; import org.jabref.gui.actions.Actions; -import org.jabref.gui.actions.ExportLinkedFilesAction; +import org.jabref.gui.copyfiles.ExportLinkedFilesAction; import org.jabref.gui.filelist.FileListTableModel; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.mergeentries.FetchAndMergeEntry; diff --git a/src/main/resources/org/jabref/gui/copyfiles/CopyResultsDialog.fxml b/src/main/resources/org/jabref/gui/copyfiles/CopyResultsDialog.fxml new file mode 100644 index 00000000000..5da81948942 --- /dev/null +++ b/src/main/resources/org/jabref/gui/copyfiles/CopyResultsDialog.fxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + +