diff --git a/CHANGELOG.md b/CHANGELOG.md index bc0063bb095..468e99f68d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We added an option on the Linked File Viewer to rename the attached file of an entry directly on the JabRef. [#4844](https://github.com/JabRef/jabref/issues/4844) - We added an option in the preference dialog box that allows user to enable helpful tooltips.[#3599](https://github.com/JabRef/jabref/issues/3599) - We moved the dropdown menu for selecting the push-application from the toolbar into the external application preferences. [#674](https://github.com/JabRef/jabref/issues/674) +- We removed the alphabetical ordering of the custom tabs and updated the error message when trying to create a general field with a name containing an illegal character. [#5019](https://github.com/JabRef/jabref/issues/5019) ### Fixed diff --git a/build.gradle b/build.gradle index 3180ee81625..2e188254c1a 100644 --- a/build.gradle +++ b/build.gradle @@ -97,7 +97,7 @@ dependencies { compile group: 'org.apache.tika', name: 'tika-core', version: '1.21' // required for reading write-protected PDFs - see https://github.com/JabRef/jabref/pull/942#issuecomment-209252635 - compile 'org.bouncycastle:bcprov-jdk15on:1.61' + compile 'org.bouncycastle:bcprov-jdk15on:1.62' compile 'commons-cli:commons-cli:1.4' diff --git a/src/main/java/org/jabref/gui/customizefields/CustomizeGeneralFieldsDialogViewModel.java b/src/main/java/org/jabref/gui/customizefields/CustomizeGeneralFieldsDialogViewModel.java index 1d388df6555..638ffc9014f 100644 --- a/src/main/java/org/jabref/gui/customizefields/CustomizeGeneralFieldsDialogViewModel.java +++ b/src/main/java/org/jabref/gui/customizefields/CustomizeGeneralFieldsDialogViewModel.java @@ -60,7 +60,7 @@ public void saveFields() { String title = Localization.lang("Error"); String content = Localization.lang("Field names are not allowed to contain white space or the following " + "characters") - + ": # { } ~ , ^ &"; + + ": # { } ( ) ~ , ^ & - \" ' ` สน \\"; dialogService.showInformationDialogAndWait(title, content); return; } diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditorTabList.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditorTabList.java index f35f8c94ad6..49a337788a9 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditorTabList.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditorTabList.java @@ -1,9 +1,9 @@ package org.jabref.gui.entryeditor; import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; import org.jabref.preferences.JabRefPreferences; @@ -17,7 +17,7 @@ private EntryEditorTabList() { } public static Map> create(JabRefPreferences preferences) { - Map> tabs = new TreeMap<>(); + Map> tabs = new LinkedHashMap<>(); int i = 0; String name; if (preferences.hasKey(JabRefPreferences.CUSTOM_TAB_NAME + 0)) { diff --git a/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java b/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java index d5b25ae7aea..a47ba6f02be 100644 --- a/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java +++ b/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java @@ -91,17 +91,16 @@ public void clearLog() { */ public void reportIssue() { try { - String issueTitle = "Automatic Bug Report - " + dateFormat.format(date); - // system info + // System info String systemInfo = String.format("JabRef %s%n%s %s %s %nJava %s", buildInfo.getVersion(), BuildInfo.OS, BuildInfo.OS_VERSION, BuildInfo.OS_ARCH, BuildInfo.JAVA_VERSION); - // steps to reproduce + // Steps to reproduce String howToReproduce = "Steps to reproduce:\n\n1. ...\n2. ...\n3. ..."; - // log messages + // Log messages String issueDetails = "
\n" + "" + "Detail information:" + "\n\n```\n" + getLogMessagesAsString(allMessagesData) + "\n```\n\n
"; clipBoardManager.setContent(issueDetails); - // bug report body + // Bug report body String issueBody = systemInfo + "\n\n" + howToReproduce + "\n\n" + "Paste your log details here."; dialogService.notify(Localization.lang("Issue on GitHub successfully reported.")); @@ -114,7 +113,6 @@ public void reportIssue() { URIBuilder uriBuilder = new URIBuilder() .setScheme("https").setHost("github.com") .setPath("/JabRef/jabref/issues/new") - .setParameter("title", issueTitle) .setParameter("body", issueBody); JabRefDesktop.openBrowser(uriBuilder.build().toString()); } catch (IOException | URISyntaxException e) { diff --git a/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java b/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java index ae5352deade..40ad459433b 100644 --- a/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java +++ b/src/main/java/org/jabref/gui/importer/ImportEntriesDialog.java @@ -20,6 +20,7 @@ import javafx.scene.layout.VBox; import javafx.scene.text.Text; +import org.jabref.Globals; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.icon.IconTheme; @@ -108,12 +109,14 @@ private void initialize() { container.getStyleClass().add("entry-container"); BindingsHelper.includePseudoClassWhen(container, entrySelected, addToggle.selectedProperty()); - if (viewModel.hasDuplicate(entry)) { - Button duplicateButton = IconTheme.JabRefIcons.DUPLICATE.asButton(); - duplicateButton.setTooltip(new Tooltip(Localization.lang("Possible duplicate of existing entry. Click to resolve."))); - duplicateButton.setOnAction(event -> viewModel.resolveDuplicate(entry)); - container.getChildren().add(1, duplicateButton); - } + BackgroundTask.wrap(() -> viewModel.hasDuplicate(entry)).onSuccess(duplicateFound -> { + if (duplicateFound) { + Button duplicateButton = IconTheme.JabRefIcons.DUPLICATE.asButton(); + duplicateButton.setTooltip(new Tooltip(Localization.lang("Possible duplicate of existing entry. Click to resolve."))); + duplicateButton.setOnAction(event -> viewModel.resolveDuplicate(entry)); + container.getChildren().add(1, duplicateButton); + } + }).executeWith(Globals.TASK_EXECUTOR); return container; }) diff --git a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java index 6f0b2fad4ad..b7fec8440c9 100644 --- a/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java +++ b/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java @@ -10,6 +10,7 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import org.jabref.Globals; import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; @@ -50,7 +51,7 @@ public ImportEntriesViewModel(BackgroundTask> task, TaskExecutor this.message.bind(task.messageProperty()); task.onSuccess(entriesToImport -> entries.addAll(entriesToImport)) - .executeWith(taskExecutor); + .executeWith(taskExecutor); } public String getMessage() { @@ -75,24 +76,32 @@ public void importEntries(List entriesToImport) { // Check if we are supposed to warn about duplicates. // If so, then see if there are duplicates, and warn if yes. if (preferences.shouldWarnAboutDuplicatesForImport()) { - boolean containsDuplicate = entriesToImport.stream() - .anyMatch(this::hasDuplicate); - - if (containsDuplicate) { - boolean continueImport = dialogService.showConfirmationDialogWithOptOutAndWait(Localization.lang("Duplicates found"), - Localization.lang("There are possible duplicates (marked with an icon) that haven't been resolved. Continue?"), - Localization.lang("Continue with import"), - Localization.lang("Cancel import"), - Localization.lang("Disable this confirmation dialog"), - optOut -> preferences.setShouldWarnAboutDuplicatesForImport(!optOut)); - - if (!continueImport) { - dialogService.notify(Localization.lang("Import canceled")); - return; + BackgroundTask.wrap(() -> entriesToImport.stream() + .anyMatch(this::hasDuplicate)).onSuccess(duplicateFound -> { + if (duplicateFound) { + boolean continueImport = dialogService.showConfirmationDialogWithOptOutAndWait(Localization.lang("Duplicates found"), + Localization.lang("There are possible duplicates (marked with an icon) that haven't been resolved. Continue?"), + Localization.lang("Continue with import"), + Localization.lang("Cancel import"), + Localization.lang("Disable this confirmation dialog"), + optOut -> preferences.setShouldWarnAboutDuplicatesForImport(!optOut)); + + if (!continueImport) { + dialogService.notify(Localization.lang("Import canceled")); + } else { + buildImportHandlerThenImportEntries(entriesToImport); + } + } else { + buildImportHandlerThenImportEntries(entriesToImport); } - } + }).executeWith(Globals.TASK_EXECUTOR); + } else { + buildImportHandlerThenImportEntries(entriesToImport); } + } + + private void buildImportHandlerThenImportEntries(List entriesToImport) { ImportHandler importHandler = new ImportHandler( dialogService, database, @@ -104,7 +113,6 @@ public void importEntries(List entriesToImport) { undoManager, stateManager); importHandler.importEntries(entriesToImport); - dialogService.notify(Localization.lang("Number of entries successfully imported") + ": " + entriesToImport.size()); } diff --git a/src/main/java/org/jabref/gui/shared/MergeSharedEntryDialog.java b/src/main/java/org/jabref/gui/shared/MergeSharedEntryDialog.java deleted file mode 100644 index 44a26afd33b..00000000000 --- a/src/main/java/org/jabref/gui/shared/MergeSharedEntryDialog.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.jabref.gui.shared; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.WindowConstants; -import javax.swing.border.EmptyBorder; - -import javafx.scene.Scene; - -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.customjfx.CustomJFXPanel; -import org.jabref.gui.mergeentries.MergeEntries; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.database.BibDatabaseMode; -import org.jabref.model.database.shared.DatabaseSynchronizer; -import org.jabref.model.entry.BibEntry; - -public class MergeSharedEntryDialog { - - private final JabRefFrame jabRefFrame; - private final DatabaseSynchronizer dbmsSynchronizer; - private final BibEntry localBibEntry; - private final BibEntry sharedBibEntry; - private final JDialog mergeDialog; - private final MergeEntries mergeEntries; - - - public MergeSharedEntryDialog(JabRefFrame jabRefFrame, DatabaseSynchronizer dbmsSynchronizer, BibEntry localBibEntry, - BibEntry sharedBibEntry, BibDatabaseMode bibDatabaseMode) { - this.jabRefFrame = jabRefFrame; - this.dbmsSynchronizer = dbmsSynchronizer; - this.localBibEntry = localBibEntry; - this.sharedBibEntry = sharedBibEntry; - this.mergeDialog = new JDialog((JFrame) null, Localization.lang("Update refused"), true); - this.mergeEntries = new MergeEntries(sharedBibEntry, localBibEntry, Localization.lang("Shared entry"), - Localization.lang("Local entry"), bibDatabaseMode); - } - - public void showMergeDialog() { - - mergeDialog.setMinimumSize(new Dimension(600, 600)); - - StringBuilder message = new StringBuilder(); - message.append(""); - message.append(""); - message.append(Localization.lang("Update could not be performed due to existing change conflicts.")); - message.append(""); - message.append("

"); - message.append(Localization.lang("You are not working on the newest version of BibEntry.")); - message.append("

"); - message.append(Localization.lang("Shared version: %0", String.valueOf(sharedBibEntry.getSharedBibEntryData().getVersion()))); - message.append("
"); - message.append(Localization.lang("Local version: %0", String.valueOf(localBibEntry.getSharedBibEntryData().getVersion()))); - message.append("

"); - message.append(Localization.lang("Please merge the shared entry with yours and press \"Merge entries\" to resolve this problem.")); - message.append("
"); - - JLabel mergeInnformation = new JLabel(message.toString()); - mergeInnformation.setBorder(new EmptyBorder(9, 9, 9, 9)); - - mergeDialog.add(mergeInnformation, BorderLayout.NORTH); - mergeDialog.add(CustomJFXPanel.wrap(new Scene(mergeEntries)), BorderLayout.CENTER); - - JButton mergeButton = new JButton(Localization.lang("Merge entries")); - mergeButton.addActionListener(e -> mergeEntries()); - - JButton cancelButton = new JButton(Localization.lang("Cancel")); - cancelButton.addActionListener(e -> showConfirmationDialog()); - - JPanel buttonPanel = new JPanel(); - buttonPanel.add(mergeButton, BorderLayout.WEST); - buttonPanel.add(cancelButton, BorderLayout.EAST); - - mergeDialog.add(buttonPanel, BorderLayout.SOUTH); - mergeDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - mergeDialog.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - showConfirmationDialog(); - } - }); - - mergeDialog.pack(); - mergeDialog.setVisible(true); - } - - private void showConfirmationDialog() { - int answer = JOptionPane.showConfirmDialog(mergeDialog, - Localization.lang("Canceling this operation will leave your changes unsynchronized. Cancel anyway?"), - Localization.lang("Warning"), JOptionPane.YES_NO_OPTION); - - if (answer == 0) { - mergeDialog.dispose(); - } - } - - private void mergeEntries() { - BibEntry mergedBibEntry = mergeEntries.getMergeEntry(); - mergedBibEntry.getSharedBibEntryData().setSharedID(sharedBibEntry.getSharedBibEntryData().getSharedID()); - mergedBibEntry.getSharedBibEntryData().setVersion(sharedBibEntry.getSharedBibEntryData().getVersion()); - - mergeDialog.dispose(); // dispose before synchronizing to avoid multiple merge windows in case of new conflict. - - dbmsSynchronizer.synchronizeSharedEntry(mergedBibEntry); - dbmsSynchronizer.synchronizeLocalDatabase(); - } -} diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index 1d9de038f98..85d6683915e 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java @@ -5,6 +5,7 @@ import java.util.Optional; import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonBar.ButtonData; import javafx.scene.control.ButtonType; @@ -14,6 +15,7 @@ import org.jabref.gui.JabRefFrame; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; +import org.jabref.gui.mergeentries.MergeEntriesDialog; import org.jabref.gui.undo.UndoableRemoveEntry; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.l10n.Localization; @@ -31,6 +33,7 @@ import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.database.shared.DatabaseNotSupportedException; import org.jabref.model.database.shared.DatabaseSynchronizer; +import org.jabref.model.entry.BibEntry; import com.google.common.eventbus.Subscribe; @@ -81,9 +84,40 @@ public void listen(UpdateRefusedEvent updateRefusedEvent) { jabRefFrame.getDialogService().notify(Localization.lang("Update refused.")); - new MergeSharedEntryDialog(jabRefFrame, dbmsSynchronizer, updateRefusedEvent.getLocalBibEntry(), - updateRefusedEvent.getSharedBibEntry(), - updateRefusedEvent.getBibDatabaseContext().getMode()).showMergeDialog(); + BibEntry localBibEntry = updateRefusedEvent.getLocalBibEntry(); + BibEntry sharedBibEntry = updateRefusedEvent.getSharedBibEntry(); + + StringBuilder message = new StringBuilder(); + message.append(Localization.lang("Update could not be performed due to existing change conflicts.")); + message.append("\r\n"); + message.append(Localization.lang("You are not working on the newest version of BibEntry.")); + message.append("\r\n"); + message.append(Localization.lang("Shared version: %0", String.valueOf(sharedBibEntry.getSharedBibEntryData().getVersion()))); + message.append("\r\n"); + message.append(Localization.lang("Local version: %0", String.valueOf(localBibEntry.getSharedBibEntryData().getVersion()))); + message.append("\r\n"); + message.append(Localization.lang("Press \"Merge entries\" to merge the changes and resolve this problem.")); + message.append("\r\n"); + message.append(Localization.lang("Canceling this operation will leave your changes unsynchronized.")); + + ButtonType merge = new ButtonType(Localization.lang("Merge entries"), ButtonBar.ButtonData.YES); + + Optional response = dialogService.showCustomButtonDialogAndWait(AlertType.CONFIRMATION, Localization.lang("Update refused"), message.toString(), ButtonType.CANCEL, merge); + + if (response.isPresent() && response.get().equals(merge)) { + MergeEntriesDialog dialog = new MergeEntriesDialog(localBibEntry, sharedBibEntry, updateRefusedEvent.getBibDatabaseContext().getMode()); + Optional mergedEntry = dialog.showAndWait(); + + mergedEntry.ifPresent(mergedBibEntry -> { + mergedBibEntry.getSharedBibEntryData().setSharedID(sharedBibEntry.getSharedBibEntryData().getSharedID()); + mergedBibEntry.getSharedBibEntryData().setVersion(sharedBibEntry.getSharedBibEntryData().getVersion()); + + dbmsSynchronizer.synchronizeSharedEntry(mergedBibEntry); + dbmsSynchronizer.synchronizeLocalDatabase(); + }); + + } + } @Subscribe diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 93f6fe91f13..aac27fc48ee 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1739,14 +1739,12 @@ Work\ offline=Work offline Working\ offline.=Working offline. Update\ refused.=Update refused. Update\ refused=Update refused -Local\ entry=Local entry -Shared\ entry=Shared entry Update\ could\ not\ be\ performed\ due\ to\ existing\ change\ conflicts.=Update could not be performed due to existing change conflicts. You\ are\ not\ working\ on\ the\ newest\ version\ of\ BibEntry.=You are not working on the newest version of BibEntry. Local\ version\:\ %0=Local version: %0 Shared\ version\:\ %0=Shared version: %0 -Please\ merge\ the\ shared\ entry\ with\ yours\ and\ press\ "Merge\ entries"\ to\ resolve\ this\ problem.=Please merge the shared entry with yours and press "Merge entries" to resolve this problem. -Canceling\ this\ operation\ will\ leave\ your\ changes\ unsynchronized.\ Cancel\ anyway?=Canceling this operation will leave your changes unsynchronized. Cancel anyway? +Press\ "Merge\ entries"\ to\ merge\ the\ changes\ and\ resolve\ this\ problem.=Press "Merge entries" to merge the changes and resolve this problem. +Canceling\ this\ operation\ will\ leave\ your\ changes\ unsynchronized.=Canceling this operation will leave your changes unsynchronized. Shared\ entry\ is\ no\ longer\ present=Shared entry is no longer present The\ entry\ you\ currently\ work\ on\ has\ been\ deleted\ on\ the\ shared\ side.=The entry you currently work on has been deleted on the shared side. You\ can\ restore\ the\ entry\ using\ the\ "Undo"\ operation.=You can restore the entry using the "Undo" operation.