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

Copy to option #12374

Merged
merged 17 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
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
9 changes: 9 additions & 0 deletions src/main/java/org/jabref/gui/actions/ActionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ public MenuItem createMenuItem(Action action, Command command) {
return menuItem;
}

public MenuItem createCustomMenuItem(Action action, Command command, String text) {
MenuItem menuItem = new MenuItem();
configureMenuItem(action, command, menuItem);
menuItem.textProperty().unbind();
menuItem.setText(text);

return menuItem;
}

public CheckMenuItem createCheckMenuItem(Action action, Command command, boolean selected) {
CheckMenuItem checkMenuItem = ActionUtils.createCheckMenuItem(new JabRefAction(action, command, keyBindingRepository));
checkMenuItem.setSelected(selected);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jabref/gui/actions/StandardActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

public enum StandardActions implements Action {

COPY_TO(Localization.lang("Copy to")),
COPY_MORE(Localization.lang("Copy") + "..."),
COPY_TITLE(Localization.lang("Copy title"), KeyBinding.COPY_TITLE),
COPY_KEY(Localization.lang("Copy citation key"), KeyBinding.COPY_CITATION_KEY),
Expand Down
72 changes: 72 additions & 0 deletions src/main/java/org/jabref/gui/edit/CopyTo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.jabref.gui.edit;

import java.util.List;

import org.jabref.gui.DialogService;
import org.jabref.gui.LibraryTab;
import org.jabref.gui.StateManager;
import org.jabref.gui.actions.ActionHelper;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CopyTo extends SimpleCommand {

private static final Logger LOGGER = LoggerFactory.getLogger(CopyMoreAction.class);

private final DialogService dialogService;
private final StateManager stateManager;
private final CopyToPreferences copyToPreferences;
private final LibraryTab libraryTab;
private final BibDatabaseContext sourceDatabaseContext;
private final BibDatabaseContext targetDatabaseContext;

public CopyTo(DialogService dialogService,
StateManager stateManager,
CopyToPreferences copyToPreferences,
LibraryTab libraryTab,
BibDatabaseContext sourceDatabaseContext,
BibDatabaseContext targetDatabaseContext) {
this.dialogService = dialogService;
this.stateManager = stateManager;
this.copyToPreferences = copyToPreferences;
this.libraryTab = libraryTab;
this.sourceDatabaseContext = sourceDatabaseContext;
this.targetDatabaseContext = targetDatabaseContext;

this.executable.bind(ActionHelper.needsEntriesSelected(stateManager));
}

@Override
public void execute() {
boolean includeCrossReferences = askForCrossReferencedEntries();
copyToPreferences.setShouldIncludeCrossReferences(includeCrossReferences);

copyEntryToAnotherLibrary(sourceDatabaseContext, targetDatabaseContext);
}

public void copyEntryToAnotherLibrary(BibDatabaseContext sourceDatabaseContext, BibDatabaseContext targetDatabaseContext) {
List<BibEntry> selectedEntries = stateManager.getSelectedEntries();

targetDatabaseContext.getDatabase().insertEntries(selectedEntries);
}

private boolean askForCrossReferencedEntries() {
if (copyToPreferences.getShouldAskForIncludingCrossReferences()) {
return dialogService.showConfirmationDialogWithOptOutAndWait(
Localization.lang("Include or exclude cross-referenced entries"),
Localization.lang("Would you like to include cross-reference entries in the current operation?"),
Localization.lang("Include"),
Localization.lang("Exclude"),
Localization.lang("Do not ask again"),
optOut -> copyToPreferences.setShouldAskForIncludingCrossReferences(!optOut)
);
} else {
return copyToPreferences.getShouldIncludeCrossReferences();
}
}
}
32 changes: 32 additions & 0 deletions src/main/java/org/jabref/gui/edit/CopyToPreferences.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.jabref.gui.edit;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;

public class CopyToPreferences {
private final BooleanProperty shouldIncludeCrossReferences = new SimpleBooleanProperty();
private final BooleanProperty shouldAskForIncludingCrossReferences = new SimpleBooleanProperty();

public CopyToPreferences(boolean shouldAskForIncludingCrossReferences,
boolean shouldIncludeCrossReferences
) {
priyanshu16095 marked this conversation as resolved.
Show resolved Hide resolved
this.shouldIncludeCrossReferences.set(shouldIncludeCrossReferences);
this.shouldAskForIncludingCrossReferences.set(shouldAskForIncludingCrossReferences);
}

public boolean getShouldIncludeCrossReferences() {
priyanshu16095 marked this conversation as resolved.
Show resolved Hide resolved
return shouldIncludeCrossReferences.get();
}

public void setShouldIncludeCrossReferences(boolean decision) {
this.shouldIncludeCrossReferences.set(decision);
}

public boolean getShouldAskForIncludingCrossReferences() {
return shouldAskForIncludingCrossReferences.get();
}

public void setShouldAskForIncludingCrossReferences(boolean decision) {
this.shouldAskForIncludingCrossReferences.set(decision);
}
}
54 changes: 54 additions & 0 deletions src/main/java/org/jabref/gui/maintable/RightClickMenu.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package org.jabref.gui.maintable;

import java.nio.file.Path;
import java.util.Optional;

import javax.swing.undo.UndoManager;

import javafx.collections.ObservableList;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
Expand All @@ -14,6 +18,7 @@
import org.jabref.gui.actions.ActionFactory;
import org.jabref.gui.actions.StandardActions;
import org.jabref.gui.edit.CopyMoreAction;
import org.jabref.gui.edit.CopyTo;
import org.jabref.gui.edit.EditAction;
import org.jabref.gui.exporter.ExportToClipboardAction;
import org.jabref.gui.frame.SendAsKindleEmailAction;
Expand All @@ -31,7 +36,11 @@
import org.jabref.logic.citationstyle.CitationStyleOutputFormat;
import org.jabref.logic.citationstyle.CitationStylePreviewLayout;
import org.jabref.logic.journals.JournalAbbreviationRepository;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.shared.DatabaseLocation;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.logic.util.io.FileUtil;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.entry.field.SpecialField;

Expand Down Expand Up @@ -61,6 +70,7 @@ public static ContextMenu create(BibEntryTableViewModel entry,
contextMenu.getItems().addAll(
factory.createMenuItem(StandardActions.COPY, new EditAction(StandardActions.COPY, () -> libraryTab, stateManager, undoManager)),
createCopySubMenu(factory, dialogService, stateManager, preferences, clipBoardManager, abbreviationRepository, taskExecutor),
createCopyToMenu(factory, dialogService, stateManager, preferences, libraryTab),
factory.createMenuItem(StandardActions.PASTE, new EditAction(StandardActions.PASTE, () -> libraryTab, stateManager, undoManager)),
factory.createMenuItem(StandardActions.CUT, new EditAction(StandardActions.CUT, () -> libraryTab, stateManager, undoManager)),
factory.createMenuItem(StandardActions.MERGE_ENTRIES, new MergeEntriesAction(dialogService, stateManager, undoManager, preferences)),
Expand Down Expand Up @@ -103,6 +113,50 @@ public static ContextMenu create(BibEntryTableViewModel entry,
return contextMenu;
}

private static Menu createCopyToMenu(ActionFactory factory,
DialogService dialogService,
StateManager stateManager,
GuiPreferences preferences,
LibraryTab libraryTab
) {
Menu copyToMenu = factory.createMenu(StandardActions.COPY_TO);

ObservableList<BibDatabaseContext> openDatabases = stateManager.getOpenDatabases();

BibDatabaseContext sourceDatabaseContext = libraryTab.getBibDatabaseContext();

Optional<Path> sourcePath = libraryTab.getBibDatabaseContext().getDatabasePath();
String sourceDatabaseName = FileUtil.getUniquePathFragment(stateManager.collectAllDatabasePaths(), sourcePath.get()).get();

if (!openDatabases.isEmpty()) {
openDatabases.forEach(bibDatabaseContext -> {
Optional<Path> destinationPath = Optional.empty();
String destinationDatabaseName = " ";
priyanshu16095 marked this conversation as resolved.
Show resolved Hide resolved

if (bibDatabaseContext.getDatabasePath().isPresent()) {
destinationPath = bibDatabaseContext.getDatabasePath();
String uniquePathName = FileUtil.getUniquePathFragment(stateManager.collectAllDatabasePaths(), destinationPath.get()).get();
if (uniquePathName.equals(sourceDatabaseName)) {
return;
subhramit marked this conversation as resolved.
Show resolved Hide resolved
}
destinationDatabaseName = uniquePathName;
} else if (bibDatabaseContext.getLocation() == DatabaseLocation.SHARED) {
destinationDatabaseName = bibDatabaseContext.getDBMSSynchronizer().getDBName() + " [" + Localization.lang("shared") + "]";
}

copyToMenu.getItems().addAll(
factory.createCustomMenuItem(
StandardActions.COPY_TO,
new CopyTo(dialogService, stateManager, preferences.getCopyToPreferences(), libraryTab, sourceDatabaseContext, bibDatabaseContext),
destinationDatabaseName
)
);
});
}

return copyToMenu;
}

private static Menu createCopySubMenu(ActionFactory factory,
DialogService dialogService,
StateManager stateManager,
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/jabref/gui/preferences/GuiPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.jabref.gui.CoreGuiPreferences;
import org.jabref.gui.WorkspacePreferences;
import org.jabref.gui.autocompleter.AutoCompletePreferences;
import org.jabref.gui.edit.CopyToPreferences;
import org.jabref.gui.entryeditor.EntryEditorPreferences;
import org.jabref.gui.externalfiles.UnlinkedFilesDialogPreferences;
import org.jabref.gui.frame.ExternalApplicationsPreferences;
Expand All @@ -19,6 +20,8 @@
import org.jabref.logic.preferences.CliPreferences;

public interface GuiPreferences extends CliPreferences {
CopyToPreferences getCopyToPreferences();

EntryEditorPreferences getEntryEditorPreferences();

MergeDialogPreferences getMergeDialogPreferences();
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.jabref.gui.autocompleter.AutoCompletePreferences;
import org.jabref.gui.desktop.os.NativeDesktop;
import org.jabref.gui.duplicationFinder.DuplicateResolverDialog;
import org.jabref.gui.edit.CopyToPreferences;
import org.jabref.gui.entryeditor.EntryEditorPreferences;
import org.jabref.gui.externalfiles.UnlinkedFilesDialogPreferences;
import org.jabref.gui.externalfiletype.ExternalFileType;
Expand Down Expand Up @@ -213,6 +214,9 @@ public class JabRefGuiPreferences extends JabRefCliPreferences implements GuiPre
private static final String UNLINKED_FILES_SELECTED_DATE_RANGE = "unlinkedFilesSelectedDateRange";
private static final String UNLINKED_FILES_SELECTED_SORT = "unlinkedFilesSelectedSort";

private static final String INCLUDE_CROSS_REFERENCES = "includeCrossReferences";
private static final String ASK_FOR_INCLUDING_CROSS_REFERENCES = "askForIncludingCrossReferences";

private static JabRefGuiPreferences singleton;

private EntryEditorPreferences entryEditorPreferences;
Expand All @@ -232,6 +236,7 @@ public class JabRefGuiPreferences extends JabRefCliPreferences implements GuiPre
private ColumnPreferences mainTableColumnPreferences;
private ColumnPreferences searchDialogColumnPreferences;
private KeyBindingRepository keyBindingRepository;
private CopyToPreferences copyToPreferences;

private JabRefGuiPreferences() {
super();
Expand Down Expand Up @@ -394,6 +399,9 @@ private JabRefGuiPreferences() {
// By default disable "Fit table horizontally on the screen"
defaults.put(AUTO_RESIZE_MODE, Boolean.FALSE);
// endregion

defaults.put(ASK_FOR_INCLUDING_CROSS_REFERENCES, Boolean.TRUE);
defaults.put(INCLUDE_CROSS_REFERENCES, Boolean.FALSE);
}

/**
Expand All @@ -409,6 +417,17 @@ public static JabRefGuiPreferences getInstance() {
return JabRefGuiPreferences.singleton;
}

public CopyToPreferences getCopyToPreferences() {
if (copyToPreferences != null) {
return copyToPreferences;
}
copyToPreferences = new CopyToPreferences(
getBoolean(ASK_FOR_INCLUDING_CROSS_REFERENCES),
getBoolean(INCLUDE_CROSS_REFERENCES)
);
return copyToPreferences;
}

// region EntryEditorPreferences
public EntryEditorPreferences getEntryEditorPreferences() {
if (entryEditorPreferences != null) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2820,3 +2820,9 @@ Citation\ Entry=Citation Entry

File\ Move\ Errors=File Move Errors
Could\ not\ move\ file\ %0.\ Please\ close\ this\ file\ and\ retry.=Could not move file %0. Please close this file and retry.

Copy\ to=Copy to
Include=Include
Exclude=Exclude
Include\ or\ exclude\ cross-referenced\ entries=Include or exclude cross-referenced entries
Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ operation?=Would you like to include cross-reference entries in the current operation?
Loading