-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Add copy linked files action to contextmneu in general tab #5068
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4b17371
6f20c85
48087ed
0c027b0
c2cacfe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| 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<Path, Path, Path> 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<Path> exportPath = dialogService.showDirectorySelectionDialog(dirDialogConfiguration); | ||
| exportPath.ifPresent(this::copyFileToDestination); | ||
|
|
||
| } | ||
|
|
||
| private void copyFileToDestination(Path exportPath) { | ||
| Optional<Path> fileToExport = linkedFile.findIn(databaseContext, Globals.prefs.getFilePreferences()); | ||
| Optional<Path> newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is a bit overly complicated as we can only copy the file if we find it (e.g. fileToExport is not empty). Moreover, please show a warning in case it is empty. |
||
|
|
||
| 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(""))); | ||
| } | ||
| } | ||
| else { | ||
| dialogService.showErrorDialogAndWait(Localization.lang("Could not resolve the file %0", fileToExport.map(Path::getParent).map(Path::toString).orElse(""))); | ||
| } | ||
|
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
| import org.jabref.gui.DialogService; | ||
| import org.jabref.gui.DragAndDropDataFormats; | ||
| import org.jabref.gui.autocompleter.AutoCompleteSuggestionProvider; | ||
| import org.jabref.gui.copyfiles.CopySingleFileAction; | ||
| import org.jabref.gui.keyboard.KeyBinding; | ||
| import org.jabref.gui.util.TaskExecutor; | ||
| import org.jabref.gui.util.ViewModelListCellFactory; | ||
|
|
@@ -48,23 +49,28 @@ public class LinkedFilesEditor extends HBox implements FieldEditorFX { | |
| @FXML private final LinkedFilesEditorViewModel viewModel; | ||
| @FXML private ListView<LinkedFileViewModel> listView; | ||
|
|
||
| private final DialogService dialogService; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use @Inject ?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually tried to inject the other stuff as well, but the key problem is that the fxml loader requires the viewModel to be intiialized beforehand cause in the fxml there is an expression on the viewModel defined. And in the ctor the Injects stuff is of course still null. |
||
| 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.viewModel = new LinkedFilesEditorViewModel(fieldName, suggestionProvider, dialogService, databaseContext, taskExecutor, fieldCheckers, preferences); | ||
| this.dialogService = dialogService; | ||
| this.databaseContext = databaseContext; | ||
| ViewLoader.view(this) | ||
| .root(this) | ||
| .load(); | ||
|
|
||
| ViewModelListCellFactory<LinkedFileViewModel> cellFactory = new ViewModelListCellFactory<LinkedFileViewModel>() | ||
| .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); | ||
|
|
||
|
|
@@ -234,6 +240,10 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) { | |
| renameAndMoveFile.setOnAction(event -> linkedFile.moveToDefaultDirectoryAndRename()); | ||
| renameAndMoveFile.setDisable(linkedFile.getFile().isOnlineLink() || linkedFile.isGeneratedPathSameAsOriginal()); | ||
|
|
||
| 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)); | ||
| deleteFile.setDisable(linkedFile.getFile().isOnlineLink()); | ||
|
|
@@ -248,7 +258,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, copyLinkedFile, deleteLink, deleteFile); | ||
|
|
||
| return menu; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove empty new line