diff --git a/CHANGELOG.md b/CHANGELOG.md index 30479976bc9..72c639ea0e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,15 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - The background color of the hit counter signals whether the group contains all/any of the entries selected in the main table. - Added a possibility to filter the groups panel [#1904](https://github.com/JabRef/jabref/issues/1904) - Removed edit mode. + - Removed the following commands in the right-click menu: + - Expand/collapse subtree + - Move up/down/left/right + - Remove option to "highlight overlapping groups" + - Moved the option to "Gray out non-hits" / "Hide non-hits" to the preferences + - Removed the following options from the group preferences: + - Show icons (icons can now be customized) + - Show dynamic groups in italics (dynamic groups are not treated specially now) + - Initially show groups tree expanded (always true now) - Redesigned about dialog. - Redesigned key bindings dialog. - Redesigned journal abbreviations dialog. @@ -47,13 +56,18 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - The `Move linked files to default file directory`-Cleanup operation respects the `File directory pattern` setting - We separated the `Move file` and `Rename Pdfs` logic and context menu entries in the `General`-Tab for the Field `file` to improve the semantics - A scrollbar was added to the cleanup panel, as a result of issue [#2501](https://github.com/JabRef/jabref/issues/2501) -- Using "Look up document identifier" in the quality menu, it is possible to look up DOIs and other identifiers for multiple entries. +- Using "Look up document identifier" in the quality menu, it is possible to look up DOIs, ArXiv ids and other identifiers for multiple entries. - F4 opens selected file in current JTable context not just from selected entry inside the main table [#2355](https://github.com/JabRef/jabref/issues/2355) - We added an option to copy the title of BibTeX entries to the clipboard through `Edit -> Copy title` (implements [#210](https://github.com/koppor/jabref/issues/210)) - Several scrollbars were added to the preference dialog which show up when content is too large [#2559](https://github.com/JabRef/jabref/issues/2559) - We fixed and improved the auto detection of the OpenOffice and LibreOffice connection +- Entries with a single corporate author are now correclty exported to the corresponding `corporate` author field in MS-Office XML. [#1497](https://github.com/JabRef/jabref/issues/1497) +- Improved author handling in MS-Office Import/Export +- The `day` part of the biblatex `date` field is now exported to the corresponding `day` field in MS-Office XML. [#2691](https://github.com/JabRef/jabref/issues/2691) ### Fixed + - We fixed an issue of duplicate keys after using a fetcher, e.g., DOI or ISBN [#2867](https://github.com/JabRef/jabref/issues/2687) + - We fixed an issue that prevented multiple parallel JabRef instances from terminating gracefully. [#2698](https://github.com/JabRef/jabref/issues/2698) - We fixed an issue where authors with multiple surnames were not presented correctly in the main table. [#2534](https://github.com/JabRef/jabref/issues/2534) - Repairs the handling of apostrophes in the LaTeX to unicode conversion. [#2500](https://github.com/JabRef/jabref/issues/2500) - Fix import of journal title in ris format. [#2506](https://github.com/JabRef/jabref/issues/2506) @@ -66,7 +80,6 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - Fixed the synchronization logic of keywords and special fields and vice versa [#2580](https://github.com/JabRef/jabref/issues/2580) - We fixed an exception that prevented JabRef from starting in rare cases [bug report in the forum](http://discourse.jabref.org/t/jabref-not-opening/476). - We fixed an unhandled exception when saving an entry containing unbalanced braces [#2571](https://github.com/JabRef/jabref/issues/2571) - - Fixed a display issue when removing a group with a long name [#1407](https://github.com/JabRef/jabref/issues/1407) - The group selection is no longer lost when switching tabs [#1104](https://github.com/JabRef/jabref/issues/1104) - We fixed an issue where the "find unlinked files" functionality threw an error when only one PDF was imported but not assigned to an entry [#2577](https://github.com/JabRef/jabref/issues/2577) @@ -81,6 +94,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We fixed an issue where the file folder could not be changed when running `Get fulltext` in the `general`-tab. [#2572](https://github.com/JabRef/jabref/issues/2572) - Newly created libraries no longer have the executable bit set under POSIX/Linux systems. The file permissions are now set to `664 (-rw-rw-r--)`. [#2635](https://github.com/JabRef/jabref/issues/#2635) - OpenOffice text formatting now handles nested tags properly [#2483](https://github.com/JabRef/jabref/issues/#2483) + - We fixed an issue where the dialog for selecting the main file directory in the preferences opened the the wrong folder ### Removed diff --git a/build.gradle b/build.gradle index ad12127b7a8..9ff197bff8f 100644 --- a/build.gradle +++ b/build.gradle @@ -96,8 +96,8 @@ dependencies { antlr3 'org.antlr:antlr:3.5.2' compile 'org.antlr:antlr-runtime:3.5.2' - antlr4 'org.antlr:antlr4:4.6' - compile 'org.antlr:antlr4-runtime:4.6' + antlr4 'org.antlr:antlr4:4.7' + compile 'org.antlr:antlr4-runtime:4.7' // VersionEye states that 6.0.5 is the most recent version, but http://dev.mysql.com/downloads/connector/j/ shows that as "Development Release" compile 'mysql:mysql-connector-java:5.1.40' @@ -137,10 +137,10 @@ dependencies { compile 'com.github.lgooddatepicker:LGoodDatePicker:8.3.0' - compile 'com.github.tomtung:latex2unicode_2.12:0.2-SNAPSHOT' + compile 'com.github.tomtung:latex2unicode_2.12:0.2' testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:2.7.18' + testCompile 'org.mockito:mockito-core:2.7.21' testCompile 'com.github.tomakehurst:wiremock:2.5.1' testCompile 'org.assertj:assertj-swing-junit:3.5.0' testCompile 'org.reflections:reflections:0.9.11' diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 51288f9c2f0..3ecb04995fb 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 265787b282e..d05f46769d9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Jan 05 09:52:38 CET 2017 +#Mon Mar 27 08:28:31 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip diff --git a/src/main/java/org/jabref/Globals.java b/src/main/java/org/jabref/Globals.java index 5b36e854012..b41d21027fb 100644 --- a/src/main/java/org/jabref/Globals.java +++ b/src/main/java/org/jabref/Globals.java @@ -4,6 +4,8 @@ import org.jabref.gui.GlobalFocusListener; import org.jabref.gui.StateManager; import org.jabref.gui.keyboard.KeyBindingPreferences; +import org.jabref.gui.util.DefaultTaskExecutor; +import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.importer.ImportFormatReader; import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jabref.logic.protectedterms.ProtectedTermsLoader; @@ -19,32 +21,26 @@ public class Globals { public static final RemoteListenerServerLifecycle REMOTE_LISTENER = new RemoteListenerServerLifecycle(); public static final ImportFormatReader IMPORT_FORMAT_READER = new ImportFormatReader(); - - + public static final TaskExecutor taskExecutor = new DefaultTaskExecutor(); // In the main program, this field is initialized in JabRef.java // Each test case initializes this field if required public static JabRefPreferences prefs; - /** * This field is initialized upon startup. * Only GUI code is allowed to access it, logic code should use dependency injection. */ public static JournalAbbreviationLoader journalAbbreviationLoader; - /** * This field is initialized upon startup. * Only GUI code is allowed to access it, logic code should use dependency injection. */ public static ProtectedTermsLoader protectedTermsLoader; - /** * Manager for the state of the GUI. */ public static StateManager stateManager = new StateManager(); - // Key binding preferences private static KeyBindingPreferences keyPrefs; - // Background tasks private static GlobalFocusListener focusListener; private static FileUpdateMonitor fileUpdateMonitor; @@ -76,4 +72,9 @@ public static GlobalFocusListener getFocusListener() { public static FileUpdateMonitor getFileUpdateMonitor() { return fileUpdateMonitor; } + + public static void shutdownThreadPools() { + taskExecutor.shutdown(); + JabRefExecutorService.INSTANCE.shutdownEverything(); + } } diff --git a/src/main/java/org/jabref/JabRefExecutorService.java b/src/main/java/org/jabref/JabRefExecutorService.java index 2cb9b9450c9..a87c23b7cda 100644 --- a/src/main/java/org/jabref/JabRefExecutorService.java +++ b/src/main/java/org/jabref/JabRefExecutorService.java @@ -16,27 +16,22 @@ */ public class JabRefExecutorService implements Executor { - private static final Log LOGGER = LogFactory.getLog(JabRefExecutorService.class); - public static final JabRefExecutorService INSTANCE = new JabRefExecutorService(); - - private Thread remoteThread; - + private static final Log LOGGER = LogFactory.getLog(JabRefExecutorService.class); private final ExecutorService executorService = Executors.newCachedThreadPool(r -> { Thread thread = new Thread(r); thread.setName("JabRef CachedThreadPool"); thread.setUncaughtExceptionHandler(new FallbackExceptionHandler()); return thread; }); - private final ExecutorService lowPriorityExecutorService = Executors.newCachedThreadPool(r -> { Thread thread = new Thread(r); thread.setName("JabRef LowPriorityCachedThreadPool"); thread.setUncaughtExceptionHandler(new FallbackExceptionHandler()); return thread; }); - private final Timer timer = new Timer("timer", true); + private Thread remoteThread; private JabRefExecutorService() {} @@ -77,29 +72,6 @@ public void executeInterruptableTask(final Runnable runnable, String taskName) { this.lowPriorityExecutorService.execute(new NamedRunnable(taskName, runnable)); } - class NamedRunnable implements Runnable { - - private final String name; - - private final Runnable task; - - public NamedRunnable(String name, Runnable runnable){ - this.name = name; - this.task = runnable; - } - - @Override - public void run() { - final String orgName = Thread.currentThread().getName(); - Thread.currentThread().setName(name); - try { - task.run(); - } finally { - Thread.currentThread().setName(orgName); - } - } - } - public void executeInterruptableTaskAndWait(Runnable runnable) { if(runnable == null) { LOGGER.debug("Received null as command for execution"); @@ -149,4 +121,27 @@ public void shutdownEverything() { // timer doesn't need to be canceled as it is run in daemon mode, which ensures that it is stopped if the application is shut down } + class NamedRunnable implements Runnable { + + private final String name; + + private final Runnable task; + + public NamedRunnable(String name, Runnable runnable) { + this.name = name; + this.task = runnable; + } + + @Override + public void run() { + final String orgName = Thread.currentThread().getName(); + Thread.currentThread().setName(name); + try { + task.run(); + } finally { + Thread.currentThread().setName(orgName); + } + } + } + } diff --git a/src/main/java/org/jabref/JabRefMain.java b/src/main/java/org/jabref/JabRefMain.java index 639b3b52a53..cf7b1440b24 100644 --- a/src/main/java/org/jabref/JabRefMain.java +++ b/src/main/java/org/jabref/JabRefMain.java @@ -115,7 +115,9 @@ private static void start(String[] args) { // We have successfully sent our command line options through the socket to another JabRef instance. // So we assume it's all taken care of, and quit. LOGGER.info(Localization.lang("Arguments passed on to running JabRef instance. Shutting down.")); - JabRefExecutorService.INSTANCE.shutdownEverything(); + Globals.shutdownThreadPools(); + // needed to tell JavaFx to stop + Platform.exit(); return; } } @@ -132,7 +134,7 @@ private static void start(String[] args) { // See if we should shut down now if (argumentProcessor.shouldShutDown()) { - JabRefExecutorService.INSTANCE.shutdownEverything(); + Globals.shutdownThreadPools(); return; } diff --git a/src/main/java/org/jabref/collab/ChangeScanner.java b/src/main/java/org/jabref/collab/ChangeScanner.java index 9568c6481d6..9c96bd27941 100644 --- a/src/main/java/org/jabref/collab/ChangeScanner.java +++ b/src/main/java/org/jabref/collab/ChangeScanner.java @@ -17,6 +17,7 @@ import org.jabref.JabRefExecutorService; import org.jabref.gui.BasePanel; import org.jabref.gui.JabRefFrame; +import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.bibtex.comparator.EntryComparator; import org.jabref.logic.exporter.BibDatabaseWriter; import org.jabref.logic.exporter.BibtexDatabaseWriter; @@ -29,7 +30,6 @@ import org.jabref.logic.importer.ParserResult; import org.jabref.logic.l10n.Localization; import org.jabref.model.Defaults; -import org.jabref.model.DuplicateCheck; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.EntrySorter; diff --git a/src/main/java/org/jabref/collab/EntryChange.java b/src/main/java/org/jabref/collab/EntryChange.java index 1ea9498f00f..eaeb5d111ec 100644 --- a/src/main/java/org/jabref/collab/EntryChange.java +++ b/src/main/java/org/jabref/collab/EntryChange.java @@ -13,8 +13,8 @@ import org.jabref.gui.BasePanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableFieldChange; +import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.l10n.Localization; -import org.jabref.model.DuplicateCheck; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; diff --git a/src/main/java/org/jabref/collab/EntryDeleteChange.java b/src/main/java/org/jabref/collab/EntryDeleteChange.java index 3d474262f3b..b9b128dc6bb 100644 --- a/src/main/java/org/jabref/collab/EntryDeleteChange.java +++ b/src/main/java/org/jabref/collab/EntryDeleteChange.java @@ -7,8 +7,8 @@ import org.jabref.gui.PreviewPanel; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.UndoableRemoveEntry; +import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.l10n.Localization; -import org.jabref.model.DuplicateCheck; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 1f15d1902d0..ec78d50a518 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -1301,33 +1301,6 @@ public void keyPressed(KeyEvent e) { if (e.isControlDown()) { switch (keyCode) { - // The up/down/left/rightkeystrokes are displayed in the - // GroupSelector's popup menu, so if they are to be changed, - // edit GroupSelector.java accordingly! - case KeyEvent.VK_UP: - e.consume(); - if (node != null) { - frame.getGroupSelector().moveNodeUp(node, true); - } - break; - case KeyEvent.VK_DOWN: - e.consume(); - if (node != null) { - frame.getGroupSelector().moveNodeDown(node, true); - } - break; - case KeyEvent.VK_LEFT: - e.consume(); - if (node != null) { - frame.getGroupSelector().moveNodeLeft(node, true); - } - break; - case KeyEvent.VK_RIGHT: - e.consume(); - if (node != null) { - frame.getGroupSelector().moveNodeRight(node, true); - } - break; case KeyEvent.VK_PAGE_DOWN: frame.nextTab.actionPerformed(null); e.consume(); diff --git a/src/main/java/org/jabref/gui/DefaultInjector.java b/src/main/java/org/jabref/gui/DefaultInjector.java index 28eacb93ae1..bb90b263c39 100644 --- a/src/main/java/org/jabref/gui/DefaultInjector.java +++ b/src/main/java/org/jabref/gui/DefaultInjector.java @@ -4,7 +4,6 @@ import org.jabref.Globals; import org.jabref.gui.keyboard.KeyBindingPreferences; -import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.TaskExecutor; import org.jabref.preferences.JabRefPreferences; @@ -17,16 +16,6 @@ public class DefaultInjector implements PresenterFactory { private static final Log LOGGER = LogFactory.getLog(DefaultInjector.class); - @Override - public T instantiatePresenter(Class clazz, Function injectionContext) { - LOGGER.debug("Instantiate " + clazz.getName()); - - // Use our own method to construct dependencies - Injector.setInstanceSupplier(DefaultInjector::createDependency); - - return Injector.instantiatePresenter(clazz, injectionContext); - } - /** * This method takes care of creating dependencies. * By default, it just creates a new instance of the class. @@ -36,7 +25,7 @@ private static Object createDependency(Class clazz) { if (clazz == DialogService.class) { return new FXDialogService(); } else if (clazz == TaskExecutor.class) { - return new DefaultTaskExecutor(); + return Globals.taskExecutor; } else if (clazz == JabRefPreferences.class) { return Globals.prefs; } else if (clazz == KeyBindingPreferences.class) { @@ -52,4 +41,14 @@ private static Object createDependency(Class clazz) { } } } + + @Override + public T instantiatePresenter(Class clazz, Function injectionContext) { + LOGGER.debug("Instantiate " + clazz.getName()); + + // Use our own method to construct dependencies + Injector.setInstanceSupplier(DefaultInjector::createDependency); + + return Injector.instantiatePresenter(clazz, injectionContext); + } } diff --git a/src/main/java/org/jabref/gui/DuplicateSearch.java b/src/main/java/org/jabref/gui/DuplicateSearch.java index 532c32c4a8d..28a8795dfbd 100644 --- a/src/main/java/org/jabref/gui/DuplicateSearch.java +++ b/src/main/java/org/jabref/gui/DuplicateSearch.java @@ -14,8 +14,8 @@ import org.jabref.gui.undo.UndoableInsertEntry; import org.jabref.gui.undo.UndoableRemoveEntry; import org.jabref.gui.worker.CallBack; +import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.l10n.Localization; -import org.jabref.model.DuplicateCheck; import org.jabref.model.entry.BibEntry; import spin.Spin; diff --git a/src/main/java/org/jabref/gui/EntryTypeDialog.java b/src/main/java/org/jabref/gui/EntryTypeDialog.java index ef4c51a467a..159e88b11f8 100644 --- a/src/main/java/org/jabref/gui/EntryTypeDialog.java +++ b/src/main/java/org/jabref/gui/EntryTypeDialog.java @@ -28,6 +28,7 @@ import org.jabref.Globals; import org.jabref.gui.keyboard.KeyBinding; +import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternUtil; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.IdBasedFetcher; import org.jabref.logic.importer.WebFetchers; @@ -96,7 +97,6 @@ private JPanel createEntryGroupsPanel() { if (!customTypes.isEmpty()) { panel.add(createEntryGroupPanel(Localization.lang("Custom"), customTypes)); } - } else { panel.add(createEntryGroupPanel("BibTeX", BibtexEntryTypes.ALL)); panel.add(createEntryGroupPanel("IEEETran", IEEETranEntryTypes.ALL)); @@ -182,7 +182,7 @@ private JPanel createIdFetcherPanel() { JPanel jPanel = new JPanel(); GridBagConstraints constraints = new GridBagConstraints(); - constraints.insets = new Insets(4,4,4,4); + constraints.insets = new Insets(4, 4, 4, 4); GridBagLayout layout = new GridBagLayout(); jPanel.setLayout(layout); @@ -305,15 +305,19 @@ protected void done() { try { Optional result = get(); if (result.isPresent()) { - frame.getCurrentBasePanel().insertEntry(result.get()); + final BibEntry bibEntry = result.get(); + // Regenerate CiteKey of imported BibEntry + BibtexKeyPatternUtil.makeAndSetLabel(Globals.prefs.getBibtexKeyPatternPreferences().getKeyPattern(), frame.getCurrentBasePanel().getDatabase(), bibEntry, Globals.prefs.getBibtexKeyPatternPreferences()); + + frame.getCurrentBasePanel().insertEntry(bibEntry); dispose(); } else if (searchID.trim().isEmpty()) { JOptionPane.showMessageDialog(frame, Localization.lang("The given search ID was empty."), Localization.lang("Empty search ID"), JOptionPane.WARNING_MESSAGE); } else if (!fetcherException) { - JOptionPane.showMessageDialog(frame, Localization.lang("Fetcher_'%0'_did_not_find_an_entry_for_id_'%1'.", fetcher.getName(), searchID)+ "\n" + fetcherExceptionMessage, Localization.lang("No files found."), JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(frame, Localization.lang("Fetcher_'%0'_did_not_find_an_entry_for_id_'%1'.", fetcher.getName(), searchID) + "\n" + fetcherExceptionMessage, Localization.lang("No files found."), JOptionPane.WARNING_MESSAGE); } else { JOptionPane.showMessageDialog(frame, - Localization.lang("Error while fetching from %0", fetcher.getName()) +"." + "\n" + fetcherExceptionMessage, + Localization.lang("Error while fetching from %0", fetcher.getName()) + "." + "\n" + fetcherExceptionMessage, Localization.lang("Error"), JOptionPane.ERROR_MESSAGE); } fetcherWorker = new FetcherWorker(); @@ -328,5 +332,4 @@ protected void done() { } } } - } diff --git a/src/main/java/org/jabref/gui/FindUnlinkedFilesDialog.java b/src/main/java/org/jabref/gui/FindUnlinkedFilesDialog.java index 8020ea8c2ca..2f146314fe7 100644 --- a/src/main/java/org/jabref/gui/FindUnlinkedFilesDialog.java +++ b/src/main/java/org/jabref/gui/FindUnlinkedFilesDialog.java @@ -87,10 +87,6 @@ /** * GUI Dialog for the feature "Find unlinked files". - * - * @author Nosh&Dan - * @version 25.11.2008 | 23:13:29 - * */ public class FindUnlinkedFilesDialog extends JDialog { private static final Log LOGGER = LogFactory.getLog(FindUnlinkedFilesDialog.class); @@ -130,7 +126,7 @@ public class FindUnlinkedFilesDialog extends JDialog { private JButton buttonClose; /* Options for the TreeView */ private JButton buttonOptionSelectAll; - private JButton buttonOptionUnselectAll; + private JButton buttonOptionDeselectAll; private JButton buttonOptionExpandAll; private JButton buttonOptionCollapseAll; @@ -711,9 +707,9 @@ public void windowClosing(WindowEvent e) { buttonOptionSelectAll = new JButton(); buttonOptionSelectAll.setMnemonic('A'); buttonOptionSelectAll.setAction(actionSelectAll); - buttonOptionUnselectAll = new JButton(); - buttonOptionUnselectAll.setMnemonic('U'); - buttonOptionUnselectAll.setAction(actionUnselectAll); + buttonOptionDeselectAll = new JButton(); + buttonOptionDeselectAll.setMnemonic('U'); + buttonOptionDeselectAll.setAction(actionUnselectAll); buttonOptionExpandAll = new JButton(); buttonOptionExpandAll.setMnemonic('E'); buttonOptionExpandAll.setAction(actionExpandTree); @@ -809,7 +805,7 @@ GridBagConstraints.HORIZONTAL, GridBagConstraints.WEST, new Insets(18, 3, 18, 6) GridBagConstraints.NORTHEAST, basicInsets, 1, 1, 1, 1, 0, 0, 0, 0); FindUnlinkedFilesDialog.addComponent(gbl, panelOptions, buttonOptionSelectAll, GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTH, noInsets, 0, 0, 1, 1, 1, 0, 0, 0); - FindUnlinkedFilesDialog.addComponent(gbl, panelOptions, buttonOptionUnselectAll, GridBagConstraints.HORIZONTAL, + FindUnlinkedFilesDialog.addComponent(gbl, panelOptions, buttonOptionDeselectAll, GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTH, noInsets, 0, 1, 1, 1, 0, 0, 0, 0); FindUnlinkedFilesDialog.addComponent(gbl, panelOptions, buttonOptionExpandAll, GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTH, new Insets(6, 0, 0, 0), 0, 2, 1, 1, 0, 0, 0, 0); diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 6fb983a25be..95494891112 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -57,7 +57,6 @@ import javafx.application.Platform; import org.jabref.Globals; -import org.jabref.JabRefExecutorService; import org.jabref.gui.actions.Actions; import org.jabref.gui.actions.AutoLinkFilesAction; import org.jabref.gui.actions.ConnectToSharedDatabaseAction; @@ -734,7 +733,7 @@ public JabRefPreferences prefs() { * @param filenames the filenames of all currently opened files - used for storing them if prefs openLastEdited is set to true */ private void tearDownJabRef(List filenames) { - JabRefExecutorService.INSTANCE.shutdownEverything(); + Globals.shutdownThreadPools(); dispose(); @@ -1178,7 +1177,7 @@ private void fillMenu() { quality.add(findUnlinkedFiles); quality.add(autoLinkFile); - for (IdFetcher fetcher : WebFetchers.getIdFetchers()) { + for (IdFetcher fetcher : WebFetchers.getIdFetchers(Globals.prefs.getImportFormatPreferences())) { lookupIdentifiers.add(new LookupIdentifierAction(this, fetcher)); } quality.add(lookupIdentifiers); diff --git a/src/main/java/org/jabref/gui/StateManager.java b/src/main/java/org/jabref/gui/StateManager.java index 83495d868d9..8700b41569f 100644 --- a/src/main/java/org/jabref/gui/StateManager.java +++ b/src/main/java/org/jabref/gui/StateManager.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import javafx.beans.binding.Bindings; import javafx.beans.property.ObjectProperty; @@ -16,6 +17,7 @@ import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.groups.GroupTreeNode; +import org.jabref.model.util.OptionalUtil; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.monadic.MonadicBinding; @@ -69,4 +71,9 @@ public Optional getSelectedGroup(BibDatabaseContext database) { public void clearSelectedGroup(BibDatabaseContext database) { selectedGroups.remove(database); } + + public List getEntriesInCurrentDatabase() { + return OptionalUtil.flatMap(activeDatabase.get(), BibDatabaseContext::getEntries) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/org/jabref/gui/errorconsole/ErrorConsole.fxml b/src/main/java/org/jabref/gui/errorconsole/ErrorConsole.fxml index c70a7723ed4..a82f9e00b4d 100644 --- a/src/main/java/org/jabref/gui/errorconsole/ErrorConsole.fxml +++ b/src/main/java/org/jabref/gui/errorconsole/ErrorConsole.fxml @@ -7,7 +7,8 @@ - + diff --git a/src/main/java/org/jabref/gui/groups/AddToGroupAction.java b/src/main/java/org/jabref/gui/groups/AddToGroupAction.java deleted file mode 100644 index bf0e1688494..00000000000 --- a/src/main/java/org/jabref/gui/groups/AddToGroupAction.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.jabref.gui.groups; - -import java.awt.event.ActionEvent; -import java.util.List; -import java.util.stream.Collectors; - -import javax.swing.AbstractAction; - -import org.jabref.gui.BasePanel; -import org.jabref.gui.undo.NamedCompound; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.FieldChange; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.groups.AbstractGroup; -import org.jabref.model.groups.GroupEntryChanger; -import org.jabref.model.groups.GroupTreeNode; - -/** - * TODO: rework code and try to reuse some from {@link GroupTreeNode#setGroup(AbstractGroup, boolean, boolean, List)}. - */ -public class AddToGroupAction extends AbstractAction { - - private final boolean move; - private GroupTreeNodeViewModel node; - private BasePanel panel; - - /** - * @param move If true, remove entries from all other groups. - */ - public AddToGroupAction(GroupTreeNodeViewModel node, boolean move, BasePanel panel) { - super(node.getNode().getGroup().getName()); - this.node = node; - this.move = move; - this.panel = panel; - } - - public AddToGroupAction(boolean move) { - super(move ? Localization.lang("Assign entry selection exclusively to this group") : Localization - .lang("Add entry selection to this group")); - this.move = move; - } - - public void setBasePanel(BasePanel panel) { - this.panel = panel; - } - - public void setNode(GroupTreeNodeViewModel node) { - this.node = node; - } - - @Override - public void actionPerformed(ActionEvent evt) { - final List entries = panel.getSelectedEntries(); - - // if an editor is showing, its fields must be updated after the assignment, - // and before that, the current edit has to be stored: - panel.storeCurrentEdit(); - - NamedCompound undoAll = new NamedCompound(Localization.lang("change assignment of entries")); - - if (move) { - moveToGroup(entries, undoAll); - } else { - addToGroup(entries, undoAll); - } - - undoAll.end(); - - panel.getUndoManager().addEdit(undoAll); - panel.markBaseChanged(); - panel.updateEntryEditorIfShowing(); - panel.getGroupSelector().valueChanged(null); - } - - private void moveToGroup(List entries, NamedCompound undoAll) { - List affectedGroups = node.getNode().getRoot() - .getContainingGroups(entries, false).stream() - .map(GroupTreeNode::getGroup) - .filter(group -> group instanceof GroupEntryChanger) - .collect(Collectors.toList()); - affectedGroups.add(node.getNode().getGroup()); - if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(affectedGroups, panel.frame())) { - return; // user aborted operation - } - - // first remove - for (AbstractGroup group : affectedGroups) { - GroupEntryChanger entryChanger = (GroupEntryChanger) group; - List changes = entryChanger.remove(entries); - if (!changes.isEmpty()) { - undoAll.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(node, changes)); - } - } - - // then add - List undoAdd = node.addEntriesToGroup(entries); - if (!undoAdd.isEmpty()) { - undoAll.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(node, undoAdd)); - } - } - - private void addToGroup(List entries, NamedCompound undo) { - if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(node.getNode().getGroup(), panel.frame())) { - return; // user aborted operation - } - - List undoAdd = node.addEntriesToGroup(entries); - if (!undoAdd.isEmpty()) { - undo.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(node, undoAdd)); - } - } - -} diff --git a/src/main/java/org/jabref/gui/groups/GroupAddRemoveDialog.java b/src/main/java/org/jabref/gui/groups/GroupAddRemoveDialog.java index ad08815ebf3..51033ab0e89 100644 --- a/src/main/java/org/jabref/gui/groups/GroupAddRemoveDialog.java +++ b/src/main/java/org/jabref/gui/groups/GroupAddRemoveDialog.java @@ -173,11 +173,9 @@ private boolean doAddOrRemove() { if (checkGroupEnable(node)) { if (add) { - AddToGroupAction action = new AddToGroupAction(node, move, panel); - action.actionPerformed(new ActionEvent(node, 0, "add")); + node.addEntriesToGroup(Globals.stateManager.getSelectedEntries()); } else { - RemoveFromGroupAction action = new RemoveFromGroupAction(node, panel); - action.actionPerformed(new ActionEvent(node, 0, "remove")); + node.removeEntriesFromGroup(Globals.stateManager.getSelectedEntries()); } return true; diff --git a/src/main/java/org/jabref/gui/groups/GroupDialog.java b/src/main/java/org/jabref/gui/groups/GroupDialog.java index 471b5b27b31..026175cdaf7 100644 --- a/src/main/java/org/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/org/jabref/gui/groups/GroupDialog.java @@ -443,6 +443,10 @@ public GroupDialog() { this(JabRefGUI.getMainFrame(), null); } + public GroupDialog(AbstractGroup editedGroup) { + this(JabRefGUI.getMainFrame(), editedGroup); + } + private static String formatRegExException(String regExp, Exception e) { String[] sa = e.getMessage().split("\\n"); StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index 19e65070ede..7d649024515 100644 --- a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -10,7 +10,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; import javafx.beans.property.SimpleBooleanProperty; @@ -23,7 +22,9 @@ import org.jabref.gui.DragAndDropDataFormats; import org.jabref.gui.IconTheme; import org.jabref.gui.StateManager; +import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.BindingsHelper; +import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.groups.DefaultGroupsFactory; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; import org.jabref.model.FieldChange; @@ -52,8 +53,11 @@ public class GroupNodeViewModel { private final SimpleBooleanProperty expandedProperty = new SimpleBooleanProperty(); private final BooleanBinding anySelectedEntriesMatched; private final BooleanBinding allSelectedEntriesMatched; - public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager stateManager, GroupTreeNode groupNode) { + private final TaskExecutor taskExecutor; + + public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager stateManager, TaskExecutor taskExecutor, GroupTreeNode groupNode) { this.databaseContext = Objects.requireNonNull(databaseContext); + this.taskExecutor = Objects.requireNonNull(taskExecutor); this.stateManager = Objects.requireNonNull(stateManager); this.groupNode = Objects.requireNonNull(groupNode); @@ -72,7 +76,7 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state .collect(Collectors.toCollection(FXCollections::observableArrayList)); } else { children = EasyBind.map(groupNode.getChildren(), - child -> new GroupNodeViewModel(databaseContext, stateManager, child)); + child -> new GroupNodeViewModel(databaseContext, stateManager, taskExecutor, child)); } hasChildren = new SimpleBooleanProperty(); hasChildren.bind(Bindings.isNotEmpty(children)); @@ -89,8 +93,8 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state allSelectedEntriesMatched = BindingsHelper.all(selectedEntriesMatchStatus, matched -> matched); } - public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager stateManager, AbstractGroup group) { - this(databaseContext, stateManager, new GroupTreeNode(group)); + public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager stateManager, TaskExecutor taskExecutor, AbstractGroup group) { + this(databaseContext, stateManager, taskExecutor, new GroupTreeNode(group)); } private static Predicate distinctByKey(Function keyExtractor) { @@ -98,13 +102,13 @@ private static Predicate distinctByKey(Function keyExtracto return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } - static GroupNodeViewModel getAllEntriesGroup(BibDatabaseContext newDatabase, StateManager stateManager) { - return new GroupNodeViewModel(newDatabase, stateManager, DefaultGroupsFactory.getAllEntriesGroup()); + static GroupNodeViewModel getAllEntriesGroup(BibDatabaseContext newDatabase, StateManager stateManager, TaskExecutor taskExecutor) { + return new GroupNodeViewModel(newDatabase, stateManager, taskExecutor, DefaultGroupsFactory.getAllEntriesGroup()); } private Stream createSubgroups(AutomaticGroup automaticGroup, BibEntry entry) { return automaticGroup.createSubgroups(entry).stream() - .map(child -> new GroupNodeViewModel(databaseContext, stateManager, child)); + .map(child -> new GroupNodeViewModel(databaseContext, stateManager, taskExecutor, child)); } public List addEntriesToGroup(List entries) { @@ -212,10 +216,10 @@ private void calculateNumberOfMatches() { // We calculate the new hit value // We could be more intelligent and try to figure out the new number of hits based on the entry change // for example, a previously matched entry gets removed -> hits = hits - 1 - new Thread(()-> { - int newHits = groupNode.calculateNumberOfMatches(databaseContext.getDatabase()); - Platform.runLater(() -> hits.setValue(newHits)); - }).start(); + BackgroundTask + .wrap(() -> groupNode.calculateNumberOfMatches(databaseContext.getDatabase())) + .onSuccess(hits::setValue) + .executeWith(taskExecutor); } public GroupTreeNode addSubgroup(AbstractGroup subgroup) { @@ -227,7 +231,7 @@ void toggleExpansion() { } boolean isMatchedBy(String searchString) { - return StringUtil.isBlank(searchString) || getDisplayName().contains(searchString); + return StringUtil.isBlank(searchString) || StringUtil.containsIgnoreCase(getDisplayName(), searchString); } public Color getColor() { @@ -239,7 +243,7 @@ public String getPath() { } public Optional getChildByPath(String pathToSource) { - return groupNode.getChildByPath(pathToSource).map(child -> new GroupNodeViewModel(databaseContext, stateManager, child)); + return groupNode.getChildByPath(pathToSource).map(child -> new GroupNodeViewModel(databaseContext, stateManager, taskExecutor, child)); } /** diff --git a/src/main/java/org/jabref/gui/groups/GroupSelector.java b/src/main/java/org/jabref/gui/groups/GroupSelector.java index 60fc064cba4..a3dc06b7fee 100644 --- a/src/main/java/org/jabref/gui/groups/GroupSelector.java +++ b/src/main/java/org/jabref/gui/groups/GroupSelector.java @@ -5,33 +5,24 @@ import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Optional; import javax.swing.AbstractAction; -import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; -import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JRadioButtonMenuItem; import javax.swing.JScrollPane; -import javax.swing.KeyStroke; import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import javax.swing.event.TreeSelectionEvent; @@ -55,15 +46,11 @@ import org.jabref.gui.help.HelpAction; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.maintable.MainTableDataModel; -import org.jabref.gui.undo.NamedCompound; import org.jabref.logic.groups.DefaultGroupsFactory; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; -import org.jabref.model.FieldChange; import org.jabref.model.entry.BibEntry; -import org.jabref.model.groups.AbstractGroup; import org.jabref.model.groups.AllEntriesGroup; -import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.event.GroupUpdatedEvent; import org.jabref.model.metadata.MetaData; @@ -71,47 +58,24 @@ import org.jabref.preferences.JabRefPreferences; import com.google.common.eventbus.Subscribe; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * The whole UI component holding the groups tree and the buttons */ public class GroupSelector extends SidePaneComponent implements TreeSelectionListener { - private static final Log LOGGER = LogFactory.getLog(GroupSelector.class); - private static final String MOVE_ONE_GROUP = Localization.lang("Please select exactly one group to move."); protected final JabRefFrame frame; private final GroupsTree groupsTree; private final JPopupMenu groupsContextMenu = new JPopupMenu(); private final JPopupMenu settings = new JPopupMenu(); - private final JRadioButtonMenuItem hideNonHits; - private final JRadioButtonMenuItem grayOut; private final JRadioButtonMenuItem andCb = new JRadioButtonMenuItem(Localization.lang("Intersection"), true); private final JRadioButtonMenuItem floatCb = new JRadioButtonMenuItem(Localization.lang("Float"), true); private final JCheckBoxMenuItem invCb = new JCheckBoxMenuItem(Localization.lang("Inverted"), false); - private final JCheckBoxMenuItem showOverlappingGroups = new JCheckBoxMenuItem( - Localization.lang("Highlight overlapping groups")); private final JCheckBoxMenuItem autoAssignGroup = new JCheckBoxMenuItem( Localization.lang("Automatically assign new entry to selected groups")); - private final JMenu moveSubmenu = new JMenu(Localization.lang("Move")); private final JMenu sortSubmenu = new JMenu(Localization.lang("Sort alphabetically")); - private final AbstractAction editGroupAction = new EditGroupAction(); - private final NodeAction editGroupPopupAction = new EditGroupAction(); - private final NodeAction addGroupPopupAction = new AddGroupAction(); - private final NodeAction removeSubgroupsPopupAction = new RemoveSubgroupsAction(); - private final NodeAction removeGroupKeepSubgroupsPopupAction = new RemoveGroupKeepSubgroupsAction(); - private final NodeAction moveNodeUpPopupAction = new MoveNodeUpAction(); - private final NodeAction moveNodeDownPopupAction = new MoveNodeDownAction(); - private final NodeAction moveNodeLeftPopupAction = new MoveNodeLeftAction(); - private final NodeAction moveNodeRightPopupAction = new MoveNodeRightAction(); - private final NodeAction expandSubtreePopupAction = new ExpandSubtreeAction(); - private final NodeAction collapseSubtreePopupAction = new CollapseSubtreeAction(); private final NodeAction sortDirectSubgroupsPopupAction = new SortDirectSubgroupsAction(); private final NodeAction sortAllSubgroupsPopupAction = new SortAllSubgroupsAction(); - private final AddToGroupAction addToGroup = new AddToGroupAction(false); - private final AddToGroupAction moveToGroup = new AddToGroupAction(true); - private final RemoveFromGroupAction removeFromGroup = new RemoveFromGroupAction(); private final ToggleAction toggleAction; private DefaultTreeModel groupsTreeModel; private GroupTreeNodeViewModel groupsRoot; @@ -132,32 +96,13 @@ public GroupSelector(JabRefFrame frame, SidePaneManager manager) { IconTheme.JabRefIcon.TOGGLE_GROUPS); this.frame = frame; - hideNonHits = new JRadioButtonMenuItem(Localization.lang("Hide non-hits"), - !Globals.prefs.getBoolean(JabRefPreferences.GRAY_OUT_NON_HITS)); - grayOut = new JRadioButtonMenuItem(Localization.lang("Gray out non-hits"), - Globals.prefs.getBoolean(JabRefPreferences.GRAY_OUT_NON_HITS)); - ButtonGroup nonHits = new ButtonGroup(); - nonHits.add(hideNonHits); - nonHits.add(grayOut); + floatCb.addChangeListener( event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_FLOAT_SELECTIONS, floatCb.isSelected())); andCb.addChangeListener( event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_INTERSECT_SELECTIONS, andCb.isSelected())); invCb.addChangeListener( event -> Globals.prefs.putBoolean(JabRefPreferences.GROUP_INVERT_SELECTIONS, invCb.isSelected())); - showOverlappingGroups.addChangeListener(new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent event) { - Globals.prefs.putBoolean(JabRefPreferences.GROUP_SHOW_OVERLAPPING, showOverlappingGroups.isSelected()); - if (!showOverlappingGroups.isSelected()) { - groupsTree.setOverlappingGroups(Collections.emptyList()); - } - } - }); - - grayOut.addChangeListener( - event -> Globals.prefs.putBoolean(JabRefPreferences.GRAY_OUT_NON_HITS, grayOut.isSelected())); JRadioButtonMenuItem highlCb = new JRadioButtonMenuItem(Localization.lang("Highlight"), false); if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_FLOAT_SELECTIONS)) { @@ -181,7 +126,6 @@ public void stateChanged(ChangeEvent event) { event -> Globals.prefs.putBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP, autoAssignGroup.isSelected())); invCb.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_INVERT_SELECTIONS)); - showOverlappingGroups.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_OVERLAPPING)); autoAssignGroup.setSelected(Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); JButton openSettings = new JButton(IconTheme.JabRefIcon.PREFERENCES.getSmallIcon()); @@ -190,11 +134,6 @@ public void stateChanged(ChangeEvent event) { settings.addSeparator(); settings.add(invCb); settings.addSeparator(); - settings.add(grayOut); - settings.add(hideNonHits); - settings.addSeparator(); - settings.add(showOverlappingGroups); - settings.addSeparator(); settings.add(autoAssignGroup); openSettings.addActionListener(e -> { if (!settings.isVisible()) { @@ -212,17 +151,12 @@ public void stateChanged(ChangeEvent event) { andCb.addActionListener(e -> valueChanged(null)); orCb.addActionListener(e -> valueChanged(null)); invCb.addActionListener(e -> valueChanged(null)); - showOverlappingGroups.addActionListener(e -> valueChanged(null)); floatCb.addActionListener(e -> valueChanged(null)); highlCb.addActionListener(e -> valueChanged(null)); - hideNonHits.addActionListener(e -> valueChanged(null)); - grayOut.addActionListener(e -> valueChanged(null)); andCb.setToolTipText(Localization.lang("Display only entries belonging to all selected groups.")); orCb.setToolTipText(Localization.lang("Display all entries belonging to one or more of the selected groups.")); openSettings.setToolTipText(Localization.lang("Settings")); invCb.setToolTipText("" + Localization.lang("Show entries not in group selection") + ""); - showOverlappingGroups.setToolTipText( - Localization.lang("Highlight groups that contain entries contained in any currently selected group")); floatCb.setToolTipText(Localization.lang("Move entries in group selection to the top")); highlCb.setToolTipText(Localization.lang("Gray out entries not in group selection")); ButtonGroup bgr = new ButtonGroup(); @@ -274,17 +208,6 @@ public void stateChanged(ChangeEvent event) { groupsTree.setBorder(BorderFactory.createEmptyBorder(5, 10, 0, 0)); this.setTitle(Localization.lang("Groups")); definePopup(); - NodeAction moveNodeUpAction = new MoveNodeUpAction(); - moveNodeUpAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_MASK)); - NodeAction moveNodeDownAction = new MoveNodeDownAction(); - moveNodeDownAction.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_MASK)); - NodeAction moveNodeLeftAction = new MoveNodeLeftAction(); - moveNodeLeftAction.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.CTRL_MASK)); - NodeAction moveNodeRightAction = new MoveNodeRightAction(); - moveNodeRightAction.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.CTRL_MASK)); setGroups(GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup())); @@ -303,27 +226,11 @@ private void definePopup() { // These key bindings are just to have the shortcuts displayed // in the popup menu. The actual keystroke processing is in // BasePanel (entryTable.addKeyListener(...)). - groupsContextMenu.add(editGroupPopupAction); - groupsContextMenu.add(addGroupPopupAction); - groupsContextMenu.addSeparator(); - groupsContextMenu.add(removeGroupKeepSubgroupsPopupAction); - groupsContextMenu.add(removeSubgroupsPopupAction); groupsContextMenu.addSeparator(); - groupsContextMenu.add(expandSubtreePopupAction); - groupsContextMenu.add(collapseSubtreePopupAction); - groupsContextMenu.addSeparator(); - groupsContextMenu.add(moveSubmenu); sortSubmenu.add(sortDirectSubgroupsPopupAction); sortSubmenu.add(sortAllSubgroupsPopupAction); groupsContextMenu.add(sortSubmenu); - moveSubmenu.add(moveNodeUpPopupAction); - moveSubmenu.add(moveNodeDownPopupAction); - moveSubmenu.add(moveNodeLeftPopupAction); - moveSubmenu.add(moveNodeRightPopupAction); groupsContextMenu.addSeparator(); - groupsContextMenu.add(addToGroup); - groupsContextMenu.add(moveToGroup); - groupsContextMenu.add(removeFromGroup); groupsTree.addMouseListener(new MouseAdapter() { @Override @@ -352,7 +259,7 @@ public void mouseClicked(MouseEvent e) { return; } if ((e.getClickCount() == 2) && (e.getButton() == MouseEvent.BUTTON1)) { // edit - editGroupAction.actionPerformed(null); // dummy event + //editGroupAction.actionPerformed(null); // dummy event } } }); @@ -379,83 +286,37 @@ public void popupMenuCanceled(PopupMenuEvent e) { private void showPopup(MouseEvent e) { final TreePath path = groupsTree.getPathForLocation(e.getPoint().x, e.getPoint().y); - addGroupPopupAction.setEnabled(true); - editGroupPopupAction.setEnabled(path != null); - removeGroupKeepSubgroupsPopupAction.setEnabled(path != null); - moveSubmenu.setEnabled(path != null); - expandSubtreePopupAction.setEnabled(path != null); - collapseSubtreePopupAction.setEnabled(path != null); - removeSubgroupsPopupAction.setEnabled(path != null); sortSubmenu.setEnabled(path != null); - addToGroup.setEnabled(false); - moveToGroup.setEnabled(false); - removeFromGroup.setEnabled(false); if (path != null) { // some path dependent enabling/disabling GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) path.getLastPathComponent(); - editGroupPopupAction.setNode(node); - removeSubgroupsPopupAction.setNode(node); - removeGroupKeepSubgroupsPopupAction.setNode(node); - expandSubtreePopupAction.setNode(node); - collapseSubtreePopupAction.setNode(node); sortDirectSubgroupsPopupAction.setNode(node); sortAllSubgroupsPopupAction.setNode(node); groupsTree.setHighlightBorderCell(node); if (node.canBeEdited()) { - editGroupPopupAction.setEnabled(false); - addGroupPopupAction.setEnabled(false); + //editGroupPopupAction.setEnabled(false); + //addGroupPopupAction.setEnabled(false); //removeGroupAndSubgroupsPopupAction.setEnabled(false); - removeGroupKeepSubgroupsPopupAction.setEnabled(false); + //removeGroupKeepSubgroupsPopupAction.setEnabled(false); } else { - editGroupPopupAction.setEnabled(true); - addGroupPopupAction.setEnabled(true); - addGroupPopupAction.setNode(node); + //editGroupPopupAction.setEnabled(true); + //addGroupPopupAction.setEnabled(true); + //addGroupPopupAction.setNode(node); //removeGroupAndSubgroupsPopupAction.setEnabled(true); - removeGroupKeepSubgroupsPopupAction.setEnabled(true); + //removeGroupKeepSubgroupsPopupAction.setEnabled(true); } - expandSubtreePopupAction - .setEnabled(groupsTree.isCollapsed(path) || groupsTree.hasCollapsedDescendant(path)); - collapseSubtreePopupAction - .setEnabled(groupsTree.isExpanded(path) || groupsTree.hasExpandedDescendant(path)); sortSubmenu.setEnabled(!node.isLeaf()); - removeSubgroupsPopupAction.setEnabled(!node.isLeaf()); - moveNodeUpPopupAction.setEnabled(node.canMoveUp()); - moveNodeDownPopupAction.setEnabled(node.canMoveDown()); - moveNodeLeftPopupAction.setEnabled(node.canMoveLeft()); - moveNodeRightPopupAction.setEnabled(node.canMoveRight()); - moveSubmenu.setEnabled(moveNodeUpPopupAction.isEnabled() || moveNodeDownPopupAction.isEnabled() - || moveNodeLeftPopupAction.isEnabled() || moveNodeRightPopupAction.isEnabled()); - moveNodeUpPopupAction.setNode(node); - moveNodeDownPopupAction.setNode(node); - moveNodeLeftPopupAction.setNode(node); - moveNodeRightPopupAction.setNode(node); + //removeSubgroupsPopupAction.setEnabled(!node.isLeaf()); // add/remove entries to/from group List selection = frame.getCurrentBasePanel().getSelectedEntries(); if (!selection.isEmpty()) { if (node.canAddEntries(selection)) { - addToGroup.setNode(node); - addToGroup.setBasePanel(panel); - addToGroup.setEnabled(true); - moveToGroup.setNode(node); - moveToGroup.setBasePanel(panel); - moveToGroup.setEnabled(true); + //addToGroup.setEnabled(true); } if (node.canRemoveEntries(selection)) { - removeFromGroup.setNode(node); - removeFromGroup.setBasePanel(panel); - removeFromGroup.setEnabled(true); + //removeFromGroup.setEnabled(true); } } } else { - editGroupPopupAction.setNode(null); - addGroupPopupAction.setNode(null); - removeSubgroupsPopupAction.setNode(null); - removeGroupKeepSubgroupsPopupAction.setNode(null); - moveNodeUpPopupAction.setNode(null); - moveNodeDownPopupAction.setNode(null); - moveNodeLeftPopupAction.setNode(null); - moveNodeRightPopupAction.setNode(null); - expandSubtreePopupAction.setNode(null); - collapseSubtreePopupAction.setNode(null); sortDirectSubgroupsPopupAction.setNode(null); sortAllSubgroupsPopupAction.setNode(null); } @@ -537,14 +398,6 @@ private void revalidateGroups(GroupTreeNodeViewModel node) { revalidateGroups(groupsTree.getSelectionPaths(), getExpandedPaths(), node); } - /** - * Revalidate the groups tree (e.g. after the data stored in the model has been changed) and set the specified - * selection and expansion state. - */ - public void revalidateGroups(TreePath[] selectionPaths, Enumeration expandedNodes) { - revalidateGroups(selectionPaths, expandedNodes, null); - } - /** * Revalidate the groups tree (e.g. after the data stored in the model has been changed) and set the specified * selection and expansion state. @@ -596,9 +449,6 @@ private void setGroups(GroupTreeNode groupsRoot) { groupsTreeModel = new DefaultTreeModel(this.groupsRoot); this.groupsRoot.subscribeToDescendantChanged(groupsTreeModel::nodeStructureChanged); groupsTree.setModel(groupsTreeModel); - if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_EXPAND_TREE)) { - this.groupsRoot.expandSubtree(groupsTree); - } } /** @@ -623,105 +473,6 @@ public TreePath getSelectionPath() { return groupsTree.getSelectionPath(); } - /** - * @param node The node to move - * @return true if move was successful, false if not. - */ - public boolean moveNodeUp(GroupTreeNodeViewModel node, boolean checkSingleSelection) { - if (checkSingleSelection && (groupsTree.getSelectionCount() != 1)) { - frame.output(MOVE_ONE_GROUP); - return false; // not possible - } - Optional moveChange; - if (!node.canMoveUp() || (!(moveChange = node.moveUp()).isPresent())) { - frame.output(Localization.lang("Cannot move group \"%0\" up.", node.getNode().getGroup().getName())); - return false; // not possible - } - // update selection/expansion state (not really needed when - // moving among siblings, but I'm paranoid) - revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()), - groupsTree.refreshPaths(getExpandedPaths())); - concludeMoveGroup(moveChange.get(), node); - return true; - } - - /** - * @param node The node to move - * @return true if move was successful, false if not. - */ - public boolean moveNodeDown(GroupTreeNodeViewModel node, boolean checkSingleSelection) { - if (checkSingleSelection && (groupsTree.getSelectionCount() != 1)) { - frame.output(MOVE_ONE_GROUP); - return false; // not possible - } - Optional moveChange; - if (!node.canMoveDown() || (!(moveChange = node.moveDown()).isPresent())) { - frame.output(Localization.lang("Cannot move group \"%0\" down.", node.getNode().getGroup().getName())); - return false; // not possible - } - // update selection/expansion state (not really needed when - // moving among siblings, but I'm paranoid) - revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()), - groupsTree.refreshPaths(getExpandedPaths())); - concludeMoveGroup(moveChange.get(), node); - return true; - } - - /** - * @param node The node to move - * @return true if move was successful, false if not. - */ - public boolean moveNodeLeft(GroupTreeNodeViewModel node, boolean checkSingleSelection) { - if (checkSingleSelection && (groupsTree.getSelectionCount() != 1)) { - frame.output(MOVE_ONE_GROUP); - return false; // not possible - } - Optional moveChange; - if (!node.canMoveLeft() || (!(moveChange = node.moveLeft()).isPresent())) { - frame.output(Localization.lang("Cannot move group \"%0\" left.", node.getNode().getGroup().getName())); - return false; // not possible - } - // update selection/expansion state - revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()), - groupsTree.refreshPaths(getExpandedPaths())); - concludeMoveGroup(moveChange.get(), node); - return true; - } - - /** - * @param node The node to move - * @return true if move was successful, false if not. - */ - public boolean moveNodeRight(GroupTreeNodeViewModel node, boolean checkSingleSelection) { - if (checkSingleSelection && (groupsTree.getSelectionCount() != 1)) { - frame.output(MOVE_ONE_GROUP); - return false; // not possible - } - Optional moveChange; - if (!node.canMoveRight() || (!(moveChange = node.moveRight()).isPresent())) { - frame.output(Localization.lang("Cannot move group \"%0\" right.", node.getNode().getGroup().getName())); - return false; // not possible - } - // update selection/expansion state - revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()), - groupsTree.refreshPaths(getExpandedPaths())); - concludeMoveGroup(moveChange.get(), node); - return true; - } - - /** - * Concludes the moving of a group tree node by storing the specified undo information, marking the change, and - * setting the status line. - * - * @param moveChange Undo information for the move operation. - * @param node The node that has been moved. - */ - public void concludeMoveGroup(MoveGroupChange moveChange, GroupTreeNodeViewModel node) { - panel.getUndoManager().addEdit(new UndoableMoveGroup(this.groupsRoot, moveChange)); - panel.markBaseChanged(); - frame.output(Localization.lang("Moved group \"%0\".", node.getNode().getGroup().getName())); - } - public void concludeAssignment(AbstractUndoableEdit undo, GroupTreeNode node, int assignedEntries) { if (undo == null) { frame.output(Localization.lang("The group \"%0\" already contains the selection.", @@ -744,7 +495,7 @@ private GroupTreeNodeViewModel getGroupTreeRoot() { return groupsRoot; } - public Enumeration getExpandedPaths() { + private Enumeration getExpandedPaths() { return groupsTree.getExpandedDescendants(groupsRoot.getTreePath()); } @@ -775,34 +526,6 @@ public void setActiveBasePanel(BasePanel panel) { } } - /** - * Highlight all groups that contain any/all of the specified entries. If entries is null or has zero length, - * highlight is cleared. - */ - public void showMatchingGroups(List list, boolean requireAll) { - if ((list == null) || (list.isEmpty())) { // nothing selected - groupsTree.setMatchingGroups(Collections.emptyList()); - groupsTree.revalidate(); - return; - } - List nodeList = groupsRoot.getNode().getContainingGroups(list, requireAll); - groupsTree.setMatchingGroups(nodeList); - // ensure that all highlighted nodes are visible - for (GroupTreeNode node : nodeList) { - node.getParent().ifPresent( - parentNode -> groupsTree.expandPath(new GroupTreeNodeViewModel(parentNode).getTreePath())); - } - groupsTree.revalidate(); - } - - /** - * Show groups that, if selected, would show at least one of the entries in the specified list. - */ - private void showOverlappingGroups(List matches) { - List nodes = groupsRoot.getNode().getMatchingGroups(matches); - groupsTree.setOverlappingGroups(nodes); - } - public GroupsTree getGroupsTree() { return this.groupsTree; } @@ -825,38 +548,29 @@ public ToggleAction getToggleAction() { class GroupingWorker { private final SearchMatcher matcher; - private final List matches = new ArrayList<>(); - private final boolean showOverlappingGroupsP; public GroupingWorker(SearchMatcher matcher) { this.matcher = matcher; - showOverlappingGroupsP = showOverlappingGroups.isSelected(); } public void run() { for (BibEntry entry : panel.getDatabase().getEntries()) { boolean hit = matcher.isMatch(entry); entry.setGroupHit(hit); - if (hit && showOverlappingGroupsP) { - matches.add(entry); - } } } public void update() { // Show the result in the chosen way: - if (hideNonHits.isSelected()) { - panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.FILTER); - } else if (grayOut.isSelected()) { + if (Globals.prefs.getBoolean(JabRefPreferences.GRAY_OUT_NON_HITS)) { panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.FLOAT); + } else { + panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.FILTER); } panel.getMainTable().getTableModel().updateSortOrder(); panel.getMainTable().getTableModel().updateGroupFilter(); panel.getMainTable().scrollTo(0); - if (showOverlappingGroupsP) { - showOverlappingGroups(matches); - } frame.output(Localization.lang("Updated group selection") + "."); } } @@ -885,140 +599,7 @@ public GroupTreeNodeViewModel getNodeToUse() { } } - private class EditGroupAction extends NodeAction { - - public EditGroupAction() { - super(Localization.lang("Edit group")); - } - @Override - public void actionPerformed(ActionEvent e) { - final GroupTreeNodeViewModel node = getNodeToUse(); - final AbstractGroup oldGroup = node.getNode().getGroup(); - final GroupDialog gd = new GroupDialog(frame, oldGroup); - gd.setVisible(true); - if (gd.okPressed()) { - AbstractGroup newGroup = gd.getResultingGroup(); - - int i = JOptionPane.showConfirmDialog(panel.frame(), - Localization.lang("Assign the original group's entries to this group?"), - Localization.lang("Change of Grouping Method"), - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - boolean keepPreviousAssignments = (i == JOptionPane.YES_OPTION) && - WarnAssignmentSideEffects.warnAssignmentSideEffects(newGroup, panel.frame()); - boolean removePreviousAssignents = (oldGroup instanceof ExplicitGroup) - && (newGroup instanceof ExplicitGroup); - - AbstractUndoableEdit undoAddPreviousEntries = null; - UndoableModifyGroup undo = new UndoableModifyGroup(GroupSelector.this, groupsRoot, node, newGroup); - List addChange = node.getNode().setGroup(newGroup, keepPreviousAssignments, - removePreviousAssignents, panel.getDatabase().getEntries()); - if (!addChange.isEmpty()) { - undoAddPreviousEntries = UndoableChangeEntriesOfGroup.getUndoableEdit(null, addChange); - } - - groupsTreeModel.reload(); - revalidateGroups(node); - - // Store undo information. - if (undoAddPreviousEntries == null) { - panel.getUndoManager().addEdit(undo); - } else { - NamedCompound nc = new NamedCompound("Modify Group"); - nc.addEdit(undo); - nc.addEdit(undoAddPreviousEntries); - nc.end(); - panel.getUndoManager().addEdit(nc); - } - panel.markBaseChanged(); - frame.output(Localization.lang("Modified group \"%0\".", newGroup.getName())); - } - } - } - - private class AddGroupAction extends NodeAction { - - public AddGroupAction() { - super(Localization.lang("Add group")); - } - - @Override - public void actionPerformed(ActionEvent e) { - final GroupDialog gd = new GroupDialog(frame, null); - gd.setVisible(true); - if (!gd.okPressed()) { - return; // ignore - } - final AbstractGroup newGroup = gd.getResultingGroup(); - final GroupTreeNode newNode = GroupTreeNode.fromGroup(newGroup); - final GroupTreeNodeViewModel node = getNodeToUse(); - if (node == null) { - groupsRoot.getNode().addChild(newNode); - } else { - ((GroupTreeNodeViewModel) node.getParent()).getNode().addChild(newNode, - node.getNode().getPositionInParent() + 1); - } - UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(groupsRoot, - new GroupTreeNodeViewModel(newNode), UndoableAddOrRemoveGroup.ADD_NODE); - groupsTree.expandPath((node == null ? groupsRoot : node).getTreePath()); - // Store undo information. - panel.getUndoManager().addEdit(undo); - panel.markBaseChanged(); - frame.output(Localization.lang("Added group \"%0\".", newGroup.getName())); - } - } - - private class RemoveSubgroupsAction extends NodeAction { - - public RemoveSubgroupsAction() { - super(Localization.lang("Remove subgroups")); - } - - @Override - public void actionPerformed(ActionEvent e) { - final GroupTreeNodeViewModel node = getNodeToUse(); - int conf = JOptionPane.showConfirmDialog(frame, - Localization.lang("Remove all subgroups of \"%0\"?", node.getName()), - Localization.lang("Remove subgroups"), JOptionPane.YES_NO_OPTION); - if (conf == JOptionPane.YES_OPTION) { - final UndoableModifySubtree undo = new UndoableModifySubtree(getGroupTreeRoot(), - node, "Remove subgroups"); - node.getNode().removeAllChildren(); - //revalidateGroups(); - // Store undo information. - panel.getUndoManager().addEdit(undo); - panel.markBaseChanged(); - frame.output(Localization.lang("Removed all subgroups of group \"%0\".", node.getName())); - } - } - } - - private class RemoveGroupKeepSubgroupsAction extends NodeAction { - - public RemoveGroupKeepSubgroupsAction() { - super(Localization.lang("Remove group, keep subgroups")); - } - - @Override - public void actionPerformed(ActionEvent e) { - final GroupTreeNodeViewModel node = getNodeToUse(); - final AbstractGroup group = node.getNode().getGroup(); - int conf = JOptionPane.showConfirmDialog(frame, Localization.lang("Remove group \"%0\"?", group.getName()), - Localization.lang("Remove group"), JOptionPane.YES_NO_OPTION); - if (conf == JOptionPane.YES_OPTION) { - final UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(groupsRoot, node, - UndoableAddOrRemoveGroup.REMOVE_NODE_KEEP_CHILDREN); - final GroupTreeNodeViewModel parent = (GroupTreeNodeViewModel) node.getParent(); - node.getNode().removeFromParent(); - node.getNode().moveAllChildrenTo(parent.getNode(), parent.getIndex(node)); - - // Store undo information. - panel.getUndoManager().addEdit(undo); - panel.markBaseChanged(); - frame.output(Localization.lang("Removed group \"%0\".", group.getName())); - } - } - } private class SortDirectSubgroupsAction extends NodeAction { @@ -1055,83 +636,4 @@ public void actionPerformed(ActionEvent ae) { frame.output(Localization.lang("Sorted all subgroups recursively.")); } } - - private class ExpandSubtreeAction extends NodeAction { - - public ExpandSubtreeAction() { - super(Localization.lang("Expand subtree")); - } - - @Override - public void actionPerformed(ActionEvent ae) { - getNodeToUse().expandSubtree(groupsTree); - revalidateGroups(); - } - } - - private class CollapseSubtreeAction extends NodeAction { - - public CollapseSubtreeAction() { - super(Localization.lang("Collapse subtree")); - } - - @Override - public void actionPerformed(ActionEvent ae) { - getNodeToUse().collapseSubtree(groupsTree); - revalidateGroups(); - } - } - - private class MoveNodeUpAction extends NodeAction { - - public MoveNodeUpAction() { - super(Localization.lang("Up")); - } - - @Override - public void actionPerformed(ActionEvent e) { - final GroupTreeNodeViewModel node = getNodeToUse(); - moveNodeUp(node, false); - } - } - - private class MoveNodeDownAction extends NodeAction { - - public MoveNodeDownAction() { - super(Localization.lang("Down")); - } - - @Override - public void actionPerformed(ActionEvent e) { - final GroupTreeNodeViewModel node = getNodeToUse(); - moveNodeDown(node, false); - } - } - - private class MoveNodeLeftAction extends NodeAction { - - public MoveNodeLeftAction() { - super(Localization.lang("Left")); - } - - @Override - public void actionPerformed(ActionEvent e) { - final GroupTreeNodeViewModel node = getNodeToUse(); - moveNodeLeft(node, false); - } - } - - private class MoveNodeRightAction extends NodeAction { - - public MoveNodeRightAction() { - super(Localization.lang("Right")); - } - - @Override - public void actionPerformed(ActionEvent e) { - final GroupTreeNodeViewModel node = getNodeToUse(); - moveNodeRight(node, false); - } - } - } diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeCellRenderer.java b/src/main/java/org/jabref/gui/groups/GroupTreeCellRenderer.java index d85a649e8ce..61c9d1c85cc 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeCellRenderer.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeCellRenderer.java @@ -7,7 +7,6 @@ import java.util.Objects; import javax.swing.BorderFactory; -import javax.swing.Icon; import javax.swing.JLabel; import javax.swing.JTree; import javax.swing.border.Border; @@ -87,10 +86,6 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean } label.setToolTipText(viewModel.getDescription()); - Icon icon = viewModel.getIcon(); - if (label.getIcon() != icon) { - label.setIcon(icon); - } return c; } @@ -111,31 +106,6 @@ private boolean printUnderlined(GroupTreeNodeViewModel viewModel) { return matchingGroups.contains(viewModel.getNode()); } - /** - * For use when dragging: The specified cell is always rendered as selected. - * - * @param cell The cell over which the user is currently dragging. - */ - public void setHighlight1Cell(Object cell) { - this.highlight1Cell = cell; - } - - /** - * Highlights the specified groups in red. - */ - public void setOverlappingGroups(List nodes) { - Objects.requireNonNull(nodes); - this.overlappingGroups = nodes; - } - - /** - * Highlights the specified groups by underlining. - */ - public void setMatchingGroups(List nodes) { - Objects.requireNonNull(nodes); - this.matchingGroups = nodes; - } - /** * Highlights the specified cells (by drawing a border around it), or disables highlight if highlightBorderCell == * null. diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeController.java b/src/main/java/org/jabref/gui/groups/GroupTreeController.java index a6bdc18e47e..a19062e3688 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeController.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeController.java @@ -13,6 +13,7 @@ import javafx.scene.control.ContextMenu; import javafx.scene.control.Control; import javafx.scene.control.MenuItem; +import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.TextField; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableColumn; @@ -30,6 +31,7 @@ import org.jabref.gui.StateManager; import org.jabref.gui.util.BindingsHelper; import org.jabref.gui.util.RecursiveTreeItem; +import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.ViewModelTreeTableCellFactory; import org.jabref.logic.l10n.Localization; @@ -51,10 +53,11 @@ public class GroupTreeController extends AbstractController @Inject private StateManager stateManager; @Inject private DialogService dialogService; + @Inject private TaskExecutor taskExecutor; @FXML public void initialize() { - viewModel = new GroupTreeViewModel(stateManager, dialogService); + viewModel = new GroupTreeViewModel(stateManager, dialogService, taskExecutor); // Set-up bindings groupTree.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> viewModel @@ -138,8 +141,6 @@ public void initialize() { .map(this::createContextMenuForGroup) .orElse((ContextMenu) null)); - - // Drag and drop support row.setOnDragDetected(event -> { TreeItem selectedItem = treeTable.getSelectionModel().getSelectedItem(); @@ -188,7 +189,6 @@ public void initialize() { event.consume(); }); - return row; }); @@ -219,23 +219,34 @@ private Optional> getTreeItemByValue(TreeItem viewModel.addNewSubgroup(group)); + MenuItem editGroup = new MenuItem(Localization.lang("Edit group")); + editGroup.setOnAction(event -> { + menu.hide(); + viewModel.editGroup(group); + }); + MenuItem addSubgroup = new MenuItem(Localization.lang("Add subgroup")); + addSubgroup.setOnAction(event -> { + menu.hide(); + viewModel.addNewSubgroup(group); + }); MenuItem removeGroupAndSubgroups = new MenuItem(Localization.lang("Remove group and subgroups")); removeGroupAndSubgroups.setOnAction(event -> viewModel.removeGroupAndSubgroups(group)); - - MenuItem sortAlphabetically = new MenuItem(Localization.lang("Sort all subgroups (recursively)")); - sortAlphabetically.setOnAction(event -> viewModel.sortAlphabetically(group)); - - MenuItem sortSubGroups = new MenuItem(Localization.lang("sort subgroups")); - sortSubGroups.setOnAction(event -> viewModel.sortSubGroupAlphabetically(group)); - - - menu.getItems().add(addSubgroup); - menu.getItems().add(removeGroupAndSubgroups); - menu.getItems().add(sortAlphabetically); - menu.getItems().add(sortSubGroups); + MenuItem removeGroupKeepSubgroups = new MenuItem(Localization.lang("Remove group, keep subgroups")); + removeGroupKeepSubgroups.setOnAction(event -> viewModel.removeGroupKeepSubgroups(group)); + MenuItem removeSubgroups = new MenuItem(Localization.lang("Remove subgroups")); + removeSubgroups.setOnAction(event -> viewModel.removeSubgroups(group)); + + MenuItem addEntries = new MenuItem(Localization.lang("Add selected entries to this group")); + removeSubgroups.setOnAction(event -> viewModel.addSelectedEntries(group)); + MenuItem removeEntries = new MenuItem(Localization.lang("Remove selected entries from this group")); + removeSubgroups.setOnAction(event -> viewModel.removeSelectedEntries(group)); + + menu.getItems().add(editGroup); + menu.getItems().add(new SeparatorMenuItem()); + menu.getItems().addAll(addSubgroup, removeSubgroups, removeGroupAndSubgroups, removeGroupKeepSubgroups); + menu.getItems().add(new SeparatorMenuItem()); + menu.getItems().addAll(addEntries, removeEntries); return menu; } diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java index 091a85ae6b2..9ba40973a42 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeNodeViewModel.java @@ -5,10 +5,8 @@ import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.Enumeration; import java.util.List; -import java.util.Optional; import java.util.function.Consumer; import javax.swing.Icon; @@ -18,7 +16,6 @@ import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.UndoManager; -import org.jabref.Globals; import org.jabref.gui.IconTheme; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.model.FieldChange; @@ -30,7 +27,6 @@ import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.SearchGroup; -import org.jabref.preferences.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -145,14 +141,6 @@ public GroupTreeNode getNode() { return node; } - /** Collapse this node and all its children. */ - public void collapseSubtree(JTree tree) { - for (GroupTreeNodeViewModel child : getChildren()) { - child.collapseSubtree(tree); - } - tree.collapsePath(this.getTreePath()); - } - /** Expand this node and all its children. */ public void expandSubtree(JTree tree) { tree.expandPath(this.getTreePath()); @@ -171,13 +159,13 @@ public List getChildren() { } protected boolean printInItalics() { - return Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_DYNAMIC) && node.getGroup().isDynamic(); + return node.getGroup().isDynamic(); } public String getDescription() { AbstractGroup group = node.getGroup(); String shortDescription = ""; - boolean showDynamic = Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_DYNAMIC); + boolean showDynamic = true; if (group instanceof ExplicitGroup) { shortDescription = GroupDescriptions.getShortDescriptionExplicitGroup((ExplicitGroup) group); } else if (group instanceof KeywordGroup) { @@ -190,21 +178,6 @@ public String getDescription() { return "" + shortDescription + ""; } - public Icon getIcon() { - if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_SHOW_ICONS)) { - switch (node.getGroup().getHierarchicalContext()) { - case REFINING: - return GROUP_REFINING_ICON; - case INCLUDING: - return GROUP_INCLUDING_ICON; - default: - return GROUP_REGULAR_ICON; - } - } else { - return null; - } - } - public TreePath getTreePath() { List pathToNode = node.getPathFromRoot(); return new TreePath(pathToNode.stream().map(GroupTreeNodeViewModel::new).toArray()); @@ -313,6 +286,10 @@ public void changeEntriesTo(List entries, UndoManager undoManager) { } } + public List removeEntriesFromGroup(List entries) { + return node.removeEntriesFromGroup(entries); + } + public boolean isAllEntriesGroup() { return getNode().getGroup() instanceof AllEntriesGroup; } @@ -326,54 +303,6 @@ public void addNewGroup(AbstractGroup newGroup, CountingUndoManager undoManager) undoManager.addEdit(undo); } - public Optional moveUp() { - final GroupTreeNode parent = node.getParent().get(); - // TODO: Null! - final int index = parent.getIndexOfChild(getNode()).get(); - if (index > 0) { - getNode().moveTo(parent, index - 1); - return Optional.of(new MoveGroupChange(parent, index, parent, index - 1)); - } - return Optional.empty(); - } - - public Optional moveDown() { - final GroupTreeNode parent = node.getParent().get(); - // TODO: Null! - final int index = parent.getIndexOfChild(node).get(); - if (index < (parent.getNumberOfChildren() - 1)) { - node.moveTo(parent, index + 1); - return Optional.of(new MoveGroupChange(parent, index, parent, index + 1)); - } - return Optional.empty(); - } - - public Optional moveLeft() { - final GroupTreeNode parent = node.getParent().get(); // TODO: Null! - final Optional grandParent = parent.getParent(); - final int index = node.getPositionInParent(); - - if (!grandParent.isPresent()) { - return Optional.empty(); - } - final int indexOfParent = grandParent.get().getIndexOfChild(parent).get(); - node.moveTo(grandParent.get(), indexOfParent + 1); - return Optional.of(new MoveGroupChange(parent, index, grandParent.get(), indexOfParent + 1)); - } - - public Optional moveRight() { - final GroupTreeNode previousSibling = node.getPreviousSibling().get(); // TODO: Null - final GroupTreeNode parent = node.getParent().get(); // TODO: Null! - final int index = node.getPositionInParent(); - - if (previousSibling == null) { - return Optional.empty(); - } - - node.moveTo(previousSibling); - return Optional.of(new MoveGroupChange(parent, index, previousSibling, previousSibling.getNumberOfChildren())); - } - /** * Adds the given entries to this node's group. */ @@ -381,17 +310,6 @@ public List addEntriesToGroup(List entries) { return node.addEntriesToGroup(entries); } - /** - * Removes the given entries from this node's group. - */ - public List removeEntriesFromGroup(List entries) { - if (node.getGroup() instanceof GroupEntryChanger) { - return ((GroupEntryChanger) node.getGroup()).remove(entries); - } else { - return Collections.emptyList(); - } - } - public void subscribeToDescendantChanged(Consumer subscriber) { getNode().subscribeToDescendantChanged(node -> subscriber.accept(new GroupTreeNodeViewModel(node))); } diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index f42a1e90d5d..fd93640e72c 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -1,6 +1,6 @@ package org.jabref.gui.groups; -import java.util.Comparator; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.function.Predicate; @@ -14,9 +14,12 @@ import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; +import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.l10n.Localization; +import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.groups.AbstractGroup; +import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.metadata.MetaData; @@ -26,26 +29,22 @@ public class GroupTreeViewModel extends AbstractViewModel { private final ObjectProperty selectedGroup = new SimpleObjectProperty<>(); private final StateManager stateManager; private final DialogService dialogService; + private final TaskExecutor taskExecutor; private final ObjectProperty> filterPredicate = new SimpleObjectProperty<>(); private final StringProperty filterText = new SimpleStringProperty(); - private final Comparator compAlphabetIgnoreCase = (GroupTreeNode v1, GroupTreeNode v2) -> v1 - .getName() - .compareToIgnoreCase(v2.getName()); - private Optional currentDatabase; - public GroupTreeViewModel(StateManager stateManager, DialogService dialogService) { + public GroupTreeViewModel(StateManager stateManager, DialogService dialogService, TaskExecutor taskExecutor) { this.stateManager = Objects.requireNonNull(stateManager); this.dialogService = Objects.requireNonNull(dialogService); + this.taskExecutor = Objects.requireNonNull(taskExecutor); // Register listener - stateManager.activeDatabaseProperty() - .addListener((observable, oldValue, newValue) -> onActiveDatabaseChanged(newValue)); + stateManager.activeDatabaseProperty().addListener((observable, oldValue, newValue) -> onActiveDatabaseChanged(newValue)); selectedGroup.addListener((observable, oldValue, newValue) -> onSelectedGroupChanged(newValue)); // Set-up bindings - filterPredicate - .bind(Bindings.createObjectBinding(() -> group -> group.isMatchedBy(filterText.get()), filterText)); + filterPredicate.bind(Bindings.createObjectBinding(() -> group -> group.isMatchedBy(filterText.get()), filterText)); // Init onActiveDatabaseChanged(stateManager.activeDatabaseProperty().getValue()); @@ -102,13 +101,12 @@ private void onActiveDatabaseChanged(Optional newDatabase) { GroupNodeViewModel newRoot = newDatabase .map(BibDatabaseContext::getMetaData) .flatMap(MetaData::getGroups) - .map(root -> new GroupNodeViewModel(newDatabase.get(), stateManager, root)) - .orElse(GroupNodeViewModel.getAllEntriesGroup(newDatabase.get(), stateManager)); + .map(root -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, root)) + .orElse(GroupNodeViewModel.getAllEntriesGroup(newDatabase.get(), stateManager, taskExecutor)); rootGroup.setValue(newRoot); stateManager.getSelectedGroup(newDatabase.get()).ifPresent( - selectedGroup -> this.selectedGroup - .setValue(new GroupNodeViewModel(newDatabase.get(), stateManager, selectedGroup))); + selectedGroup -> this.selectedGroup.setValue(new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup))); } currentDatabase = newDatabase; @@ -133,6 +131,81 @@ public void addNewSubgroup(GroupNodeViewModel parent) { }); } + /** + * Opens "Edit Group Dialog" and changes the given group to the edited one. + */ + public void editGroup(GroupNodeViewModel oldGroup) { + Optional newGroup = dialogService.showCustomDialogAndWait(new GroupDialog(oldGroup.getGroupNode().getGroup())); + newGroup.ifPresent(group -> { + + // TODO: Keep assignments + boolean keepPreviousAssignments = dialogService.showConfirmationDialogAndWait( + Localization.lang("Change of Grouping Method"), + Localization.lang("Assign the original group's entries to this group?")); + // WarnAssignmentSideEffects.warnAssignmentSideEffects(newGroup, panel.frame()); + boolean removePreviousAssignents = + (oldGroup.getGroupNode().getGroup() instanceof ExplicitGroup) && (group instanceof ExplicitGroup); + + List addChange = oldGroup. + getGroupNode().setGroup( + group, + keepPreviousAssignments, + removePreviousAssignents, + stateManager.getEntriesInCurrentDatabase()); + + // TODO: Add undo + // Store undo information. + // AbstractUndoableEdit undoAddPreviousEntries = null; + // UndoableModifyGroup undo = new UndoableModifyGroup(GroupSelector.this, groupsRoot, node, newGroup); + // if (undoAddPreviousEntries == null) { + // panel.getUndoManager().addEdit(undo); + //} else { + // NamedCompound nc = new NamedCompound("Modify Group"); + // nc.addEdit(undo); + // nc.addEdit(undoAddPreviousEntries); + // nc.end();/ + // panel.getUndoManager().addEdit(nc); + //} + //if (!addChange.isEmpty()) { + // undoAddPreviousEntries = UndoableChangeEntriesOfGroup.getUndoableEdit(null, addChange); + //} + + dialogService.notify(Localization.lang("Modified group \"%0\".", group.getName())); + }); + } + + public void removeSubgroups(GroupNodeViewModel group) { + boolean confirmation = dialogService.showConfirmationDialogAndWait( + Localization.lang("Remove subgroups"), + Localization.lang("Remove all subgroups of \"%0\"?", group.getDisplayName())); + if (confirmation) { + /// TODO: Add undo + //final UndoableModifySubtree undo = new UndoableModifySubtree(getGroupTreeRoot(), node, "Remove subgroups"); + //panel.getUndoManager().addEdit(undo); + group.getGroupNode().removeAllChildren(); + dialogService.notify(Localization.lang("Removed all subgroups of group \"%0\".", group.getDisplayName())); + } + } + + public void removeGroupKeepSubgroups(GroupNodeViewModel group) { + boolean confirmation = dialogService.showConfirmationDialogAndWait( + Localization.lang("Remove group"), + Localization.lang("Remove group \"%0\"?", group.getDisplayName())); + + if (confirmation) { + // TODO: Add undo + //final UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(groupsRoot, node, UndoableAddOrRemoveGroup.REMOVE_NODE_KEEP_CHILDREN); + //panel.getUndoManager().addEdit(undo); + GroupTreeNode groupNode = group.getGroupNode(); + groupNode.getParent().ifPresent(parent -> + groupNode.moveAllChildrenTo(parent, parent.getIndexOfChild(groupNode).get())); + groupNode.removeFromParent(); + + dialogService.notify(Localization.lang("Removed group \"%0\".", group.getDisplayName())); + } + } + + /** * Removes the specified group and its subgroups (after asking for confirmation). */ @@ -152,11 +225,28 @@ public void removeGroupAndSubgroups(GroupNodeViewModel group) { } } - public void sortAlphabetically(GroupNodeViewModel group) { - group.getGroupNode().getRoot().sortChildren(compAlphabetIgnoreCase, true); + public void addSelectedEntries(GroupNodeViewModel group) { + // TODO: Warn + // if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(node.getNode().getGroup(), panel.frame())) { + // return; // user aborted operation + + List addChange = group.getGroupNode().addEntriesToGroup(stateManager.getSelectedEntries()); + + // TODO: Add undo + // NamedCompound undoAll = new NamedCompound(Localization.lang("change assignment of entries")); + // if (!undoAdd.isEmpty()) { undo.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(node, undoAdd)); } + // panel.getUndoManager().addEdit(undoAll); } - public void sortSubGroupAlphabetically(GroupNodeViewModel group) { - group.getGroupNode().sortChildren(compAlphabetIgnoreCase, true); + public void removeSelectedEntries(GroupNodeViewModel group) { + // TODO: warn if assignment has undesired side effects (modifies a field != keywords) + // if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(mNode.getNode().getGroup(), mPanel.frame())) { + // return; // user aborted operation + + List removeChange = group.getGroupNode().removeEntriesFromGroup(stateManager.getSelectedEntries()); + + // TODO: Add undo + // if (!undo.isEmpty()) { + // mPanel.getUndoManager().addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(mNode, undo)); } } diff --git a/src/main/java/org/jabref/gui/groups/GroupsTree.java b/src/main/java/org/jabref/gui/groups/GroupsTree.java index e628f30d5c7..e95ea812bc5 100644 --- a/src/main/java/org/jabref/gui/groups/GroupsTree.java +++ b/src/main/java/org/jabref/gui/groups/GroupsTree.java @@ -1,17 +1,9 @@ package org.jabref.gui.groups; -import java.util.Enumeration; -import java.util.List; -import java.util.Objects; -import java.util.Vector; - import javax.swing.JTree; import javax.swing.ToolTipManager; -import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; -import org.jabref.model.groups.GroupTreeNode; - public class GroupsTree extends JTree { private final GroupTreeCellRenderer localCellRenderer = new GroupTreeCellRenderer(); @@ -31,68 +23,6 @@ public GroupsTree(GroupSelector groupSelector) { } - /** Returns the first selected node, or null if nothing is selected. */ - private GroupTreeNodeViewModel getSelectedNode() { - TreePath selectionPath = getSelectionPath(); - return selectionPath == null ? null : (GroupTreeNodeViewModel) selectionPath.getLastPathComponent(); - } - - /** - * Refresh paths that may have become invalid due to node movements within - * the tree. This method creates new paths to the last path components - * (which must still exist) of the specified paths. - * - * @param paths - * Paths that may have become invalid. - * @return Refreshed paths that are all valid. - */ - public Enumeration refreshPaths(Enumeration paths) { - if (paths == null) { - return new Vector().elements(); - } - - Vector freshPaths = new Vector<>(); - while (paths.hasMoreElements()) { - freshPaths.add(((GroupTreeNodeViewModel) paths.nextElement().getLastPathComponent()).getTreePath()); - } - return freshPaths.elements(); - } - - /** - * Refresh paths that may have become invalid due to node movements within - * the tree. This method creates new paths to the last path components - * (which must still exist) of the specified paths. - * - * @param paths - * Paths that may have become invalid. - * @return Refreshed paths that are all valid. - */ - public TreePath[] refreshPaths(TreePath[] paths) { - TreePath[] freshPaths = new TreePath[paths.length]; - for (int i = 0; i < paths.length; ++i) { - freshPaths[i] = ((GroupTreeNodeViewModel) paths[i].getLastPathComponent()).getTreePath(); - } - return freshPaths; - } - - /** - * Highlights the specified groups in red - **/ - public void setOverlappingGroups(List nodes) { - Objects.requireNonNull(nodes); - localCellRenderer.setOverlappingGroups(nodes); - repaint(); - } - - /** - * Highlights the specified groups by underlining - **/ - public void setMatchingGroups(List nodes) { - Objects.requireNonNull(nodes); - localCellRenderer.setMatchingGroups(nodes); - repaint(); - } - /** Highlights the specified cell or disables highlight if cell == null */ public void setHighlightBorderCell(GroupTreeNodeViewModel node) { localCellRenderer.setHighlightBorderCell(node); @@ -103,40 +33,4 @@ public void setHighlightBorderCell(GroupTreeNodeViewModel node) { public void sort(GroupTreeNodeViewModel node, boolean recursive) { node.sortChildrenByName(recursive); } - - /** - * Returns true if the node specified by path has at least one descendant - * that is currently expanded. - */ - public boolean hasExpandedDescendant(TreePath path) { - GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) path.getLastPathComponent(); - for (GroupTreeNodeViewModel child : node.getChildren()) { - if (child.isLeaf()) { - continue; // don't care about this case - } - TreePath pathToChild = path.pathByAddingChild(child); - if (isExpanded(pathToChild) || hasExpandedDescendant(pathToChild)) { - return true; - } - } - return false; - } - - /** - * Returns true if the node specified by path has at least one descendant - * that is currently collapsed. - */ - public boolean hasCollapsedDescendant(TreePath path) { - GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) path.getLastPathComponent(); - for (GroupTreeNodeViewModel child : node.getChildren()) { - if (child.isLeaf()) { - continue; // don't care about this case - } - TreePath pathToChild = path.pathByAddingChild(child); - if (isCollapsed(pathToChild) || hasCollapsedDescendant(pathToChild)) { - return true; - } - } - return false; - } } diff --git a/src/main/java/org/jabref/gui/groups/RemoveFromGroupAction.java b/src/main/java/org/jabref/gui/groups/RemoveFromGroupAction.java deleted file mode 100644 index a279b16ab5b..00000000000 --- a/src/main/java/org/jabref/gui/groups/RemoveFromGroupAction.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.jabref.gui.groups; - -import java.awt.event.ActionEvent; -import java.util.List; - -import javax.swing.AbstractAction; - -import org.jabref.gui.BasePanel; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.FieldChange; - -public class RemoveFromGroupAction extends AbstractAction { - - private GroupTreeNodeViewModel mNode; - private BasePanel mPanel; - - public RemoveFromGroupAction(GroupTreeNodeViewModel node, BasePanel panel) { - super(node.getNode().getGroup().getName()); - mNode = node; - mPanel = panel; - } - - public RemoveFromGroupAction() { - super(Localization.lang("Remove entry selection from this group")); - } - - public void setNode(GroupTreeNodeViewModel node) { - mNode = node; - } - - public void setBasePanel(BasePanel panel) { - mPanel = panel; - } - - @Override - public void actionPerformed(ActionEvent evt) { - // warn if assignment has undesired side effects (modifies a field != keywords) - if (!WarnAssignmentSideEffects.warnAssignmentSideEffects(mNode.getNode().getGroup(), mPanel.frame())) { - return; // user aborted operation - } - - List undo = mNode.removeEntriesFromGroup(mPanel.getSelectedEntries()); - if (undo.isEmpty()) { - return; // no changed made - } - - mPanel.getUndoManager().addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(mNode, undo)); - mPanel.markBaseChanged(); - mPanel.updateEntryEditorIfShowing(); - mPanel.getGroupSelector().valueChanged(null); - } -} diff --git a/src/main/java/org/jabref/gui/importer/ImportInspectionDialog.java b/src/main/java/org/jabref/gui/importer/ImportInspectionDialog.java index e68a03d9c5d..a6c6d65248a 100644 --- a/src/main/java/org/jabref/gui/importer/ImportInspectionDialog.java +++ b/src/main/java/org/jabref/gui/importer/ImportInspectionDialog.java @@ -75,6 +75,7 @@ import org.jabref.gui.undo.UndoableRemoveEntry; import org.jabref.gui.util.comparator.IconComparator; import org.jabref.gui.util.component.CheckBoxMessage; +import org.jabref.logic.bibtex.DuplicateCheck; import org.jabref.logic.bibtex.comparator.FieldComparator; import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternUtil; import org.jabref.logic.help.HelpFile; @@ -83,7 +84,6 @@ import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.UpdateField; import org.jabref.model.Defaults; -import org.jabref.model.DuplicateCheck; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; @@ -141,7 +141,11 @@ public class ImportInspectionDialog extends JDialog implements ImportInspector, OutputPrinter { private static final Log LOGGER = LogFactory.getLog(ImportInspectionDialog.class); - private BasePanel panel; + private static final List INSPECTION_FIELDS = Arrays.asList(FieldName.AUTHOR, FieldName.TITLE, FieldName.YEAR, BibEntry.KEY_FIELD); + private static final int DUPL_COL = 1; + private static final int FILE_COL = 2; + private static final int URL_COL = 3; + private static final int PAD = 4; private final JabRefFrame frame; private final BibDatabaseContext bibDatabaseContext; private final JSplitPane contentPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); @@ -153,7 +157,6 @@ public class ImportInspectionDialog extends JDialog implements ImportInspector, private final JButton generate = new JButton(Localization.lang("Generate now")); private final EventList entries = new BasicEventList<>(); private final SortedList sortedList; - /** * Duplicate resolving may require deletion of old entries. */ @@ -165,8 +168,6 @@ public class ImportInspectionDialog extends JDialog implements ImportInspector, private final JButton deselectAllDuplicates = new JButton(Localization.lang("Deselect all duplicates")); private final JButton stop = new JButton(Localization.lang("Stop")); private final PreviewPanel preview; - private boolean generatedKeys; // Set to true after keys have been generated. - private boolean defaultSelected = true; private final Rectangle toRect = new Rectangle(0, 0, 1, 1); private final Map> groupAdditions = new HashMap<>(); private final JCheckBox autoGenerate = new JCheckBox(Localization.lang("Generate keys"), @@ -174,11 +175,9 @@ public class ImportInspectionDialog extends JDialog implements ImportInspector, private final JLabel duplLabel = new JLabel(IconTheme.JabRefIcon.DUPLICATE.getSmallIcon()); private final JLabel fileLabel = new JLabel(IconTheme.JabRefIcon.FILE.getSmallIcon()); private final JLabel urlLabel = new JLabel(IconTheme.JabRefIcon.WWW.getSmallIcon()); - private static final List INSPECTION_FIELDS = Arrays.asList(FieldName.AUTHOR, FieldName.TITLE, FieldName.YEAR, BibEntry.KEY_FIELD); - private static final int DUPL_COL = 1; - private static final int FILE_COL = 2; - private static final int URL_COL = 3; - private static final int PAD = 4; + private BasePanel panel; + private boolean generatedKeys; // Set to true after keys have been generated. + private boolean defaultSelected = true; /** @@ -560,6 +559,115 @@ private AbstractAction getAction(GroupTreeNode node) { return action; } + public void addCallBack(CallBack cb) { + callBacks.add(cb); + } + + private void signalStopFetching() { + callBacks.forEach(CallBack::stopFetching); + } + + private void setWidths() { + TableColumnModel cm = glTable.getColumnModel(); + cm.getColumn(0).setPreferredWidth(55); + cm.getColumn(0).setMinWidth(55); + cm.getColumn(0).setMaxWidth(55); + for (int i = 1; i < PAD; i++) { + // Lock the width of icon columns. + cm.getColumn(i).setPreferredWidth(GUIGlobals.WIDTH_ICON_COL); + cm.getColumn(i).setMinWidth(GUIGlobals.WIDTH_ICON_COL); + cm.getColumn(i).setMaxWidth(GUIGlobals.WIDTH_ICON_COL); + } + + for (int i = 0; i < INSPECTION_FIELDS.size(); i++) { + int width = InternalBibtexFields.getFieldLength(INSPECTION_FIELDS.get(i)); + glTable.getColumnModel().getColumn(i + PAD).setPreferredWidth(width); + } + } + + private void setupComparatorChooser() { + // First column: + + List comparators = comparatorChooser.getComparatorsForColumn(0); + comparators.clear(); + + comparators = comparatorChooser.getComparatorsForColumn(1); + comparators.clear(); + + // Icon columns: + for (int i = 2; i < PAD; i++) { + comparators = comparatorChooser.getComparatorsForColumn(i); + comparators.clear(); + if (i == FILE_COL) { + comparators.add(new IconComparator(Collections.singletonList(FieldName.FILE))); + } else if (i == URL_COL) { + comparators.add(new IconComparator(Collections.singletonList(FieldName.URL))); + } + } + // Remaining columns: + for (int i = PAD; i < (PAD + INSPECTION_FIELDS.size()); i++) { + comparators = comparatorChooser.getComparatorsForColumn(i); + comparators.clear(); + comparators.add(new FieldComparator(INSPECTION_FIELDS.get(i - PAD))); + } + + sortedList.getReadWriteLock().writeLock().lock(); + try { + comparatorChooser.appendComparator(PAD, 0, false); + } finally { + sortedList.getReadWriteLock().writeLock().unlock(); + } + } + + /** + * The "defaultSelected" boolean value determines if new entries added are + * selected for import or not. This value is true by default. + * + * @param defaultSelected The desired value. + */ + public void setDefaultSelected(boolean defaultSelected) { + this.defaultSelected = defaultSelected; + } + + @Override + public void setStatus(String s) { + frame.setStatus(s); + } + + @Override + public void showMessage(String message, String title, int msgType) { + JOptionPane.showMessageDialog(this, message, title, msgType); + } + + @Override + public void showMessage(String message) { + JOptionPane.showMessageDialog(this, message); + } + + /** + * Displays a dialog which tells the user that an error occurred while fetching entries + */ + public void showErrorMessage(String fetcherTitle, String localizedException) { + showMessage(Localization.lang("Error while fetching from %0", fetcherTitle) + "\n" + + Localization.lang("Please try again later and/or check your network connection.") + "\n" + + localizedException, + Localization.lang("Search %0", fetcherTitle), JOptionPane.ERROR_MESSAGE); + } + + public JabRefFrame getFrame() { + return frame; + } + + @FunctionalInterface + public interface CallBack { + + /** + * This method is called by the dialog when the user has canceled or + * signaled a stop. It is expected that any long-running fetch + * operations will stop after this method is called. + */ + void stopFetching(); + } /** * Stores the information about the selected entries being scheduled for @@ -600,12 +708,6 @@ public void actionPerformed(ActionEvent event) { } } - - public void addCallBack(CallBack cb) { - callBacks.add(cb); - } - - private class OkListener implements ActionListener { @Override @@ -729,10 +831,9 @@ private void addSelectedEntries(NamedCompound ce, final List selected) } entry.setId(IdGenerator.next()); - panel.getDatabase().insertEntry(entry); ce.addEdit(new UndoableInsertEntry(panel.getDatabase(), entry, panel)); - } + panel.getDatabase().insertEntries(selected); ce.end(); panel.getUndoManager().addEdit(ce); @@ -792,30 +893,6 @@ private List getSelectedEntries() { } - - private void signalStopFetching() { - callBacks.forEach(CallBack::stopFetching); - } - - private void setWidths() { - TableColumnModel cm = glTable.getColumnModel(); - cm.getColumn(0).setPreferredWidth(55); - cm.getColumn(0).setMinWidth(55); - cm.getColumn(0).setMaxWidth(55); - for (int i = 1; i < PAD; i++) { - // Lock the width of icon columns. - cm.getColumn(i).setPreferredWidth(GUIGlobals.WIDTH_ICON_COL); - cm.getColumn(i).setMinWidth(GUIGlobals.WIDTH_ICON_COL); - cm.getColumn(i).setMaxWidth(GUIGlobals.WIDTH_ICON_COL); - } - - for (int i = 0; i < INSPECTION_FIELDS.size(); i++) { - int width = InternalBibtexFields.getFieldLength(INSPECTION_FIELDS.get(i)); - glTable.getColumnModel().getColumn(i + PAD).setPreferredWidth(width); - } - } - - private class DeleteListener extends AbstractAction { public DeleteListener() { @@ -1283,67 +1360,6 @@ public void downloadComplete(FileListEntry file) { } } - - private void setupComparatorChooser() { - // First column: - - List comparators = comparatorChooser.getComparatorsForColumn(0); - comparators.clear(); - - comparators = comparatorChooser.getComparatorsForColumn(1); - comparators.clear(); - - // Icon columns: - for (int i = 2; i < PAD; i++) { - comparators = comparatorChooser.getComparatorsForColumn(i); - comparators.clear(); - if (i == FILE_COL) { - comparators.add(new IconComparator(Collections.singletonList(FieldName.FILE))); - } else if (i == URL_COL) { - comparators.add(new IconComparator(Collections.singletonList(FieldName.URL))); - } - - } - // Remaining columns: - for (int i = PAD; i < (PAD + INSPECTION_FIELDS.size()); i++) { - comparators = comparatorChooser.getComparatorsForColumn(i); - comparators.clear(); - comparators.add(new FieldComparator(INSPECTION_FIELDS.get(i - PAD))); - } - - sortedList.getReadWriteLock().writeLock().lock(); - try { - comparatorChooser.appendComparator(PAD, 0, false); - } finally { - sortedList.getReadWriteLock().writeLock().unlock(); - } - - } - - - @FunctionalInterface - public interface CallBack { - - /** - * This method is called by the dialog when the user has canceled or - * signaled a stop. It is expected that any long-running fetch - * operations will stop after this method is called. - */ - void stopFetching(); - } - - - /** - * The "defaultSelected" boolean value determines if new entries added are - * selected for import or not. This value is true by default. - * - * @param defaultSelected The desired value. - */ - public void setDefaultSelected(boolean defaultSelected) { - this.defaultSelected = defaultSelected; - } - - class EntryTable extends JTable { private final GeneralRenderer renderer = new GeneralRenderer(Color.white); @@ -1448,34 +1464,4 @@ public Object getColumnValue(BibEntry entry, int i) { } } - - - @Override - public void setStatus(String s) { - frame.setStatus(s); - } - - @Override - public void showMessage(String message, String title, int msgType) { - JOptionPane.showMessageDialog(this, message, title, msgType); - } - - @Override - public void showMessage(String message) { - JOptionPane.showMessageDialog(this, message); - } - - /** - * Displays a dialog which tells the user that an error occurred while fetching entries - */ - public void showErrorMessage(String fetcherTitle, String localizedException) { - showMessage(Localization.lang("Error while fetching from %0", fetcherTitle) + "\n" + - Localization.lang("Please try again later and/or check your network connection.") + "\n" + - localizedException, - Localization.lang("Search %0", fetcherTitle), JOptionPane.ERROR_MESSAGE); - } - - public JabRefFrame getFrame() { - return frame; - } } diff --git a/src/main/java/org/jabref/gui/importer/UnlinkedFilesCrawler.java b/src/main/java/org/jabref/gui/importer/UnlinkedFilesCrawler.java index fe409ff66c7..f3b456fa937 100644 --- a/src/main/java/org/jabref/gui/importer/UnlinkedFilesCrawler.java +++ b/src/main/java/org/jabref/gui/importer/UnlinkedFilesCrawler.java @@ -54,7 +54,7 @@ public CheckableTreeNode searchDirectory(File directory, FileFilter filter) { * resolve its recursion and return what it has saved so far. */ public CheckableTreeNode searchDirectory(File directory, UnlinkedPDFFileFilter ff, AtomicBoolean state, ChangeListener changeListener) { - /* Cancelation of the search from outside! */ + /* Cancellation of the search from outside! */ if ((state == null) || !state.get()) { return null; } diff --git a/src/main/java/org/jabref/gui/importer/fetcher/IdBasedEntryFetcher.java b/src/main/java/org/jabref/gui/importer/fetcher/IdBasedEntryFetcher.java deleted file mode 100644 index 13e93e64d4e..00000000000 --- a/src/main/java/org/jabref/gui/importer/fetcher/IdBasedEntryFetcher.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.jabref.gui.importer.fetcher; - -import java.util.Objects; -import java.util.Optional; - -import javax.swing.JPanel; - -import org.jabref.gui.importer.ImportInspectionDialog; -import org.jabref.logic.help.HelpFile; -import org.jabref.logic.importer.FetcherException; -import org.jabref.logic.importer.IdBasedFetcher; -import org.jabref.logic.importer.ImportInspector; -import org.jabref.logic.importer.OutputPrinter; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.entry.BibEntry; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class IdBasedEntryFetcher implements EntryFetcher { - - private static final Log LOGGER = LogFactory.getLog(IdBasedEntryFetcher.class); - private final IdBasedFetcher fetcher; - - public IdBasedEntryFetcher(IdBasedFetcher fetcher) { - this.fetcher = Objects.requireNonNull(fetcher); - } - - @Override - public boolean processQuery(String query, ImportInspector inspector, OutputPrinter status) { - - status.setStatus(Localization.lang("Processing %0", query)); - try { - Optional match = fetcher.performSearchById(query); - match.ifPresent(inspector::addEntry); - return match.isPresent(); - } catch (FetcherException e) { - LOGGER.error("Error while fetching from " + getTitle(), e); - ((ImportInspectionDialog)inspector).showErrorMessage(this.getTitle(), e.getLocalizedMessage()); - } - - return false; - } - - @Override - public String getTitle() { - return fetcher.getName(); - } - - @Override - public HelpFile getHelpPage() { - return fetcher.getHelpPage(); - } - - @Override - public JPanel getOptionsPanel() { - // not supported - return null; - } - - @Override - public void stopFetching() { - // not supported - } -} diff --git a/src/main/java/org/jabref/gui/journals/ManageJournalAbbreviationsViewModel.java b/src/main/java/org/jabref/gui/journals/ManageJournalAbbreviationsViewModel.java index d279ab5c187..e4d16f7d7ac 100644 --- a/src/main/java/org/jabref/gui/journals/ManageJournalAbbreviationsViewModel.java +++ b/src/main/java/org/jabref/gui/journals/ManageJournalAbbreviationsViewModel.java @@ -112,17 +112,18 @@ public boolean isAbbreviationEditableAndRemovable() { * and add them to the list of journal abbreviation files. */ void addBuiltInLists() { - BackgroundTask> loadBuiltIn = BackgroundTask - .run(JournalAbbreviationLoader::getBuiltInAbbreviations) + BackgroundTask + .wrap(JournalAbbreviationLoader::getBuiltInAbbreviations) .onRunning(() -> isLoadingBuiltIn.setValue(true)) .onSuccess(result -> { isLoadingBuiltIn.setValue(false); addList(Localization.lang("JabRef built in list"), result); }) - .onFailure(dialogService::showErrorDialogAndWait); + .onFailure(dialogService::showErrorDialogAndWait) + .executeWith(taskExecutor); - BackgroundTask> loadIeee = BackgroundTask - .run(() -> { + BackgroundTask + .wrap(() -> { if (preferences.getBoolean(JabRefPreferences.USE_IEEE_ABRV)) { return JournalAbbreviationLoader.getOfficialIEEEAbbreviations(); } else { @@ -134,10 +135,8 @@ void addBuiltInLists() { isLoadingIeee.setValue(false); addList(Localization.lang("IEEE built in list"), result); }) - .onFailure(dialogService::showErrorDialogAndWait); - - taskExecutor.execute(loadBuiltIn); - taskExecutor.execute(loadIeee); + .onFailure(dialogService::showErrorDialogAndWait) + .executeWith(taskExecutor); } private void addList(String name, List abbreviations) { diff --git a/src/main/java/org/jabref/gui/preftabs/FileTab.java b/src/main/java/org/jabref/gui/preftabs/FileTab.java index 717ed368c94..1045114b445 100644 --- a/src/main/java/org/jabref/gui/preftabs/FileTab.java +++ b/src/main/java/org/jabref/gui/preftabs/FileTab.java @@ -18,9 +18,12 @@ import javax.swing.JRadioButton; import javax.swing.JTextField; -import org.jabref.gui.FileDialog; +import org.jabref.gui.DialogService; +import org.jabref.gui.FXDialogService; import org.jabref.gui.JabRefFrame; import org.jabref.gui.help.HelpAction; +import org.jabref.gui.util.DefaultTaskExecutor; +import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; @@ -55,11 +58,12 @@ class FileTab extends JPanel implements PrefsTab { private final JCheckBox runAutoFileSearch; private final JCheckBox allowFileAutoOpenBrowse; private final JRadioButton useRegExpComboBox; - private final JRadioButton matchExactKeyOnly = new JRadioButton(Localization.lang("Autolink only files that match the BibTeX key")); - private final JRadioButton matchStartsWithKey = new JRadioButton(Localization.lang("Autolink files with names starting with the BibTeX key")); + private final JRadioButton matchExactKeyOnly = new JRadioButton( + Localization.lang("Autolink only files that match the BibTeX key")); + private final JRadioButton matchStartsWithKey = new JRadioButton( + Localization.lang("Autolink files with names starting with the BibTeX key")); private final JTextField regExpTextField; - public FileTab(JabRefFrame frame, JabRefPreferences prefs) { this.prefs = prefs; this.frame = frame; @@ -68,8 +72,10 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { bibLocAsPrimaryDir = new JCheckBox(Localization.lang("Use the BIB file location as primary file directory")); bibLocAsPrimaryDir.setToolTipText(Localization.lang("When downloading files, or moving linked files to the " + "file directory, prefer the BIB file location rather than the file directory set above")); - runAutoFileSearch = new JCheckBox(Localization.lang("When opening file link, search for matching file if no link is defined")); - allowFileAutoOpenBrowse = new JCheckBox(Localization.lang("Automatically open browse dialog when creating new file link")); + runAutoFileSearch = new JCheckBox( + Localization.lang("When opening file link, search for matching file if no link is defined")); + allowFileAutoOpenBrowse = new JCheckBox( + Localization.lang("Automatically open browse dialog when creating new file link")); regExpTextField = new JTextField(25); useRegExpComboBox = new JRadioButton(Localization.lang("Use regular expression search")); ItemListener regExpListener = e -> regExpTextField.setEditable(useRegExpComboBox.isSelected()); @@ -131,10 +137,16 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { builder.append(fileDir); JButton browse = new JButton(Localization.lang("Browse")); - browse.addActionListener(e -> - new FileDialog(this.frame).showDialogAndGetSelectedDirectory() - .ifPresent(f -> fileDir.setText(f.toAbsolutePath().toString())) - ); + browse.addActionListener(e -> { + + DialogService ds = new FXDialogService(); + DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder() + .withInitialDirectory(Paths.get(fileDir.getText())).build(); + + DefaultTaskExecutor.runInJavaFXThread(() -> ds.showDirectorySelectionDialog(dirDialogConfiguration)) + .ifPresent(f -> fileDir.setText(f.toString())); + + }); builder.append(browse); builder.nextLine(); @@ -149,7 +161,7 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { builder.append(new HelpAction(Localization.lang("Help on regular expression search"), HelpFile.REGEX_SEARCH) - .getHelpButton()); + .getHelpButton()); builder.nextLine(); builder.append(runAutoFileSearch, 3); builder.nextLine(); @@ -172,7 +184,6 @@ public FileTab(JabRefFrame frame, JabRefPreferences prefs) { add(pan, BorderLayout.CENTER); } - @Override public void setValues() { fileDir.setText(prefs.get(FieldName.FILE + FileDirectoryPreferences.DIR_SUFFIX)); diff --git a/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java b/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java index 57dd4721bc1..6b6cd35e365 100644 --- a/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java +++ b/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java @@ -5,6 +5,7 @@ import java.awt.event.FocusListener; import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; @@ -18,11 +19,8 @@ class GroupsPrefsTab extends JPanel implements PrefsTab { - private final JCheckBox showIcons = new JCheckBox(Localization.lang("Show icons for groups")); - private final JCheckBox showDynamic = new JCheckBox( - "" + Localization.lang("Show dynamic groups in italics") + ""); - private final JCheckBox expandTree = new JCheckBox( - Localization.lang("Initially show groups tree expanded")); + private final JCheckBox hideNonHits = new JCheckBox(Localization.lang("Hide non-hits")); + private final JCheckBox grayOut = new JCheckBox(Localization.lang("Gray out non-hits")); private final JCheckBox autoAssignGroup = new JCheckBox( Localization.lang("Automatically assign new entry to selected groups")); private final JTextField groupingField = new JTextField(20); @@ -47,23 +45,22 @@ public void focusLost(FocusEvent e) { } }); + ButtonGroup hideMode = new ButtonGroup(); + hideMode.add(grayOut); + hideMode.add(hideNonHits); + FormLayout layout = new FormLayout("9dlu, pref", //500px", - "p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, " + - "p, 3dlu, p"); + "p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p"); DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.appendSeparator(Localization.lang("View")); builder.nextLine(); builder.nextLine(); builder.nextColumn(); - builder.append(showIcons); - builder.nextLine(); - builder.nextLine(); - builder.nextColumn(); - builder.append(showDynamic); + builder.append(hideNonHits); builder.nextLine(); builder.nextLine(); builder.nextColumn(); - builder.append(expandTree); + builder.append(grayOut); builder.nextLine(); builder.nextLine(); builder.nextColumn(); @@ -94,9 +91,7 @@ public void focusLost(FocusEvent e) { @Override public void setValues() { - showIcons.setSelected(prefs.getBoolean(JabRefPreferences.GROUP_SHOW_ICONS)); - showDynamic.setSelected(prefs.getBoolean(JabRefPreferences.GROUP_SHOW_DYNAMIC)); - expandTree.setSelected(prefs.getBoolean(JabRefPreferences.GROUP_EXPAND_TREE)); + grayOut.setSelected(prefs.getBoolean(JabRefPreferences.GRAY_OUT_NON_HITS)); groupingField.setText(prefs.get(JabRefPreferences.GROUPS_DEFAULT_FIELD)); keywordSeparator.setText(prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); autoAssignGroup.setSelected(prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); @@ -104,9 +99,7 @@ public void setValues() { @Override public void storeSettings() { - prefs.putBoolean(JabRefPreferences.GROUP_SHOW_ICONS, showIcons.isSelected()); - prefs.putBoolean(JabRefPreferences.GROUP_SHOW_DYNAMIC, showDynamic.isSelected()); - prefs.putBoolean(JabRefPreferences.GROUP_EXPAND_TREE, expandTree.isSelected()); + prefs.putBoolean(JabRefPreferences.GRAY_OUT_NON_HITS, grayOut.isSelected()); prefs.put(JabRefPreferences.GROUPS_DEFAULT_FIELD, groupingField.getText().trim()); prefs.putBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP, autoAssignGroup.isSelected()); prefs.put(JabRefPreferences.KEYWORD_SEPARATOR, keywordSeparator.getText()); diff --git a/src/main/java/org/jabref/gui/util/BackgroundTask.java b/src/main/java/org/jabref/gui/util/BackgroundTask.java index ed33cad1757..4acde6eef13 100644 --- a/src/main/java/org/jabref/gui/util/BackgroundTask.java +++ b/src/main/java/org/jabref/gui/util/BackgroundTask.java @@ -23,7 +23,7 @@ private BackgroundTask(Callable callable) { this.callable = callable; } - public static BackgroundTask run(Callable callable) { + public static BackgroundTask wrap(Callable callable) { return new BackgroundTask<>(callable); } @@ -57,4 +57,8 @@ public BackgroundTask onFailure(Consumer onException) { this.onException = onException; return this; } + + public void executeWith(TaskExecutor taskExecutor) { + taskExecutor.execute(this); + } } diff --git a/src/main/java/org/jabref/gui/util/CurrentThreadTaskExecutor.java b/src/main/java/org/jabref/gui/util/CurrentThreadTaskExecutor.java index af782d90014..54d704afb46 100644 --- a/src/main/java/org/jabref/gui/util/CurrentThreadTaskExecutor.java +++ b/src/main/java/org/jabref/gui/util/CurrentThreadTaskExecutor.java @@ -40,4 +40,9 @@ public void execute(BackgroundTask task) { } } } + + @Override + public void shutdown() { + // Nothing to do here + } } diff --git a/src/main/java/org/jabref/gui/util/DefaultTaskExecutor.java b/src/main/java/org/jabref/gui/util/DefaultTaskExecutor.java index 63b0a615cb0..f35404df261 100644 --- a/src/main/java/org/jabref/gui/util/DefaultTaskExecutor.java +++ b/src/main/java/org/jabref/gui/util/DefaultTaskExecutor.java @@ -2,6 +2,8 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.function.Consumer; @@ -19,6 +21,8 @@ public class DefaultTaskExecutor implements TaskExecutor { private static final Log LOGGER = LogFactory.getLog(DefaultTaskExecutor.class); + private ExecutorService executor = Executors.newFixedThreadPool(5); + public static V runInJavaFXThread(Callable callable) { FutureTask task = new FutureTask<>(callable); Platform.runLater(task); @@ -36,7 +40,12 @@ public static void runInJavaFXThread(Runnable runnable) { @Override public void execute(BackgroundTask task) { - new Thread(getJavaFXTask(task)).start(); + executor.submit(getJavaFXTask(task)); + } + + @Override + public void shutdown() { + executor.shutdownNow(); } private Task getJavaFXTask(BackgroundTask task) { diff --git a/src/main/java/org/jabref/gui/util/DirectoryDialogConfiguration.java b/src/main/java/org/jabref/gui/util/DirectoryDialogConfiguration.java index 0bce9d54be7..c66409e1c0f 100644 --- a/src/main/java/org/jabref/gui/util/DirectoryDialogConfiguration.java +++ b/src/main/java/org/jabref/gui/util/DirectoryDialogConfiguration.java @@ -26,13 +26,16 @@ public DirectoryDialogConfiguration build() { public Builder withInitialDirectory(Path directory) { + directory = directory.toAbsolutePath(); //Dir must be a folder, not a file if (!Files.isDirectory(directory)) { directory = directory.getParent(); } //The lines above work also if the dir does not exist at all! //NULL is accepted by the filechooser as no inital path + if (!Files.exists(directory)) { + directory = null; } initialDirectory = directory; diff --git a/src/main/java/org/jabref/gui/util/TaskExecutor.java b/src/main/java/org/jabref/gui/util/TaskExecutor.java index 6ba9bb79f78..76c2db991cd 100644 --- a/src/main/java/org/jabref/gui/util/TaskExecutor.java +++ b/src/main/java/org/jabref/gui/util/TaskExecutor.java @@ -17,4 +17,9 @@ public interface TaskExecutor { * @param type of return value of the task */ void execute(BackgroundTask task); + + /** + * Shutdown the task executor. + */ + void shutdown(); } diff --git a/src/main/java/org/jabref/model/DuplicateCheck.java b/src/main/java/org/jabref/logic/bibtex/DuplicateCheck.java similarity index 86% rename from src/main/java/org/jabref/model/DuplicateCheck.java rename to src/main/java/org/jabref/logic/bibtex/DuplicateCheck.java index de68ddfd6a9..b0773a11c37 100644 --- a/src/main/java/org/jabref/model/DuplicateCheck.java +++ b/src/main/java/org/jabref/logic/bibtex/DuplicateCheck.java @@ -1,4 +1,4 @@ -package org.jabref.model; +package org.jabref.logic.bibtex; import java.util.HashMap; import java.util.HashSet; @@ -8,6 +8,8 @@ import java.util.Optional; import java.util.Set; +import org.jabref.logic.util.strings.StringSimilarity; +import org.jabref.model.EntryTypes; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.AuthorList; @@ -24,12 +26,10 @@ * This class contains utility method for duplicate checking of entries. */ public class DuplicateCheck { - private static final Log LOGGER = LogFactory.getLog(DuplicateCheck.class); /* * Integer values for indicating result of duplicate check (for entries): - * */ private static final int NOT_EQUAL = 0; private static final int EQUAL = 1; @@ -47,7 +47,6 @@ public class DuplicateCheck { // Extra weighting of those fields that are most likely to provide correct duplicate detection: private static final Map FIELD_WEIGHTS = new HashMap<>(); - static { DuplicateCheck.FIELD_WEIGHTS.put(FieldName.AUTHOR, 2.5); DuplicateCheck.FIELD_WEIGHTS.put(FieldName.EDITOR, 2.5); @@ -55,8 +54,7 @@ public class DuplicateCheck { DuplicateCheck.FIELD_WEIGHTS.put(FieldName.JOURNAL, 2.); } - private DuplicateCheck() { - } + private DuplicateCheck() {} /** * Checks if the two entries represent the same publication. @@ -66,13 +64,17 @@ private DuplicateCheck() { * @return boolean */ public static boolean isDuplicate(BibEntry one, BibEntry two, BibDatabaseMode bibDatabaseMode) { + // same identifier + if (hasSameIdentifier(one, two)) { + return true; + } - // First check if they are of the same type - a necessary condition: + // same entry type if (!one.getType().equals(two.getType())) { return false; } - EntryType type = EntryTypes.getTypeOrDefault(one.getType(), bibDatabaseMode); + EntryType type = EntryTypes.getTypeOrDefault(one.getType(), bibDatabaseMode); // The check if they have the same required fields: List var = type.getRequiredFieldsFlat(); double[] req; @@ -96,6 +98,15 @@ public static boolean isDuplicate(BibEntry one, BibEntry two, BibDatabaseMode bi return req[0] >= DuplicateCheck.duplicateThreshold; } + private static boolean hasSameIdentifier(BibEntry one, BibEntry two) { + for (String name : FieldName.getIdentifierFieldNames()) { + if (one.getField(name).isPresent() && one.getField(name).equals(two.getField(name))) { + return true; + } + } + return false; + } + private static double[] compareFieldSet(List fields, BibEntry one, BibEntry two) { double res = 0; double totWeights = 0.; @@ -249,51 +260,18 @@ private static double similarity(String s1, String s2) { String longer = s1; String shorter = s2; - if (s1.length() < s2.length()) { // longer should always have greater length + if (s1.length() < s2.length()) { longer = s2; shorter = s1; } + int longerLength = longer.length(); + // both strings are zero length if (longerLength == 0) { return 1.0; - /* both strings are zero length */ } - double sim = (longerLength - editDistance(longer, shorter)) / (double) longerLength; + } + double sim = (longerLength - new StringSimilarity().editDistanceIgnoreCase(longer, shorter)) / (double) longerLength; LOGGER.debug("Longer string: " + longer + " Shorter string: " + shorter + " Similarity: " + sim); return sim; - - } - - /* - * Levenshtein Edit Distance - * http://stackoverflow.com/questions/955110/similarity-string-comparison-in-java - */ - private static int editDistance(String s1, String s2) { - String s1LowerCase = s1.toLowerCase(Locale.ROOT); - String s2LowerCase = s2.toLowerCase(Locale.ROOT); - - int[] costs = new int[s2LowerCase.length() + 1]; - for (int i = 0; i <= s1LowerCase.length(); i++) { - int lastValue = i; - for (int j = 0; j <= s2LowerCase.length(); j++) { - if (i == 0) { - costs[j] = j; - } else if (j > 0) { - int newValue = costs[j - 1]; - if (s1LowerCase.charAt(i - 1) != s2LowerCase.charAt(j - 1)) { - newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1; - } - costs[j - 1] = lastValue; - lastValue = newValue; - - } - } - if (i > 0) { - costs[s2LowerCase.length()] = lastValue; - } - } - LOGGER.debug("String 1: " + s1LowerCase + " String 2: " + s2LowerCase + " Distance: " + costs[s2LowerCase.length()]); - return costs[s2LowerCase.length()]; } - - } diff --git a/src/main/java/org/jabref/logic/importer/IdParserFetcher.java b/src/main/java/org/jabref/logic/importer/IdParserFetcher.java index 89d5a5568d0..f9608feac73 100644 --- a/src/main/java/org/jabref/logic/importer/IdParserFetcher.java +++ b/src/main/java/org/jabref/logic/importer/IdParserFetcher.java @@ -89,6 +89,7 @@ default Optional findIdentifier(BibEntry entry) throws FetcherException { return Optional.empty(); } catch (IOException e) { // TODO: Catch HTTP Response 401 errors and report that user has no rights to access resource + // TODO catch 503 service unavailable and alert user throw new FetcherException("An I/O exception occurred", e); } catch (ParseException e) { throw new FetcherException("An internal parser error occurred", e); diff --git a/src/main/java/org/jabref/logic/importer/WebFetchers.java b/src/main/java/org/jabref/logic/importer/WebFetchers.java index 5e4c3903531..3f17abbaee4 100644 --- a/src/main/java/org/jabref/logic/importer/WebFetchers.java +++ b/src/main/java/org/jabref/logic/importer/WebFetchers.java @@ -94,9 +94,10 @@ public static List getEntryBasedFetchers(ImportFormatPreferen return list; } - public static List getIdFetchers() { + public static List getIdFetchers(ImportFormatPreferences importFormatPreferences) { ArrayList list = new ArrayList<>(); list.add(new CrossRef()); + list.add(new ArXiv(importFormatPreferences)); list.sort(Comparator.comparing(WebFetcher::getName)); return list; } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java b/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java index 5575d0f1602..af617d5c289 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java @@ -20,6 +20,7 @@ import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.FulltextFetcher; import org.jabref.logic.importer.IdBasedFetcher; +import org.jabref.logic.importer.IdFetcher; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.SearchBasedFetcher; import org.jabref.logic.importer.util.OAI2Handler; @@ -32,6 +33,7 @@ import org.jabref.model.entry.identifier.ArXivIdentifier; import org.jabref.model.entry.identifier.DOI; import org.jabref.model.strings.StringUtil; +import org.jabref.model.util.OptionalUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,7 +53,7 @@ * arxiv2bib which is live * dspace-portalmec */ -public class ArXiv implements FulltextFetcher, SearchBasedFetcher, IdBasedFetcher { +public class ArXiv implements FulltextFetcher, SearchBasedFetcher, IdBasedFetcher, IdFetcher { private static final Log LOGGER = LogFactory.getLog(ArXiv.class); private static final String API_URL = "http://export.arxiv.org/api/query"; @@ -65,51 +67,23 @@ public ArXiv(ImportFormatPreferences importFormatPreferences) { @Override public Optional findFullText(BibEntry entry) throws IOException { Objects.requireNonNull(entry); - Optional pdfUrl = Optional.empty(); - // 1. Eprint - Optional identifier = entry.getField(FieldName.EPRINT); - if (StringUtil.isNotBlank(identifier)) { - try { - // Get pdf of entry with the specified id - pdfUrl = searchForEntryById(identifier.get()).flatMap(ArXivEntry::getPdfUrl); - if (pdfUrl.isPresent()) { - LOGGER.info("Fulltext PDF found @ arXiv."); - return pdfUrl; - } - } catch (FetcherException e) { - LOGGER.warn("arXiv eprint API request failed", e); - } - } - - // 2. DOI - Optional doi = entry.getField(FieldName.DOI).flatMap(DOI::build); - if (doi.isPresent()) { - String doiString = doi.get().getDOI(); - // Search for an entry in the ArXiv which is linked to the doi - try { - Optional arxivEntry = searchForEntry("doi:" + doiString); - - if (arxivEntry.isPresent()) { - // Check if entry is a match - StringSimilarity match = new StringSimilarity(); - String arxivTitle = arxivEntry.get().title.orElse(""); - String entryTitle = entry.getField(FieldName.TITLE).orElse(""); - - if (match.isSimilar(arxivTitle, entryTitle)) { - pdfUrl = arxivEntry.get().getPdfUrl(); - if (pdfUrl.isPresent()) { - LOGGER.info("Fulltext PDF found @ arXiv."); - return pdfUrl; - } - } - } - } catch (FetcherException e) { - LOGGER.warn("arXiv DOI API request failed", e); + try { + Optional pdfUrl = searchForEntries(entry).stream() + .map(ArXivEntry::getPdfUrl) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + + if (pdfUrl.isPresent()) { + LOGGER.info("Fulltext PDF found @ arXiv."); } + return pdfUrl; + } catch (FetcherException e) { + LOGGER.warn("arXiv API request failed", e); } - return pdfUrl; + return Optional.empty(); } private Optional searchForEntry(String searchQuery) throws FetcherException { @@ -135,6 +109,47 @@ private Optional searchForEntryById(String id) throws FetcherExcepti } } + private List searchForEntries(BibEntry entry) throws FetcherException { + // 1. Eprint + Optional identifier = entry.getField(FieldName.EPRINT); + if (StringUtil.isNotBlank(identifier)) { + try { + // Get pdf of entry with the specified id + return OptionalUtil.toList(searchForEntryById(identifier.get())); + } catch (FetcherException e) { + LOGGER.warn("arXiv eprint API request failed", e); + } + } + + // 2. DOI and other fields + String query; + + Optional doi = entry.getField(FieldName.DOI).flatMap(DOI::build).map(DOI::getNormalized); + if (doi.isPresent()) { + // Search for an entry in the ArXiv which is linked to the doi + query = "doi:" + doi.get(); + } else { + Optional authorQuery = entry.getField(FieldName.AUTHOR).map(author -> "au:" + author); + Optional titleQuery = entry.getField(FieldName.TITLE).map(title -> "ti:" + title); + query = OptionalUtil.toList(authorQuery, titleQuery).stream().collect(Collectors.joining("+AND+")); + } + + Optional arxivEntry = searchForEntry(query); + + if (arxivEntry.isPresent()) { + // Check if entry is a match + StringSimilarity match = new StringSimilarity(); + String arxivTitle = arxivEntry.get().title.orElse(""); + String entryTitle = entry.getField(FieldName.TITLE).orElse(""); + + if (match.isSimilar(arxivTitle, entryTitle)) { + return OptionalUtil.toList(arxivEntry); + } + } + + return Collections.emptyList(); + } + private List searchForEntries(String searchQuery) throws FetcherException { return queryApi(searchQuery, Collections.emptyList(), 0, 10); } @@ -242,6 +257,19 @@ public Optional performSearchById(String identifier) throws FetcherExc (arXivEntry) -> arXivEntry.toBibEntry(importFormatPreferences.getKeywordSeparator())); } + @Override + public Optional findIdentifier(BibEntry entry) throws FetcherException { + return searchForEntries(entry).stream() + .map(ArXivEntry::getId) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + } + + @Override + public String getIdentifierName() { + return "ArXiv"; + } private static class ArXivEntry { @@ -326,7 +354,7 @@ public Optional getPdfUrl() { /** * Returns the arXiv identifier */ - public Optional getId() { + public Optional getIdString() { // remove leading http://arxiv.org/abs/ from abstract url to get arXiv ID String prefix = "http://arxiv.org/abs/"; return urlAbstractPage.map(abstractUrl -> { @@ -338,6 +366,10 @@ public Optional getId() { }); } + public Optional getId() { + return getIdString().flatMap(ArXivIdentifier::parse); + } + /** * Returns the date when the first version was put on the arXiv */ @@ -358,7 +390,7 @@ public BibEntry toBibEntry(Character keywordDelimiter) { bibEntry.setField(FieldName.EPRINTTYPE, "arXiv"); bibEntry.setField(FieldName.AUTHOR, String.join(" and ", authorNames)); bibEntry.addKeywords(categories, keywordDelimiter); - getId().ifPresent(id -> bibEntry.setField(FieldName.EPRINT, id)); + getIdString().ifPresent(id -> bibEntry.setField(FieldName.EPRINT, id)); title.ifPresent(titleContent -> bibEntry.setField(FieldName.TITLE, titleContent)); doi.ifPresent(doiContent -> bibEntry.setField(FieldName.DOI, doiContent)); abstractText.ifPresent(abstractContent -> bibEntry.setField(FieldName.ABSTRACT, abstractContent)); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java index d2d9f8e6e47..37fd25fe1da 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java @@ -251,9 +251,6 @@ private void parseAndAddEntry(String type) { boolean duplicateKey = database.insertEntry(entry); if (duplicateKey) { parserResult.addDuplicateKey(entry.getCiteKey()); - } else if (!entry.getCiteKeyOptional().isPresent() || entry.getCiteKeyOptional().get().isEmpty()) { - parserResult.addWarning(Localization.lang("Empty BibTeX key") + ": " + entry.getAuthorTitleYear(40) - + " (" + Localization.lang("Grouping may not work for this entry.") + ")"); } } catch (IOException ex) { LOGGER.debug("Could not parse entry", ex); diff --git a/src/main/java/org/jabref/logic/integrity/BibtexkeyChecker.java b/src/main/java/org/jabref/logic/integrity/BibtexKeyChecker.java similarity index 56% rename from src/main/java/org/jabref/logic/integrity/BibtexkeyChecker.java rename to src/main/java/org/jabref/logic/integrity/BibtexKeyChecker.java index d6274578599..414f29a2105 100644 --- a/src/main/java/org/jabref/logic/integrity/BibtexkeyChecker.java +++ b/src/main/java/org/jabref/logic/integrity/BibtexKeyChecker.java @@ -13,23 +13,21 @@ /** * Currently only checks the key if there is an author, year, and title present. */ -public class BibtexkeyChecker implements Checker { +public class BibtexKeyChecker implements Checker { @Override public List check(BibEntry entry) { - Optional valuekey = entry.getCiteKeyOptional(); - Optional valueauthor = entry.getField(FieldName.AUTHOR); - Optional valuetitle = entry.getField(FieldName.TITLE); - Optional valueyear = entry.getField(FieldName.YEAR); - String authortitleyear = entry.getAuthorTitleYear(100); - - if (!valueauthor.isPresent() || !valuetitle.isPresent() || !valueyear.isPresent()) { + Optional author = entry.getField(FieldName.AUTHOR); + Optional title = entry.getField(FieldName.TITLE); + Optional year = entry.getField(FieldName.YEAR); + if (!author.isPresent() || !title.isPresent() || !year.isPresent()) { return Collections.emptyList(); } - if (StringUtil.isBlank(valuekey)) { + if (StringUtil.isBlank(entry.getCiteKeyOptional())) { + String authorTitleYear = entry.getAuthorTitleYear(100); return Collections.singletonList(new IntegrityMessage( - Localization.lang("empty BibTeX key") + ": " + authortitleyear, entry, BibEntry.KEY_FIELD)); + Localization.lang("empty BibTeX key") + ": " + authorTitleYear, entry, BibEntry.KEY_FIELD)); } return Collections.emptyList(); diff --git a/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java index 8e0df0e093b..e349e4ef093 100644 --- a/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java @@ -60,7 +60,7 @@ private List checkBibtexEntry(BibEntry entry) { result.addAll(new JournalInAbbreviationListChecker(FieldName.JOURNALTITLE, journalAbbreviationRepository).check(entry)); } - result.addAll(new BibtexkeyChecker().check(entry)); + result.addAll(new BibtexKeyChecker().check(entry)); result.addAll(new TypeChecker().check(entry)); result.addAll(new BibStringChecker().check(entry)); result.addAll(new HTMLCharacterChecker().check(entry)); diff --git a/src/main/java/org/jabref/logic/msbib/BibTeXConverter.java b/src/main/java/org/jabref/logic/msbib/BibTeXConverter.java index 671db1ebdb0..9b9c7ecb079 100644 --- a/src/main/java/org/jabref/logic/msbib/BibTeXConverter.java +++ b/src/main/java/org/jabref/logic/msbib/BibTeXConverter.java @@ -103,11 +103,11 @@ public static BibEntry convert(MSBibEntry entry) { return result; } - private static void addAuthor(Map map, String type, List authors) { + private static void addAuthor(Map map, String type, List authors) { if (authors == null) { return; } - String allAuthors = authors.stream().map(PersonName::getFullname).collect(Collectors.joining(" and ")); + String allAuthors = authors.stream().map(MsBibAuthor::getLastFirst).collect(Collectors.joining(" and ")); map.put(type, allAuthors); } diff --git a/src/main/java/org/jabref/logic/msbib/MSBibConverter.java b/src/main/java/org/jabref/logic/msbib/MSBibConverter.java index a7bc4f49a4b..1094fe34585 100644 --- a/src/main/java/org/jabref/logic/msbib/MSBibConverter.java +++ b/src/main/java/org/jabref/logic/msbib/MSBibConverter.java @@ -2,8 +2,9 @@ import java.util.ArrayList; import java.util.List; -import java.util.Locale; +import org.jabref.model.entry.Author; +import org.jabref.model.entry.AuthorList; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; @@ -54,12 +55,13 @@ public static MSBibEntry convert(BibEntry entry) { result.number = null; } - result.journalName = entry.getFieldOrAlias(FieldName.JOURNAL).orElse(null); + result.day = entry.getFieldOrAlias(FieldName.DAY).orElse(null); result.month = entry.getFieldOrAlias(FieldName.MONTH).orElse(null); if (!entry.getField(FieldName.YEAR).isPresent()) { result.year = entry.getFieldOrAlias(FieldName.YEAR).orElse(null); } + result.journalName = entry.getFieldOrAlias(FieldName.JOURNAL).orElse(null); // Value must be converted //Currently only english is supported @@ -103,23 +105,25 @@ public static MSBibEntry convert(BibEntry entry) { result.publicationTitle = entry.getField(FieldName.TITLE).orElse(null); } - entry.getLatexFreeField(FieldName.AUTHOR).ifPresent(authors -> result.authors = getAuthors(authors)); - entry.getLatexFreeField(FieldName.EDITOR).ifPresent(editors -> result.editors = getAuthors(editors)); + entry.getField(FieldName.AUTHOR).ifPresent(authors -> result.authors = getAuthors(authors)); + entry.getField(FieldName.EDITOR).ifPresent(editors -> result.editors = getAuthors(editors)); return result; } - private static List getAuthors(String authors) { - List result = new ArrayList<>(); + private static List getAuthors(String authors) { + List result = new ArrayList<>(); + boolean corporate = false; + //Only one corporate authors is supported + if (authors.startsWith("{") && authors.endsWith("}")) { + corporate = true; + } + AuthorList authorList = AuthorList.parse(authors); - if (authors.toUpperCase(Locale.ENGLISH).contains(" AND ")) { - String[] names = authors.split(" (?i)and "); - for (String name : names) { - result.add(new PersonName(name)); - } - } else { - result.add(new PersonName(authors)); + for (Author author : authorList.getAuthors()) { + result.add(new MsBibAuthor(author, corporate)); } + return result; } diff --git a/src/main/java/org/jabref/logic/msbib/MSBibEntry.java b/src/main/java/org/jabref/logic/msbib/MSBibEntry.java index 8443f40e60a..85566964b84 100644 --- a/src/main/java/org/jabref/logic/msbib/MSBibEntry.java +++ b/src/main/java/org/jabref/logic/msbib/MSBibEntry.java @@ -4,9 +4,12 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.jabref.model.entry.Author; +import org.jabref.model.entry.AuthorList; import org.jabref.model.strings.StringUtil; import org.w3c.dom.Document; @@ -26,21 +29,21 @@ class MSBibEntry { // MSBib fields and values public Map fields = new HashMap<>(); - public List authors; - public List bookAuthors; - public List editors; - public List translators; - public List producerNames; - public List composers; - public List conductors; - public List performers; - public List writers; - public List directors; - public List compilers; - public List interviewers; - public List interviewees; - public List inventors; - public List counsels; + public List authors; + public List bookAuthors; + public List editors; + public List translators; + public List producerNames; + public List composers; + public List conductors; + public List performers; + public List writers; + public List directors; + public List compilers; + public List interviewers; + public List interviewees; + public List inventors; + public List counsels; public PageNumbers pages; @@ -203,8 +206,8 @@ private void getAuthors(Element authorsElem) { counsels = getSpecificAuthors("Counsel", authorsElem); } - private List getSpecificAuthors(String type, Element authors) { - List result = null; + private List getSpecificAuthors(String type, Element authors) { + List result = null; NodeList nodeLst = authors.getElementsByTagNameNS("*", type); if (nodeLst.getLength() <= 0) { return result; @@ -223,17 +226,25 @@ private List getSpecificAuthors(String type, Element authors) { NodeList firstName = ((Element) person.item(i)).getElementsByTagNameNS("*", "First"); NodeList lastName = ((Element) person.item(i)).getElementsByTagNameNS("*", "Last"); NodeList middleName = ((Element) person.item(i)).getElementsByTagNameNS("*", "Middle"); - PersonName name = new PersonName(); + + StringBuilder sb = new StringBuilder(); + if (firstName.getLength() > 0) { - name.setFirstname(firstName.item(0).getTextContent()); + sb.append(firstName.item(0).getTextContent()); + sb.append(" "); } if (middleName.getLength() > 0) { - name.setMiddlename(middleName.item(0).getTextContent()); + sb.append(middleName.item(0).getTextContent()); + sb.append(" "); } if (lastName.getLength() > 0) { - name.setSurname(lastName.item(0).getTextContent()); + sb.append(lastName.item(0).getTextContent()); + } + + AuthorList authorList = AuthorList.parse(sb.toString()); + for (Author author : authorList.getAuthors()) { + result.add(new MsBibAuthor(author)); } - result.add(name); } return result; @@ -286,6 +297,7 @@ public Element getEntryDom(Document document) { } addField(document, rootNode, "Year", year); addField(document, rootNode, "Month", month); + addField(document, rootNode, "Day", day); addField(document, rootNode, "JournalName", journalName); addField(document, rootNode, "PatentNumber", patentNumber); @@ -316,21 +328,37 @@ private void addField(Document document, Element parent, String name, String val parent.appendChild(elem); } - private void addAuthor(Document document, Element allAuthors, String entryName, List authorsLst) { + //Add authors for export + private void addAuthor(Document document, Element allAuthors, String entryName, List authorsLst) { if (authorsLst == null) { return; } Element authorTop = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + entryName); - Element nameList = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "NameList"); - for (PersonName name : authorsLst) { - Element person = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "Person"); - addField(document, person, "Last", name.getSurname()); - addField(document, person, "Middle", name.getMiddlename()); - addField(document, person, "First", name.getFirstname()); - nameList.appendChild(person); + + Optional personName = authorsLst.stream().filter(MsBibAuthor::isCorporate) + .findFirst(); + if (personName.isPresent()) { + MsBibAuthor person = personName.get(); + + Element corporate = document.createElementNS(MSBibDatabase.NAMESPACE, + MSBibDatabase.PREFIX + "Corporate"); + corporate.setTextContent(person.getFirstLast()); + authorTop.appendChild(corporate); + } else { + + Element nameList = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "NameList"); + for (MsBibAuthor name : authorsLst) { + Element person = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "Person"); + addField(document, person, "Last", name.getLastName()); + addField(document, person, "Middle", name.getMiddleName()); + addField(document, person, "First", name.getFirstName()); + nameList.appendChild(person); + + } + authorTop.appendChild(nameList); } - authorTop.appendChild(nameList); allAuthors.appendChild(authorTop); + } private void addAddress(Document document, Element parent, String addressToSplit) { diff --git a/src/main/java/org/jabref/logic/msbib/MsBibAuthor.java b/src/main/java/org/jabref/logic/msbib/MsBibAuthor.java new file mode 100644 index 00000000000..caad384ec22 --- /dev/null +++ b/src/main/java/org/jabref/logic/msbib/MsBibAuthor.java @@ -0,0 +1,66 @@ +package org.jabref.logic.msbib; + +import org.jabref.model.entry.Author; + +public class MsBibAuthor { + + private String firstName; + private String middleName; + private final Author author; + private boolean isCorporate; + + public MsBibAuthor(Author author) { + this.author = author; + + StringBuilder sb = new StringBuilder(); + author.getFirst().ifPresent(firstNames -> { + + String[] names = firstNames.split(" "); + for (int i = 1; i < names.length; i++) { + sb.append(names[i]); + sb.append(" "); + } + this.middleName = sb.toString().trim(); + this.firstName = names[0]; + }); + + } + + public MsBibAuthor(Author author, boolean isCorporate) { + this(author); + this.isCorporate = isCorporate; + + } + + public String getFirstName() { + + if (!"".equals(firstName)) { + return firstName; + } + return author.getFirst().orElse(null); + } + + public String getMiddleName() { + if ("".equals(middleName)) { + return null; + } + return middleName; + } + + public String getLastName() { + return author.getLast().orElse(null); + } + + public String getFirstLast() { + return author.getFirstLast(false); + } + + public String getLastFirst() { + return author.getLastFirst(false); + } + + public boolean isCorporate() { + return isCorporate; + } + +} diff --git a/src/main/java/org/jabref/logic/msbib/PersonName.java b/src/main/java/org/jabref/logic/msbib/PersonName.java deleted file mode 100644 index 08f28149cc4..00000000000 --- a/src/main/java/org/jabref/logic/msbib/PersonName.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.jabref.logic.msbib; - -import java.util.List; - -import org.jabref.model.entry.AuthorList; -import org.jabref.model.strings.StringUtil; - -/** - * @author Michael Wrighton, S M Mahbub Murshed - * - * S M Mahbub Murshed : added few functions for convenience. May 15, 2007 - * - * History - * Dec 16, 2011 - Changed parseName(String) to export authorname with - * more than 3 names correctly - * - */ -public class PersonName { - - private String givenName; - private String surname; - private String middleName; - - - public PersonName() { - // Empty constructor - } - - public PersonName(String name) { - parseName(name); - } - - public PersonName(String firstName, String middleName, String lastName) { - givenName = firstName; - this.middleName = middleName; - surname = lastName; - } - - private void parseName(String author) { - String authorMod = AuthorList.fixAuthorLastNameFirst(author, false); - - //Formating names and replacing escape Char for ',' back to a comma - // XMLChars xmlChars = new XMLChars(); - // authorMod = xmlChars.format(authorMod).replace(",", ","); - - int endOfLastName = authorMod.indexOf(','); - - // Tokenize just the firstName and middleNames as we have the surname - // before the comma. - List names = StringUtil.tokenizeToList(authorMod.substring(endOfLastName + 1).trim(), " \n\r"); - if (endOfLastName >= 0) { - names.add(authorMod.substring(0, endOfLastName)); - } - - int amountOfNames = names.size(); - - if (amountOfNames == 1) { - surname = names.get(0); - } else if (amountOfNames == 2) { - givenName = names.get(0); - surname = names.get(1); - } - else { - givenName = names.get(0); - middleName = ""; - for (int i = 1; i < (amountOfNames - 1); i++) { - middleName += ' ' + names.get(i); - } - middleName = middleName.trim(); - surname = names.get(amountOfNames - 1); - } - } - - public String getGivenNames() { - StringBuilder result = new StringBuilder(); - if (givenName != null) { - result.append(givenName); - } - if (middleName != null) { - result.append(' ').append(middleName); - } - return result.toString(); - } - - public String getSurname() { - return surname; - } - - public void setSurname(String lastName) { - surname = lastName; - } - - public String getFirstname() { - return givenName; - } - - public void setFirstname(String firstName) { - givenName = firstName; - } - - public String getMiddlename() { - return middleName; - } - - public void setMiddlename(String middleName) { - this.middleName = middleName; - } - - public String getFullname() { - StringBuilder fullName = new StringBuilder(); - if ((givenName != null) && !givenName.isEmpty()) { - fullName.append(givenName).append(' '); - } - if ((middleName != null) && !middleName.isEmpty()) { - fullName.append(middleName).append(' '); - } - if ((surname != null) && !surname.isEmpty()) { - fullName.append(surname); - } - - return fullName.toString().trim(); - } - - @Override - public String toString() { - return surname; - } -} diff --git a/src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java b/src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java index 981b943e0bd..37aff755086 100644 --- a/src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java +++ b/src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java @@ -57,7 +57,7 @@ public Map> importAnnotationsFromFiles(BibDatabaseC for (ParsedFileField parsedFileField : this.getFilteredFileList()) { Optional expandedFileName = FileUtil.expandFilename(databaseContext, parsedFileField.getLink(), JabRefPreferences.getInstance().getFileDirectoryPreferences()); - expandedFileName.ifPresent(file -> annotations.put(file.toString(), importer.importAnnotations(file.toPath()))); + expandedFileName.ifPresent(file -> annotations.put(file.getName(), importer.importAnnotations(file.toPath()))); } return annotations; } diff --git a/src/main/java/org/jabref/logic/util/io/RegExpFileSearch.java b/src/main/java/org/jabref/logic/util/io/RegExpFileSearch.java index 0b43ee0b2cd..ec6a5e72efc 100644 --- a/src/main/java/org/jabref/logic/util/io/RegExpFileSearch.java +++ b/src/main/java/org/jabref/logic/util/io/RegExpFileSearch.java @@ -21,7 +21,6 @@ import org.apache.commons.logging.LogFactory; public class RegExpFileSearch { - private static final Log LOGGER = LogFactory.getLog(RegExpFileSearch.class); private static final String EXT_MARKER = "__EXTENSION__"; @@ -120,7 +119,6 @@ private static List findFile(BibEntry entry, List dirs, String file, /** * Internal Version of findFile, which also accepts a current directory to * base the search on. - * */ private static List findFile(BibEntry entry, String directory, String file, String extensionRegExp, Character keywordDelimiter) { diff --git a/src/main/java/org/jabref/logic/util/strings/StringSimilarity.java b/src/main/java/org/jabref/logic/util/strings/StringSimilarity.java index c17443f07fb..2b83e2b9a8d 100644 --- a/src/main/java/org/jabref/logic/util/strings/StringSimilarity.java +++ b/src/main/java/org/jabref/logic/util/strings/StringSimilarity.java @@ -6,7 +6,7 @@ public class StringSimilarity { private final Levenshtein METRIC_DISTANCE = new Levenshtein(); - // edit distance threshold for entry title comnparison + // edit distance threshold for entry title comparison private final int METRIC_THRESHOLD = 4; /** @@ -20,8 +20,8 @@ public boolean isSimilar(String a, String b) { return editDistanceIgnoreCase(a, b) <= METRIC_THRESHOLD; } - private double editDistanceIgnoreCase(String a, String b) { - // TODO: locale is dependent on the language of the strings?! + public double editDistanceIgnoreCase(String a, String b) { + // TODO: Locale is dependent on the language of the strings. English is a good denominator. return METRIC_DISTANCE.distance(a.toLowerCase(Locale.ENGLISH), b.toLowerCase(Locale.ENGLISH)); } } diff --git a/src/main/java/org/jabref/model/database/BibDatabase.java b/src/main/java/org/jabref/model/database/BibDatabase.java index ff9a1593141..5ce9bbb7b52 100644 --- a/src/main/java/org/jabref/model/database/BibDatabase.java +++ b/src/main/java/org/jabref/model/database/BibDatabase.java @@ -4,6 +4,7 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; @@ -193,21 +194,32 @@ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionExcep * @return false if the insert was done without a duplicate warning */ public synchronized boolean insertEntry(BibEntry entry, EntryEventSource eventSource) throws KeyCollisionException { - Objects.requireNonNull(entry); + insertEntries(Collections.singletonList(entry), eventSource); + return duplicationChecker.isDuplicateCiteKeyExisting(entry); + } - String id = entry.getId(); - if (containsEntryWithId(id)) { - throw new KeyCollisionException("ID is already in use, please choose another"); - } + public synchronized void insertEntries(List entries) throws KeyCollisionException { + insertEntries(entries, EntryEventSource.LOCAL); + } - internalIDs.add(id); - entries.add(entry); - entry.registerListener(this); + private synchronized void insertEntries(List newEntries, EntryEventSource eventSource) throws KeyCollisionException { + Objects.requireNonNull(newEntries); - eventBus.post(new EntryAddedEvent(entry, eventSource)); - return duplicationChecker.isDuplicateCiteKeyExisting(entry); + for (BibEntry entry : newEntries) { + String id = entry.getId(); + if (containsEntryWithId(id)) { + throw new KeyCollisionException("ID is already in use, please choose another"); + } + + internalIDs.add(id); + entry.registerListener(this); + + eventBus.post(new EntryAddedEvent(entry, eventSource)); + } + entries.addAll(newEntries); } + /** * Removes the given entry. * The Entry is removed based on the id {@link BibEntry#id} diff --git a/src/main/java/org/jabref/model/database/BibDatabaseContext.java b/src/main/java/org/jabref/model/database/BibDatabaseContext.java index 392584039a2..0bb5e863e40 100644 --- a/src/main/java/org/jabref/model/database/BibDatabaseContext.java +++ b/src/main/java/org/jabref/model/database/BibDatabaseContext.java @@ -11,6 +11,7 @@ import org.jabref.model.Defaults; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; +import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; import org.jabref.model.metadata.FileDirectoryPreferences; import org.jabref.model.metadata.MetaData; @@ -267,4 +268,8 @@ public void convertToLocalDatabase() { this.location = DatabaseLocation.LOCAL; } + + public List getEntries() { + return database.getEntries(); + } } diff --git a/src/main/java/org/jabref/model/entry/Author.java b/src/main/java/org/jabref/model/entry/Author.java index b6c08235c2d..bbf6c8b5a05 100644 --- a/src/main/java/org/jabref/model/entry/Author.java +++ b/src/main/java/org/jabref/model/entry/Author.java @@ -69,32 +69,32 @@ public static String addDotIfAbbreviation(String name) { StringBuilder sb = new StringBuilder(); char lastChar = name.charAt(0); for (int i = 0; i < name.length(); i++) { - if(i > 0) { + if (i > 0) { lastChar = name.charAt(i - 1); } char currentChar = name.charAt(i); sb.append(currentChar); - if(currentChar == '.') { + if (currentChar == '.') { // A.A. -> A. A. - if(((i + 1) < name.length()) && Character.isUpperCase(name.charAt(i + 1))) { + if (((i + 1) < name.length()) && Character.isUpperCase(name.charAt(i + 1))) { sb.append(' '); } } boolean currentIsUppercaseLetter = Character.isLetter(currentChar) && Character.isUpperCase(currentChar); - if(!currentIsUppercaseLetter) { + if (!currentIsUppercaseLetter) { // No uppercase letter, hence nothing to do continue; } boolean lastIsLowercaseLetter = Character.isLetter(lastChar) && Character.isLowerCase(lastChar); - if(lastIsLowercaseLetter) { + if (lastIsLowercaseLetter) { // previous character was lowercase (probably an acronym like JabRef) -> don't change anything continue; } - if((i + 1) >= name.length()) { + if ((i + 1) >= name.length()) { // Current character is last character in input, so append dot sb.append('.'); continue; @@ -106,7 +106,7 @@ public static String addDotIfAbbreviation(String name) { sb.append("."); continue; } - if('.' == nextChar) { + if ('.' == nextChar) { // Dot already there, so nothing to do continue; } @@ -116,18 +116,20 @@ public static String addDotIfAbbreviation(String name) { boolean nextWordIsUppercase = true; for (int j = i + 1; j < name.length(); j++) { char furtherChar = name.charAt(j); - if(Character.isWhitespace(furtherChar) || (furtherChar == '-') || (furtherChar == '~') || (furtherChar == '.')) { + if (Character.isWhitespace(furtherChar) || (furtherChar == '-') || (furtherChar == '~') + || (furtherChar == '.')) { // end of word break; } - boolean furtherIsUppercaseLetter = Character.isLetter(furtherChar) && Character.isUpperCase(furtherChar); - if(!furtherIsUppercaseLetter) { + boolean furtherIsUppercaseLetter = Character.isLetter(furtherChar) + && Character.isUpperCase(furtherChar); + if (!furtherIsUppercaseLetter) { nextWordIsUppercase = false; break; } } - if(nextWordIsUppercase) { + if (nextWordIsUppercase) { sb.append(". "); } } @@ -146,15 +148,17 @@ public int hashCode() { * Will return true iff the other object is an Author and all fields are identical on a string comparison. */ @Override - public boolean equals(Object o) { - if (this == o) { + public boolean equals(Object other) { + if (this == other) { return true; } - if (o instanceof org.jabref.model.entry.Author) { - org.jabref.model.entry.Author a = (org.jabref.model.entry.Author) o; - return Objects.equals(firstPart, a.firstPart) && Objects.equals(firstAbbr, a.firstAbbr) && Objects.equals( - vonPart, a.vonPart) && Objects.equals(lastPart, a.lastPart) && Objects.equals(jrPart, a.jrPart); + if (other instanceof Author) { + Author that = (Author) other; + return Objects.equals(firstPart, that.firstPart) && Objects.equals(firstAbbr, that.firstAbbr) + && Objects.equals( + vonPart, that.vonPart) + && Objects.equals(lastPart, that.lastPart) && Objects.equals(jrPart, that.jrPart); } return false; } diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index f3825205b5f..47e9d91eadb 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -37,6 +37,7 @@ import org.apache.commons.logging.LogFactory; public class BibEntry implements Cloneable { + public static final String TYPE_HEADER = "entrytype"; public static final String OBSOLETE_TYPE_HEADER = "bibtextype"; public static final String KEY_FIELD = "bibtexkey"; @@ -101,7 +102,7 @@ private BibEntry(String id, String type) { } public Optional replaceKeywords(KeywordList keywordsToReplace, Optional newValue, - Character keywordDelimiter) { + Character keywordDelimiter) { KeywordList keywordList = getKeywords(keywordDelimiter); if (newValue.isPresent()) { keywordList.replaceAll(keywordsToReplace, newValue.get()); @@ -300,7 +301,8 @@ private Optional genericGetFieldOrAlias(String name, GetFieldInterface g if (FieldName.DATE.equals(name)) { Optional year = getFieldInterface.getValueForField(FieldName.YEAR); if (year.isPresent()) { - MonthUtil.Month month = MonthUtil.getMonth(getFieldInterface.getValueForField(FieldName.MONTH).orElse("")); + MonthUtil.Month month = MonthUtil + .getMonth(getFieldInterface.getValueForField(FieldName.MONTH).orElse("")); if (month.isValid()) { return Optional.of(year.get() + '-' + month.twoDigitNumber); } else { @@ -308,7 +310,7 @@ private Optional genericGetFieldOrAlias(String name, GetFieldInterface g } } } - if (FieldName.YEAR.equals(name) || FieldName.MONTH.equals(name)) { + if (FieldName.YEAR.equals(name) || FieldName.MONTH.equals(name) || FieldName.DAY.equals(name)) { Optional date = getFieldInterface.getValueForField(FieldName.DATE); if (!date.isPresent()) { return Optional.empty(); @@ -322,7 +324,6 @@ private Optional genericGetFieldOrAlias(String name, GetFieldInterface g final SimpleDateFormat sdf1 = new SimpleDateFormat(FORMAT1); final SimpleDateFormat sdf2 = new SimpleDateFormat(FORMAT2); - @Override public StringBuffer format(Date dDate, StringBuffer toAppendTo, FieldPosition fieldPosition) { throw new UnsupportedOperationException(); @@ -347,6 +348,9 @@ public Date parse(String source, ParsePosition pos) { if (FieldName.MONTH.equals(name)) { return Optional.of(Integer.toString(calendar.get(Calendar.MONTH) + 1)); // Shift by 1 since in this calendar Jan = 0 } + if (FieldName.DAY.equals(name)) { + return Optional.of(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH))); + } } catch (ParseException e) { // So not a date with year and month, try just to parse years df = new SimpleDateFormat("yyyy"); @@ -600,7 +604,7 @@ public void setGroupHit(boolean groupHit) { * Author1, Author2: Title (Year) */ public String getAuthorTitleYear(int maxCharacters) { - String[] s = new String[]{getField(FieldName.AUTHOR).orElse("N/A"), getField(FieldName.TITLE).orElse("N/A"), + String[] s = new String[] {getField(FieldName.AUTHOR).orElse("N/A"), getField(FieldName.TITLE).orElse("N/A"), getField(FieldName.YEAR).orElse("N/A")}; String text = s[0] + ": \"" + s[1] + "\" (" + s[2] + ')'; @@ -839,6 +843,7 @@ public Optional setFiles(List files) { } private interface GetFieldInterface { + Optional getValueForField(String fieldName); } diff --git a/src/main/java/org/jabref/model/entry/FieldName.java b/src/main/java/org/jabref/model/entry/FieldName.java index b15b8b5f513..78348cafcf5 100644 --- a/src/main/java/org/jabref/model/entry/FieldName.java +++ b/src/main/java/org/jabref/model/entry/FieldName.java @@ -1,6 +1,5 @@ package org.jabref.model.entry; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -191,10 +190,12 @@ public static String getDisplayName(String field) { return StringUtil.capitalizeFirst(field); } - public static ArrayList getNotTextFieldNames() { - ArrayList notTextFieldNames = new ArrayList<>(); - notTextFieldNames.addAll(Arrays.asList(FieldName.DOI, FieldName.FILE, FieldName.URL, FieldName.URI, FieldName.ISBN, FieldName.ISSN, FieldName.MONTH, FieldName.DATE, FieldName.YEAR)); - return notTextFieldNames; + public static List getNotTextFieldNames() { + return Arrays.asList(FieldName.DOI, FieldName.FILE, FieldName.URL, FieldName.URI, FieldName.ISBN, FieldName.ISSN, FieldName.MONTH, FieldName.DATE, FieldName.YEAR); + } + + public static List getIdentifierFieldNames() { + return Arrays.asList(FieldName.DOI, FieldName.EPRINT, FieldName.PMID); } } diff --git a/src/main/java/org/jabref/model/entry/identifier/ArXivIdentifier.java b/src/main/java/org/jabref/model/entry/identifier/ArXivIdentifier.java index 19c49bfb979..3c73f7064e5 100644 --- a/src/main/java/org/jabref/model/entry/identifier/ArXivIdentifier.java +++ b/src/main/java/org/jabref/model/entry/identifier/ArXivIdentifier.java @@ -3,7 +3,9 @@ import java.util.Objects; import java.util.Optional; -public class ArXivIdentifier { +import org.jabref.model.entry.FieldName; + +public class ArXivIdentifier implements Identifier { private final String identifier; @@ -31,6 +33,12 @@ public int hashCode() { return identifier.hashCode(); } + @Override + public String getDefaultField() { + return FieldName.EPRINT; + } + + @Override public String getNormalized() { return identifier; } diff --git a/src/main/java/org/jabref/model/groups/GroupTreeNode.java b/src/main/java/org/jabref/model/groups/GroupTreeNode.java index fe176e4ae78..d75bcede4a6 100644 --- a/src/main/java/org/jabref/model/groups/GroupTreeNode.java +++ b/src/main/java/org/jabref/model/groups/GroupTreeNode.java @@ -282,4 +282,16 @@ public List addEntriesToGroup(List entries) { return Collections.emptyList(); } } + + /** + * Removes the given entries from this group. If the group does not support the explicit removal of entries (i.e., + * does not implement {@link GroupEntryChanger}), then no action is performed. + */ + public List removeEntriesFromGroup(List entries) { + if (getGroup() instanceof GroupEntryChanger) { + return ((GroupEntryChanger) getGroup()).remove(entries); + } else { + return Collections.emptyList(); + } + } } diff --git a/src/main/java/org/jabref/model/strings/StringUtil.java b/src/main/java/org/jabref/model/strings/StringUtil.java index c6875b2e88a..29ffbf4dd2f 100644 --- a/src/main/java/org/jabref/model/strings/StringUtil.java +++ b/src/main/java/org/jabref/model/strings/StringUtil.java @@ -706,4 +706,8 @@ public static String capitalizeFirst(String toCapitalize) { public static List getStringAsWords(String text) { return Arrays.asList(text.split("[\\s,;]+")); } + + public static boolean containsIgnoreCase(String text, String searchString) { + return StringUtils.containsIgnoreCase(text, searchString); + } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index fa36f129669..cda4f46e9de 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -181,11 +181,7 @@ public class JabRefPreferences { public static final String EDITOR_EMACS_KEYBINDINGS = "editorEMACSkeyBindings"; public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CA = "editorEMACSkeyBindingsRebindCA"; public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CF = "editorEMACSkeyBindingsRebindCF"; - public static final String GROUP_EXPAND_TREE = "groupExpandTree"; - public static final String GROUP_SHOW_DYNAMIC = "groupShowDynamic"; - public static final String GROUP_SHOW_ICONS = "groupShowIcons"; public static final String GROUPS_DEFAULT_FIELD = "groupsDefaultField"; - public static final String GROUP_SHOW_OVERLAPPING = "groupShowOverlapping"; public static final String GROUP_INVERT_SELECTIONS = "groupInvertSelections"; public static final String GROUP_INTERSECT_SELECTIONS = "groupIntersectSelections"; public static final String GROUP_FLOAT_SELECTIONS = "groupFloatSelections"; @@ -566,11 +562,7 @@ private JabRefPreferences() { defaults.put(GROUP_FLOAT_SELECTIONS, Boolean.TRUE); defaults.put(GROUP_INTERSECT_SELECTIONS, Boolean.TRUE); defaults.put(GROUP_INVERT_SELECTIONS, Boolean.FALSE); - defaults.put(GROUP_SHOW_OVERLAPPING, Boolean.FALSE); defaults.put(GROUPS_DEFAULT_FIELD, FieldName.KEYWORDS); - defaults.put(GROUP_SHOW_ICONS, Boolean.TRUE); - defaults.put(GROUP_SHOW_DYNAMIC, Boolean.TRUE); - defaults.put(GROUP_EXPAND_TREE, Boolean.TRUE); defaults.put(AUTO_ASSIGN_GROUP, Boolean.TRUE); defaults.put(KEYWORD_SEPARATOR, ", "); defaults.put(TOOLBAR_VISIBLE, Boolean.TRUE); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 67b03bd6939..7b70baf3b75 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Stien_behøver_ikke_at_være_p Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Tilføj_en_kompileret_Importer-klasse_fra_en_ZIP-fil. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=ZIP-filen_behøver_ikke_at_være_i_din_classpath. -Add_entry_selection_to_this_group=Føj_valgte_poster_til_denne_gruppe +Add_selected_entries_to_this_group= Add_from_folder=Tilføj_fra_mappe @@ -58,8 +58,6 @@ Add_from_JAR=Tilføj_fra_JAR-fil add_group=tilføj_gruppe -Add_group=Tilføj_gruppe - Add_new=Tilføj_ny Add_subgroup=Tilføj_undergruppe @@ -107,8 +105,6 @@ Apply=Udfør Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumenterne_sendt_til_allerede_aktiv_JabRef-instans._Afslutter. -Assign_entry_selection_exclusively_to_this_group=Føj_valgte_poster_eksklusivt_til_denne_gruppe - Assign_new_file=Tildel_ny_fil Assign_the_original_group's_entries_to_this_group?=Føj_den_oprindelige_gruppes_poster_til_denne_gruppe? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Kan_ikke Cannot_merge_this_change=Kan_ikke_inkorporere_denne_ændring -Cannot_move_group_"%0"_down.=Kan_ikke_flytte_gruppen_"%0"_ned. - -Cannot_move_group_"%0"_left.=Kan_ikke_flytte_gruppen_"%0"_til_venstre. - -Cannot_move_group_"%0"_right.=Kan_ikke_flytte_gruppen_"%0"_til_højre. - -Cannot_move_group_"%0"_up.=Kan_ikke_flytte_gruppen_"%0"_op. - case_insensitive=skelner_ikke_mellem_store_og_små_bogstaver case_sensitive=skelner_mellem_store_og_små_bogstaver @@ -229,8 +217,6 @@ Close_window=Luk_vindue Closed_library=Lukkede_library -Collapse_subtree=Luk_forgrening - Color_codes_for_required_and_optional_fields=Farvekoder_for_nødvendige_og_valgfrie_felter Color_for_marking_incomplete_entries=Farve_til_markering_af_ufuldstændige_poster @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Fejl_ved_skrivning_til_%0_fil(er). '%0'_exists._Overwrite_file?='%0'_eksisterer._Erstat_filen? Overwrite_file?=Erstat_filen? -Expand_subtree=Åbn_forgrening - Export=Eksporter Export_name=Navn_på_filter @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Fremhæv_overlappende_grupper - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Hint\:_For_kun_at_søge_i_specifikke_felter,_skriv_f.eks.\:

author\=smith_and_title\=electrical HTML_table=HTML-tabel @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Uafhængig_gruppe\:_Vis_kun_denne_gruppes_poster -Initially_show_groups_tree_expanded=Vis_gruppetræet_ekspanderet_som_udgangspunkt - Work_options= Insert=Tilføj @@ -782,8 +762,6 @@ Modify=Ændre modify_group=ændre_gruppe -Move=Flyt - Move_down=Flyt_ned Move_entries_in_group_selection_to_the_top=Flyt_poster_i_valgte_grupper_til_toppen @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Skriv_et_navn_for_strengen Please_select_an_importer.=Vælg_venligst_et_importfilter. -Please_select_exactly_one_group_to_move.=Vælg_præcis_én_gruppe_til_flytning. - Possible_duplicate_entries=Mulige_dubletter Possible_duplicate_of_existing_entry._Click_to_resolve.=Mulig_dublet_af_eksisterende_post._Klik_for_at_løse_problemet. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Fjern_alle_undergrupper_af_"%0"? Remove_entry_from_import=Fjern_post_fra_import -Remove_entry_selection_from_this_group=Fjern_valgte_poster_fra_denne_gruppe +Remove_selected_entries_from_this_group= Remove_entry_type=Slet_posttype Remove_file_link_(DELETE)=Slet_link_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Vis_dialog_for_at_bekræfte_sletn Show_description=Vis_beskrivelse -Show_dynamic_groups_in_italics=Vis_dynamiske_grupper_i_kursiv - Show_entries_not_in_group_selection=Vis_poster_udenfor_valgte_grupper Show_file_column=Vis_'file'-kolonne -Show_icons_for_groups=Vis_ikoner_for_grupper Show_last_names_only=Vis_kun_efternavn Show_names_unchanged=Vis_navn_uændret @@ -1513,7 +1486,6 @@ General_file_directory=Generelt_filbibliotek User-specific_file_directory=Brugerspecifikt_filbibliotek Search_failed\:_illegal_search_expression=Søgning_fejlede\:_illegalt_søgeudtryk Show_ArXiv_column=Vis_ArXiv-kolonne -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Fremhæv_grupper_der_indeholder_poster,_som_er_med_i_en_af_de_valgte_grupper You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Der_skal_indtastes_et_heltal_i_intervallet_1025-65535_i_tekstfeltet_til Automatically_open_browse_dialog_when_creating_new_file_link=Åbn_automatisk_fildialog_når_nyt_link_oprettes diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 889b28cb1ff..5feb04acdf8 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Das_Verzeichnis_muss_nicht_im_K Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Füge_eine_(kompilierte)_externe_Importer_Klasse_aus_Verzeichnis_hinzu. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Das_Verzeichnis_muss_nicht_im_Klassenpfad_von_JabRef_enthalten_sein. -Add_entry_selection_to_this_group=Ausgewählte_Einträge_zu_dieser_Gruppe_hinzufügen +Add_selected_entries_to_this_group= Add_from_folder=Aus_Klassenpfad_hinzufügen @@ -58,8 +58,6 @@ Add_from_JAR=Aus_Archiv-Datei_hinzufügen add_group=Gruppe_hinzufügen -Add_group=Gruppe_hinzufügen - Add_new=Neu Add_subgroup=Untergruppe_hinzufügen @@ -107,8 +105,6 @@ Apply=Übernehmen Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumente_wurden_der_laufenden_JabRef-Instanz_übergeben._Schließen_läuft. -Assign_entry_selection_exclusively_to_this_group=Ausgewählte_Einträge_ausschließlich_dieser_Gruppe_zuordnen - Assign_new_file=Neue_Datei_zuordnen Assign_the_original_group's_entries_to_this_group?=Einträge_der_ursprünglichen_Gruppe_zu_dieser_Gruppe_hinzufügen? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Einträg Cannot_merge_this_change=Kann_diese_Änderung_nicht_einfügen -Cannot_move_group_"%0"_down.=Gruppe_"%0"_kann_nicht_nach_unten_bewegt_werden. - -Cannot_move_group_"%0"_left.=Gruppe_"%0"_kann_nicht_nach_links_bewegt_werden. - -Cannot_move_group_"%0"_right.=Gruppe_"%0"_kann_nicht_nach_rechts_bewegt_werden. - -Cannot_move_group_"%0"_up.=Gruppe_"%0"_kann_nicht_nach_oben_bewegt_werden. - case_insensitive=Groß-/Kleinschreibung_wird_nicht_unterschieden case_sensitive=Groß-/Kleinschreibung_wird_unterschieden @@ -229,8 +217,6 @@ Close_window=Fenster_schließen Closed_library=Datenbank_geschlossen -Collapse_subtree=Unterbaum_zuklappen - Color_codes_for_required_and_optional_fields=Farbanzeige_für_benötigte_und_optionale_Felder Color_for_marking_incomplete_entries=Farbe_zum_Markieren_unvollständiger_Einträge @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Fehler_beim_Schreiben_in_%0_Datei(en). '%0'_exists._Overwrite_file?='%0'_existiert_bereits._Überschreiben? Overwrite_file?=_Überschreiben? -Expand_subtree=Unterbaum_aufklappen - Export=Exportieren Export_name=Filtername @@ -622,8 +606,6 @@ Empty_Marking=Leere_Markierung Empty_Underline=Leere_Unterstreichung The_marked_area_does_not_contain_any_legible_text!=Der_markierte_Bereich_enthält_keinen_lesbaren_Text! -Highlight_overlapping_groups=Sich_überschneidende_Gruppen_markieren - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Hinweis\:_Um_ausschließlich_bestimmte_Felder_zu_durchsuchen,_geben_Sie_z.B._ein\:

author\=smith_and_title\=electrical HTML_table=HTML-Tabelle @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Unabhängige_Gruppen\:_Nur_die_Einträge_dieser_Gruppe_anzeigen -Initially_show_groups_tree_expanded=Baumansicht_der_Gruppen_standardmäßig_aufklappen - Work_options=Bearbeitungsoptionen Insert=einfügen @@ -782,8 +762,6 @@ Modify=Bearbeiten modify_group=Gruppe_bearbeiten -Move=Verschieben - Move_down=Nach_unten Move_entries_in_group_selection_to_the_top=Sortiere_Einträge_der_Gruppenauswahl_nach_oben @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Geben_Sie_bitte_den_Namen_des_Strings_ein. Please_select_an_importer.=Bitte_Importer_auswählen. -Please_select_exactly_one_group_to_move.=Bitte_genau_eine_zu_bewegende_Gruppe_auswählen. - Possible_duplicate_entries=Mögliche_doppelte_Einträge Possible_duplicate_of_existing_entry._Click_to_resolve.=Möglicherweise_doppelter_Eintrag._Klicken_um_Konflikt_zu_lösen. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Alle_Untergruppen_von_"%0"_entfernen? Remove_entry_from_import=Eintrag_von_Importierung_entfernen -Remove_entry_selection_from_this_group=Ausgewählte_Einträge_aus_dieser_Gruppe_entfernen +Remove_selected_entries_from_this_group= Remove_entry_type=Eintragstyp_löschen Remove_file_link_(DELETE)=Dateilink_entfernen_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Dialog_zum_Löschen_von_Einträge Show_description=Beschreibung_anzeigen -Show_dynamic_groups_in_italics=Dynamische_Gruppen_kursiv_anzeigen - Show_entries_not_in_group_selection=Zeige_Einträge,_die_nicht_in_der_Gruppenauswahl_sind Show_file_column=Datei-Spalte_anzeigen -Show_icons_for_groups=Gruppen-Icon_anzeigen Show_last_names_only=Zeige_nur_Nachnamen Show_names_unchanged=Namen_unverändert_anzeigen @@ -1513,7 +1486,6 @@ General_file_directory=Standard-Dateiverzeichnis User-specific_file_directory=Benutzerdefiniertes_Dateiverzeichnis Search_failed\:_illegal_search_expression=Suche_fehlgeschlagen\:_Ungültiger_Suchausdruck Show_ArXiv_column=ArXiv-Spalte_anzeigen -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Gruppen_hervorheben,_die_Einträge_in_einer_der_ausgewählten_Gruppen_enthalten You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Sie_müssen_einen_Zahlwert_zwischen_1025_und_65535_eintragen_in_das_Textfeld_für Automatically_open_browse_dialog_when_creating_new_file_link=Beim_Erstellen_eines_neuen_Datei-Links_den_Durchsuchen-Dialog_automatisch_öffnen diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 035e5426cbe..e3b80248b44 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=The_path_need_not_be_on_the_cla Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef. -Add_entry_selection_to_this_group=Add_entry_selection_to_this_group +Add_selected_entries_to_this_group=Add_selected_entries_to_this_group Add_from_folder=Add_from_folder @@ -58,8 +58,6 @@ Add_from_JAR=Add_from_JAR add_group=add_group -Add_group=Add_group - Add_new=Add_new Add_subgroup=Add_subgroup @@ -107,8 +105,6 @@ Apply=Apply Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Arguments_passed_on_to_running_JabRef_instance._Shutting_down. -Assign_entry_selection_exclusively_to_this_group=Assign_entry_selection_exclusively_to_this_group - Assign_new_file=Assign_new_file Assign_the_original_group's_entries_to_this_group?=Assign_the_original_group's_entries_to_this_group? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Cannot_a Cannot_merge_this_change=Cannot_merge_this_change -Cannot_move_group_"%0"_down.=Cannot_move_group_"%0"_down. - -Cannot_move_group_"%0"_left.=Cannot_move_group_"%0"_left. - -Cannot_move_group_"%0"_right.=Cannot_move_group_"%0"_right. - -Cannot_move_group_"%0"_up.=Cannot_move_group_"%0"_up. - case_insensitive=case_insensitive case_sensitive=case_sensitive @@ -229,8 +217,6 @@ Close_window=Close_window Closed_library=Closed_library -Collapse_subtree=Collapse_subtree - Color_codes_for_required_and_optional_fields=Color_codes_for_required_and_optional_fields Color_for_marking_incomplete_entries=Color_for_marking_incomplete_entries @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Error_writing_to_%0_file(s). '%0'_exists._Overwrite_file?='%0'_exists._Overwrite_file? Overwrite_file?=Overwrite_file? -Expand_subtree=Expand_subtree - Export=Export Export_name=Export_name @@ -622,8 +606,6 @@ Empty_Marking=Empty_Marking Empty_Underline=Empty_Underline The_marked_area_does_not_contain_any_legible_text!=The_marked_area_does_not_contain_any_legible_text! -Highlight_overlapping_groups=Highlight_overlapping_groups - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical HTML_table=HTML_table @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Independent_group\:_When_selected,_view_only_this_group's_entries -Initially_show_groups_tree_expanded=Initially_show_groups_tree_expanded - Work_options=Work_options Insert=Insert @@ -782,8 +762,6 @@ Modify=Modify modify_group=modify_group -Move=Move - Move_down=Move_down Move_entries_in_group_selection_to_the_top=Move_entries_in_group_selection_to_the_top @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Please_enter_the_string's_label Please_select_an_importer.=Please_select_an_importer. -Please_select_exactly_one_group_to_move.=Please_select_exactly_one_group_to_move. - Possible_duplicate_entries=Possible_duplicate_entries Possible_duplicate_of_existing_entry._Click_to_resolve.=Possible_duplicate_of_existing_entry._Click_to_resolve. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Remove_all_subgroups_of_"%0"? Remove_entry_from_import=Remove_entry_from_import -Remove_entry_selection_from_this_group=Remove_entry_selection_from_this_group +Remove_selected_entries_from_this_group=Remove_selected_entries_from_this_group Remove_entry_type=Remove_entry_type Remove_file_link_(DELETE)=Remove_file_link_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Show_confirmation_dialog_when_del Show_description=Show_description -Show_dynamic_groups_in_italics=Show_dynamic_groups_in_italics - Show_entries_not_in_group_selection=Show_entries_not_in_group_selection Show_file_column=Show_file_column -Show_icons_for_groups=Show_icons_for_groups Show_last_names_only=Show_last_names_only Show_names_unchanged=Show_names_unchanged @@ -1513,7 +1486,6 @@ General_file_directory=General_file_directory User-specific_file_directory=User-specific_file_directory Search_failed\:_illegal_search_expression=Search_failed\:_illegal_search_expression Show_ArXiv_column=Show_ArXiv_column -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for Automatically_open_browse_dialog_when_creating_new_file_link=Automatically_open_browse_dialog_when_creating_new_file_link diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 8f426682d7f..7400a04a140 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=La_ruta_no_debe_estar_en_la_cla Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Añadir_una_clase_personalizada_(compilada)_Importer_desde_un_archivo_ZIP. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=El_archivo_ZIP_no_tiene_por_qué_estar_en_la_classpath_de_JabRef. -Add_entry_selection_to_this_group=Añadir_selección_de_entrada_al_grupo +Add_selected_entries_to_this_group= Add_from_folder=Añadir_desde_carpeta @@ -58,8 +58,6 @@ Add_from_JAR=Añadir_desde_JAR add_group=añadir_grupo -Add_group=Añadir_grupo - Add_new=Añadir_nuevo Add_subgroup=Añadir_subgrupo @@ -107,8 +105,6 @@ Apply=Aplicar Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumentos_pasados_a_una_instancia_JabRef_en_ejecución._Cerrando_el_programa. -Assign_entry_selection_exclusively_to_this_group=Asignar_la_seleccion_de_entradas_exclusivamente_a_este_grupo - Assign_new_file=Asignar_nuevo_archivo Assign_the_original_group's_entries_to_this_group?=¿Asignar_las_entradas_del_grupo_original_a_este_grupo? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=No_se_pu Cannot_merge_this_change=No_se_puede_incorporar_este_cambio -Cannot_move_group_"%0"_down.=No_se_puede_mover_el_grupo_"%0"_hacia_abajo. - -Cannot_move_group_"%0"_left.=No_se_puede_mover_el_grupo_"%0"_hacia_la_izquierda - -Cannot_move_group_"%0"_right.=No_se_puede_mover_el_grupo_"%0"_hacia_la_derecha. - -Cannot_move_group_"%0"_up.=No_se_puede_mover_el_grupo_"%0"_hacia_arriba. - case_insensitive=insensible_al_uso_de_mayúsculas/minúsculas case_sensitive=sensible_al_uso_de_mayúsculas/minúsculas @@ -229,8 +217,6 @@ Close_window=Cerrar_ventana Closed_library=Base_de_datos_cerrada -Collapse_subtree=Colapsar_subárbol - Color_codes_for_required_and_optional_fields=Códigos_de_color_para_campos_requeridos_y_opcionales Color_for_marking_incomplete_entries=Color_para_marcar_entradas_incompletas @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Error_escribiendo_%0_archivo(s). '%0'_exists._Overwrite_file?='%0'_existe._¿Sobreescribir? Overwrite_file?=¿Sobreescribir? -Expand_subtree=Expandir_subárbol - Export=Exportar Export_name=Exportar_nombre @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Resaltar_grupos_solapados - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Pista_\:_Para_buscar_sólo_campos_específicos,_introduzca,_por_ejemplo,_\:_

author\=smith_and_title\=electrical HTML_table=Tabla_HTML @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Grupo_independiente\:_ver_sólo_las_entradas_de_este_grupo_cuando_esté_seleccionado. -Initially_show_groups_tree_expanded=Mostrar_inicialmente_árbol_de_grupos_extendido - Work_options=Opciones_de_trabajo Insert=Insertar @@ -782,8 +762,6 @@ Modify=Modificar modify_group=Modificar_grupo -Move=Mover - Move_down=Mover_hacia_abajo Move_entries_in_group_selection_to_the_top=Mover_entradas_en_el_grupo_seleccionado_al_inicio @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Introduzca_la_etiqueta_de_la_cadena Please_select_an_importer.=Seleccionar_un_importador. -Please_select_exactly_one_group_to_move.=Seleccione_exactamente_un_grupo_para_mover. - Possible_duplicate_entries=Posibles_entradas_duplicadas Possible_duplicate_of_existing_entry._Click_to_resolve.=Posible_duplicado_de_entrada_existente._Clique_para_resolver. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=¿Eliminar_todos_los_subrgrupos_de_"%0"? Remove_entry_from_import=Eliminar_entrada_importada -Remove_entry_selection_from_this_group=Eliminar_selección_de_entradas_de_este_grupo +Remove_selected_entries_from_this_group= Remove_entry_type=Eliminar_tipo_de_entrada Remove_file_link_(DELETE)=Eliminar_enlace_a_archivo_(BORRAR) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Mostra_diálogo_de_confirmación_ Show_description=Mostrar_descripción -Show_dynamic_groups_in_italics=Mostrar_grupos_dinámicos_en_cursiva - Show_entries_not_in_group_selection=Mostrar_entradas_que_NO_estén_en_la_selección_de_grupo Show_file_column=Mostrar_columna_de_archivo -Show_icons_for_groups=Mostrar_iconos_para_grupos Show_last_names_only=Mostrar_sólo_apellidos Show_names_unchanged=Mostrar_nombres_sin_cambios @@ -1513,7 +1486,6 @@ General_file_directory=Carpeta_general_de_archivos. User-specific_file_directory=Carpeta_de_archivos_de_usuario Search_failed\:_illegal_search_expression=La_búsqueda_ha_fallado._Expresión_de_búsqueda_ilegal Show_ArXiv_column=Mostrar_columna_ArXiv -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Resaltar_grupos_con_entradas_contenidas_en_cualquier_grupo_seleccionado_actualmente. You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Es_preciso_introducir_un_valor_entero_comprendido_entre_1025_y_65535_en_el_campo_de_texto_para Automatically_open_browse_dialog_when_creating_new_file_link=Abrir_automáticamente_el_diálogo_de_exploración_al_crear_nuevo_enlace_a_archivo diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index fc7fd1c225f..6b09a0dd8df 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.= Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.= The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.= -Add_entry_selection_to_this_group= +Add_selected_entries_to_this_group= Add_from_folder= @@ -58,8 +58,6 @@ Add_from_JAR= add_group= -Add_group= - Add_new= Add_subgroup= @@ -107,8 +105,6 @@ Apply= Arguments_passed_on_to_running_JabRef_instance._Shutting_down.= -Assign_entry_selection_exclusively_to_this_group= - Assign_new_file= Assign_the_original_group's_entries_to_this_group?= @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?= Cannot_merge_this_change= -Cannot_move_group_"%0"_down.= - -Cannot_move_group_"%0"_left.= - -Cannot_move_group_"%0"_right.= - -Cannot_move_group_"%0"_up.= - case_insensitive= case_sensitive= @@ -229,8 +217,6 @@ Close_window= Closed_library= -Collapse_subtree= - Color_codes_for_required_and_optional_fields= Color_for_marking_incomplete_entries= @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).= '%0'_exists._Overwrite_file?= Overwrite_file?= -Expand_subtree= - Export= Export_name= @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups= - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical= HTML_table= @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries= -Initially_show_groups_tree_expanded= - Work_options= Insert= @@ -782,8 +762,6 @@ Modify= modify_group= -Move= - Move_down= Move_entries_in_group_selection_to_the_top= @@ -950,8 +928,6 @@ Please_enter_the_string's_label= Please_select_an_importer.= -Please_select_exactly_one_group_to_move.= - Possible_duplicate_entries= Possible_duplicate_of_existing_entry._Click_to_resolve.= @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?= Remove_entry_from_import= -Remove_entry_selection_from_this_group= +Remove_selected_entries_from_this_group= Remove_entry_type= Remove_file_link_(DELETE)= @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries= Show_description= -Show_dynamic_groups_in_italics= - Show_entries_not_in_group_selection= Show_file_column= -Show_icons_for_groups= Show_last_names_only= Show_names_unchanged= @@ -1513,7 +1486,6 @@ General_file_directory= User-specific_file_directory= Search_failed\:_illegal_search_expression= Show_ArXiv_column= -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group= You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for= Automatically_open_browse_dialog_when_creating_new_file_link= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 1e6e854e068..8ccb16c388d 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Le_chemin_n'a_pas_besoin_d'êtr Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Ajouter_une_classe_Importer_personnalisée_(compilée)_à_partir_d'une_archive_ZIP. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=L'archive_ZIP_n'a_pas_besoin_d'être_dans_le_chemin_de_classe_de_JabRef. -Add_entry_selection_to_this_group=Ajouter_les_entrées_sélectionnées_à_ce_groupe +Add_selected_entries_to_this_group= Add_from_folder=Ajouter_à_partir_du_répertoire @@ -58,8 +58,6 @@ Add_from_JAR=Ajouter_à_partir_de_JAR add_group=ajouter_un_groupe -Add_group=Ajouter_un_groupe - Add_new=Ajouter_nouvelle Add_subgroup=Ajouter_un_sous-groupe @@ -107,8 +105,6 @@ Apply=Appliquer Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Arguments_transmis_à_l'instance_JabRef_active._Arrêt. -Assign_entry_selection_exclusively_to_this_group=Assigner_les_entrées_sélectionnées_uniquement_à_ce_groupe - Assign_new_file=Assigner_un_nouveau_fichier Assign_the_original_group's_entries_to_this_group?=Assigner_les_entrées_originales_du_groupe_à_ce_groupe_? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Les_entr Cannot_merge_this_change=Cette_modification_ne_peut_pas_être_fusionnée -Cannot_move_group_"%0"_down.=Le_groupe_"%0"_ne_peut_pas_être_déplacé_vers_le_bas. - -Cannot_move_group_"%0"_left.=Le_groupe_"%0"_ne_peut_pas_être_déplacé_vers_la_gauche. - -Cannot_move_group_"%0"_right.=Le_groupe_"%0"_ne_peut_pas_être_déplacé_vers_la_droite. - -Cannot_move_group_"%0"_up.=Le_groupe_"%0"_ne_peut_pas_être_déplacé_vers_le_haut - case_insensitive=insensible_à_la_casse case_sensitive=sensible_à_la_casse @@ -229,8 +217,6 @@ Close_window=Fermer_la_fenêtre Closed_library=Fichier_fermé -Collapse_subtree=Masquer_le_sous-arbre - Color_codes_for_required_and_optional_fields=Codes_de_couleurs_pour_les_champs_requis_et_optionnels Color_for_marking_incomplete_entries=Couleur_pour_marquer_les_entrées_incomplètes @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Erreur_lors_de_l'écriture_de_%0_fichier(s). '%0'_exists._Overwrite_file?='%0'_existe._Ecraser_le_fichier_? Overwrite_file?=Ecraser_le_fichier_? -Expand_subtree=Développer_le_sous-arbre - Export=Exporter Export_name=Nom_de_l'exportation @@ -622,8 +606,6 @@ Empty_Marking=Annuler_l'étiquetage Empty_Underline=Annuler_le_soulignement The_marked_area_does_not_contain_any_legible_text!=La_zone_marquée_ne_contient_aucun_texte_lisible_! -Highlight_overlapping_groups=Surligner_les_groupes_se_chevauchant - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Astuce_\:_Pour_chercher_uniquement_dans_des_champs_spécifiques,_entrez_par_exemple_\:

author\=smith_and_title\=électrique HTML_table=Tableau_HTML @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Groupe_indépendant_\:_Quand_sélectionné,_afficher_uniquement_les_entrées_de_ce_groupe -Initially_show_groups_tree_expanded=Afficher_au_départ_l'arbre_des_groupes_développé - Work_options=Attribution_des_champs Insert=Insérer @@ -782,8 +762,6 @@ Modify=Modifier modify_group=Modifier_le_groupe -Move=Déplacer - Move_down=Déplacer_vers_le_bas Move_entries_in_group_selection_to_the_top=Déplacer_les_entrées_sélectionnées_en_haut @@ -950,8 +928,6 @@ Please_enter_the_string's_label=SVP,_entrez_le_nom_de_la_chaîne Please_select_an_importer.=Sélectionner_un_filtre_d'importation,_SVP. -Please_select_exactly_one_group_to_move.=SVP,_sélectionnez_uniquement_un_groupe_à_déplacer. - Possible_duplicate_entries=Entrées_potentiellement_dupliquées Possible_duplicate_of_existing_entry._Click_to_resolve.=Duplication_possible_d'une_entrée_existante._Cliquer_pour_vérifier. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Supprimer_tous_les_sous-groupes_de_"%0"_? Remove_entry_from_import=Supprimer_l'entrée_de_l'importation -Remove_entry_selection_from_this_group=Supprimer_les_entrées_sélectionnées_de_ce_groupe +Remove_selected_entries_from_this_group= Remove_entry_type=Supprimer_le_type_d'entrée Remove_file_link_(DELETE)=Supprimer_le_lien_de_fichier_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Demander_une_confirmation_lors_de Show_description=Montrer_la_description -Show_dynamic_groups_in_italics=Afficher_les_groupes_dynamiques_en_italique - Show_entries_not_in_group_selection=Montrer_les_entrées_non_sélectionnées Show_file_column=Afficher_la_colonne_Fichier -Show_icons_for_groups=Afficher_les_icônes_pour_les_groupes Show_last_names_only=Afficher_uniquement_les_noms_propres Show_names_unchanged=Ordre_des_noms_inchangé @@ -1513,7 +1486,6 @@ General_file_directory=Répertoire_général User-specific_file_directory=Répertoire_spécifique_à_l'utilisateur Search_failed\:_illegal_search_expression=Echec_de_la_recherche_\:_Expression_de_recherche_illégale Show_ArXiv_column=Montrer_la_colonne_ArXiv -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Surligner_les_groupes_qui_contiennent_des_entrées_contenues_dans_un_des_groupes_sélectionnés You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Vous_devez_entrer_dans_le_champ_texte_une_valeur_entière_comprise_entre_1025_et_65535_pour Automatically_open_browse_dialog_when_creating_new_file_link=Ouvrir_automatiquement_la_fenêtre_de_navigation_lors_de_la_création_d'un_nouveau_lien_de_fichier diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index c0ef83566fa..1de13e2260f 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Lokasi_tidak_harus_pada_lokasi_ Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Tambah_suaian_kelas_Importer_dari_arsip_ZIP. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Lokasi_arsip_ZIP_tidak_harus_dalam_lokasi_kelas_JabRef. -Add_entry_selection_to_this_group=Tambah_entri_pilihan_ke_grup_ini +Add_selected_entries_to_this_group= Add_from_folder=Tambah_dari_folder @@ -58,8 +58,6 @@ Add_from_JAR=Tambah_dari_JAR add_group=tambah_grup -Add_group=Tambah_Grup - Add_new=Tambah_baru Add_subgroup=Tambah_Anak_Grup @@ -107,8 +105,6 @@ Apply=Terapkan Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumen_dimasukkan_pada_JabRef_yang_sedang_dibuka._Dimatikan. -Assign_entry_selection_exclusively_to_this_group=Terapkan_pilihan_entri_hanya_ke_grup_ini - Assign_new_file=Terapkan_ke_berkas_baru Assign_the_original_group's_entries_to_this_group?=Terapkan_entri_grup_asli_ke_grup_ini? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Tidak_bi Cannot_merge_this_change=Tidak_bisa_menggabung_perubahan_ini -Cannot_move_group_"%0"_down.=Tidak_bisa_meggeser_grup_"%0"_kebawah. - -Cannot_move_group_"%0"_left.=Tidak_bisa_meggeser_grup_"%0"_kekiri. - -Cannot_move_group_"%0"_right.=Tidak_bisa_meggeser_grup_"%0"_kekanan. - -Cannot_move_group_"%0"_up.=Tidak_bisa_meggeser_grup_"%0"_keatas. - case_insensitive=huruf_besar_kecil_tidak_penting case_sensitive=memperhitungkan_huruf_besar_kecil @@ -229,8 +217,6 @@ Close_window=Tutup_jendela Closed_library=Basisdata_ditutup -Collapse_subtree=Tutup_cabang_pohon - Color_codes_for_required_and_optional_fields=Kode_warna_untuk_bidang_utama_dan_tambahan Color_for_marking_incomplete_entries=Tanda_untuk_entri_kosong @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Kesalahan_menulis_ke_berkas_%0. '%0'_exists._Overwrite_file?='%0'_esudah_ada._Berkas_ditindih? Overwrite_file?=Berkas_ditindih? -Expand_subtree=Paparkan_cabang - Export=Ekspor Export_name=Ekspor_nama @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Warnakan_grup_yang_bertindih - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Sarant\:_untuk_mencari_hanya_bidang_tertentu,_misal_tulis\:

author\=smith_dan_title\=electrical HTML_table=Tabel_HTML @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Grup_bebas\:_Ketika_dipilih,_lihat_hanya_entri_grup_ini -Initially_show_groups_tree_expanded=Awalnya_grup_tampil_dengan_detail_dibuka - Work_options= Insert=Sisipkan @@ -782,8 +762,6 @@ Modify=Memodifikasi modify_group=memodifikasi_grup -Move=Memindah - Move_down=Pindah_kebawah Move_entries_in_group_selection_to_the_top=Pindah_entri_dalam_grup_pilihan_ke_atas @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Tuliskan_label_string Please_select_an_importer.=Silahkan_pilih_pengimpor. -Please_select_exactly_one_group_to_move.=Silahkan_pilih_satu_grup_yang_akan_dipindah. - Possible_duplicate_entries=Mungkin_entri_sama Possible_duplicate_of_existing_entry._Click_to_resolve.=Mungkin_entri_sama_dengan_lainnya._Klik_untuk_menyelesaikan. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Hapus_semua_sub-grup_dari_"%0"? Remove_entry_from_import=Hapus_entri_dari_impor -Remove_entry_selection_from_this_group=Hapus_entri_pilihan_dari_grup_ini +Remove_selected_entries_from_this_group= Remove_entry_type=Hapus_tipe_entri Remove_file_link_(DELETE)=Hapus_tautan_berkas_(HAPUS) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Tampilkan_dialog_konfirmasi_jika_ Show_description=Tampilkan_deskripsi -Show_dynamic_groups_in_italics=Tampilkan_grup_dinamik_dengan_huruf_miring - Show_entries_not_in_group_selection=Tampilkan_entri_tidak_dalam_pilihan_grup Show_file_column=Tampilkan_kolom_berkas -Show_icons_for_groups=Tampilkan_ikon_untuk_grup Show_last_names_only=Tampil_hanya_nama_belakang Show_names_unchanged=Nama_apa_adanya @@ -1513,7 +1486,6 @@ General_file_directory=Direktori_berkas_umum User-specific_file_directory=Direktori_berkas_khusus_pengguna Search_failed\:_illegal_search_expression=Pencarian_gagal\:_ekspresi_pencarian_tidak_benar Show_ArXiv_column=Tampilkan_kolom_ArXiv -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Warnakan_grup_yang_mengandung_entri_pada_grup_yang_dipilih You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Anda_harus_memasukkan_angka_bulat_antara_1025-65535_di_bidang_teks Automatically_open_browse_dialog_when_creating_new_file_link=Otomatis_membuka_dialog_jelajah_ketika_membuat_tautan_berkas_baru diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 25585a900af..f6b0eaff43b 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Il_percorso_non_deve_necessaria Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Aggiungi_una_classe_Importer_personalizzata_(compilata)_da_un_archivio_ZIP. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=L'archivio_ZIP_non_deve_necessariamente_essere_nel_classpath_di_JabRef. -Add_entry_selection_to_this_group=Aggiungi_le_voci_selezionate_a_questo_gruppo +Add_selected_entries_to_this_group= Add_from_folder=Aggiungi_da_una_cartella @@ -58,8 +58,6 @@ Add_from_JAR=Aggiungi_da_un_file_JAR add_group=aggiungi_un_gruppo -Add_group=Aggiungi_un_gruppo - Add_new=Aggiungi_nuovo Add_subgroup=Aggiungi_un_sottogruppo @@ -107,8 +105,6 @@ Apply=Applica Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argomenti_passati_all'istanza_attiva_di_JabRef._Chiusura_in_corso. -Assign_entry_selection_exclusively_to_this_group=Assegna_le_voci_selezionate_esclusivamente_a_questo_gruppo - Assign_new_file=Assegna_un_nuovo_file Assign_the_original_group's_entries_to_this_group?=Assegnare_le_voci_originali_del_gruppo_a_questo_gruppo? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Le_voci_ Cannot_merge_this_change=Questa_modifica_non__può_essere_incorporata -Cannot_move_group_"%0"_down.=Impossibile_spostare_il_gruppo_"%0"_in_giù - -Cannot_move_group_"%0"_left.=Impossibile_spostare_il_gruppo_"%0"_a_sinistra - -Cannot_move_group_"%0"_right.=Impossibile_spostare_il_gruppo_"%0"_a_destra - -Cannot_move_group_"%0"_up.=Impossibile_spostare_il_gruppo_"%0"_in_su - case_insensitive=non_distingue_maiuscole_e_minuscole case_sensitive=distingue_maiuscole_e_minuscole @@ -229,8 +217,6 @@ Close_window=Chiudi_la_finestra Closed_library=Library_chiuso -Collapse_subtree=Collassa_il_sotto-albero - Color_codes_for_required_and_optional_fields=Codifica_a_colori_per_campi_obbligatori_e_opzionali Color_for_marking_incomplete_entries=Colore_per_contrassegnare_voci_incomplete @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Errore_di_scrittura_di_%0_file. '%0'_exists._Overwrite_file?='%0'_esiste._Sovrascrivere_il_file? Overwrite_file?=Sovrascrivere_il_file? -Expand_subtree=Espandere_il_sotto-albero - Export=Esporta Export_name=Esporta_nome @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Evidenzia_gruppi_con_voci_in_comune - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Suggerimento\:_Per_ricercare_in_un_campo_specifico_digitare,_per_esempio\:

author\=smith_and_title\=electrical HTML_table=Tabella_HTML @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Gruppo_indipendente\:_Quando_selezionato,_mostra_solo_le_voci_di_questo_gruppo -Initially_show_groups_tree_expanded=Inizialmente_mostra_l'albero_dei_gruppi_espanso - Work_options=Attribuzione_dei_campi Insert=Inserisci @@ -782,8 +762,6 @@ Modify=Modifica modify_group=modifica_gruppo -Move=Sposta - Move_down=Sposta_in_giù Move_entries_in_group_selection_to_the_top=Sposta_le_voci_selezionate_in_su @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Immettere_l'etichetta_della_stringa Please_select_an_importer.=Selezionare_un_filtro_di_importazione. -Please_select_exactly_one_group_to_move.=Selezionare_un_solo_gruppo_da_spostare. - Possible_duplicate_entries=Voci_potenzialmente_duplicate Possible_duplicate_of_existing_entry._Click_to_resolve.=Possibile_duplicazione_di_una_voce_esistente._Cliccare_per_effettuare_la_verifica. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Rimuovere_tutti_i_sottogruppi_di_"%0"? Remove_entry_from_import=Rimuovi_la_voce_dall'importazione -Remove_entry_selection_from_this_group=Rimuovi_le_voci_selezionate_da_questo_gruppo +Remove_selected_entries_from_this_group= Remove_entry_type=Rimuovi_il_tipo_di_voce Remove_file_link_(DELETE)=Rimuovi_collegamento_a_file_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Chiedere_conferma_della_cancellaz Show_description=Mostra_descrizione -Show_dynamic_groups_in_italics=Mostra_gruppi_dinamici_in_corsivo - Show_entries_not_in_group_selection=Mostra_le_voci_non_comprese_nei_gruppi_selezionati Show_file_column=Visualizza_la_colonna_File -Show_icons_for_groups=Mostra_le_icone_per_i_gruppi Show_last_names_only=Mostra_solo_i_cognomi Show_names_unchanged=Mostra_i_nomi_immodificati @@ -1513,7 +1486,6 @@ General_file_directory=Cartella_dei_file_generale User-specific_file_directory=Cartella_dei_file_specifica_dell'utente Search_failed\:_illegal_search_expression=Ricerca_fallita\:_espressione_di_ricerca_illegale Show_ArXiv_column=Mostra_la_colonna_ArXiv -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Evidenzia_i_gruppi_contenenti_voci_incluse_in_uno_dei_gruppi_selezionati You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=È_necessario_inserire_un_intero_nell'intervallo_1025-65535_nel_campo_di_testo_per Automatically_open_browse_dialog_when_creating_new_file_link=Apri_automaticamente_la_finestra_di_dialogo_"Sfoglia"_quando_viene_creato_un_nuovo_collegamento_ad_un_file diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 94de36f25fc..3483866005c 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=このパスは、JabRefのク Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=(コンパイルした)ユーザー定義ImportFormatクラスをZIP書庫から追加します。 The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=このZIP書庫は、JabRefのクラスパスにあるとは限りません。 -Add_entry_selection_to_this_group=選択項目をこのグループに追加 +Add_selected_entries_to_this_group= Add_from_folder=フォルダから追加 @@ -58,8 +58,6 @@ Add_from_JAR=jarから追加 add_group=グループを追加 -Add_group=グループを追加 - Add_new=新規追加 Add_subgroup=下層グループを追加 @@ -107,8 +105,6 @@ Apply=適用 Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=引数は実行中のJabRefインスタンスに渡されました。終了します。 -Assign_entry_selection_exclusively_to_this_group=選択項目を排他的にこのグループに割り当てます - Assign_new_file=新規ファイルを割り当て Assign_the_original_group's_entries_to_this_group?=元のグループの項目をこのグループに割り当てますか? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=鍵を Cannot_merge_this_change=この変更を統合することができません -Cannot_move_group_"%0"_down.=グループ「%0」を下に動かすことができません。 - -Cannot_move_group_"%0"_left.=グループ「%0」を左に動かすことができません。 - -Cannot_move_group_"%0"_right.=グループ「%0」を右に動かすことができません。 - -Cannot_move_group_"%0"_up.=グループ「%0」を上に動かすことができません。 - case_insensitive=大小文字を区別しない case_sensitive=大小文字を区別 @@ -229,8 +217,6 @@ Close_window=ウィンドウを閉じる Closed_library=データベースを閉じました -Collapse_subtree=下層ツリーを閉じる - Color_codes_for_required_and_optional_fields=必須フィールドと非必須フィールドのコードに着色 Color_for_marking_incomplete_entries=不完全な項目を標識するのに使用する色 @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=%0ファイルを書き込み中にエラー発生 '%0'_exists._Overwrite_file?='%0'_は存在します。ファイルを上書きしますか? Overwrite_file?=ファイルを上書きしますか? -Expand_subtree=下層ツリーを開く - Export=書き出す Export_name=書出名 @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=重複のあるグループを着色 - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=ヒント\:_特定のフィールドのみを検索するには、たとえば\:

author\=smith_and_title\=electricalと入力してください HTML_table=HTMLテーブル @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=独立グループ:このグループの項目のみを表示 -Initially_show_groups_tree_expanded=最初にグループツリーを展開した状態で表示 - Work_options=作業オプション Insert=挿入 @@ -782,8 +762,6 @@ Modify=修正 modify_group=グループを修正 -Move=移動 - Move_down=下げる Move_entries_in_group_selection_to_the_top=グループ選択中の項目を上に移動 @@ -950,8 +928,6 @@ Please_enter_the_string's_label=文字列のラベルを入力してください Please_select_an_importer.=読込を選択してください。 -Please_select_exactly_one_group_to_move.=移動するグループを一つだけ選択してください。 - Possible_duplicate_entries=重複の可能性のある項目 Possible_duplicate_of_existing_entry._Click_to_resolve.=既存項目と重複している可能性があります。解消するにはクリックしてください。 @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=「%0」の下層グループをすべて削除し Remove_entry_from_import=読み込み分から項目を削除 -Remove_entry_selection_from_this_group=このグループから選択項目を削除 +Remove_selected_entries_from_this_group= Remove_entry_type=項目型を削除 Remove_file_link_(DELETE)=ファイルリンクを削除(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=項目を削除する際に確認 Show_description=説明を表示 -Show_dynamic_groups_in_italics=動的グループをイタリック体で表示 - Show_entries_not_in_group_selection=グループ選択に「ない」項目を表示する Show_file_column=ファイル列を表示 -Show_icons_for_groups=グループにアイコンを表示 Show_last_names_only=姓のみを表示する Show_names_unchanged=氏名をそのまま表示 @@ -1513,7 +1486,6 @@ General_file_directory=一般ファイルディレクトリ User-specific_file_directory=ユーザーファイルディレクトリ Search_failed\:_illegal_search_expression=検索に失敗\:_誤った検索表現です Show_ArXiv_column=ArXiv列を表示 -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=現在選択されているグループに含まれている項目を持つグループを着色 You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=テキストフィールドに1025〜65535の間の整数値を入力しなくてはなりません: Automatically_open_browse_dialog_when_creating_new_file_link=新しくファイルリンクを作成する際、自動的にブラウズダイアログを開く diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 58d8fe15a71..aed7a2d2233 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Het_pad_moet_niet_in_het_classp Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Voeg_een_(gecompileerde)_externe_Importer_klasse_van_een_ZIP-archief_toe. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Het_pad_moet_niet_in_het_classpath_van_JabRef_staan. -Add_entry_selection_to_this_group=Voeg_entry_selectie_toe_aan_deze_groep +Add_selected_entries_to_this_group= Add_from_folder=Voeg_toe_uit_map @@ -58,8 +58,6 @@ Add_from_JAR=_Voeg_toe_uit_JAR add_group=groep_toevoegen -Add_group=Groep_toevoegen - Add_new=Voeg_nieuw_toe Add_subgroup=Voeg_subgroep_toe @@ -107,8 +105,6 @@ Apply=Toepassen Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumenten_doorgegeven_aan_de_draaiende_JabRef_instantie._Wordt_nu_afgesloten. -Assign_entry_selection_exclusively_to_this_group=Ken_entry_selectie_exclusief_aan_deze_groep_toe - Assign_new_file=Ken_nieuw_bestand_toe Assign_the_original_group's_entries_to_this_group?=De_entries_van_de_originele_groep_aan_deze_groep_toekennen? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Kan_entr Cannot_merge_this_change=Kan_deze_verandering_niet_samenvoegen -Cannot_move_group_"%0"_down.=Kan_groep_"%0"_niet_naar_beneden_verplaatsen - -Cannot_move_group_"%0"_left.=Kan_groep_"%0"_niet_naar_links_verplaatsen - -Cannot_move_group_"%0"_right.=Kan_groep_"%0"_niet_naar_rechts_verplaatsen - -Cannot_move_group_"%0"_up.=Kan_groep_"%0"_niet_naar_boven_verplaatsen - case_insensitive=hoofdletter_ongevoelig case_sensitive=hoofdletter_gevoelig @@ -229,8 +217,6 @@ Close_window=Sluit_venster Closed_library=Sluit_library -Collapse_subtree=Subboom_in_mekaar_klappen - Color_codes_for_required_and_optional_fields=Kleurcodes_voor_vereiste_en_optionele_velden Color_for_marking_incomplete_entries=Kleur_om_onvolledige_entries_te_markeren @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).= '%0'_exists._Overwrite_file?='%0'_bestaat_reeds._Bestand_overschrijven? Overwrite_file?=Bestand_overschrijven? -Expand_subtree=Subboom_uitklappen - Export=Exporteren Export_name=Naam_exporteren @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Markeer_overlappende_groepen - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Hint\:_Om_specifieke_velden_alleen_te_zoeken,_geef_bijvoorbeeld_in\:

auteur\=smith_en_titel\=electrical HTML_table=HTML_tabel @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Onafhankelijke_groep\:_Wanneer_geselecteerd,_toon_enkel_de_entries_van_deze_groep -Initially_show_groups_tree_expanded=Initieel,_toon_alle_bomen_van_de_groepen_uitgeklapt - Work_options= Insert=Invoegen @@ -782,8 +762,6 @@ Modify=Wijzigen modify_group=wijzig_groep -Move=Verplaats - Move_down=Verplaats_naar_beneden Move_entries_in_group_selection_to_the_top=Verplaats_entries_in_de_groep_selectie_naar_de_top @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Geef_a.u.b._het_label_van_de_constante_in Please_select_an_importer.=Selecteer_a.u.b._een_importer. -Please_select_exactly_one_group_to_move.=Selecteer_a.u.b._exact_\u00e9\u00e9n_groep_om_te_verplaatsen. - Possible_duplicate_entries=Mogelijke_dubbele_entries Possible_duplicate_of_existing_entry._Click_to_resolve.=Mogelijk_duplicaat_van_bestaande_entry. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Alle_subgroepen_van_"%0"_verwijderen? Remove_entry_from_import=Verwijder_entry_uit_importering -Remove_entry_selection_from_this_group=Verwijder_entry_selectie_van_deze_groep +Remove_selected_entries_from_this_group= Remove_entry_type=Verwijder_entry_type Remove_file_link_(DELETE)= @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Toon_bevestigingsdialoog_bij_verw Show_description=Toon_beschrijving -Show_dynamic_groups_in_italics=Toon_dynamische_groepen_cursief - Show_entries_not_in_group_selection=Toon_entries_die_zich_niet_in_de_groep_selectie_bevinden Show_file_column= -Show_icons_for_groups=Toon_iconen_voor_groepen Show_last_names_only=Toon_enkel_laatste_namen Show_names_unchanged=Toon_namen_onveranderd @@ -1513,7 +1486,6 @@ General_file_directory= User-specific_file_directory= Search_failed\:_illegal_search_expression= Show_ArXiv_column= -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group= You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for= Automatically_open_browse_dialog_when_creating_new_file_link= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 2103a69f13d..fed5a986c73 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Stien_trenger_ikke_\u00e5_v\u00 Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Legg_til_en_(kompilert)_egendefinert_Importer-klasse_fra_en_zip-fil. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=ZIP-filen_trenger_ikke_\u00e5_v\u00e6re_p\u00e5_JabRefs_classpath. -Add_entry_selection_to_this_group=Legg_valgte_enheter_til_denne_gruppen +Add_selected_entries_to_this_group= Add_from_folder=Legg_til_fra_mappe @@ -58,8 +58,6 @@ Add_from_JAR=Legg_til_fra_JAR-fil add_group=legg_til_gruppe -Add_group=Legg_til_gruppe - Add_new=Legg_til_ny Add_subgroup=Legg_til_undergruppe @@ -107,8 +105,6 @@ Apply=Utf\u00f8r Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumentene_sendt_til_allerede_aktiv_JabRef-instans._Avslutter. -Assign_entry_selection_exclusively_to_this_group=Legg_valgte_enheter_eksklusivt_til_denne_gruppen - Assign_new_file=Tilordne_ny_fil Assign_the_original_group's_entries_to_this_group?=Legg_den_opprinnelige_gruppens_enheter_til_denne_gruppen? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Kan_ikke Cannot_merge_this_change=Kan_ikke_inkorporere_denne_endringen -Cannot_move_group_"%0"_down.=Kan_ikke_flytte_gruppen_"%0"_ned. - -Cannot_move_group_"%0"_left.=Kan_ikke_flytte_gruppen_"%0"_til_venstre. - -Cannot_move_group_"%0"_right.=Kan_ikke_flytte_gruppen_"%0"_til_h\u00f8yre. - -Cannot_move_group_"%0"_up.=Kan_ikke_flytte_gruppen_"%0"_opp. - case_insensitive=skiller_ikke_mellom_store_og_sm\u00e5_bokstaver case_sensitive=skiller_mellom_store_og_sm\u00e5_bokstaver @@ -229,8 +217,6 @@ Close_window=Lukk_vindu Closed_library=Lukket_library -Collapse_subtree=Lukk_forgrening - Color_codes_for_required_and_optional_fields=Fargekoder_for_n\u00f8dvendige_og_valgfrie_felter Color_for_marking_incomplete_entries=Farge_for_markering_av_ufullstendige_enheter @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Feil_ved_skriving_til_%0_fil(er). '%0'_exists._Overwrite_file?='%0'_eksisterer._Erstatt_filen? Overwrite_file?=Erstatt_filen? -Expand_subtree=\u00c5pne_forgrening - Export=Eksporter Export_name=Navn_p\u00e5_filter @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Uthev_overlappende_grupper - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Hint\:_For_bare_\u00e5_s\u00f8ke_i_spesifikke_felt,_skriv_f._eks.\:

author\=smith_and_title\=electrical HTML_table=HTML-tabell @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Uavhengig_gruppe\:_Vis_bare_denne_gruppens_enheter -Initially_show_groups_tree_expanded=Vis_gruppetreet_ekspandert_i_utgangspunktet - Work_options= Insert=Legg_til @@ -782,8 +762,6 @@ Modify=Endre modify_group=endre_gruppe -Move=Flytt - Move_down=Flytt_ned Move_entries_in_group_selection_to_the_top=Flytt_enheter_i_valgte_grupper_\u00f8verst @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Skriv_inn_et_navn_for_strengen Please_select_an_importer.=Velg_et_importfilter. -Please_select_exactly_one_group_to_move.=Velg_eksakt_en_gruppe_for_flytting. - Possible_duplicate_entries=Mulige_duplikater Possible_duplicate_of_existing_entry._Click_to_resolve.=Mulig_duplikat_av_eksisterende_enhet._Klikk_for_\u00e5_h\u00e5ndtere. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Remove_all_subgroups_of_"%0"? Remove_entry_from_import=Fjern_enhet_fra_import -Remove_entry_selection_from_this_group=Fjern_valgte_enheter_fra_denne_gruppen +Remove_selected_entries_from_this_group= Remove_entry_type=Slett_enhetstype Remove_file_link_(DELETE)=Slett_link_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Vis_dialog_for_\u00e5_bekrefte_sl Show_description=Vis_beskrivelse -Show_dynamic_groups_in_italics=Vis_dynamiske_grupper_i_kursiv - Show_entries_not_in_group_selection=Vis_enheter_utenfor_valgte_grupper Show_file_column=Vis_'file'-kolonne -Show_icons_for_groups=Vis_ikoner_for_grupper Show_last_names_only=Vis_bare_etternavn Show_names_unchanged=Vis_navn_uforandret @@ -1513,7 +1486,6 @@ General_file_directory=Standard_filkatalog User-specific_file_directory=Brukerdefinert_filkatalog Search_failed\:_illegal_search_expression=Kunne_ikke_s\u00f8ke\:_feil_i_s\u00f8keuttrykk Show_ArXiv_column=Vis_ArXiv-kolonne -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Uthev_grupper_som_inneholder_enheter_inneholdt_i_valgte_grupper You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Du_m\u00e5_velge_en_heltallsverdi_i_intervallet_1025-65535_i_feltet_for Automatically_open_browse_dialog_when_creating_new_file_link=\u00c5pne_fildialog_automatisk_n\u00e5r_ny_link_opprettes diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 05b6156456d..d0ecaeaf91e 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=O_caminho_não_precisa_estar_no Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Adicionar_uma_classe_Importer_customizada_(compilada)_a_partir_de_um_arquivo_zip. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=O_arquivo_zip_não_precisa_estar_no_classpath_do_JabRef. -Add_entry_selection_to_this_group=Adicionar_referências_selecionadas_a_um_grupo +Add_selected_entries_to_this_group= Add_from_folder=Adicionar_a_partir_de_uma_pasta @@ -58,8 +58,6 @@ Add_from_JAR=Adicionar_a_partir_de_um_JAR add_group=adicionar_grupo -Add_group=Adicionar_grupo - Add_new=Adicionar_novo Add_subgroup=Adicionar_subgrupo @@ -107,8 +105,6 @@ Apply=Aplicar Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Parâmetros_passados_ao_JabRef_em_execução._Encerrando_o_programa. -Assign_entry_selection_exclusively_to_this_group=Atribuir_referências_selecionadas_exclusivamente_para_este_grupo - Assign_new_file=Associar_novo_arquivo Assign_the_original_group's_entries_to_this_group?=Atribuir_as_referênciass_originais_do_grupo_à_este_grupo? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Não_é_ Cannot_merge_this_change=Não_é_possível_mesclar_esta_mudança. -Cannot_move_group_"%0"_down.=Não_é_possível_mover_o_grupo_"%0"_para_baixo. - -Cannot_move_group_"%0"_left.=Não_é_possível_mover_o_grupo_"%0"_para_a_esquerda. - -Cannot_move_group_"%0"_right.=Não_é_possível_mover_o_grupo_"%0"_para_a_direita. - -Cannot_move_group_"%0"_up.=Não_é_possível_mover_o_grupo_"%0"_para_cima. - case_insensitive=Insensível_ao_caso case_sensitive=sensível_ao_caso @@ -229,8 +217,6 @@ Close_window=Fechar_Janela Closed_library=Base_de_dados_fechada -Collapse_subtree=Colapsar_subárvore - Color_codes_for_required_and_optional_fields=Códigos_de_cores_para_campos_obrigatórios_e_opcionais Color_for_marking_incomplete_entries=Cores_para_marcar_referências_incompletas @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Erro_ao_escrever_para_%0_arquivos. '%0'_exists._Overwrite_file?='%0'_existe._Sobrescrever_o_arquivo? Overwrite_file?=Sobrescrever_o_arquivo?? -Expand_subtree=Expandir_a_subárvore - Export=Exportar Export_name=Exportar_nome @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Destacar_grupos_sobrepostos - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Dica\:_Para_procurar_apenas_campos_específicos,_digite_por_exemplo\:

author\=smith_and_title\=electrical HTML_table=Tabela_HTML @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Grupo_independente\:_Quando_selecionado,_mostra_apenas_as_referências_deste_grupo -Initially_show_groups_tree_expanded=Inicialmente_mostra_árvore_de_grupos_expandida - Work_options=Atribuição_do_campo Insert=Inserir @@ -782,8 +762,6 @@ Modify=Modificar modify_group=Modificar_grupo -Move=Mover - Move_down=Mover_para_baixo Move_entries_in_group_selection_to_the_top=Mover_referências_nos_grupos_selecionados_para_o_topo @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Por_favor,_digite_o_rótulo_da_string Please_select_an_importer.=Por_favor,_selecione_um_importador. -Please_select_exactly_one_group_to_move.=Por_favor,_selecione_exatamente_um_grupo_a_ser_movido. - Possible_duplicate_entries=Possíveis_referências_duplicadas Possible_duplicate_of_existing_entry._Click_to_resolve.=Possível_duplicata_de_referência_existente._Clique_para_resolver. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Remover_todos_os_subgrupos_de_"%0"? Remove_entry_from_import=Remover_referência_da_importação -Remove_entry_selection_from_this_group=Remover_seleção_de_referências_deste_grupo +Remove_selected_entries_from_this_group= Remove_entry_type=remover_tipo_de_referência Remove_file_link_(DELETE)=Remover_link_de_arquivo_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Exibir_diálogo_de_confirmação_ Show_description=Exibir_descrição -Show_dynamic_groups_in_italics=Exibir_grupos_dinâmicos_em_itálico - Show_entries_not_in_group_selection=Exibir_referências_que_não_estão_no_grupo_selecionado Show_file_column=Exibir_coluna_de_arquivo -Show_icons_for_groups=Exibir_ícones_para_grupos Show_last_names_only=Exibir_apenas_últimos_nomes Show_names_unchanged=Exibir_nomes_não_modificados @@ -1513,7 +1486,6 @@ General_file_directory=Diretório_geral_de_arquivos User-specific_file_directory=Diretório_de_arquivo_específico_do_usuário Search_failed\:_illegal_search_expression=A_pesquisa_falhou\:_expressão_de_pesquisa_ilegal Show_ArXiv_column=Exibir_coluna_ArXiv -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Destacar_grupos_que_contém_referências_presentes_em_qualquer_um_dos_grupos_selecionados You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Você_deve_digitar_um_valor_inteiro_entre_1025_e_65535_no_campo_de_texto_para Automatically_open_browse_dialog_when_creating_new_file_link=Abrir_janela_de_diálogo_automaticamente_ao_criar_um_novo_link_de_arquivo diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index dafd7b27bec..9223b86c700 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Путь_может_не_сов Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Добавить_(скомпил.)_пользовательский_класс_Importer_из_ZIP-архива. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=ZIP-архив_может_не_совпадать_с_путем_классов_JabRef. -Add_entry_selection_to_this_group=Добавить_выбранные_записи_в_эту_группу +Add_selected_entries_to_this_group= Add_from_folder=Добавить_из_папки @@ -58,8 +58,6 @@ Add_from_JAR=Добавить_из_JAR add_group=добавить_группу -Add_group=Добавить_группу - Add_new=Добавить_новую Add_subgroup=Добавить_подгруппу @@ -107,8 +105,6 @@ Apply=Применить Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Аргументы_переданы_в_запущенный_экземпляр_JabRef._Отключение. -Assign_entry_selection_exclusively_to_this_group=Назначение_выбора_записей_исключительно_для_этой_группы. - Assign_new_file=Назначить_новый_файл Assign_the_original_group's_entries_to_this_group?=Назначить_исходные_записи_группы_этой_группе? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Нево Cannot_merge_this_change=Невозможно_выполнить_объединение_для_этого_изменения -Cannot_move_group_"%0"_down.=Невозможно_переместить_группу_"%0"_вниз. - -Cannot_move_group_"%0"_left.=Невозможно_переместить_группу_"%0"_налево. - -Cannot_move_group_"%0"_right.=Невозможно_переместить_группу_"%0"_направо. - -Cannot_move_group_"%0"_up.=Невозможно_переместить_группу_"%0"_вверх. - case_insensitive=без_учета_регистра case_sensitive=с_учетом_регистра @@ -229,8 +217,6 @@ Close_window=Закрыть_окно Closed_library=Закрытая_БД -Collapse_subtree=Свернуть_поддерево - Color_codes_for_required_and_optional_fields=Цветовые_коды_обязательных_и_дополнительных_полей Color_for_marking_incomplete_entries=Цвет_маркировки_неполных_записей @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Ошибка_при_записи_в_файл(ы)_%0 '%0'_exists._Overwrite_file?='%0'_существует._Перезаписать_файл? Overwrite_file?=Перезаписать_файл? -Expand_subtree=Развернуть_поддерево - Export=Экспорт Export_name=Имя_экспорта @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Выделить_пересекающиеся_группы - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Подсказка\:_Для_поиска_только_по_определенным_полям,_напр.\:

автор\=smith_и_заглавие\=electrical HTML_table=Таблица_HTML @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Независимая_группа\:_Просмотр_записей_только_этой_группы_(если_выбрано) -Initially_show_groups_tree_expanded=Разворачивать_дерево_групп_по_умолчанию - Work_options=Рабочие_параметры Insert=Вставить @@ -782,8 +762,6 @@ Modify=Модифицировать modify_group=модифицировать_группу -Move=Переместить - Move_down=Переместить_вниз Move_entries_in_group_selection_to_the_top=Переместить_выделенные_записи_вверх @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Введите_подпись_для_строк Please_select_an_importer.=Выберите_фильтр_импорта. -Please_select_exactly_one_group_to_move.=Выберите_только_одну_группу_для_перемещения. - Possible_duplicate_entries=Возможные_дубликаты_записей Possible_duplicate_of_existing_entry._Click_to_resolve.=Возможный_дубликат_существующей_записи._Щелкните_для_разрешения. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Удалить_все_подгруппы_"%0"? Remove_entry_from_import=Удалить_запись_из_импортируемых -Remove_entry_selection_from_this_group=Удалить_выбранные_записи_из_этой_группы +Remove_selected_entries_from_this_group= Remove_entry_type=Удалить_тип_записи Remove_file_link_(DELETE)=Удалить_ссылку_для_файла_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Запрос_подтвержде Show_description=Показать_описание -Show_dynamic_groups_in_italics=Шрифт_для_отображения_динамических_групп_курсив - Show_entries_not_in_group_selection=Показать_записи_не_выбранные_в_группе Show_file_column=Показать_столбец_Файл -Show_icons_for_groups=Показать_значки_для_групп Show_last_names_only=Показать_только_фамилии Show_names_unchanged=Показать_имена_без_изменений @@ -1513,7 +1486,6 @@ General_file_directory=Общий_каталог_файлов User-specific_file_directory=Пользовательский_каталог_файлов Search_failed\:_illegal_search_expression=Ошибка_поиска\:_недопустимое_выражение_для_поиска Show_ArXiv_column=Показать_столбец_ArXiv -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Выделить_цветом_группы_с_записями,_содержащимися_в_любой_выбранной_в_настоящее_время_группе You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Необходимо_ввести_целое_число_из_интервала_1025-65535_в_текстовое_поле_для Automatically_open_browse_dialog_when_creating_new_file_link=Автоматически_открывать_диалоговое_окно_обзора_при_создании_новой_ссылки_на_файл diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index e7628422a56..8f2121c866e 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.= Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Lägg_till_en_(kompilerad)_Importer-klass_från_en_zip-fil. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.= -Add_entry_selection_to_this_group=Lägg_till_valda_poster_till_denna_grupp +Add_selected_entries_to_this_group= Add_from_folder=Lägg_till_från_mapp @@ -58,8 +58,6 @@ Add_from_JAR=Lägg_till_från_JAR-fil add_group=lägg_till_grupp -Add_group=Lägg_till_grupp - Add_new=Lägg_till_ny Add_subgroup=Lägg_till_undergrupp @@ -107,8 +105,6 @@ Apply=Tillämpa Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumenten_skickades_till_JabRef-instansen_som_redan_kördes._Stänger_ned. -Assign_entry_selection_exclusively_to_this_group= - Assign_new_file=Tilldela_ny_fil Assign_the_original_group's_entries_to_this_group?=Tilldela_den_ursprungliga_gruppens_poster_till_denna_grupp? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Kan_inte Cannot_merge_this_change=Kan_inte_införa_den_här_ändringen -Cannot_move_group_"%0"_down.=Kan_inte_flytta_gruppen_"%0"_nedåt. - -Cannot_move_group_"%0"_left.=Kan_inte_flytta_gruppen_"%0"_till_vänster. - -Cannot_move_group_"%0"_right.=Kan_inte_flytta_gruppen_"%0"_till_höger. - -Cannot_move_group_"%0"_up.=Kan_inte_flytta_gruppen_"%0"_uppåt. - case_insensitive=ej_skiftlägeskänsligt case_sensitive=skiftlägeskänsligt @@ -229,8 +217,6 @@ Close_window=Stäng_fönster Closed_library=Stängde_libraryn -Collapse_subtree=Fäll_ihop_delträd - Color_codes_for_required_and_optional_fields=Färgkodning_av_obligatoriska_och_valfria_fält Color_for_marking_incomplete_entries=Färg_för_markering_av_ofullständiga_poster @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Fel_vid_skrivning_till_%0_fil(er). '%0'_exists._Overwrite_file?='%0'_finns_redan._Skriv_över_filen? Overwrite_file?=Skriva_över_fil? -Expand_subtree=Expandera_delträd - Export=Exportera Export_name=Exportnamn @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Framhäv_överlappande_grupper - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Tips\:_För_att_söka_i_specifika_fält,_skriv_t.ex.\:

author\=smith_and_title\=electrical HTML_table=HTML-tabell @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries= -Initially_show_groups_tree_expanded=Visa_gruppträdet_expanderat_från_början - Work_options= Insert=Infoga @@ -782,8 +762,6 @@ Modify=Ändra modify_group=ändra_grupp -Move=Flytta - Move_down=Flytta_nedåt Move_entries_in_group_selection_to_the_top= @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Ange_namnet_på_strängen Please_select_an_importer.= -Please_select_exactly_one_group_to_move.=Välj_exakt_en_grupp_att_flytta. - Possible_duplicate_entries=Möjliga_dubbletter Possible_duplicate_of_existing_entry._Click_to_resolve.=Möjlig_dubblett_av_befintlig_post._Klicka_för_att_reda_ut. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Ta_bort_alla_undergrupper_till_"%0"? Remove_entry_from_import=Ta_bort_post_från_import -Remove_entry_selection_from_this_group=Ta_bort_valda_poster_från_denna_grupp +Remove_selected_entries_from_this_group= Remove_entry_type=Ta_bort_posttyp Remove_file_link_(DELETE)=Ta_bort_fillänk_(RADERA) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Visa_bekräftelseruta_när_poster Show_description=Visa_beskrivning -Show_dynamic_groups_in_italics=Visa_dynamiska_grupper_kursivt - Show_entries_not_in_group_selection=Visa_poster_som_inte_är_i_vald_grupp Show_file_column=Visa_filkolumn -Show_icons_for_groups=Visa_ikoner_för_grupper Show_last_names_only=Visa_bara_efternamn Show_names_unchanged=Visa_namnen_som_de_är @@ -1513,7 +1486,6 @@ General_file_directory=Generell_filmapp User-specific_file_directory=Användarspecifik_filmapp Search_failed\:_illegal_search_expression=Sökning_misslyckades\:_ogiltigt_sökuttryck Show_ArXiv_column=Visa_ArXiv-kolumn -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Framhäv_grupper_som_innehåller_poster_från_någon_av_det_valda_grupperna You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Du_måste_ange_ett_heltal_i_området_1025-65536_i_fältet_för Automatically_open_browse_dialog_when_creating_new_file_link=Öppna_fildialog_automatiskt_när_ny_fillänk_skapas diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index ef3eebe8a19..b892dca2986 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Yolun_JabRef'in_sınıf_yolunda Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Bir_ZIP_arşivinden_(derlenmiş)_özel_İçeAlmaBiçemi_sınıfı_ekle. The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Yolun_JabRef'in_sınıf_yolunda_olması_gerekmez. -Add_entry_selection_to_this_group=Bu_gruba_girdi_seçimini_ekle +Add_selected_entries_to_this_group= Add_from_folder=Klasörden_ekle @@ -58,8 +58,6 @@ Add_from_JAR=Jar'dan_ekle add_group=grup_ekle -Add_group=Grup_Ekle - Add_new=Yeni_ekle Add_subgroup=Altgrup_ekle @@ -107,8 +105,6 @@ Apply=Uygula Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argümanlar_çalışan_JabRef_oturumuna_aktarıldı._Kapatılıyor. -Assign_entry_selection_exclusively_to_this_group=Girdi_seçimini_özellikle_bu_gruba_ata - Assign_new_file=Yeni_dosya_ata Assign_the_original_group's_entries_to_this_group?=Orijinal_grubun_girdileri_bu_gruba_atansın_mı? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Anahtarl Cannot_merge_this_change=Bu_değişiklik_birleştirilemiyor -Cannot_move_group_"%0"_down.="%0"_grubu_aşağıya_taşınamıyor. - -Cannot_move_group_"%0"_left.="%0"_grubu_sola_taşınamıyor. - -Cannot_move_group_"%0"_right.="%0"_grubu_sağa_taşınamıyor. - -Cannot_move_group_"%0"_up.="%0"_grubu_yukarıya_taşınamıyor. - case_insensitive=büyük/kü.ük_harfe_duyarsız case_sensitive=büyük/küçük_harfe_duyarlı @@ -229,8 +217,6 @@ Close_window=Pencereyi_kapat Closed_library=Kapalı_veritabanı -Collapse_subtree=Altağacı_daralt - Color_codes_for_required_and_optional_fields=Zorunlu_ve_seçmeli_alanlar_için_renk_kodları Color_for_marking_incomplete_entries=Tamamlanmamış_girdileri_işaretlemek_için_renk @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=%0_dosya(lar)_yazılırken_hata. '%0'_exists._Overwrite_file?='%0'_mevcut._Dosyanın_üzerine_yazılsın_mı? Overwrite_file?=_Dosyanın_üzerine_yazılsın_mı? -Expand_subtree=Altağacı_genişlet - Export=Dışa_aktar Export_name=Adı_dışa_aktar @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Örtüşen_grupları_vurgula - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=İpucu\:_Yalnızca_belirli_alanları_aramak_için,_örneğin_şunu_giriniz\:

author\=smith_and_title\=electrical HTML_table=HTML_tablosu @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Bağımsız_grup\:_Seçildiğinde,_yalnızca_bu_grubun_girdilerini_göster -Initially_show_groups_tree_expanded=Başlangıçta_grup_ağacını_genişletilmiş_göster - Work_options=Çalışma_seçenekleri Insert=Ekle @@ -782,8 +762,6 @@ Modify=Değiştir modify_group=grubu_değiştir -Move=Taşı - Move_down=Aşağı_taşı Move_entries_in_group_selection_to_the_top=Grup_seçimindeki_girdileri_en_üste_taşı @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Lütfen_dizgenin_etiketini_giriniz Please_select_an_importer.=Lütfen_bir_içe_aktarıcı_seçiniz. -Please_select_exactly_one_group_to_move.=Lütfen_taşımak_için_yalnızca_bir_grup_seçiniz. - Possible_duplicate_entries=Olası_çift_nüsha_girdiler Possible_duplicate_of_existing_entry._Click_to_resolve.=Mevcut_girdinin_olası_çift_nüshası._Düzeltmek_için_tıklayınız. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?="%0"in_tüm_altgruplarını_sil? Remove_entry_from_import=İçe_aktarımdan_girdiyi_sil -Remove_entry_selection_from_this_group=Bu_gruptan_girdi_seçimini_sil +Remove_selected_entries_from_this_group= Remove_entry_type=Girdi_türünü_sil Remove_file_link_(DELETE)=Dosya_linkini_sil_(DELETE) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Girdileri_silerken_onaylama_ileti Show_description=Açıklamayı_göster -Show_dynamic_groups_in_italics=Dinamik_grupları_italik_biçimde_göster - Show_entries_not_in_group_selection=Girdileri_grup_seçiminde_gösterme Show_file_column=Dosya_sütununu_göster -Show_icons_for_groups=Gruplar_için_simgeler_göster Show_last_names_only=Yalnızca_soyadları_göster Show_names_unchanged=Adları_değiştirmeden_göster @@ -1513,7 +1486,6 @@ General_file_directory=Genel_dosya_dizini User-specific_file_directory=Kullanıcıya_özel_dosya_dizini Search_failed\:_illegal_search_expression=Arama_başarısız\:_uygunsuz_arama_dizgesi Show_ArXiv_column=ArXiv_sütununu_göster -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Herhangi_bir_mevcut_seçilmiş_grupça_içerilen_girdileri_içeren_grupları_vurgula You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Metin_alanına_1025-65535_aralığında_bir_tamsayı_girmelisiniz Automatically_open_browse_dialog_when_creating_new_file_link=Yeni_dosya_bağlantısını_oluştururken_gözatma_iletişim_kutusunu_otomatikman_aç diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 880c925f6d3..4cf9606c390 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Đường_dẫn_không_được Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Thêm_một_lớp_ĐịnhdạngNhập_tùy_biến_(được_biên_dịch)_từ_một_tập_tin-zip._ The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Tập_tin-zip_không_được_trùng_với_đường_dẫn_lớp_của_JabRef. -Add_entry_selection_to_this_group=Thêm_phép_chọn_mục_vào_nhóm_này +Add_selected_entries_to_this_group= Add_from_folder=Thêm_từ_thư_mục @@ -58,8 +58,6 @@ Add_from_JAR=Thêm_từ_tập_tin_JAR add_group=thêm_nhóm -Add_group=Thêm_nhóm - Add_new=Thêm_mới Add_subgroup=Thêm_nhóm_con @@ -107,8 +105,6 @@ Apply=Áp_dụng Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Các_đối_số_được_truyền_cho_phiên_JabRef_đang_chạy._Đang_tắt. -Assign_entry_selection_exclusively_to_this_group=Gán_phép_chọn_mục_chỉ_cho_nhóm_này - Assign_new_file=Gán_tập_tin_mới Assign_the_original_group's_entries_to_this_group?=Gán_các_mục_của_nhóm_ban_đầu_vào_nhóm_này? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Không_t Cannot_merge_this_change=Không_thể_gộp_thay_đổi_này -Cannot_move_group_"%0"_down.=Không_thể_chuyển_nhóm_"%0"_xuống. - -Cannot_move_group_"%0"_left.=Không_thể_chuyển_nhóm_"%0"_qua_trái. - -Cannot_move_group_"%0"_right.=Không_thể_chuyển_nhóm_"%0"_qua_phải. - -Cannot_move_group_"%0"_up.=Không_thể_chuyển_nhóm_"%0"_lên_trên. - case_insensitive=không_phân_biệt_chữ_hoa/thường case_sensitive=phân_biệt_chữ_hoa/thường @@ -229,8 +217,6 @@ Close_window=Đóng_cửa_sổ Closed_library=CSDL_được_đóng -Collapse_subtree=Thu_sơ_đồ_phụ_hình_cây_lại - Color_codes_for_required_and_optional_fields=Đánh_mã_màu_các_dữ_liệu_bắt_buộc_và_tùy_chọn Color_for_marking_incomplete_entries=Màu_để_đánh_dấu_các_mục_chưa_hoàn_tất @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=Lỗi_khi_đang_ghi_vào_tập_tin_%0. '%0'_exists._Overwrite_file?='%0'_đã_có._Ghi_đè_tập_tin_không? Overwrite_file?=Ghi_đè_tập_tin_không? -Expand_subtree=Mổ_rộng_sơ_đồ_cây_phụ - Export=Xuất Export_name=Xuất_tên @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=Tô_sáng_các_nhóm_gối_nhau - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=Gợi_ý\:_Để_chỉ_tìm_kiếm_các_dữ_liệu_đặc_thù,_nhập,_ví_dụ_như\:

author\=smith_and_title\=electrical HTML_table=Bảng_HTML @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=Nhóm_độc_lập\:_Khi_được_chọn,_chỉ_xem_các_mục_của_nhóm_này -Initially_show_groups_tree_expanded=Ban_đầu_hiển_thị_cây_sơ_đồ_nhóm_dạng_mở_rộng - Work_options=Các_tùy_chọn_làm_việc Insert=Chèn @@ -782,8 +762,6 @@ Modify=Điều_chỉnh modify_group=điều_chỉnh_nhóm -Move=Chuyển - Move_down=Chuyển_xuống Move_entries_in_group_selection_to_the_top=Chuyển_các_mục_trong_nhóm_được_chọn_lên_trên_cùng @@ -950,8 +928,6 @@ Please_enter_the_string's_label=Vui_lòng_nhập_nhãn_của_chuỗi Please_select_an_importer.=Vui_lòng_chọn_một_trình_nhập. -Please_select_exactly_one_group_to_move.=Vui_lòng_chọn_chính_xác_một_nhóm_cần_di_chuyển - Possible_duplicate_entries=Các_mục_có_thể_bị_trùng Possible_duplicate_of_existing_entry._Click_to_resolve.=Có_thể_mục_hiện_có_bị_trùng._Nhắp_chuột_để_giải. @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=Loại_bỏ_tất_cả_các_nhóm_con_của_"%0"? Remove_entry_from_import=Loại_bỏ_mục_khỏi_lệnh_nhập -Remove_entry_selection_from_this_group=Loại_bỏ_phép_chọn_mục_khỏi_nhóm_này +Remove_selected_entries_from_this_group= Remove_entry_type=Loại_bỏ_kiểu_mục Remove_file_link_(DELETE)=Loại_bỏ_đường_liên_kết_tập_tin_(XÓA) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=Hiển_thị_hộp_thoại_xác_n Show_description=Hiển_thị_mô_tả -Show_dynamic_groups_in_italics=Hiển_thị_các_nhóm_động_ở_dạng_chữ_nghiêng - Show_entries_not_in_group_selection=Hiển_thị_các_mục_không_ở_trong_phép_chọn_nhóm Show_file_column=Hiển_thị_cột_tập_tin -Show_icons_for_groups=Hiển_thị_các_biểu_tượng_của_nhóm Show_last_names_only=Chỉ_hiển_thị_Họ Show_names_unchanged=Hiển_thị_các_tên_không_bị_thay_đổi @@ -1513,7 +1486,6 @@ General_file_directory=Tổng_quát_thư_mục_tập_tin User-specific_file_directory=Thư_mục_tập_tin_của_người_sử_dụng_cụ_thể Search_failed\:_illegal_search_expression=Tìm_kiếm_thất_bại\:_biểu_thức_tìm_kiếm_bất_hợp_lệ Show_ArXiv_column=Hiển_thị_cột_ArXiv -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Làm_nổi_bật_nhóm_chứa_các_mục_có_nội_dung_trong_bất_cứ_nhóm_hiện_được_tuyển_chọn You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=Bạn_phải_nhập_giá_trị_nằm_trong_khoảng_cách_1025-65535_trong_các_dữ_liệu_văn_bản_cho Automatically_open_browse_dialog_when_creating_new_file_link=Mở_tự_động_hộp_thoại_khi_tạo_ra_đường_dẫn_tập_tin_mới diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index f527fe5f2df..5624511ab31 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -50,7 +50,7 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=该路径不需要在_JabRef_ Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=从一个_ZIP_压缩包中添加(编译好的)自定义导入类。 The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=该_ZIP_压缩包不需要在_JabRef_的_classpath_下。 -Add_entry_selection_to_this_group=添加选中记录到此分组 +Add_selected_entries_to_this_group= Add_from_folder=从文件夹中添加 @@ -58,8 +58,6 @@ Add_from_JAR=从_JAR_中添加 add_group=添加分组 -Add_group=添加分组 - Add_new=新建 Add_subgroup=添加子分组 @@ -107,8 +105,6 @@ Apply=应用 Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=参数传递给了正在执行的_JabRef_实例,关闭自身程序。 -Assign_entry_selection_exclusively_to_this_group=排它地分配记录到此分组 - Assign_new_file=分配新文件 Assign_the_original_group's_entries_to_this_group?=将原分组中的记录分配到此分组? @@ -169,14 +165,6 @@ Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=不生 Cannot_merge_this_change=无法合并该更改 -Cannot_move_group_"%0"_down.=无法下移分组_"%0"。 - -Cannot_move_group_"%0"_left.=无法左移分组_"%0"。 - -Cannot_move_group_"%0"_right.=无法右移分组_"%0"。 - -Cannot_move_group_"%0"_up.=无法上移分组_"%0"。 - case_insensitive=忽略大小写 case_sensitive=区分大小写 @@ -229,8 +217,6 @@ Close_window=关闭窗口 Closed_library=关闭数据库 -Collapse_subtree=折叠子树 - Color_codes_for_required_and_optional_fields=列表记录项的可选域和必选域用不同颜色显示 Color_for_marking_incomplete_entries=标记不完整记录的颜色 @@ -475,8 +461,6 @@ Error_writing_to_%0_file(s).=写入到_%0_文件错误。 '%0'_exists._Overwrite_file?='%0'_已存在,覆盖文件? Overwrite_file?=覆盖文件? -Expand_subtree=展开子树 - Export=导出 Export_name=导出名称 @@ -622,8 +606,6 @@ Empty_Marking= Empty_Underline= The_marked_area_does_not_contain_any_legible_text!= -Highlight_overlapping_groups=高亮显示有重叠记录的分组 - Hint\:_To_search_specific_fields_only,_enter_for_example\:

author\=smith_and_title\=electrical=提示\:_若想只搜索特定域的话,可以像这样写\:

author\=smith_and_title\=electrical HTML_table=HTML_表 @@ -677,8 +659,6 @@ Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_s Independent_group\:_When_selected,_view_only_this_group's_entries=独立分组:当分组被选中时,只显示属于此分组的记录 -Initially_show_groups_tree_expanded=初始时显示展开的分组树 - Work_options=工作选项 Insert=插入 @@ -782,8 +762,6 @@ Modify=修改 modify_group=修改分组 -Move=移动 - Move_down=下移 Move_entries_in_group_selection_to_the_top=移动选中分组的记录到顶部 @@ -950,8 +928,6 @@ Please_enter_the_string's_label=请输入简写字串的标签 Please_select_an_importer.=请选择一个导入器。 -Please_select_exactly_one_group_to_move.=请选中一个分组来移动。 - Possible_duplicate_entries=可能的重复记录 Possible_duplicate_of_existing_entry._Click_to_resolve.=可能与已存在记录重复,点击以解决此问题。 @@ -1013,7 +989,7 @@ Remove_all_subgroups_of_"%0"?=移除_"%0"_的所有子分组? Remove_entry_from_import=从导入中移除记录 -Remove_entry_selection_from_this_group=从该分组中移除记录 +Remove_selected_entries_from_this_group= Remove_entry_type=移除记录类型 Remove_file_link_(DELETE)=移除文件链接(删除) @@ -1151,13 +1127,10 @@ Show_confirmation_dialog_when_deleting_entries=删除多条记录时发出警告 Show_description=显示描述 -Show_dynamic_groups_in_italics=用_斜体_显示动态分组 - Show_entries_not_in_group_selection=显示那些在选中分组中的记录 Show_file_column=显示“文件”列 -Show_icons_for_groups=显示分组类型图标 Show_last_names_only=只显示“姓_(Lastname)” Show_names_unchanged=显示原始姓名字串 @@ -1513,7 +1486,6 @@ General_file_directory=生成文件目录 User-specific_file_directory=用户指定的文件目录 Search_failed\:_illegal_search_expression=搜索失败\:_不合法的搜索表达式 Show_ArXiv_column=显示_ArXiv_列 -Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=高亮显示包含选中分组中记录的分组 You_must_enter_an_integer_value_in_the_interval_1025-65535_in_the_text_field_for=请输入_1025-65535_之间的整数值。设置项: Automatically_open_browse_dialog_when_creating_new_file_link=创建新的文件链接时自动打开文件浏览对话框 diff --git a/src/test/java/org/jabref/CodeStyleTests.java b/src/test/java/org/jabref/CodeStyleTests.java index 3d61a5bbe27..7a1cef60a65 100644 --- a/src/test/java/org/jabref/CodeStyleTests.java +++ b/src/test/java/org/jabref/CodeStyleTests.java @@ -19,6 +19,6 @@ public void StringUtilClassIsSmall() throws Exception { Assert.assertTrue("StringUtil increased in size. " + "We try to keep this class as small as possible. " - + "Thus think twice if you add something to StringUtil.", lineCount <= 709); + + "Thus think twice if you add something to StringUtil.", lineCount <= 715); } } diff --git a/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java b/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java index 2b71b6bc3f1..281cf995790 100644 --- a/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java +++ b/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java @@ -3,6 +3,8 @@ import javafx.collections.FXCollections; import org.jabref.gui.StateManager; +import org.jabref.gui.util.CurrentThreadTaskExecutor; +import org.jabref.gui.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.groups.AbstractGroup; import org.jabref.model.groups.GroupHierarchyType; @@ -21,12 +23,14 @@ public class GroupNodeViewModelTest { private StateManager stateManager; private BibDatabaseContext databaseContext; private GroupNodeViewModel viewModel; + private TaskExecutor taskExecutor; @Before public void setUp() throws Exception { stateManager = mock(StateManager.class); when(stateManager.getSelectedEntries()).thenReturn(FXCollections.emptyObservableList()); databaseContext = new BibDatabaseContext(); + taskExecutor = new CurrentThreadTaskExecutor(); viewModel = getViewModelForGroup( new WordKeywordGroup("Test group", GroupHierarchyType.INDEPENDENT, "test", "search", true, ',', false)); @@ -51,6 +55,6 @@ public void isMatchedIfContainsPartOfSearchString() throws Exception { } private GroupNodeViewModel getViewModelForGroup(AbstractGroup group) { - return new GroupNodeViewModel(databaseContext, stateManager, group); + return new GroupNodeViewModel(databaseContext, stateManager, taskExecutor, group); } } diff --git a/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java b/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java index 9daa38ce34c..6f99caac98c 100644 --- a/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java +++ b/src/test/java/org/jabref/gui/groups/GroupTreeViewModelTest.java @@ -4,6 +4,8 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; +import org.jabref.gui.util.CurrentThreadTaskExecutor; +import org.jabref.gui.util.TaskExecutor; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.groups.AllEntriesGroup; @@ -17,18 +19,20 @@ public class GroupTreeViewModelTest { StateManager stateManager; GroupTreeViewModel groupTree; BibDatabaseContext databaseContext; + private TaskExecutor taskExecutor; @Before public void setUp() throws Exception { databaseContext = new BibDatabaseContext(); stateManager = new StateManager(); stateManager.activeDatabaseProperty().setValue(Optional.of(databaseContext)); - groupTree = new GroupTreeViewModel(stateManager, mock(DialogService.class)); + taskExecutor = new CurrentThreadTaskExecutor(); + groupTree = new GroupTreeViewModel(stateManager, mock(DialogService.class), taskExecutor); } @Test public void rootGroupIsAllEntriesByDefault() throws Exception { AllEntriesGroup allEntriesGroup = new AllEntriesGroup("All entries"); - assertEquals(new GroupNodeViewModel(databaseContext, stateManager, allEntriesGroup), groupTree.rootGroupProperty().getValue()); + assertEquals(new GroupNodeViewModel(databaseContext, stateManager, taskExecutor, allEntriesGroup), groupTree.rootGroupProperty().getValue()); } } diff --git a/src/test/java/org/jabref/model/DuplicateCheckTest.java b/src/test/java/org/jabref/logic/bibtex/DuplicateCheckTest.java similarity index 54% rename from src/test/java/org/jabref/model/DuplicateCheckTest.java rename to src/test/java/org/jabref/logic/bibtex/DuplicateCheckTest.java index c5a68e3b45d..ea4b7d42952 100644 --- a/src/test/java/org/jabref/model/DuplicateCheckTest.java +++ b/src/test/java/org/jabref/logic/bibtex/DuplicateCheckTest.java @@ -1,9 +1,11 @@ -package org.jabref.model; +package org.jabref.logic.bibtex; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibtexEntryTypes; +import org.jabref.model.entry.FieldName; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -12,6 +14,21 @@ public class DuplicateCheckTest { + private BibEntry simpleArticle; + private BibEntry unrelatedArticle; + + @Before + public void setUp() { + simpleArticle = new BibEntry(BibtexEntryTypes.ARTICLE.getName()) + .withField(FieldName.AUTHOR, "Single Author") + .withField(FieldName.TITLE, "A serious paper about something") + .withField(FieldName.YEAR, "2017"); + unrelatedArticle = new BibEntry(BibtexEntryTypes.ARTICLE.getName()) + .withField(FieldName.AUTHOR, "Completely Different") + .withField(FieldName.TITLE, "Holy Moly Uffdada und Trallalla") + .withField(FieldName.YEAR, "1992"); + } + @Test public void testDuplicateDetection() { BibEntry one = new BibEntry(BibtexEntryTypes.ARTICLE.getName()); @@ -79,4 +96,50 @@ public void testWordCorrelation() { assertEquals(0.78, (DuplicateCheck.correlateByWords(d2, d3)), 0.01); } + @Test + public void twoUnrelatedEntriesAreNoDuplicates() { + assertFalse(DuplicateCheck.isDuplicate(simpleArticle, unrelatedArticle, BibDatabaseMode.BIBTEX)); + } + + @Test + public void twoUnrelatedEntriesWithDifferentDoisAreNoDuplicates() { + simpleArticle.setField(FieldName.DOI, "10.1016/j.is.2004.02.002"); + unrelatedArticle.setField(FieldName.DOI, "10.1016/j.is.2004.02.00X"); + + assertFalse(DuplicateCheck.isDuplicate(simpleArticle, unrelatedArticle, BibDatabaseMode.BIBTEX)); + } + + @Test + public void twoUnrelatedEntriesWithEqualDoisAreDuplicates() { + simpleArticle.setField(FieldName.DOI, "10.1016/j.is.2004.02.002"); + unrelatedArticle.setField(FieldName.DOI, "10.1016/j.is.2004.02.002"); + + assertTrue(DuplicateCheck.isDuplicate(simpleArticle, unrelatedArticle, BibDatabaseMode.BIBTEX)); + } + + @Test + public void twoUnrelatedEntriesWithEqualPmidAreDuplicates() { + simpleArticle.setField(FieldName.PMID, "12345678"); + unrelatedArticle.setField(FieldName.PMID, "12345678"); + + assertTrue(DuplicateCheck.isDuplicate(simpleArticle, unrelatedArticle, BibDatabaseMode.BIBTEX)); + } + + @Test + public void twoUnrelatedEntriesWithEqualEprintAreDuplicates() { + simpleArticle.setField(FieldName.EPRINT, "12345678"); + unrelatedArticle.setField(FieldName.EPRINT, "12345678"); + + assertTrue(DuplicateCheck.isDuplicate(simpleArticle, unrelatedArticle, BibDatabaseMode.BIBTEX)); + } + + @Test + public void twoEntriesWithSameDoiButDifferentTypesAreDuplicates() { + simpleArticle.setField(FieldName.DOI, "10.1016/j.is.2004.02.002"); + BibEntry duplicateWithDifferentType = (BibEntry) simpleArticle.clone(); + duplicateWithDifferentType.setType(BibtexEntryTypes.INCOLLECTION); + + assertTrue(DuplicateCheck.isDuplicate(simpleArticle, duplicateWithDifferentType, BibDatabaseMode.BIBTEX)); + } + } diff --git a/src/test/java/org/jabref/logic/importer/WebFetchersTest.java b/src/test/java/org/jabref/logic/importer/WebFetchersTest.java index 7f179ef5fc5..0d09defd4a1 100644 --- a/src/test/java/org/jabref/logic/importer/WebFetchersTest.java +++ b/src/test/java/org/jabref/logic/importer/WebFetchersTest.java @@ -60,7 +60,7 @@ public void getSearchBasedFetchersReturnsAllFetcherDerivingFromSearchBasedFetche @Test public void getIdFetchersReturnsAllFetcherDerivingFromIdFetcher() throws Exception { - List idFetchers = WebFetchers.getIdFetchers(); + List idFetchers = WebFetchers.getIdFetchers(importFormatPreferences); Set> expected = reflections.getSubTypesOf(IdFetcher.class); expected.remove(IdParserFetcher.class); diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java index 47af5898eea..1e6a4545f6e 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java @@ -10,6 +10,7 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BiblatexEntryTypes; import org.jabref.model.entry.FieldName; +import org.jabref.model.entry.identifier.ArXivIdentifier; import org.jabref.testutils.category.FetcherTests; import org.junit.Assert; @@ -52,39 +53,40 @@ public void setUp() { } @Test - public void noIdentifierPresent() throws IOException { + public void findFullTextForEmptyEntryResultsEmptyOptional() throws IOException { assertEquals(Optional.empty(), finder.findFullText(entry)); } @Test(expected = NullPointerException.class) - public void rejectNullParameter() throws IOException { + public void findFullTextRejectsNullParameter() throws IOException { finder.findFullText(null); Assert.fail(); } @Test - public void findByDOI() throws IOException { + public void findFullTextByDOI() throws IOException { entry.setField(FieldName.DOI, "10.1529/biophysj.104.047340"); entry.setField(FieldName.TITLE, "Pause Point Spectra in DNA Constant-Force Unzipping"); assertEquals(Optional.of(new URL("http://arxiv.org/pdf/cond-mat/0406246v1")), finder.findFullText(entry)); + } @Test - public void findByEprint() throws IOException { + public void findFullTextByEprint() throws IOException { entry.setField("eprint", "1603.06570"); assertEquals(Optional.of(new URL("http://arxiv.org/pdf/1603.06570v1")), finder.findFullText(entry)); } @Test - public void findByEprintWithPrefix() throws IOException { + public void findFullTextByEprintWithPrefix() throws IOException { entry.setField("eprint", "arXiv:1603.06570"); assertEquals(Optional.of(new URL("http://arxiv.org/pdf/1603.06570v1")), finder.findFullText(entry)); } @Test - public void findByEprintWithUnknownDOI() throws IOException { + public void findFullTextByEprintWithUnknownDOI() throws IOException { entry.setField("doi", "10.1529/unknown"); entry.setField("eprint", "1603.06570"); @@ -92,21 +94,36 @@ public void findByEprintWithUnknownDOI() throws IOException { } @Test - public void notFoundByUnknownDOI() throws IOException { + public void findFullTextByTitle() throws IOException { + entry.setField("title", "Pause Point Spectra in DNA Constant-Force Unzipping"); + + assertEquals(Optional.of(new URL("http://arxiv.org/pdf/cond-mat/0406246v1")), finder.findFullText(entry)); + } + + @Test + public void findFullTextByTitleAndPartOfAuthor() throws IOException { + entry.setField("title", "Pause Point Spectra in DNA Constant-Force Unzipping"); + entry.setField("author", "Weeks and Lucks"); + + assertEquals(Optional.of(new URL("http://arxiv.org/pdf/cond-mat/0406246v1")), finder.findFullText(entry)); + } + + @Test + public void notFindFullTextByUnknownDOI() throws IOException { entry.setField("doi", "10.1529/unknown"); assertEquals(Optional.empty(), finder.findFullText(entry)); } @Test - public void notFoundByUnknownId() throws IOException { + public void notFindFullTextByUnknownId() throws IOException { entry.setField("eprint", "1234.12345"); assertEquals(Optional.empty(), finder.findFullText(entry)); } @Test - public void findByDOINotAvailableInCatalog() throws IOException { + public void findFullTextByDOINotAvailableInCatalog() throws IOException { entry.setField(FieldName.DOI, "10.1016/0370-2693(77)90015-6"); entry.setField(FieldName.TITLE, "Superspace formulation of supergravity"); @@ -173,4 +190,11 @@ public void searchWithMalformedIdThrowsException() throws Exception { expectedException.expectMessage("incorrect id format"); finder.performSearchById("123412345"); } + + @Test + public void searchIdentifierForSlicePaper() throws Exception { + sliceTheoremPaper.clearField(FieldName.EPRINT); + + assertEquals(ArXivIdentifier.parse("1405.2249v1"), finder.findIdentifier(sliceTheoremPaper)); + } } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/IsbnViaChimboriFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/IsbnViaChimboriFetcherTest.java index 3857d2e4d18..4ee3b955b34 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/IsbnViaChimboriFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/IsbnViaChimboriFetcherTest.java @@ -28,7 +28,8 @@ public void setUp() { bibEntry.setField("year", "2008"); bibEntry.setField("author", "Joshua Bloch"); bibEntry.setField("isbn", "978-0321356680"); - bibEntry.setField("url", "https://www.amazon.com/Effective-Java-Joshua-Bloch-ebook/dp/B00B8V09HY%3FSubscriptionId%3D0JYN1NVW651KCA56C102%26tag%3Dtechkie-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB00B8V09HY"); + bibEntry.setField("url", + "https://www.amazon.com/Effective-Java-Joshua-Bloch-ebook/dp/B00B8V09HY?SubscriptionId=0JYN1NVW651KCA56C102&tag=techkie-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B00B8V09HY"); fetcher = new IsbnViaChimboriFetcher(JabRefPreferences.getInstance().getImportFormatPreferences()); } @@ -65,7 +66,8 @@ public void authorsAreCorrectlyFormatted() throws Exception { bibEntry.setField("year", "2015"); bibEntry.setField("author", "Marlon Dumas and Marcello La Rosa and Jan Mendling and Hajo A. Reijers"); bibEntry.setField("isbn", "3642434738"); - bibEntry.setField("url", "https://www.amazon.com/Fundamentals-Business-Process-Management-Marlon/dp/3642434738%3FSubscriptionId%3D0JYN1NVW651KCA56C102%26tag%3Dtechkie-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D3642434738"); + bibEntry.setField("url", + "https://www.amazon.com/Fundamentals-Business-Process-Management-Marlon/dp/3642434738?SubscriptionId=0JYN1NVW651KCA56C102&tag=techkie-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=3642434738"); Optional fetchedEntry = fetcher.performSearchById("3642434738"); assertEquals(Optional.of(bibEntry), fetchedEntry); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java index 58cebf7bf2e..89013c0ed58 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java @@ -648,12 +648,12 @@ public void parseRecognizesDuplicateBibtexKeys() throws IOException { } @Test - public void parseWarnsAboutEntryWithoutBibtexKey() throws IOException { + public void parseNotWarnsAboutEntryWithoutBibtexKey() throws IOException { ParserResult result = parser .parse(new StringReader("@article{,author={Ed von Test}}")); - assertTrue(result.hasWarnings()); + assertFalse(result.hasWarnings()); Collection c = result.getDatabase().getEntries(); diff --git a/src/test/java/org/jabref/logic/msbib/MsBibAuthorTest.java b/src/test/java/org/jabref/logic/msbib/MsBibAuthorTest.java new file mode 100644 index 00000000000..9a7dd384ca8 --- /dev/null +++ b/src/test/java/org/jabref/logic/msbib/MsBibAuthorTest.java @@ -0,0 +1,48 @@ +package org.jabref.logic.msbib; + +import org.jabref.model.entry.Author; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MsBibAuthorTest { + + @Test + public void testGetFirstName() { + Author author = new Author("Gustav Peter Johann", null, null, "Bach", null); + MsBibAuthor msBibAuthor = new MsBibAuthor(author); + assertEquals("Gustav", msBibAuthor.getFirstName()); + } + + @Test + public void testGetMiddleName() { + Author author = new Author("Gustav Peter Johann", null, null, "Bach", null); + MsBibAuthor msBibAuthor = new MsBibAuthor(author); + assertEquals("Peter Johann", msBibAuthor.getMiddleName()); + } + + @Test + public void testGetNoMiddleName() { + + Author author = new Author("Gustav", null, null, "Bach", null); + MsBibAuthor msBibAuthor = new MsBibAuthor(author); + assertEquals(null, msBibAuthor.getMiddleName()); + } + + @Test + public void testGetNoFirstName() { + + Author author = new Author(null, null, null, "Bach", null); + MsBibAuthor msBibAuthor = new MsBibAuthor(author); + assertEquals(null, msBibAuthor.getMiddleName()); + } + + @Test + public void testGetLastName() { + Author author = new Author("Gustav Peter Johann", null, null, "Bach", null); + MsBibAuthor msBibAuthor = new MsBibAuthor(author); + assertEquals("Bach", msBibAuthor.getLastName()); + } + +} diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest3.xml b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest3.xml index 703feb72938..f5a6955a364 100644 --- a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest3.xml +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest3.xml @@ -1,4 +1,4 @@ - + 0 diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest7.xml b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest7.xml index a7a386f6f55..0dd0135497c 100644 --- a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest7.xml +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest7.xml @@ -14,9 +14,12 @@ Czarnecki -and Orłowski, Cezary Adam + +Orłowski +Cezary + diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestCorporateAuthor.bib b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestCorporateAuthor.bib new file mode 100644 index 00000000000..3e8fa949685 --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestCorporateAuthor.bib @@ -0,0 +1,10 @@ +% Encoding: UTF-8 + +@Article{Test, + author = {{JabRef Developers}}, + title = {Test}, + journaltitle = {Test}, + year = {2012}, +} + +@Comment{jabref-meta: databaseType:biblatex;} diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestCorporateAuthor.xml b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestCorporateAuthor.xml new file mode 100644 index 00000000000..30f295dbe36 --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestCorporateAuthor.xml @@ -0,0 +1,16 @@ + + + +2012 +article +JournalArticle +Test +Test + + +JabRef Developers + + +Test + + diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDay.bib b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDay.bib new file mode 100644 index 00000000000..1dda42f4e01 --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDay.bib @@ -0,0 +1,8 @@ +% Encoding: UTF-8 + +@TechReport{, + author = {Sam and jason}, + date = {2002-07-03}, +} + +@Comment{jabref-meta: databaseType:bibtex;} diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDay.xml b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDay.xml new file mode 100644 index 00000000000..b3d1554f78a --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDay.xml @@ -0,0 +1,23 @@ + + + +techreport +Report + + + + +Sam + + +jason + + + + +2002 +7 +3 +Tech. rep. + + diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/MsBibPatent.bib b/src/test/resources/org/jabref/logic/importer/fileformat/MsBibPatent.bib index 59da8f86d2a..179ad054558 100644 --- a/src/test/resources/org/jabref/logic/importer/fileformat/MsBibPatent.bib +++ b/src/test/resources/org/jabref/logic/importer/fileformat/MsBibPatent.bib @@ -1,7 +1,7 @@ % Encoding: UTF-8 @patent{Lincoln1978, - author = {Abraham Lincoln}, + author = {Lincoln, Abraham}, title = {The Vampire hunter}, number = {12345677}, year = {1978},