Skip to content

Commit add35be

Browse files
authored
Merge pull request #5068 from JabRef/copyLinkedFilesInContextmenu
Add copy linked files action to contextmneu in general tab
2 parents a50cb34 + c2cacfe commit add35be

File tree

12 files changed

+155
-70
lines changed

12 files changed

+155
-70
lines changed

src/main/java/org/jabref/gui/copyfiles/CopyFilesAction.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ public CopyFilesAction(StateManager stateManager, DialogService dialogService) {
3232
this.executable.bind(needsDatabase(this.stateManager).and(needsEntriesSelected(stateManager)));
3333
}
3434

35-
private void showDialog(List<CopyFilesResultItemViewModel> data, BibDatabaseContext database) {
35+
private void showDialog(List<CopyFilesResultItemViewModel> data) {
3636
if (data.isEmpty()) {
3737
dialogService.showInformationDialogAndWait(Localization.lang("Copy linked files to folder..."), Localization.lang("No linked files found for export."));
3838
return;
3939
}
40-
CopyFilesDialogView dialog = new CopyFilesDialogView(database, new CopyFilesResultListDependency(data));
40+
CopyFilesDialogView dialog = new CopyFilesDialogView(new CopyFilesResultListDependency(data));
4141
dialog.showAndWait();
4242
}
4343

@@ -57,7 +57,7 @@ public void execute() {
5757
Localization.lang("Copy linked files to folder..."),
5858
exportTask);
5959
Globals.TASK_EXECUTOR.execute(exportTask);
60-
exportTask.setOnSucceeded((e) -> showDialog(exportTask.getValue(), database));
60+
exportTask.setOnSucceeded((e) -> showDialog(exportTask.getValue()));
6161
});
6262
}
6363
}

src/main/java/org/jabref/gui/copyfiles/CopyFilesDialogView.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import org.jabref.gui.util.BaseDialog;
1111
import org.jabref.gui.util.ValueTableCellFactory;
1212
import org.jabref.logic.l10n.Localization;
13-
import org.jabref.model.database.BibDatabaseContext;
1413

1514
import com.airhacks.afterburner.views.ViewLoader;
1615
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
@@ -24,7 +23,7 @@ public class CopyFilesDialogView extends BaseDialog<Void> {
2423
@FXML private TableColumn<CopyFilesResultItemViewModel, String> colFile;
2524
private final CopyFilesDialogViewModel viewModel;
2625

27-
public CopyFilesDialogView(BibDatabaseContext bibDatabaseContext, CopyFilesResultListDependency results) {
26+
public CopyFilesDialogView(CopyFilesResultListDependency results) {
2827
this.setTitle(Localization.lang("Result"));
2928

3029
this.getDialogPane().getButtonTypes().addAll(ButtonType.OK);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.jabref.gui.copyfiles;
2+
3+
import java.nio.file.Path;
4+
import java.nio.file.Paths;
5+
import java.util.Optional;
6+
import java.util.function.BiFunction;
7+
8+
import org.jabref.Globals;
9+
import org.jabref.gui.DialogService;
10+
import org.jabref.gui.util.DirectoryDialogConfiguration;
11+
import org.jabref.logic.l10n.Localization;
12+
import org.jabref.logic.util.io.FileUtil;
13+
import org.jabref.model.database.BibDatabaseContext;
14+
import org.jabref.model.entry.LinkedFile;
15+
import org.jabref.model.util.OptionalUtil;
16+
import org.jabref.preferences.JabRefPreferences;
17+
18+
public class CopySingleFileAction {
19+
20+
private LinkedFile linkedFile;
21+
private DialogService dialogService;
22+
private BibDatabaseContext databaseContext;
23+
private final BiFunction<Path, Path, Path> resolvePathFilename = (path, file) -> {
24+
return path.resolve(file.getFileName());
25+
};
26+
27+
public CopySingleFileAction(LinkedFile linkedFile, DialogService dialogService, BibDatabaseContext databaseContext) {
28+
this.linkedFile = linkedFile;
29+
this.dialogService = dialogService;
30+
this.databaseContext = databaseContext;
31+
}
32+
33+
public void copyFile() {
34+
DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder()
35+
.withInitialDirectory(Paths.get(Globals.prefs.get(JabRefPreferences.EXPORT_WORKING_DIRECTORY)))
36+
.build();
37+
Optional<Path> exportPath = dialogService.showDirectorySelectionDialog(dirDialogConfiguration);
38+
exportPath.ifPresent(this::copyFileToDestination);
39+
40+
}
41+
42+
private void copyFileToDestination(Path exportPath) {
43+
Optional<Path> fileToExport = linkedFile.findIn(databaseContext, Globals.prefs.getFilePreferences());
44+
Optional<Path> newPath = OptionalUtil.combine(Optional.of(exportPath), fileToExport, resolvePathFilename);
45+
46+
if (newPath.isPresent()) {
47+
Path newFile = newPath.get();
48+
boolean success = FileUtil.copyFile(fileToExport.get(), newFile, false);
49+
if (success) {
50+
dialogService.showInformationDialogAndWait(Localization.lang("Copy linked file"), Localization.lang("Sucessfully copied file to %0", newPath.map(Path::getParent).map(Path::toString).orElse("")));
51+
}
52+
else {
53+
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("")));
54+
}
55+
}
56+
else {
57+
dialogService.showErrorDialogAndWait(Localization.lang("Could not resolve the file %0", fileToExport.map(Path::getParent).map(Path::toString).orElse("")));
58+
}
59+
60+
}
61+
}

src/main/java/org/jabref/gui/externalfiles/FindFullTextAction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ private void addLinkedFileFromURL(URL url, BibEntry entry, Path targetDirectory)
137137
basePanel.getBibDatabaseContext(),
138138
Globals.TASK_EXECUTOR,
139139
dialogService,
140-
JabRefPreferences.getInstance(), ExternalFileTypes.getInstance());
140+
JabRefPreferences.getInstance().getXMPPreferences(),
141+
JabRefPreferences.getInstance().getFilePreferences(),
142+
ExternalFileTypes.getInstance());
141143

142144
try {
143145
URLDownload urlDownload = new URLDownload(newLinkedFile.getLink());

src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import org.jabref.model.metadata.FilePreferences;
4646
import org.jabref.model.strings.StringUtil;
4747
import org.jabref.model.util.OptionalUtil;
48-
import org.jabref.preferences.JabRefPreferences;
4948

5049
import org.slf4j.Logger;
5150
import org.slf4j.LoggerFactory;
@@ -73,19 +72,20 @@ public LinkedFileViewModel(LinkedFile linkedFile,
7372
BibDatabaseContext databaseContext,
7473
TaskExecutor taskExecutor,
7574
DialogService dialogService,
76-
JabRefPreferences preferences,
75+
XmpPreferences xmpPreferences,
76+
FilePreferences filePreferences,
7777
ExternalFileTypes externalFileTypes) {
7878

7979
this.linkedFile = linkedFile;
80-
this.filePreferences = preferences.getFilePreferences();
80+
this.filePreferences = filePreferences;
8181
this.linkedFileHandler = new LinkedFileHandler(linkedFile, entry, databaseContext, filePreferences);
8282
this.databaseContext = databaseContext;
8383
this.entry = entry;
8484
this.dialogService = dialogService;
8585
this.taskExecutor = taskExecutor;
8686
this.externalFileTypes = externalFileTypes;
87-
88-
xmpPreferences = preferences.getXMPPreferences();
87+
this.xmpPreferences = xmpPreferences;
88+
8989
downloadOngoing.bind(downloadProgress.greaterThanOrEqualTo(0).and(downloadProgress.lessThan(1)));
9090
canWriteXMPMetadata.setValue(!linkedFile.isOnlineLink() && linkedFile.getFileType().equalsIgnoreCase("pdf"));
9191
}

src/main/java/org/jabref/gui/fieldeditors/LinkedFilesEditor.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.jabref.gui.DialogService;
3030
import org.jabref.gui.DragAndDropDataFormats;
3131
import org.jabref.gui.autocompleter.AutoCompleteSuggestionProvider;
32+
import org.jabref.gui.copyfiles.CopySingleFileAction;
3233
import org.jabref.gui.keyboard.KeyBinding;
3334
import org.jabref.gui.util.TaskExecutor;
3435
import org.jabref.gui.util.ViewModelListCellFactory;
@@ -48,23 +49,28 @@ public class LinkedFilesEditor extends HBox implements FieldEditorFX {
4849
@FXML private final LinkedFilesEditorViewModel viewModel;
4950
@FXML private ListView<LinkedFileViewModel> listView;
5051

52+
private final DialogService dialogService;
53+
private final BibDatabaseContext databaseContext;
54+
5155
public LinkedFilesEditor(String fieldName, DialogService dialogService, BibDatabaseContext databaseContext, TaskExecutor taskExecutor, AutoCompleteSuggestionProvider<?> suggestionProvider,
5256
FieldCheckers fieldCheckers,
5357
JabRefPreferences preferences) {
54-
this.viewModel = new LinkedFilesEditorViewModel(fieldName, suggestionProvider, dialogService, databaseContext, taskExecutor, fieldCheckers, preferences);
5558

59+
this.viewModel = new LinkedFilesEditorViewModel(fieldName, suggestionProvider, dialogService, databaseContext, taskExecutor, fieldCheckers, preferences);
60+
this.dialogService = dialogService;
61+
this.databaseContext = databaseContext;
5662
ViewLoader.view(this)
5763
.root(this)
5864
.load();
5965

6066
ViewModelListCellFactory<LinkedFileViewModel> cellFactory = new ViewModelListCellFactory<LinkedFileViewModel>()
61-
.withTooltip(LinkedFileViewModel::getDescription)
62-
.withGraphic(LinkedFilesEditor::createFileDisplay)
63-
.withContextMenu(this::createContextMenuForFile)
64-
.withOnMouseClickedEvent(this::handleItemMouseClick)
65-
.setOnDragDetected(this::handleOnDragDetected)
66-
.setOnDragDropped(this::handleOnDragDropped)
67-
.setOnDragOver(this::handleOnDragOver);
67+
.withTooltip(LinkedFileViewModel::getDescription)
68+
.withGraphic(LinkedFilesEditor::createFileDisplay)
69+
.withContextMenu(this::createContextMenuForFile)
70+
.withOnMouseClickedEvent(this::handleItemMouseClick)
71+
.setOnDragDetected(this::handleOnDragDetected)
72+
.setOnDragDropped(this::handleOnDragDropped)
73+
.setOnDragOver(this::handleOnDragOver);
6874

6975
listView.setCellFactory(cellFactory);
7076

@@ -234,6 +240,10 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) {
234240
renameAndMoveFile.setOnAction(event -> linkedFile.moveToDefaultDirectoryAndRename());
235241
renameAndMoveFile.setDisable(linkedFile.getFile().isOnlineLink() || linkedFile.isGeneratedPathSameAsOriginal());
236242

243+
MenuItem copyLinkedFile = new MenuItem(Localization.lang("Copy linked file to folder..."));
244+
copyLinkedFile.setOnAction(event -> new CopySingleFileAction(linkedFile.getFile(), dialogService, databaseContext).copyFile());
245+
copyLinkedFile.setDisable(linkedFile.getFile().isOnlineLink());
246+
237247
MenuItem deleteFile = new MenuItem(Localization.lang("Permanently delete local file"));
238248
deleteFile.setOnAction(event -> viewModel.deleteFile(linkedFile));
239249
deleteFile.setDisable(linkedFile.getFile().isOnlineLink());
@@ -248,7 +258,7 @@ private ContextMenu createContextMenuForFile(LinkedFileViewModel linkedFile) {
248258
if (linkedFile.getFile().isOnlineLink()) {
249259
menu.getItems().add(download);
250260
}
251-
menu.getItems().addAll(renameFile, renameFileName, moveFile, renameAndMoveFile, deleteLink, deleteFile);
261+
menu.getItems().addAll(renameFile, renameFileName, moveFile, renameAndMoveFile, copyLinkedFile, deleteLink, deleteFile);
252262

253263
return menu;
254264
}

0 commit comments

Comments
 (0)