From 528b7092ebbbb1500538d46f2ec7f46de75f7940 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sat, 7 Sep 2024 18:51:13 +0200 Subject: [PATCH 1/6] Move cut and copy out of MainTable into LibraryTab --- src/main/java/org/jabref/gui/LibraryTab.java | 34 +++++++++++++------ .../org/jabref/gui/frame/JabRefFrame.java | 1 - .../importer/actions/OpenDatabaseAction.java | 1 - .../org/jabref/gui/maintable/MainTable.java | 33 ------------------ .../gui/openoffice/OpenOfficePanel.java | 1 - .../gui/shared/SharedDatabaseUIManager.java | 1 - 6 files changed, 24 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index ecfaa501e70..47f9ecf317a 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -1,5 +1,6 @@ package org.jabref.gui; +import java.io.IOException; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -63,7 +64,6 @@ import org.jabref.gui.util.OptionalObjectProperty; import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.UiTaskExecutor; -import org.jabref.logic.ai.AiService; import org.jabref.logic.citationstyle.CitationStyleCache; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.journals.JournalAbbreviationRepository; @@ -82,6 +82,7 @@ import org.jabref.model.entry.Author; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.model.entry.BibtexString; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.FieldChangedEvent; @@ -118,7 +119,6 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private final CountingUndoManager undoManager; private final DialogService dialogService; private final PreferencesService preferencesService; - private final AiService aiService; private final FileUpdateMonitor fileUpdateMonitor; private final StateManager stateManager; private final BibEntryTypesManager entryTypesManager; @@ -174,7 +174,6 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext, LibraryTabContainer tabContainer, DialogService dialogService, PreferencesService preferencesService, - AiService aiService, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, @@ -187,7 +186,6 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext, this.undoManager = undoManager; this.dialogService = dialogService; this.preferencesService = Objects.requireNonNull(preferencesService); - this.aiService = Objects.requireNonNull(aiService); this.stateManager = Objects.requireNonNull(stateManager); this.fileUpdateMonitor = fileUpdateMonitor; this.entryTypesManager = entryTypesManager; @@ -948,7 +946,26 @@ public void resetChangeMonitor() { } public void copy() { - mainTable.copy(); + List selectedEntries = getSelectedEntries(); + + if (!selectedEntries.isEmpty()) { + List stringConstants = getUsedStringValues(selectedEntries); + try { + if (stringConstants.isEmpty()) { + clipBoardManager.setContent(selectedEntries, entryTypesManager); + } else { + clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants); + } + dialogService.notify(Localization.lang("Copied %0 entry(ies)", selectedEntries.size())); + } catch ( + IOException e) { + LOGGER.error("Error while copying selected entries to clipboard.", e); + } + } + } + + private List getUsedStringValues(List entries) { + return bibDatabaseContext.getDatabase().getUsedStrings(entries); } public void paste() { @@ -960,7 +977,8 @@ public void dropEntry(List entriesToAdd) { } public void cut() { - mainTable.cut(); + copy(); + delete(StandardActions.CUT); } public boolean isModified() { @@ -991,7 +1009,6 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi Path file, DialogService dialogService, PreferencesService preferencesService, - AiService aiService, StateManager stateManager, LibraryTabContainer tabContainer, FileUpdateMonitor fileUpdateMonitor, @@ -1007,7 +1024,6 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, @@ -1029,7 +1045,6 @@ public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, LibraryTabContainer tabContainer, DialogService dialogService, PreferencesService preferencesService, - AiService aiService, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, @@ -1043,7 +1058,6 @@ public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 499b47162bc..15e98498ef8 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -434,7 +434,6 @@ public void addTab(@NonNull BibDatabaseContext databaseContext, boolean raisePan this, dialogService, prefs, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index 97ccf23758d..2074b7f4081 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -200,7 +200,6 @@ private void openTheFile(Path file) { file, dialogService, preferencesService, - aiService, stateManager, tabContainer, fileUpdateMonitor, diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index 91daebd7088..04646d022d3 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -1,7 +1,6 @@ package org.jabref.gui.maintable; import java.io.File; -import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -54,7 +53,6 @@ import org.jabref.model.database.event.EntriesAddedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; -import org.jabref.model.entry.BibtexString; import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.FilePreferences; import org.jabref.preferences.PreferencesService; @@ -81,8 +79,6 @@ public class MainTable extends TableView { private final ImportHandler importHandler; private final CustomLocalDragboard localDragboard; - private final ClipBoardManager clipBoardManager; - private final BibEntryTypesManager entryTypesManager; private final TaskExecutor taskExecutor; private final UndoManager undoManager; private final FilePreferences filePreferences; @@ -108,8 +104,6 @@ public MainTable(MainTableDataModel model, this.stateManager = stateManager; this.database = Objects.requireNonNull(database); this.model = model; - this.clipBoardManager = clipBoardManager; - this.entryTypesManager = entryTypesManager; this.taskExecutor = taskExecutor; this.undoManager = libraryTab.getUndoManager(); this.filePreferences = preferencesService.getFilePreferences(); @@ -272,29 +266,6 @@ public void clearAndSelect(BibEntry bibEntry) { }); } - public void copy() { - List selectedEntries = getSelectedEntries(); - - if (!selectedEntries.isEmpty()) { - List stringConstants = getUsedStringValues(selectedEntries); - try { - if (stringConstants.isEmpty()) { - clipBoardManager.setContent(selectedEntries, entryTypesManager); - } else { - clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants); - } - dialogService.notify(Localization.lang("Copied %0 entry(ies)", selectedEntries.size())); - } catch (IOException e) { - LOGGER.error("Error while copying selected entries to clipboard.", e); - } - } - } - - public void cut() { - copy(); - libraryTab.delete(StandardActions.CUT); - } - private void scrollToNextMatchCategory() { BibEntryTableViewModel selectedEntry = getSelectionModel().getSelectedItem(); if (selectedEntry == null) { @@ -558,8 +529,4 @@ private Optional findEntry(BibEntry entry) { .filter(viewModel -> viewModel.getEntry().equals(entry)) .findFirst(); } - - private List getUsedStringValues(List entries) { - return database.getDatabase().getUsedStrings(entries); - } } diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index c4416876ed8..4eb29ff872f 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -310,7 +310,6 @@ private void exportEntries() { tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index d6ef1dce709..480ecab64ff 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java @@ -176,7 +176,6 @@ public LibraryTab openNewSharedDatabaseTab(DBMSConnectionProperties dbmsConnecti tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, From f909c77fd14b469971983835e4a66d5335609c67 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sat, 7 Sep 2024 19:41:12 +0200 Subject: [PATCH 2/6] Move ImportHandler to LibraryTab and Reword methods --- src/main/java/org/jabref/gui/LibraryTab.java | 66 +++++++++++++++---- .../java/org/jabref/gui/edit/EditAction.java | 8 +-- .../jabref/gui/entryeditor/EntryEditor.java | 2 +- .../org/jabref/gui/maintable/MainTable.java | 55 +--------------- 4 files changed, 61 insertions(+), 70 deletions(-) diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index 47f9ecf317a..de371909e5c 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -47,6 +47,7 @@ import org.jabref.gui.dialogs.AutosaveUiManager; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; +import org.jabref.gui.externalfiles.ImportHandler; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.gui.importer.actions.OpenDatabaseAction; import org.jabref.gui.linkedfile.DeleteFileAction; @@ -65,6 +66,9 @@ import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.UiTaskExecutor; import org.jabref.logic.citationstyle.CitationStyleCache; +import org.jabref.logic.importer.FetcherClientException; +import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.importer.FetcherServerException; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; @@ -162,6 +166,8 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private final ClipBoardManager clipBoardManager; private final TaskExecutor taskExecutor; private final DirectoryMonitorManager directoryMonitorManager; + + private ImportHandler importHandler; private LuceneManager luceneManager; /** @@ -220,6 +226,14 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { new CitationStyleCache(bibDatabaseContext); annotationCache = new FileAnnotationCache(bibDatabaseContext, preferencesService.getFilePreferences()); + importHandler = new ImportHandler( + bibDatabaseContext, + preferencesService, + fileUpdateMonitor, + undoManager, + stateManager, + dialogService, + taskExecutor); setupMainPanel(); setupAutoCompletion(); @@ -452,8 +466,8 @@ public SuggestionProviders getSuggestionProviders() { * * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" */ - public void delete(StandardActions mode) { - delete(mode, mainTable.getSelectedEntries()); + public void deleteEntry(StandardActions mode) { + deleteEntry(mode, mainTable.getSelectedEntries()); } /** @@ -461,7 +475,7 @@ public void delete(StandardActions mode) { * * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" */ - private void delete(StandardActions mode, List entries) { + private void deleteEntry(StandardActions mode, List entries) { if (entries.isEmpty()) { return; } @@ -500,8 +514,8 @@ private void delete(StandardActions mode, List entries) { mainTable.requestFocus(); } - public void delete(BibEntry entry) { - delete(StandardActions.DELETE_ENTRY, Collections.singletonList(entry)); + public void deleteEntry(BibEntry entry) { + deleteEntry(StandardActions.DELETE_ENTRY, Collections.singletonList(entry)); } public void registerUndoableChanges(List changes) { @@ -561,7 +575,7 @@ private void createMainTable() { clipBoardManager, entryTypesManager, taskExecutor, - fileUpdateMonitor); + importHandler); // Add the listener that binds selection to state manager (TODO: should be replaced by proper JavaFX binding as soon as table is implemented in JavaFX) // content binding between StateManager#getselectedEntries and mainTable#getSelectedEntries does not work here as it does not trigger the ActionHelper#needsEntriesSelected checker for the menubar mainTable.addSelectionListener(event -> { @@ -945,7 +959,7 @@ public void resetChangeMonitor() { stateManager)); } - public void copy() { + public void copyEntry() { List selectedEntries = getSelectedEntries(); if (!selectedEntries.isEmpty()) { @@ -968,17 +982,43 @@ private List getUsedStringValues(List entries) { return bibDatabaseContext.getDatabase().getUsedStrings(entries); } - public void paste() { - mainTable.paste(); + public void pasteEntry() { + List entriesToAdd; + String content = ClipBoardManager.getContents(); + entriesToAdd = importHandler.handleBibTeXData(content); + if (entriesToAdd.isEmpty()) { + entriesToAdd = handleNonBibTeXStringData(content); + } + if (entriesToAdd.isEmpty()) { + return; + } + + importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); + } + + private List handleNonBibTeXStringData(String data) { + try { + return this.importHandler.handleStringData(data); + } catch ( + FetcherException exception) { + if (exception instanceof FetcherClientException) { + dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("No data was found for the identifier")); + } else if (exception instanceof FetcherServerException) { + dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("Server not available")); + } else { + dialogService.showErrorDialogAndWait(exception); + } + return List.of(); + } } public void dropEntry(List entriesToAdd) { - mainTable.dropEntry(entriesToAdd); + importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); } - public void cut() { - copy(); - delete(StandardActions.CUT); + public void cutEntry() { + copyEntry(); + deleteEntry(StandardActions.CUT); } public boolean isModified() { diff --git a/src/main/java/org/jabref/gui/edit/EditAction.java b/src/main/java/org/jabref/gui/edit/EditAction.java index 2c870a821cb..096539e8574 100644 --- a/src/main/java/org/jabref/gui/edit/EditAction.java +++ b/src/main/java/org/jabref/gui/edit/EditAction.java @@ -78,10 +78,10 @@ public void execute() { // Not sure what is selected -> copy/paste/cut selected entries except for Preview and CodeArea switch (action) { - case COPY -> tabSupplier.get().copy(); - case CUT -> tabSupplier.get().cut(); - case PASTE -> tabSupplier.get().paste(); - case DELETE_ENTRY -> tabSupplier.get().delete(StandardActions.DELETE_ENTRY); + case COPY -> tabSupplier.get().copyEntry(); + case CUT -> tabSupplier.get().cutEntry(); + case PASTE -> tabSupplier.get().pasteEntry(); + case DELETE_ENTRY -> tabSupplier.get().deleteEntry(StandardActions.DELETE_ENTRY); case UNDO -> { if (undoManager.canUndo()) { undoManager.undo(); diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 67be8a5f908..e13eb0ecb6c 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -249,7 +249,7 @@ public void close() { @FXML private void deleteEntry() { - libraryTab.delete(currentlyEditedEntry); + libraryTab.deleteEntry(currentlyEditedEntry); } @FXML diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index 04646d022d3..8cfbbaa5dbd 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -44,16 +44,11 @@ import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.UiTaskExecutor; import org.jabref.gui.util.ViewModelTableRowFactory; -import org.jabref.logic.importer.FetcherClientException; -import org.jabref.logic.importer.FetcherException; -import org.jabref.logic.importer.FetcherServerException; import org.jabref.logic.journals.JournalAbbreviationRepository; -import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.event.EntriesAddedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; -import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.FilePreferences; import org.jabref.preferences.PreferencesService; @@ -72,16 +67,14 @@ public class MainTable extends TableView { private static final PseudoClass NOT_MATCHING_SEARCH_AND_GROUPS = PseudoClass.getPseudoClass("not-matching-search-and-groups"); private final LibraryTab libraryTab; - private final DialogService dialogService; private final StateManager stateManager; private final BibDatabaseContext database; private final MainTableDataModel model; - - private final ImportHandler importHandler; private final CustomLocalDragboard localDragboard; private final TaskExecutor taskExecutor; private final UndoManager undoManager; private final FilePreferences filePreferences; + private final ImportHandler importHandler; private long lastKeyPressTime; private String columnSearchTerm; @@ -96,29 +89,20 @@ public MainTable(MainTableDataModel model, ClipBoardManager clipBoardManager, BibEntryTypesManager entryTypesManager, TaskExecutor taskExecutor, - FileUpdateMonitor fileUpdateMonitor) { + ImportHandler importHandler) { super(); this.libraryTab = libraryTab; - this.dialogService = dialogService; this.stateManager = stateManager; this.database = Objects.requireNonNull(database); this.model = model; this.taskExecutor = taskExecutor; this.undoManager = libraryTab.getUndoManager(); this.filePreferences = preferencesService.getFilePreferences(); + this.importHandler = importHandler; MainTablePreferences mainTablePreferences = preferencesService.getMainTablePreferences(); - importHandler = new ImportHandler( - database, - preferencesService, - fileUpdateMonitor, - undoManager, - stateManager, - dialogService, - taskExecutor); - localDragboard = stateManager.getLocalDragboard(); this.setOnDragOver(this::handleOnDragOverTableView); @@ -374,39 +358,6 @@ private void clearAndSelectLast() { scrollTo(getItems().size() - 1); } - public void paste() { - List entriesToAdd; - String content = ClipBoardManager.getContents(); - entriesToAdd = importHandler.handleBibTeXData(content); - if (entriesToAdd.isEmpty()) { - entriesToAdd = handleNonBibTeXStringData(content); - } - if (entriesToAdd.isEmpty()) { - return; - } - - importHandler.importEntriesWithDuplicateCheck(database, entriesToAdd); - } - - private List handleNonBibTeXStringData(String data) { - try { - return this.importHandler.handleStringData(data); - } catch (FetcherException exception) { - if (exception instanceof FetcherClientException) { - dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("No data was found for the identifier")); - } else if (exception instanceof FetcherServerException) { - dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("Server not available")); - } else { - dialogService.showErrorDialogAndWait(exception); - } - return List.of(); - } - } - - public void dropEntry(List entriesToAdd) { - importHandler.importEntriesWithDuplicateCheck(database, entriesToAdd); - } - private void handleOnDragOver(TableRow row, BibEntryTableViewModel item, DragEvent event) { if (event.getDragboard().hasFiles()) { event.acceptTransferModes(TransferMode.ANY); From 4c6d1a3ed9332039d437627ec86eb06d23d90569 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:19:58 +0200 Subject: [PATCH 3/6] Seperated notifications --- src/main/java/org/jabref/gui/LibraryTab.java | 158 +++++++++--------- .../java/org/jabref/gui/edit/EditAction.java | 8 +- .../jabref/gui/importer/NewEntryAction.java | 2 +- 3 files changed, 86 insertions(+), 82 deletions(-) diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index de371909e5c..0ce7d557b77 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -75,7 +75,6 @@ import org.jabref.logic.pdf.FileAnnotationCache; import org.jabref.logic.search.LuceneManager; import org.jabref.logic.shared.DatabaseLocation; -import org.jabref.logic.util.UpdateField; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; @@ -461,63 +460,6 @@ public SuggestionProviders getSuggestionProviders() { return suggestionProviders; } - /** - * Removes the selected entries and files linked to selected entries from the database - * - * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" - */ - public void deleteEntry(StandardActions mode) { - deleteEntry(mode, mainTable.getSelectedEntries()); - } - - /** - * Removes the selected entries and files linked to selected entries from the database - * - * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" - */ - private void deleteEntry(StandardActions mode, List entries) { - if (entries.isEmpty()) { - return; - } - if (mode == StandardActions.DELETE_ENTRY && !showDeleteConfirmationDialog(entries.size())) { - return; - } - - // Delete selected entries - getUndoManager().addEdit(new UndoableRemoveEntries(bibDatabaseContext.getDatabase(), entries, mode == StandardActions.CUT)); - bibDatabaseContext.getDatabase().removeEntries(entries); - - if (mode != StandardActions.CUT) { - List linkedFileList = entries.stream() - .flatMap(entry -> entry.getFiles().stream()) - .distinct() - .toList(); - - if (!linkedFileList.isEmpty()) { - List viewModels = linkedFileList.stream() - .map(linkedFile -> linkedFile.toModel(null, bibDatabaseContext, null, null, preferencesService)) - .collect(Collectors.toList()); - - new DeleteFileAction(dialogService, preferencesService.getFilePreferences(), bibDatabaseContext, viewModels).execute(); - } - } - - ensureNotShowingBottomPanel(entries); - - this.changedProperty.setValue(true); - switch (mode) { - case StandardActions.CUT -> dialogService.notify(Localization.lang("Cut %0 entry(ies)", entries.size())); - case StandardActions.DELETE_ENTRY -> dialogService.notify(Localization.lang("Deleted %0 entry(ies)", entries.size())); - } - - // prevent the main table from loosing focus - mainTable.requestFocus(); - } - - public void deleteEntry(BibEntry entry) { - deleteEntry(StandardActions.DELETE_ENTRY, Collections.singletonList(entry)); - } - public void registerUndoableChanges(List changes) { NamedCompound ce = new NamedCompound(Localization.lang("Save actions")); for (FieldChange change : changes) { @@ -537,16 +479,12 @@ public void insertEntry(final BibEntry bibEntry) { public void insertEntries(final List entries) { if (!entries.isEmpty()) { - bibDatabaseContext.getDatabase().insertEntries(entries); + importHandler.importCleanedEntries(entries); - // Set owner and timestamp - UpdateField.setAutomaticFields(entries, - preferencesService.getOwnerPreferences(), - preferencesService.getTimestampPreferences()); // Create an UndoableInsertEntries object. getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries)); - this.changedProperty.setValue(true); // The database just changed. + markBaseChanged(); if (preferencesService.getEntryEditorPreferences().shouldOpenOnNewEntry()) { showAndEdit(entries.getFirst()); } @@ -959,30 +897,35 @@ public void resetChangeMonitor() { stateManager)); } - public void copyEntry() { - List selectedEntries = getSelectedEntries(); + public void copy() { + int entriesCopied = doCopy(getSelectedEntries()); + if (entriesCopied >= 0) { + dialogService.notify(Localization.lang("Copied %0 entry(ies)", entriesCopied)); + } else { + dialogService.notify(Localization.lang("Copy failed", entriesCopied)); + } + } + private int doCopy(List selectedEntries) { if (!selectedEntries.isEmpty()) { - List stringConstants = getUsedStringValues(selectedEntries); + List stringConstants = bibDatabaseContext.getDatabase().getUsedStrings(selectedEntries); try { if (stringConstants.isEmpty()) { clipBoardManager.setContent(selectedEntries, entryTypesManager); } else { clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants); } - dialogService.notify(Localization.lang("Copied %0 entry(ies)", selectedEntries.size())); - } catch ( - IOException e) { + return selectedEntries.size(); + } catch (IOException e) { LOGGER.error("Error while copying selected entries to clipboard.", e); + return -1; } } - } - private List getUsedStringValues(List entries) { - return bibDatabaseContext.getDatabase().getUsedStrings(entries); + return 0; } - public void pasteEntry() { + public void paste() { List entriesToAdd; String content = ClipBoardManager.getContents(); entriesToAdd = importHandler.handleBibTeXData(content); @@ -1016,9 +959,70 @@ public void dropEntry(List entriesToAdd) { importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); } - public void cutEntry() { - copyEntry(); - deleteEntry(StandardActions.CUT); + public void cut() { + int entriesCopied = doCopy(getSelectedEntries()); + int entriesDeleted = doDeleteEntry(StandardActions.CUT, mainTable.getSelectedEntries()); + + if (entriesCopied == entriesDeleted) { + dialogService.notify(Localization.lang("Cut %0 entry(ies)", entriesCopied)); + } else { + dialogService.notify(Localization.lang("Cut failed", entriesCopied)); + undoManager.undo(); + clipBoardManager.setContent(""); + } + } + + /** + * Removes the selected entries and files linked to selected entries from the database + */ + public void delete() { + int entriesDeleted = doDeleteEntry(StandardActions.DELETE_ENTRY, mainTable.getSelectedEntries()); + dialogService.notify(Localization.lang("Deleted %0 entry(ies)", entriesDeleted)); + } + + public void deleteEntry(BibEntry entry) { + doDeleteEntry(StandardActions.DELETE_ENTRY, Collections.singletonList(entry)); + } + + /** + * Removes the selected entries and files linked to selected entries from the database + * + * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" + */ + private int doDeleteEntry(StandardActions mode, List entries) { + if (entries.isEmpty()) { + return 0; + } + if (mode == StandardActions.DELETE_ENTRY && !showDeleteConfirmationDialog(entries.size())) { + return -1; + } + + // Delete selected entries + getUndoManager().addEdit(new UndoableRemoveEntries(bibDatabaseContext.getDatabase(), entries, mode == StandardActions.CUT)); + bibDatabaseContext.getDatabase().removeEntries(entries); + + if (mode != StandardActions.CUT) { + List linkedFileList = entries.stream() + .flatMap(entry -> entry.getFiles().stream()) + .distinct() + .toList(); + + if (!linkedFileList.isEmpty()) { + List viewModels = linkedFileList.stream() + .map(linkedFile -> linkedFile.toModel(null, bibDatabaseContext, null, null, preferencesService)) + .collect(Collectors.toList()); + + new DeleteFileAction(dialogService, preferencesService.getFilePreferences(), bibDatabaseContext, viewModels).execute(); + } + } + + ensureNotShowingBottomPanel(entries); + markBaseChanged(); + + // prevent the main table from loosing focus + mainTable.requestFocus(); + + return entries.size(); } public boolean isModified() { diff --git a/src/main/java/org/jabref/gui/edit/EditAction.java b/src/main/java/org/jabref/gui/edit/EditAction.java index 096539e8574..e0f3663f029 100644 --- a/src/main/java/org/jabref/gui/edit/EditAction.java +++ b/src/main/java/org/jabref/gui/edit/EditAction.java @@ -78,10 +78,10 @@ public void execute() { // Not sure what is selected -> copy/paste/cut selected entries except for Preview and CodeArea switch (action) { - case COPY -> tabSupplier.get().copyEntry(); - case CUT -> tabSupplier.get().cutEntry(); - case PASTE -> tabSupplier.get().pasteEntry(); - case DELETE_ENTRY -> tabSupplier.get().deleteEntry(StandardActions.DELETE_ENTRY); + case COPY -> tabSupplier.get().copy(); + case CUT -> tabSupplier.get().cut(); + case PASTE -> tabSupplier.get().paste(); + case DELETE_ENTRY -> tabSupplier.get().delete(); case UNDO -> { if (undoManager.canUndo()) { undoManager.undo(); diff --git a/src/main/java/org/jabref/gui/importer/NewEntryAction.java b/src/main/java/org/jabref/gui/importer/NewEntryAction.java index a47e1a9f6c6..6a3e70cc249 100644 --- a/src/main/java/org/jabref/gui/importer/NewEntryAction.java +++ b/src/main/java/org/jabref/gui/importer/NewEntryAction.java @@ -43,7 +43,7 @@ public NewEntryAction(Supplier tabSupplier, DialogService dialogServ public NewEntryAction(Supplier tabSupplier, EntryType type, DialogService dialogService, PreferencesService preferences, StateManager stateManager) { this(tabSupplier, dialogService, preferences, stateManager); - this.type = Optional.of(type); + this.type = Optional.ofNullable(type); } @Override From 7442e75b07850972f725114001bb9aea3e4f57fd Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:22:36 +0200 Subject: [PATCH 4/6] l10n --- src/main/resources/l10n/JabRef_en.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index b105285632a..c2c8bb4ce56 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2765,6 +2765,9 @@ Ask\ every\ time=Ask every time Value\ is\ not\ in\ Unicode's\ Normalization\ Form\ "Canonical\ Composition"\ (NFC)\ format=Value is not in Unicode's Normalization Form "Canonical Composition" (NFC) format +Copy\ failed=Copy failed +Cut\ failed=Cut failed + Group\ icons=Group icons Redownload\ file=Redownload file Redownload\ missing\ files=Redownload missing files From 9398f9660d9c21f579800a7bc3db55378d25f2b2 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sat, 7 Sep 2024 22:31:39 +0200 Subject: [PATCH 5/6] CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ff60969f28..4aec4ed2dc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed an issue where the full-text search results were incomplete. [#8626](https://github.com/JabRef/jabref/issues/8626) - We fixed an issue where search result highlighting was incorrectly highlighting the boolean operators. [#11595](https://github.com/JabRef/jabref/issues/11595) - We fixed an issue where search result highlighting was broken at complex searches. [#8067](https://github.com/JabRef/jabref/issues/8067) +- We fixed an issue where two contradicting notifications were shown when cutting an entry in the maintaible. [#11724](https://github.com/JabRef/jabref/pull/11724) + ### Removed From 83d48aee4fa3525ade482cd81c878f270a4f4d2d Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sat, 7 Sep 2024 22:44:21 +0200 Subject: [PATCH 6/6] Wording consistency --- src/main/java/org/jabref/gui/LibraryTab.java | 54 +++++++++---------- .../java/org/jabref/gui/edit/EditAction.java | 8 +-- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index 0ce7d557b77..d50a9b8cb8e 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -471,27 +471,6 @@ public void registerUndoableChanges(List changes) { } } - public void insertEntry(final BibEntry bibEntry) { - if (bibEntry != null) { - insertEntries(Collections.singletonList(bibEntry)); - } - } - - public void insertEntries(final List entries) { - if (!entries.isEmpty()) { - importHandler.importCleanedEntries(entries); - - // Create an UndoableInsertEntries object. - getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries)); - - markBaseChanged(); - if (preferencesService.getEntryEditorPreferences().shouldOpenOnNewEntry()) { - showAndEdit(entries.getFirst()); - } - clearAndSelect(entries.getFirst()); - } - } - public void editEntryAndFocusField(BibEntry entry, Field field) { showAndEdit(entry); Platform.runLater(() -> { @@ -897,8 +876,27 @@ public void resetChangeMonitor() { stateManager)); } - public void copy() { - int entriesCopied = doCopy(getSelectedEntries()); + public void insertEntry(final BibEntry bibEntry) { + insertEntries(List.of(bibEntry)); + } + + public void insertEntries(final List entries) { + if (!entries.isEmpty()) { + importHandler.importCleanedEntries(entries); + + // Create an UndoableInsertEntries object. + getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries)); + + markBaseChanged(); + if (preferencesService.getEntryEditorPreferences().shouldOpenOnNewEntry()) { + showAndEdit(entries.getFirst()); + } + clearAndSelect(entries.getFirst()); + } + } + + public void copyEntry() { + int entriesCopied = doCopyEntry(getSelectedEntries()); if (entriesCopied >= 0) { dialogService.notify(Localization.lang("Copied %0 entry(ies)", entriesCopied)); } else { @@ -906,7 +904,7 @@ public void copy() { } } - private int doCopy(List selectedEntries) { + private int doCopyEntry(List selectedEntries) { if (!selectedEntries.isEmpty()) { List stringConstants = bibDatabaseContext.getDatabase().getUsedStrings(selectedEntries); try { @@ -925,7 +923,7 @@ private int doCopy(List selectedEntries) { return 0; } - public void paste() { + public void pasteEntry() { List entriesToAdd; String content = ClipBoardManager.getContents(); entriesToAdd = importHandler.handleBibTeXData(content); @@ -959,8 +957,8 @@ public void dropEntry(List entriesToAdd) { importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); } - public void cut() { - int entriesCopied = doCopy(getSelectedEntries()); + public void cutEntry() { + int entriesCopied = doCopyEntry(getSelectedEntries()); int entriesDeleted = doDeleteEntry(StandardActions.CUT, mainTable.getSelectedEntries()); if (entriesCopied == entriesDeleted) { @@ -975,7 +973,7 @@ public void cut() { /** * Removes the selected entries and files linked to selected entries from the database */ - public void delete() { + public void deleteEntry() { int entriesDeleted = doDeleteEntry(StandardActions.DELETE_ENTRY, mainTable.getSelectedEntries()); dialogService.notify(Localization.lang("Deleted %0 entry(ies)", entriesDeleted)); } diff --git a/src/main/java/org/jabref/gui/edit/EditAction.java b/src/main/java/org/jabref/gui/edit/EditAction.java index e0f3663f029..c6be070e0e8 100644 --- a/src/main/java/org/jabref/gui/edit/EditAction.java +++ b/src/main/java/org/jabref/gui/edit/EditAction.java @@ -78,10 +78,10 @@ public void execute() { // Not sure what is selected -> copy/paste/cut selected entries except for Preview and CodeArea switch (action) { - case COPY -> tabSupplier.get().copy(); - case CUT -> tabSupplier.get().cut(); - case PASTE -> tabSupplier.get().paste(); - case DELETE_ENTRY -> tabSupplier.get().delete(); + case COPY -> tabSupplier.get().copyEntry(); + case CUT -> tabSupplier.get().cutEntry(); + case PASTE -> tabSupplier.get().pasteEntry(); + case DELETE_ENTRY -> tabSupplier.get().deleteEntry(); case UNDO -> { if (undoManager.canUndo()) { undoManager.undo();