Skip to content
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

Enable groups drag'n'drop to new library #9460

Merged
Merged
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 60 additions & 2 deletions src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,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 @@ -138,6 +139,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 @@ -235,7 +237,7 @@ private void initDragAndDrop() {
// 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())) {
if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard()) || tabDragEvent.getDragboard().hasContent(DragAndDropDataFormats.GROUP)) {
tabDragEvent.acceptTransferModes(TransferMode.ANY);
if (!tabbedPane.getTabs().contains(dndIndicator)) {
tabbedPane.getTabs().add(dndIndicator);
Expand All @@ -252,6 +254,8 @@ private void initDragAndDrop() {
});
tab.setOnDragExited(event1 -> tabbedPane.getTabs().remove(dndIndicator));
tab.setOnDragDropped(tabDragEvent -> {
Dragboard dragboard = tabDragEvent.getDragboard();

if (DragAndDropHelper.hasBibFiles(tabDragEvent.getDragboard())) {
tabbedPane.getTabs().remove(dndIndicator);
List<Path> bibFiles = DragAndDropHelper.getBibFiles(tabDragEvent.getDragboard());
Expand All @@ -263,7 +267,43 @@ private void initDragAndDrop() {
for (Tab libraryTab : tabbedPane.getTabs()) {
if (libraryTab.getId().equals(tab.getId()) &&
!tabbedPane.getSelectionModel().getSelectedItem().equals(libraryTab)) {
((LibraryTab) libraryTab).dropEntry(stateManager.getLocalDragboard().getBibEntries());
if (dragboard.hasContent(DragAndDropDataFormats.GROUP)) {
List<String> groupPathToSources = (List<String>) dragboard.getContent(DragAndDropDataFormats.GROUP);
if (((LibraryTab) libraryTab).getBibDatabaseContext().getMetaData().getGroups().isEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would extract this casting to LibraryTab to a new variable, then you don't have to add the casting everywhere
e.g. LibraryTab libraryTab = (LibraryTab) tab;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted, thanks for that, I will update the file accordingly. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm that this has been updated.

// a root (all entries) GroupTreeNode
GroupTreeNode rootNode = getCurrentLibraryTab().getBibDatabaseContext()
.getMetaData()
.getGroups()
.get()
.copyNode();

// add rootNode to the Library if it does not have a root.
((LibraryTab) libraryTab).getBibDatabaseContext()
.getMetaData()
.setGroups(rootNode);
}
Optional<GroupTreeNode> parentGroup = Optional.of(((LibraryTab) libraryTab)
.getBibDatabaseContext()
.getMetaData()
.getGroups().get());

for (String pathToSource : groupPathToSources) {
List<BibEntry> allEntries = getCurrentLibraryTab()
.getBibDatabaseContext()
.getEntries();
Optional<GroupTreeNode> groupTreeNodeToCopy = getCurrentLibraryTab()
.getBibDatabaseContext()
.getMetaData()
.getGroups()
.get()
.getChildByPath(pathToSource);

// call the copy function
copyGroupTreeNode((LibraryTab) libraryTab, parentGroup, groupTreeNodeToCopy, allEntries);
}
} else {
((LibraryTab) libraryTab).dropEntry(stateManager.getLocalDragboard().getBibEntries());
}
}
}
tabDragEvent.consume();
Expand Down Expand Up @@ -1410,4 +1450,22 @@ private void updateTexts(UndoChangeEvent event) {
*/
}
}

private void copyGroupTreeNode(LibraryTab libraryTab, Optional<GroupTreeNode> parent, Optional<GroupTreeNode> groupTreeNodeToCopy, List<BibEntry> allEntries) {
// add groupTreeNodeToCopy to the parent-- in the first run that will the source/main GroupTreeNode
GroupTreeNode copiedNode = parent.get().addSubgroup(groupTreeNodeToCopy.get().getGroup().deepCopy());

// add all entries of a groupTreeNode to the new library.
((LibraryTab) libraryTab).dropEntry(groupTreeNodeToCopy.get().getEntriesInGroup(allEntries));

// List of all children of groupTreeNodeToCopy
List<GroupTreeNode> children = groupTreeNodeToCopy.get().getChildren();

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