From 4b173714784faacd23083df44b5874754a3a2097 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Thu, 20 Jun 2019 13:27:56 +0200 Subject: [PATCH 1/4] Add copy linked files action to contextmneu in general tab --- .../jabref/gui/fieldeditors/LinkedFilesEditor.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java index 6a2a134042f..f53245a4a60 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java @@ -2,6 +2,8 @@ import java.util.Optional; +import javax.inject.Inject; + import javafx.beans.binding.Bindings; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -28,7 +30,9 @@ import org.jabref.Globals; import org.jabref.gui.DialogService; import org.jabref.gui.DragAndDropDataFormats; +import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.AutoCompleteSuggestionProvider; +import org.jabref.gui.copyfiles.CopyFilesAction; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.ViewModelListCellFactory; @@ -48,10 +52,14 @@ public class LinkedFilesEditor extends HBox implements FieldEditorFX { @FXML private final LinkedFilesEditorViewModel viewModel; @FXML private ListView listView; + @Inject private StateManager stateManager; + private final DialogService dialogService; + public LinkedFilesEditor(String fieldName, DialogService dialogService, BibDatabaseContext databaseContext, TaskExecutor taskExecutor, AutoCompleteSuggestionProvider suggestionProvider, FieldCheckers fieldCheckers, JabRefPreferences preferences) { this.viewModel = new LinkedFilesEditorViewModel(fieldName, suggestionProvider, dialogService, databaseContext, taskExecutor, fieldCheckers, preferences); + this.dialogService = dialogService; ViewLoader.view(this) .root(this) @@ -234,6 +242,10 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) { renameAndMoveFile.setOnAction(event -> linkedFile.moveToDefaultDirectoryAndRename()); renameAndMoveFile.setDisable(linkedFile.getFile().isOnlineLink() || linkedFile.isGeneratedPathSameAsOriginal()); + MenuItem copyLinkedFiles = new MenuItem(Localization.lang("Copy linked files to folder...")); + copyLinkedFiles.setOnAction(event->new CopyFilesAction(stateManager, dialogService).execute()); + copyLinkedFiles.setDisable(linkedFile.getFile().isOnlineLink()); + MenuItem deleteFile = new MenuItem(Localization.lang("Permanently delete local file")); deleteFile.setOnAction(event -> viewModel.deleteFile(linkedFile)); deleteFile.setDisable(linkedFile.getFile().isOnlineLink()); @@ -248,7 +260,7 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) { if (linkedFile.getFile().isOnlineLink()) { menu.getItems().add(download); } - menu.getItems().addAll(renameFile, renameFileName, moveFile, renameAndMoveFile, deleteLink, deleteFile); + menu.getItems().addAll(renameFile, renameFileName, moveFile, renameAndMoveFile, copyLinkedFiles, deleteLink, deleteFile); return menu; } From 6f20c85291ccc32ca0b321965b630fd9b8776252 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 22 Jun 2019 22:28:25 +0200 Subject: [PATCH 2/4] Add option to copy single file only Refactor preferences parameter Remove unsused parameter from dialog --- .../jabref/gui/copyfiles/CopyFilesAction.java | 6 +- .../gui/copyfiles/CopyFilesDialogView.java | 2 +- .../gui/copyfiles/CopySingleFileAction.java | 60 +++++++++++++++ .../gui/externalfiles/FindFullTextAction.java | 2 +- .../gui/fieldeditors/LinkedFileViewModel.java | 9 ++- .../gui/fieldeditors/LinkedFilesEditor.java | 28 ++++--- .../LinkedFilesEditorViewModel.java | 76 +++++++++---------- .../gui/maintable/MainTableColumnFactory.java | 4 +- .../jabref/preferences/JabRefPreferences.java | 2 + .../preferences/PreferencesService.java | 6 ++ src/main/resources/l10n/JabRef_en.properties | 5 ++ .../fieldeditors/LinkedFileViewModelTest.java | 18 ++--- 12 files changed, 144 insertions(+), 74 deletions(-) create mode 100644 src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java index 5235f164088..a425631f2bd 100644 --- a/src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java @@ -32,12 +32,12 @@ public CopyFilesAction(StateManager stateManager, DialogService dialogService) { this.executable.bind(needsDatabase(this.stateManager).and(needsEntriesSelected(stateManager))); } - private void showDialog(List data, BibDatabaseContext database) { + private void showDialog(List data) { if (data.isEmpty()) { dialogService.showInformationDialogAndWait(Localization.lang("Copy linked files to folder..."), Localization.lang("No linked files found for export.")); return; } - CopyFilesDialogView dialog = new CopyFilesDialogView(database, new CopyFilesResultListDependency(data)); + CopyFilesDialogView dialog = new CopyFilesDialogView(new CopyFilesResultListDependency(data)); dialog.showAndWait(); } @@ -57,7 +57,7 @@ public void execute() { Localization.lang("Copy linked files to folder..."), exportTask); Globals.TASK_EXECUTOR.execute(exportTask); - exportTask.setOnSucceeded((e) -> showDialog(exportTask.getValue(), database)); + exportTask.setOnSucceeded((e) -> showDialog(exportTask.getValue())); }); } } diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java index eff25118bdb..891b029f4f0 100644 --- a/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java @@ -24,7 +24,7 @@ public class CopyFilesDialogView extends BaseDialog { @FXML private TableColumn colFile; private final CopyFilesDialogViewModel viewModel; - public CopyFilesDialogView(BibDatabaseContext bibDatabaseContext, CopyFilesResultListDependency results) { + public CopyFilesDialogView(CopyFilesResultListDependency results) { this.setTitle(Localization.lang("Result")); this.getDialogPane().getButtonTypes().addAll(ButtonType.OK); diff --git a/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java b/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java new file mode 100644 index 00000000000..e5dce5e5b70 --- /dev/null +++ b/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java @@ -0,0 +1,60 @@ +package org.jabref.gui.copyfiles; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.function.BiFunction; + +import org.jabref.Globals; +import org.jabref.gui.DialogService; +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.LinkedFile; +import org.jabref.model.util.OptionalUtil; +import org.jabref.preferences.JabRefPreferences; + +public class CopySingleFileAction { + + private LinkedFile linkedFile; + private DialogService dialogService; + private BibDatabaseContext databaseContext; + private final BiFunction resolvePathFilename = (path, file) -> { + return path.resolve(file.getFileName()); + }; + + public CopySingleFileAction(LinkedFile linkedFile, DialogService dialogService, BibDatabaseContext databaseContext) { + this.linkedFile = linkedFile; + this.dialogService = dialogService; + this.databaseContext = databaseContext; + } + + public void copyFile() { + DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder() + .withInitialDirectory(Paths.get(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY))) + .build(); + Optional exportPath = dialogService.showDirectorySelectionDialog(dirDialogConfiguration); + exportPath.ifPresent(this::copyFileToDestination); + + } + + private void copyFileToDestination(Path exportPath) { + Optional fileToExport = linkedFile.findIn(databaseContext, Globals.prefs.getFilePreferences()); + + Optional newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename); + + if (newPath.isPresent()) { + + Path newFile = newPath.get(); + boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); + if (success) { + dialogService.showInformationDialogAndWait(Localization.lang("Copy linked file"), Localization.lang("Sucessfully copied file to %0", newPath.map(Path::getParent).map(Path::toString).orElse(""))); + } + else { + dialogService.showErrorDialogAndWait(Localization.lang("Copy linked file"), Localization.lang("Could not copy file to %0, maybe the file is already existing?", newPath.map(Path::getParent).map(Path::toString).orElse(""))); + } + } + + } +} diff --git a/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java b/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java index d8ac847130e..f889c03f4c5 100644 --- a/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java +++ b/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java @@ -137,7 +137,7 @@ private void addLinkedFileFromURL(URL url, BibEntry entry, Path targetDirectory) basePanel.getBibDatabaseContext(), Globals.TASK_EXECUTOR, dialogService, - JabRefPreferences.getInstance(), ExternalFileTypes.getInstance()); + JabRefPreferences.getInstance().getXMPPreferences(),JabRefPreferences.getInstance().getFilePreferences(), ExternalFileTypes.getInstance()); try { URLDownload urlDownload = new URLDownload(newLinkedFile.getLink()); diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 847847f836e..5fa9d03aecd 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -73,19 +73,20 @@ public LinkedFileViewModel(LinkedFile linkedFile, BibDatabaseContext databaseContext, TaskExecutor taskExecutor, DialogService dialogService, - JabRefPreferences preferences, + XmpPreferences xmpPreferences, + FilePreferences filePreferences, ExternalFileTypes externalFileTypes) { this.linkedFile = linkedFile; - this.filePreferences = preferences.getFilePreferences(); + this.filePreferences = filePreferences; this.linkedFileHandler = new LinkedFileHandler(linkedFile, entry, databaseContext, filePreferences); this.databaseContext = databaseContext; this.entry = entry; this.dialogService = dialogService; this.taskExecutor = taskExecutor; this.externalFileTypes = externalFileTypes; - - xmpPreferences = preferences.getXMPPreferences(); + this.xmpPreferences = xmpPreferences; + downloadOngoing.bind(downloadProgress.greaterThanOrEqualTo(0).and(downloadProgress.lessThan(1))); canWriteXMPMetadata.setValue(!linkedFile.isOnlineLink() && linkedFile.getFileType().equalsIgnoreCase("pdf")); } diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java index f53245a4a60..4f7b83a00ab 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java @@ -2,8 +2,6 @@ import java.util.Optional; -import javax.inject.Inject; - import javafx.beans.binding.Bindings; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -30,9 +28,8 @@ import org.jabref.Globals; import org.jabref.gui.DialogService; import org.jabref.gui.DragAndDropDataFormats; -import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.AutoCompleteSuggestionProvider; -import org.jabref.gui.copyfiles.CopyFilesAction; +import org.jabref.gui.copyfiles.CopySingleFileAction; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.ViewModelListCellFactory; @@ -52,27 +49,28 @@ public class LinkedFilesEditor extends HBox implements FieldEditorFX { @FXML private final LinkedFilesEditorViewModel viewModel; @FXML private ListView listView; - @Inject private StateManager stateManager; private final DialogService dialogService; + private final BibDatabaseContext databaseContext; public LinkedFilesEditor(String fieldName, DialogService dialogService, BibDatabaseContext databaseContext, TaskExecutor taskExecutor, AutoCompleteSuggestionProvider suggestionProvider, FieldCheckers fieldCheckers, JabRefPreferences preferences) { + this.viewModel = new LinkedFilesEditorViewModel(fieldName, suggestionProvider, dialogService, databaseContext, taskExecutor, fieldCheckers, preferences); this.dialogService = dialogService; - + this.databaseContext = databaseContext; ViewLoader.view(this) .root(this) .load(); ViewModelListCellFactory cellFactory = new ViewModelListCellFactory() - .withTooltip(LinkedFileViewModel::getDescription) - .withGraphic(LinkedFilesEditor::createFileDisplay) - .withContextMenu(this::createContextMenuForFile) - .withOnMouseClickedEvent(this::handleItemMouseClick) - .setOnDragDetected(this::handleOnDragDetected) - .setOnDragDropped(this::handleOnDragDropped) - .setOnDragOver(this::handleOnDragOver); + .withTooltip(LinkedFileViewModel::getDescription) + .withGraphic(LinkedFilesEditor::createFileDisplay) + .withContextMenu(this::createContextMenuForFile) + .withOnMouseClickedEvent(this::handleItemMouseClick) + .setOnDragDetected(this::handleOnDragDetected) + .setOnDragDropped(this::handleOnDragDropped) + .setOnDragOver(this::handleOnDragOver); listView.setCellFactory(cellFactory); @@ -242,8 +240,8 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) { renameAndMoveFile.setOnAction(event -> linkedFile.moveToDefaultDirectoryAndRename()); renameAndMoveFile.setDisable(linkedFile.getFile().isOnlineLink() || linkedFile.isGeneratedPathSameAsOriginal()); - MenuItem copyLinkedFiles = new MenuItem(Localization.lang("Copy linked files to folder...")); - copyLinkedFiles.setOnAction(event->new CopyFilesAction(stateManager, dialogService).execute()); + MenuItem copyLinkedFiles = new MenuItem(Localization.lang("Copy linked file to folder...")); + copyLinkedFiles.setOnAction(event -> new CopySingleFileAction(linkedFile.getFile(), dialogService, databaseContext).copyFile()); copyLinkedFiles.setDisable(linkedFile.getFile().isOnlineLink()); MenuItem deleteFile = new MenuItem(Localization.lang("Permanently delete local file")); diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java index 6b55626202f..3a0cf3fbfb6 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditorViewModel.java @@ -4,7 +4,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -39,6 +38,7 @@ import org.jabref.model.entry.LinkedFile; import org.jabref.model.util.FileHelper; import org.jabref.preferences.JabRefPreferences; +import org.jabref.preferences.PreferencesService; public class LinkedFilesEditorViewModel extends AbstractEditorViewModel { @@ -47,7 +47,7 @@ public class LinkedFilesEditorViewModel extends AbstractEditorViewModel { private final DialogService dialogService; private final BibDatabaseContext databaseContext; private final TaskExecutor taskExecutor; - private final JabRefPreferences preferences; + private final PreferencesService preferences; private final ExternalFileTypes externalFileTypes = ExternalFileTypes.getInstance(); public LinkedFilesEditorViewModel(String fieldName, AutoCompleteSuggestionProvider suggestionProvider, @@ -56,7 +56,7 @@ public LinkedFilesEditorViewModel(String fieldName, AutoCompleteSuggestionProvid TaskExecutor taskExecutor, FieldCheckers fieldCheckers, JabRefPreferences preferences) { - + super(fieldName, suggestionProvider, fieldCheckers); this.dialogService = dialogService; @@ -65,18 +65,18 @@ public LinkedFilesEditorViewModel(String fieldName, AutoCompleteSuggestionProvid this.preferences = preferences; BindingsHelper.bindContentBidirectional( - files, - text, - LinkedFilesEditorViewModel::getStringRepresentation, - this::parseToFileViewModel); + files, + text, + LinkedFilesEditorViewModel::getStringRepresentation, + this::parseToFileViewModel); } private static String getStringRepresentation(List files) { // Only serialize linked files, not the ones that are automatically found List filesToSerialize = files.stream() - .filter(file -> !file.isAutomaticallyFound()) - .map(LinkedFileViewModel::getFile) - .collect(Collectors.toList()); + .filter(file -> !file.isAutomaticallyFound()) + .map(LinkedFileViewModel::getFile) + .collect(Collectors.toList()); return FileFieldWriter.getStringRepresentation(filesToSerialize); } @@ -90,8 +90,8 @@ private static String getStringRepresentation(List files) { public static LinkedFile fromFile(Path file, List fileDirectories, ExternalFileTypes externalFileTypesFile) { String fileExtension = FileHelper.getFileExtension(file).orElse(""); ExternalFileType suggestedFileType = externalFileTypesFile - .getExternalFileTypeByExt(fileExtension) - .orElse(new UnknownExternalFileType(fileExtension)); + .getExternalFileTypeByExt(fileExtension) + .orElse(new UnknownExternalFileType(fileExtension)); Path relativePath = FileUtil.relativize(file, fileDirectories); return new LinkedFile("", relativePath.toString(), suggestedFileType.getName()); } @@ -100,7 +100,7 @@ public LinkedFileViewModel fromFile(Path file) { List fileDirectories = databaseContext.getFileDirectoriesAsPaths(preferences.getFilePreferences()); LinkedFile linkedFile = fromFile(file, fileDirectories, externalFileTypes); - return new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileTypes); + return new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences.getXMPPreferences(), preferences.getFilePreferences(), externalFileTypes); } @@ -114,7 +114,7 @@ public BooleanProperty fulltextLookupInProgressProperty() { private List parseToFileViewModel(String stringValue) { return FileFieldParser.parse(stringValue).stream() - .map(linkedFile -> new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileTypes)) + .map(linkedFile -> new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences.getXMPPreferences(), preferences.getFilePreferences(), externalFileTypes)) .collect(Collectors.toList()); } @@ -128,17 +128,17 @@ public ListProperty filesProperty() { public void addNewFile() { Path workingDirectory = databaseContext.getFirstExistingFileDir(preferences.getFilePreferences()) - .orElse(Paths.get(preferences.get(JabRefPreferences.WORKING_DIRECTORY))); + .orElse(preferences.getWorkingDir()); FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() - .withInitialDirectory(workingDirectory) - .build(); + .withInitialDirectory(workingDirectory) + .build(); List fileDirectories = databaseContext.getFileDirectoriesAsPaths(preferences.getFilePreferences()); dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(newFile -> { - LinkedFile newLinkedFile = fromFile(newFile, fileDirectories, externalFileTypes); - files.add(new LinkedFileViewModel(newLinkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileTypes)); - }); + LinkedFile newLinkedFile = fromFile(newFile, fileDirectories, externalFileTypes); + files.add(new LinkedFileViewModel(newLinkedFile, entry, databaseContext, taskExecutor, dialogService, preferences.getXMPPreferences(), preferences.getFilePreferences(), externalFileTypes)); + }); } @Override @@ -147,8 +147,8 @@ public void bindToEntry(BibEntry entry) { if (entry != null) { BackgroundTask> findAssociatedNotLinkedFiles = BackgroundTask - .wrap(() -> findAssociatedNotLinkedFiles(entry)) - .onSuccess(files::addAll); + .wrap(() -> findAssociatedNotLinkedFiles(entry)) + .onSuccess(files::addAll); taskExecutor.execute(findAssociatedNotLinkedFiles); } } @@ -163,7 +163,7 @@ private List findAssociatedNotLinkedFiles(BibEntry entry) { try { List linkedFiles = util.findAssociatedNotLinkedFiles(entry); for (LinkedFile linkedFile : linkedFiles) { - LinkedFileViewModel newLinkedFile = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileTypes); + LinkedFileViewModel newLinkedFile = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences.getXMPPreferences(), preferences.getFilePreferences(), externalFileTypes); newLinkedFile.markAsAutomaticallyFound(); result.add(newLinkedFile); } @@ -177,36 +177,36 @@ private List findAssociatedNotLinkedFiles(BibEntry entry) { public void fetchFulltext() { FulltextFetchers fetcher = new FulltextFetchers(preferences.getImportFormatPreferences()); BackgroundTask - .wrap(() -> fetcher.findFullTextPDF(entry)) - .onRunning(() -> fulltextLookupInProgress.setValue(true)) - .onFinished(() -> fulltextLookupInProgress.setValue(false)) - .onSuccess(url -> { - if (url.isPresent()) { - addFromURL(url.get()); - } else { - dialogService.notify(Localization.lang("No full text document found")); - } - }) - .executeWith(taskExecutor); + .wrap(() -> fetcher.findFullTextPDF(entry)) + .onRunning(() -> fulltextLookupInProgress.setValue(true)) + .onFinished(() -> fulltextLookupInProgress.setValue(false)) + .onSuccess(url -> { + if (url.isPresent()) { + addFromURL(url.get()); + } else { + dialogService.notify(Localization.lang("No full text document found")); + } + }) + .executeWith(taskExecutor); } public void addFromURL() { Optional urlText = dialogService.showInputDialogAndWait( - Localization.lang("Download file"), Localization.lang("Enter URL to download")); + Localization.lang("Download file"), Localization.lang("Enter URL to download")); if (urlText.isPresent()) { try { URL url = new URL(urlText.get()); addFromURL(url); } catch (MalformedURLException exception) { dialogService.showErrorDialogAndWait( - Localization.lang("Invalid URL"), - exception); + Localization.lang("Invalid URL"), + exception); } } } private void addFromURL(URL url) { - LinkedFileViewModel onlineFile = new LinkedFileViewModel(new LinkedFile(url, ""), entry, databaseContext, taskExecutor, dialogService, preferences, externalFileTypes); + LinkedFileViewModel onlineFile = new LinkedFileViewModel(new LinkedFile(url, ""), entry, databaseContext, taskExecutor, dialogService, preferences.getXMPPreferences(), preferences.getFilePreferences(), externalFileTypes); files.add(onlineFile); onlineFile.download(); } diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index 28ae799f41b..5042fdccf24 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -265,7 +265,7 @@ private TableColumn> createFileColumn() .withOnMouseClickedEvent((entry, linkedFiles) -> event -> { if ((event.getButton() == MouseButton.PRIMARY) && (linkedFiles.size() == 1)) { // Only one linked file -> open directly - LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFiles.get(0), entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs, externalFileTypes); + LinkedFileViewModel linkedFileViewModel = new LinkedFileViewModel(linkedFiles.get(0), entry.getEntry(), database, Globals.TASK_EXECUTOR, dialogService, Globals.prefs.getXMPPreferences(), Globals.prefs.getFilePreferences(), externalFileTypes); linkedFileViewModel.open(); } }) @@ -288,7 +288,7 @@ private ContextMenu createFileMenu(BibEntryTableViewModel entry, List linkedFileViewModel.open()); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index e002caa979b..cd906dece37 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -1541,6 +1541,7 @@ public LayoutFormatterPreferences getLayoutFormatterPreferences(JournalAbbreviat getFileLinkPreferences(), journalAbbreviationLoader); } + @Override public XmpPreferences getXMPPreferences() { return new XmpPreferences(getBoolean(USE_XMP_PRIVACY_FILTER), getStringList(XMP_PRIVACY_FILTERS), getKeywordDelimiter()); @@ -1815,6 +1816,7 @@ public void storeJournalAbbreviationPreferences(JournalAbbreviationPreferences a putBoolean(JabRefPreferences.USE_IEEE_ABRV, abbreviationsPreferences.useIEEEAbbreviations()); } + @Override public AutoLinkPreferences getAutoLinkPreferences() { return new AutoLinkPreferences( getBoolean(JabRefPreferences.AUTOLINK_USE_REG_EXP_SEARCH_KEY), diff --git a/src/main/java/org/jabref/preferences/PreferencesService.java b/src/main/java/org/jabref/preferences/PreferencesService.java index 4947c9da8bc..02ac64b96c3 100644 --- a/src/main/java/org/jabref/preferences/PreferencesService.java +++ b/src/main/java/org/jabref/preferences/PreferencesService.java @@ -15,6 +15,8 @@ import org.jabref.logic.openoffice.OpenOfficePreferences; import org.jabref.logic.protectedterms.ProtectedTermsLoader; import org.jabref.logic.util.UpdateFieldPreferences; +import org.jabref.logic.util.io.AutoLinkPreferences; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.metadata.FilePreferences; import org.jabref.model.metadata.SaveOrderConfig; @@ -33,6 +35,10 @@ public interface PreferencesService { void storeJournalAbbreviationPreferences(JournalAbbreviationPreferences abbreviationsPreferences); FilePreferences getFilePreferences(); + + XmpPreferences getXMPPreferences(); + + AutoLinkPreferences getAutoLinkPreferences(); Path getWorkingDir(); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index bae2e82011d..b0decc76ba8 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1894,6 +1894,11 @@ Delete\ from\ disk=Delete from disk Remove\ from\ entry=Remove from entry There\ exists\ already\ a\ group\ with\ the\ same\ name.=There exists already a group with the same name. +Copy\ linked\ file=Copy linked file +Copy\ linked\ file\ to\ folder...=Copy linked file to folder... +Could\ not\ copy\ file\ to\ %0,\ maybe\ the\ file\ is\ already\ existing?=Could not copy file to %0, maybe the file is already existing? +Sucessfully\ copied\ file\ to\ %0=Sucessfully copied file to %0 + Copy\ linked\ files\ to\ folder...=Copy linked files to folder... Copied\ file\ successfully=Copied file successfully Copying\ files...=Copying files... diff --git a/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java b/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java index e67ffd1bdb8..86ab685cc8c 100644 --- a/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java +++ b/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java @@ -18,18 +18,17 @@ import org.jabref.gui.util.CurrentThreadTaskExecutor; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.jabref.model.metadata.FilePreferences; -import org.jabref.preferences.JabRefPreferences; import org.jabref.testutils.category.FetcherTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.mockito.Answers; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -45,7 +44,6 @@ class LinkedFileViewModelTest { private Path tempFile; - private final JabRefPreferences preferences = mock(JabRefPreferences.class, Answers.RETURNS_DEEP_STUBS); private LinkedFile linkedFile; private BibEntry entry; private BibDatabaseContext databaseContext; @@ -53,6 +51,7 @@ class LinkedFileViewModelTest { private DialogService dialogService; private ExternalFileTypes externalFileType = mock(ExternalFileTypes.class); private FilePreferences filePreferences = mock(FilePreferences.class); + private XmpPreferences xmpPreferences = mock(XmpPreferences.class); @BeforeEach void setUp(@TempDir Path tempFolder) throws Exception { @@ -75,7 +74,7 @@ void deleteWhenFilePathNotPresentReturnsTrue() { linkedFile = spy(new LinkedFile("", "nonexistent file", "")); doReturn(Optional.empty()).when(linkedFile).findIn(any(BibDatabaseContext.class), any(FilePreferences.class)); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, xmpPreferences, filePreferences, externalFileType); boolean removed = viewModel.delete(); assertTrue(removed); @@ -93,7 +92,7 @@ void deleteWhenRemoveChosenReturnsTrueButDoesNotDeletesFile() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(3))); // first vararg - remove button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, xmpPreferences, filePreferences, externalFileType); boolean removed = viewModel.delete(); assertTrue(removed); @@ -111,7 +110,7 @@ void deleteWhenDeleteChosenReturnsTrueAndDeletesFile() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(4))); // second vararg - delete button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, xmpPreferences, filePreferences, externalFileType); boolean removed = viewModel.delete(); assertTrue(removed); @@ -129,7 +128,7 @@ void deleteMissingFileReturnsTrue() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(4))); // second vararg - delete button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, xmpPreferences, filePreferences, externalFileType); boolean removed = viewModel.delete(); assertTrue(removed); @@ -146,7 +145,7 @@ void deleteWhenDialogCancelledReturnsFalseAndDoesNotRemoveFile() { any(ButtonType.class), any(ButtonType.class))).thenAnswer(invocation -> Optional.of(invocation.getArgument(5))); // third vararg - cancel button - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, taskExecutor, dialogService, xmpPreferences, filePreferences, externalFileType); boolean removed = viewModel.delete(); assertFalse(removed); @@ -159,9 +158,8 @@ void downloadDoesNotOverwriteFileTypeExtension() throws MalformedURLException { databaseContext = mock(BibDatabaseContext.class); when(filePreferences.getFileNamePattern()).thenReturn("[bibtexkey]"); //use this variant, as we cannot mock the linkedFileHandler cause it's initialized inside the viewModel - when(preferences.getFilePreferences()).thenReturn(filePreferences); - LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, preferences, externalFileType); + LinkedFileViewModel viewModel = new LinkedFileViewModel(linkedFile, entry, databaseContext, new CurrentThreadTaskExecutor(), dialogService, xmpPreferences, filePreferences, externalFileType); BackgroundTask task = viewModel.prepareDownloadTask(tempFile.getParent(), new URLDownload("http://arxiv.org/pdf/1207.0408v1")); task.onSuccess(destination -> { From 48087ed98c4284d14017ab5db62bd7914e2acda0 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 22 Jun 2019 22:46:29 +0200 Subject: [PATCH 3/4] fix checkstyle --- src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java | 1 - .../java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java index 891b029f4f0..52f46bf22d3 100644 --- a/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java @@ -10,7 +10,6 @@ import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.ValueTableCellFactory; import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabaseContext; import com.airhacks.afterburner.views.ViewLoader; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 5fa9d03aecd..2f76bc4e65e 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -45,7 +45,6 @@ import org.jabref.model.metadata.FilePreferences; import org.jabref.model.strings.StringUtil; import org.jabref.model.util.OptionalUtil; -import org.jabref.preferences.JabRefPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From c2cacfe36f18b601b8afa0795270756e9eb4bae0 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 6 Jul 2019 15:45:27 +0200 Subject: [PATCH 4/4] rename variables, add message if file not resolved --- .../org/jabref/gui/copyfiles/CopySingleFileAction.java | 5 +++-- .../org/jabref/gui/externalfiles/FindFullTextAction.java | 4 +++- .../org/jabref/gui/fieldeditors/LinkedFilesEditor.java | 8 ++++---- src/main/resources/l10n/JabRef_en.properties | 2 ++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java b/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java index e5dce5e5b70..aa00a394524 100644 --- a/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopySingleFileAction.java @@ -41,11 +41,9 @@ public void copyFile() { private void copyFileToDestination(Path exportPath) { Optional fileToExport = linkedFile.findIn(databaseContext, Globals.prefs.getFilePreferences()); - Optional newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename); if (newPath.isPresent()) { - Path newFile = newPath.get(); boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false); if (success) { @@ -55,6 +53,9 @@ private void copyFileToDestination(Path exportPath) { dialogService.showErrorDialogAndWait(Localization.lang("Copy linked file"), Localization.lang("Could not copy file to %0, maybe the file is already existing?", newPath.map(Path::getParent).map(Path::toString).orElse(""))); } } + else { + dialogService.showErrorDialogAndWait(Localization.lang("Could not resolve the file %0", fileToExport.map(Path::getParent).map(Path::toString).orElse(""))); + } } } diff --git a/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java b/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java index f889c03f4c5..4e47d41b61d 100644 --- a/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java +++ b/src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java @@ -137,7 +137,9 @@ private void addLinkedFileFromURL(URL url, BibEntry entry, Path targetDirectory) basePanel.getBibDatabaseContext(), Globals.TASK_EXECUTOR, dialogService, - JabRefPreferences.getInstance().getXMPPreferences(),JabRefPreferences.getInstance().getFilePreferences(), ExternalFileTypes.getInstance()); + JabRefPreferences.getInstance().getXMPPreferences(), + JabRefPreferences.getInstance().getFilePreferences(), + ExternalFileTypes.getInstance()); try { URLDownload urlDownload = new URLDownload(newLinkedFile.getLink()); diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java index 4f7b83a00ab..10495bda7fd 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java @@ -240,9 +240,9 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) { renameAndMoveFile.setOnAction(event -> linkedFile.moveToDefaultDirectoryAndRename()); renameAndMoveFile.setDisable(linkedFile.getFile().isOnlineLink() || linkedFile.isGeneratedPathSameAsOriginal()); - MenuItem copyLinkedFiles = new MenuItem(Localization.lang("Copy linked file to folder...")); - copyLinkedFiles.setOnAction(event -> new CopySingleFileAction(linkedFile.getFile(), dialogService, databaseContext).copyFile()); - copyLinkedFiles.setDisable(linkedFile.getFile().isOnlineLink()); + MenuItem copyLinkedFile = new MenuItem(Localization.lang("Copy linked file to folder...")); + copyLinkedFile.setOnAction(event -> new CopySingleFileAction(linkedFile.getFile(), dialogService, databaseContext).copyFile()); + copyLinkedFile.setDisable(linkedFile.getFile().isOnlineLink()); MenuItem deleteFile = new MenuItem(Localization.lang("Permanently delete local file")); deleteFile.setOnAction(event -> viewModel.deleteFile(linkedFile)); @@ -258,7 +258,7 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) { if (linkedFile.getFile().isOnlineLink()) { menu.getItems().add(download); } - menu.getItems().addAll(renameFile, renameFileName, moveFile, renameAndMoveFile, copyLinkedFiles, deleteLink, deleteFile); + menu.getItems().addAll(renameFile, renameFileName, moveFile, renameAndMoveFile, copyLinkedFile, deleteLink, deleteFile); return menu; } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index b0decc76ba8..ba49ffa31fe 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1898,6 +1898,8 @@ Copy\ linked\ file=Copy linked file Copy\ linked\ file\ to\ folder...=Copy linked file to folder... Could\ not\ copy\ file\ to\ %0,\ maybe\ the\ file\ is\ already\ existing?=Could not copy file to %0, maybe the file is already existing? Sucessfully\ copied\ file\ to\ %0=Sucessfully copied file to %0 +Could\ not\ resolve\ the\ file\ %0=Could not resolve the file %0 + Copy\ linked\ files\ to\ folder...=Copy linked files to folder... Copied\ file\ successfully=Copied file successfully