Skip to content

Commit

Permalink
Enable groups drag'n'drop to new library (JabRef#9460)
Browse files Browse the repository at this point in the history
* groups drag'n'drop enabled

* Update JabRefFrame.java

* Update JabRefFrame.java

fixing all issues raised by checkstlye/reviewdog tests

* Update JabRefFrame.java

* Update JabRefFrame.java

* Update JabRefFrame.java

* Update JabRefFrame.java

* Update JabRefFrame.java

* Update JabRefFrame.java

* Update JabRefFrame.java

* Update JabRefFrame.java

Extract this casting to LibraryTab to a new variable. 
Fix the "Use a single space to separate non-whitespace characters."  error.

* Update JabRefFrame.java

Enable transferring colours and icons of each group.

* fix issues raised by HoussemNasri

* fix conflict in JabRefFrame.java

* Update JabRefFrame.java

* remove checkstyle

* fix merge conflicts

* fix checkstyle

Co-authored-by: rafatd <[email protected]>
Co-authored-by: Siedlerchr <[email protected]>
  • Loading branch information
3 people authored Dec 21, 2022
1 parent 69d504a commit 41c8b48
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 8 deletions.
12 changes: 12 additions & 0 deletions src/main/java/org/jabref/gui/DragAndDropHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,16 @@ public static List<Path> getBibFiles(Dragboard dragboard) {
return dragboard.getFiles().stream().map(File::toPath).filter(FileUtil::isBibFile).collect(Collectors.toList());
}
}

public static boolean hasGroups(Dragboard dragboard) {
return !getGroups(dragboard).isEmpty();
}

public static List<String> getGroups(Dragboard dragboard) {
if (!dragboard.hasContent(DragAndDropDataFormats.GROUP)) {
return Collections.emptyList();
} else {
return (List<String>) dragboard.getContent(DragAndDropDataFormats.GROUP);
}
}
}
79 changes: 71 additions & 8 deletions src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import javafx.scene.control.ToolBar;
import javafx.scene.control.Tooltip;
import javafx.scene.control.skin.TabPaneSkin;
import javafx.scene.input.Dragboard;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
Expand Down Expand Up @@ -137,6 +138,7 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.SpecialField;
import org.jabref.model.entry.types.StandardEntryType;
import org.jabref.model.groups.GroupTreeNode;
import org.jabref.preferences.PreferencesService;
import org.jabref.preferences.TelemetryPreferences;

Expand Down Expand Up @@ -232,9 +234,9 @@ private void initDragAndDrop() {
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(tab -> {
tab.setOnDragOver(tabDragEvent -> {
if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) {
tabbedPane.lookupAll(".tab").forEach(destinationTabNode -> {
destinationTabNode.setOnDragOver(tabDragEvent -> {
if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard()) || DragAndDropHelper.hasGroups(tabDragEvent.getDragboard())) {
tabDragEvent.acceptTransferModes(TransferMode.ANY);
if (!tabbedPane.getTabs().contains(dndIndicator)) {
tabbedPane.getTabs().add(dndIndicator);
Expand All @@ -249,8 +251,11 @@ private void initDragAndDrop() {
tabDragEvent.consume();
}
});
tab.setOnDragExited(event1 -> tabbedPane.getTabs().remove(dndIndicator));
tab.setOnDragDropped(tabDragEvent -> {
destinationTabNode.setOnDragExited(event1 -> tabbedPane.getTabs().remove(dndIndicator));
destinationTabNode.setOnDragDropped(tabDragEvent -> {

Dragboard dragboard = tabDragEvent.getDragboard();

if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) {
tabbedPane.getTabs().remove(dndIndicator);
List<Path> bibFiles = DragAndDropHelper.getBibFiles(tabDragEvent.getDragboard());
Expand All @@ -260,9 +265,32 @@ private void initDragAndDrop() {
tabDragEvent.consume();
} else {
for (Tab libraryTab : tabbedPane.getTabs()) {
if (libraryTab.getId().equals(tab.getId()) &&
if (libraryTab.getId().equals(destinationTabNode.getId()) &&
!tabbedPane.getSelectionModel().getSelectedItem().equals(libraryTab)) {
((LibraryTab) libraryTab).dropEntry(stateManager.getLocalDragboard().getBibEntries());
LibraryTab destinationLibraryTab = (LibraryTab) libraryTab;
if (DragAndDropHelper.hasGroups(tabDragEvent.getDragboard())) {
List<String> groupPathToSources = DragAndDropHelper.getGroups(tabDragEvent.getDragboard());

copyRootNode(destinationLibraryTab);

GroupTreeNode destinationLibraryGroupRoot = destinationLibraryTab
.getBibDatabaseContext()
.getMetaData()
.getGroups().get();

for (String pathToSource : groupPathToSources) {
GroupTreeNode groupTreeNodeToCopy = getCurrentLibraryTab()
.getBibDatabaseContext()
.getMetaData()
.getGroups()
.get()
.getChildByPath(pathToSource)
.get();
copyGroupTreeNode((LibraryTab) libraryTab, destinationLibraryGroupRoot, groupTreeNodeToCopy);
}
return;
}
destinationLibraryTab.dropEntry(stateManager.getLocalDragboard().getBibEntries());
}
}
tabDragEvent.consume();
Expand All @@ -273,7 +301,6 @@ private void initDragAndDrop() {
});

this.getScene().setOnDragExited(event -> tabbedPane.getTabs().remove(dndIndicator));

this.getScene().setOnDragDropped(event -> {
tabbedPane.getTabs().remove(dndIndicator);
List<Path> bibFiles = DragAndDropHelper.getBibFiles(event.getDragboard());
Expand Down Expand Up @@ -1315,6 +1342,42 @@ public DialogService getDialogService() {
return dialogService;
}

private void copyGroupTreeNode(LibraryTab destinationLibraryTab, GroupTreeNode parent, GroupTreeNode groupTreeNodeToCopy) {
List<BibEntry> allEntries = getCurrentLibraryTab()
.getBibDatabaseContext()
.getEntries();
// add groupTreeNodeToCopy to the parent-- in the first run that will the source/main GroupTreeNode
GroupTreeNode copiedNode = parent.addSubgroup(groupTreeNodeToCopy.copyNode().getGroup());
// add all entries of a groupTreeNode to the new library.
destinationLibraryTab.dropEntry(groupTreeNodeToCopy.getEntriesInGroup(allEntries));
// List of all children of groupTreeNodeToCopy
List<GroupTreeNode> children = groupTreeNodeToCopy.getChildren();

if (!children.isEmpty()) {
// use recursion to add all subgroups of the original groupTreeNodeToCopy
for (GroupTreeNode child : children) {
copyGroupTreeNode(destinationLibraryTab, copiedNode, child);
}
}
}

private void copyRootNode(LibraryTab destinationLibraryTab) {
if (!destinationLibraryTab.getBibDatabaseContext().getMetaData().getGroups().isEmpty()) {
return;
}
// a root (all entries) GroupTreeNode
GroupTreeNode currentLibraryGroupRoot = getCurrentLibraryTab().getBibDatabaseContext()
.getMetaData()
.getGroups()
.get()
.copyNode();

// add currentLibraryGroupRoot to the Library if it does not have a root.
destinationLibraryTab.getBibDatabaseContext()
.getMetaData()
.setGroups(currentLibraryGroupRoot);
}

/**
* The action concerned with closing the window.
*/
Expand Down

0 comments on commit 41c8b48

Please sign in to comment.