diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index df789a51733..9ebdf89bf6b 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -192,6 +192,7 @@ public enum StandardActions implements Action { GROUP_REMOVE_KEEP_SUBGROUPS(Localization.lang("Keep subgroups")), GROUP_REMOVE_WITH_SUBGROUPS(Localization.lang("Also remove subgroups")), GROUP_CHAT(Localization.lang("Chat with group")), + GROUP_RENAME(Localization.lang("Rename group"), KeyBinding.RENAME_GROUP), GROUP_EDIT(Localization.lang("Edit group")), GROUP_GENERATE_SUMMARIES(Localization.lang("Generate summaries for entries in the group")), GROUP_GENERATE_EMBEDDINGS(Localization.lang("Generate embeddings for linked files in the group")), diff --git a/src/main/java/org/jabref/gui/groups/GroupDialogView.java b/src/main/java/org/jabref/gui/groups/GroupDialogView.java index ebdf45c3ae9..031890db6b0 100644 --- a/src/main/java/org/jabref/gui/groups/GroupDialogView.java +++ b/src/main/java/org/jabref/gui/groups/GroupDialogView.java @@ -105,7 +105,6 @@ public class GroupDialogView extends BaseDialog { private final EnumMap hierarchyToolTip = new EnumMap<>(GroupHierarchyType.class); private final ControlsFxVisualizer validationVisualizer = new ControlsFxVisualizer(); - private final BibDatabaseContext currentDatabase; private final @Nullable GroupTreeNode parentNode; private final @Nullable AbstractGroup editedGroup; @@ -121,6 +120,7 @@ public GroupDialogView(BibDatabaseContext currentDatabase, @Nullable GroupTreeNode parentNode, @Nullable AbstractGroup editedGroup, GroupDialogHeader groupDialogHeader) { + this.currentDatabase = currentDatabase; this.parentNode = parentNode; this.editedGroup = editedGroup; diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeView.java b/src/main/java/org/jabref/gui/groups/GroupTreeView.java index 7b6efa2ecdd..c8c621756de 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeView.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeView.java @@ -538,6 +538,7 @@ private ContextMenu createContextMenuForGroup(GroupNodeViewModel group) { ActionFactory factory = new ActionFactory(); MenuItem removeGroup; + if (group.hasSubgroups() && group.canAddGroupsIn() && !group.isRoot()) { removeGroup = new Menu(Localization.lang("Remove group"), null, factory.createMenuItem(StandardActions.GROUP_REMOVE_KEEP_SUBGROUPS, @@ -557,6 +558,7 @@ private ContextMenu createContextMenuForGroup(GroupNodeViewModel group) { factory.createMenuItem(StandardActions.GROUP_EDIT, new ContextAction(StandardActions.GROUP_EDIT, group)), factory.createMenuItem(StandardActions.GROUP_GENERATE_EMBEDDINGS, new ContextAction(StandardActions.GROUP_GENERATE_EMBEDDINGS, group)), factory.createMenuItem(StandardActions.GROUP_GENERATE_SUMMARIES, new ContextAction(StandardActions.GROUP_GENERATE_SUMMARIES, group)), + factory.createMenuItem(StandardActions.GROUP_RENAME, new ContextAction(StandardActions.GROUP_RENAME, group)), removeGroup, new SeparatorMenuItem(), factory.createMenuItem(StandardActions.GROUP_SUBGROUP_ADD, new ContextAction(StandardActions.GROUP_SUBGROUP_ADD, group)), @@ -639,6 +641,8 @@ public ContextAction(StandardActions command, GroupNodeViewModel group) { switch (command) { case GROUP_EDIT -> group.isEditable(); + case GROUP_RENAME -> + group.isEditable(); case GROUP_REMOVE, GROUP_REMOVE_WITH_SUBGROUPS, GROUP_REMOVE_KEEP_SUBGROUPS -> group.isEditable() && group.canRemove(); case GROUP_SUBGROUP_ADD -> @@ -662,6 +666,10 @@ public void execute() { switch (command) { case GROUP_REMOVE -> viewModel.removeGroupNoSubgroups(group); + case GROUP_RENAME -> { + viewModel.renameGroup(group); + groupTree.refresh(); + } case GROUP_REMOVE_KEEP_SUBGROUPS -> viewModel.removeGroupKeepSubgroups(group); case GROUP_REMOVE_WITH_SUBGROUPS -> diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index 48def6325c8..b20b540715b 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -260,6 +260,54 @@ boolean onlyMinorChanges(AbstractGroup oldGroup, AbstractGroup newGroup) { return true; } + /** + * Opens "Rename Group Dialog" and change name of group + */ + public void renameGroup(GroupNodeViewModel oldGroup) { + currentDatabase.ifPresent(database -> { + AbstractGroup oldGroupDef = oldGroup.getGroupNode().getGroup(); + String oldGroupName = oldGroupDef.getName(); + Optional newGroup = dialogService.showCustomDialogAndWait( + new RenameGroupView(database, + oldGroup.getGroupNode().getGroup()) + ); + + newGroup.ifPresent(group -> { + String newGroupName = group.getName(); + if (oldGroupName.equals(newGroupName)) { + dialogService.notify(Localization.lang("Same name as old group")); + renameGroup(oldGroup); + return; + } + + if (newGroupName.trim().isEmpty()) { + dialogService.notify(Localization.lang("Empty name for group")); + renameGroup(oldGroup); + return; + } + + if (newGroupName.contains(Character.toString(preferences.getBibEntryPreferences().getKeywordSeparator()))) { + dialogService.notify(Localization.lang("You had some special symbol in name of group")); + renameGroup(oldGroup); + return; + } + int groupsWithSameName = 0; + Optional databaseRootGroup = currentDatabase.get().getMetaData().getGroups(); + if (databaseRootGroup.isPresent()) { + groupsWithSameName = databaseRootGroup.get().findChildrenSatisfying(g -> g.getName().equals(newGroupName)).size(); + } + if (groupsWithSameName < 2) { + oldGroup.getGroupNode().setGroup(group, true, true, database.getEntries()); + writeGroupChangesToMetaData(); + refresh(); + } else { + dialogService.notify(Localization.lang("Some group have this name")); + renameGroup(oldGroup); + } + }); + }); + } + /** * Opens "Edit Group Dialog" and changes the given group to the edited one. */ diff --git a/src/main/java/org/jabref/gui/groups/RenameGroupView.java b/src/main/java/org/jabref/gui/groups/RenameGroupView.java new file mode 100644 index 00000000000..1d45addd1e5 --- /dev/null +++ b/src/main/java/org/jabref/gui/groups/RenameGroupView.java @@ -0,0 +1,69 @@ +package org.jabref.gui.groups; + +import java.util.Optional; + +import javafx.fxml.FXML; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.VBox; + +import org.jabref.gui.DialogService; +import org.jabref.gui.util.BaseDialog; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.groups.AbstractGroup; + +import jakarta.inject.Inject; + +public class RenameGroupView extends BaseDialog { + @FXML + private TextField nameField; + @Inject + private DialogService dialogService; + private final BibDatabaseContext currentDatabase; + private final AbstractGroup editedGroup; + + public RenameGroupView(BibDatabaseContext currentDatabase, + AbstractGroup editedGroup) { + this.currentDatabase = currentDatabase; + this.editedGroup = editedGroup; + + setWidth(400); + setHeight(150); + + setTitle(Localization.lang("Rename group")); + getDialogPane().getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL); + + nameField = new TextField(); + nameField.setPromptText(Localization.lang("Name")); + + VBox vbox = new VBox(new Label(Localization.lang("New group")), nameField); + getDialogPane().setContent(vbox); + + setResultConverter(buttonType -> { + if (buttonType == ButtonType.OK) { + return resultConverter(ButtonType.OK).orElse(null); + } else { + return null; + } + }); + } + + protected Optional resultConverter(ButtonType button) { + if (button != ButtonType.OK) { + return Optional.empty(); + } + try { + String newGroupName = nameField.getText().trim(); + if (editedGroup != null) { + editedGroup.nameProperty().setValue(newGroupName); + return Optional.of(editedGroup); + } + return Optional.empty(); + } catch (Exception exception) { + dialogService.showErrorDialogAndWait(exception.getLocalizedMessage(), exception); + return Optional.empty(); + } + } +} diff --git a/src/main/java/org/jabref/gui/keyboard/KeyBinding.java b/src/main/java/org/jabref/gui/keyboard/KeyBinding.java index d0cb6100338..f36be28585f 100644 --- a/src/main/java/org/jabref/gui/keyboard/KeyBinding.java +++ b/src/main/java/org/jabref/gui/keyboard/KeyBinding.java @@ -6,10 +6,11 @@ * @implNote Cannot be sorted alphabetically, as {@link KeyBindingRepository#getKeyCombination(KeyBinding)} iterates over the enum in order and returns the first match. */ public enum KeyBinding { - EDITOR_DELETE("Delete", Localization.lang("Delete text"), "", KeyBindingCategory.EDITOR), // DELETE BACKWARDS = Rubout EDITOR_BACKWARD("Move caret left", Localization.lang("Move caret left"), "", KeyBindingCategory.EDITOR), EDITOR_FORWARD("Move caret right", Localization.lang("Move caret right"), "", KeyBindingCategory.EDITOR), + EDITOR_DELETE("Delete", Localization.lang("Delete text"), "", KeyBindingCategory.EDITOR), + RENAME_GROUP("Rename Group", Localization.lang("Rename group"), "F2", KeyBindingCategory.EDIT), EDITOR_WORD_BACKWARD("Move caret to previous word", Localization.lang("Move caret to previous word"), "", KeyBindingCategory.EDITOR), EDITOR_WORD_FORWARD("Move caret to next word", Localization.lang("Move caret to next word"), "", KeyBindingCategory.EDITOR), EDITOR_BEGINNING("Move caret to beginning of line", Localization.lang("Move caret to beginning of line"), "", KeyBindingCategory.EDITOR), diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 2a4ab3bef81..317ace455af 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2810,3 +2810,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. + +Empty\ name\ for\ group=Empty name for group +You\ had\ some\ special\ symbol\ in\ name\ of\ group=You had some special symbol in name of group +Same\ name\ as\ old\ group=Same name as old group +Some\ group\ have\ this\ name=Some group have this name +Rename\ group=Rename group