diff --git a/CHANGELOG.md b/CHANGELOG.md index 98b3a24c19e..d3f8daa73c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We added an extra option in the 'Find Unlinked Files' dialog view to ignore unnecessary files like Thumbs.db, DS_Store, etc. [koppor#373](https://github.com/koppor/jabref/issues/373) - JabRef now writes log files. Linux: `$home/.cache/jabref/logs/version`, Windows: `%APPDATA%\..\Local\harawata\jabref\version\logs`, Mac: `Users/.../Library/Logs/jabref/version` - We added an importer for Citavi backup files, support ".ctv5bak" and ".ctv6bak" file formats. [#8322](https://github.com/JabRef/jabref/issues/8322) +- We added a feature to drag selected entries and drop them to other opened inactive library tabs [koppor521](https://github.com/koppor/jabref/issues/521). ### Changed diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 2bbbf8f4412..6e53c74ecd5 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -222,6 +222,54 @@ private void initDragAndDrop() { } else { tabbedPane.getTabs().remove(dndIndicator); } + // Accept drag entries from MainTable + if (event.getDragboard().hasContent(DragAndDropDataFormats.ENTRIES)) { + event.acceptTransferModes(TransferMode.COPY); + event.consume(); + } + }); + + this.getScene().setOnDragEntered(event -> { + // It is necessary to setOnDragOver for newly opened tabs + // drag'n'drop on tabs covered dnd on tabbedPane, so dnd on tabs should contain all dnds on tabbedPane + tabbedPane.lookupAll(".tab").forEach(t -> { + t.setOnDragOver(tabDragEvent -> { + if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) { + tabDragEvent.acceptTransferModes(TransferMode.ANY); + if (!tabbedPane.getTabs().contains(dndIndicator)) { + tabbedPane.getTabs().add(dndIndicator); + } + event.consume(); + } else { + tabbedPane.getTabs().remove(dndIndicator); + } + + if (tabDragEvent.getDragboard().hasContent(DragAndDropDataFormats.ENTRIES)) { + tabDragEvent.acceptTransferModes(TransferMode.COPY); + tabDragEvent.consume(); + } + }); + t.setOnDragExited(event1 -> tabbedPane.getTabs().remove(dndIndicator)); + t.setOnDragDropped(tabDragEvent -> { + if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) { + tabbedPane.getTabs().remove(dndIndicator); + List bibFiles = DragAndDropHelper.getBibFiles(tabDragEvent.getDragboard()); + OpenDatabaseAction openDatabaseAction = this.getOpenDatabaseAction(); + openDatabaseAction.openFiles(bibFiles, true); + tabDragEvent.setDropCompleted(true); + tabDragEvent.consume(); + } else { + for (Tab libraryTab : tabbedPane.getTabs()) { + if (libraryTab.getId().equals(t.getId()) && + !tabbedPane.getSelectionModel().getSelectedItem().equals(libraryTab)) { + ((LibraryTab) libraryTab).dropEntry(stateManager.getLocalDragboard().getBibEntries()); + } + } + tabDragEvent.consume(); + } + }); + }); + event.consume(); }); this.getScene().setOnDragExited(event -> tabbedPane.getTabs().remove(dndIndicator)); diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index c62741b37c1..48bc0b2a92e 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Random; import javafx.animation.PauseTransition; import javafx.application.Platform; @@ -153,6 +154,10 @@ public LibraryTab(JabRefFrame frame, this.entryEditor = new EntryEditor(this, externalFileTypes); + // set LibraryTab ID for drag'n'drop + // ID content doesn't matter, we only need different tabs to have different ID + this.setId(Long.valueOf(new Random().nextLong()).toString()); + Platform.runLater(() -> { EasyBind.subscribe(changedProperty, this::updateTabTitle); stateManager.getOpenDatabases().addListener((ListChangeListener) c -> @@ -758,6 +763,10 @@ public void paste() { mainTable.paste(); } + public void dropEntry(List entriesToAdd) { + mainTable.dropEntry(entriesToAdd); + } + public void cut() { mainTable.cut(); } diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index 51494fe6315..67ff3b2dcb5 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -314,6 +314,12 @@ public void paste() { } } + public void dropEntry(List entriesToAdd) { + for (BibEntry entry : entriesToAdd) { + importHandler.importEntryWithDuplicateCheck(database, (BibEntry) entry.clone()); + } + } + private void handleOnDragOver(TableRow row, BibEntryTableViewModel item, DragEvent event) { if (event.getDragboard().hasFiles()) { event.acceptTransferModes(TransferMode.ANY); @@ -350,8 +356,9 @@ private void handleOnDragDetected(TableRow row, BibEntry // The following is necesary to initiate the drag and drop in javafx, although we don't need the contents // It doesn't work without + // Drag'n'drop to other tabs use COPY TransferMode, drop to group sidepane use MOVE ClipboardContent content = new ClipboardContent(); - Dragboard dragboard = startDragAndDrop(TransferMode.MOVE); + Dragboard dragboard = startDragAndDrop(TransferMode.COPY_OR_MOVE); content.put(DragAndDropDataFormats.ENTRIES, ""); dragboard.setContent(content);