diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 04dcd12dfe1..7926baf221c 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -13,6 +13,10 @@ Steps to reproduce: -``` -Put the excerpt of the log file here -``` +
+ Log File + + ``` + Paste an excerpt of your log file here + ``` +
diff --git a/.gitignore b/.gitignore index 437e861ddb7..d901b0dbeff 100644 --- a/.gitignore +++ b/.gitignore @@ -269,3 +269,4 @@ gradle-app.setting # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 # gradle/wrapper/gradle-wrapper.properties +scenicView.properties diff --git a/CHANGELOG.md b/CHANGELOG.md index bd44b24218c..6a6d45b3ee9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,15 +11,27 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ## [Unreleased] ### Changed -- Continued to redesign the user interface: this time the editor got a fresh coat of paint: +- We moved the `adsurl` field to `url` field when fetching with the ADS fetcher. +- We continued to improve the new groups interface: + - You can now again select multiple groups (and a few related settings were added to the preferences) [#2786](https://github.com/JabRef/jabref/issues/2786). + - We further improved performance of group operations, especially of the new filter feature [#2852](https://github.com/JabRef/jabref/issues/2852). + - It is now possible to resort groups using drag & drop [#2785](https://github.com/JabRef/jabref/issues/2785). +- The entry editor got a fresh coat of paint: + - Homogenize the size of text fields. - The buttons were changed to icons. + - Completely new interface to add or modify linked files. - Removed the hidden feature that a double click in the editor inserted the current date. - All authors and editors are separated using semicolons when exporting to csv. [#2762](https://github.com/JabRef/jabref/issues/2762) -- Improved wording of "Show recommendationns: into "Show 'Related Articles' tab" in the preferences +- Improved wording of "Show recommendations: into "Show 'Related Articles' tab" in the preferences +- We added integration of the Library of Congress catalog as a fetcher based on the [LCCN identifier](https://en.wikipedia.org/wiki/Library_of_Congress_Control_Number). [Feature request 636 in the forum](http://discourse.jabref.org/t/loc-marc-mods-connection/636) ### Fixed - We fixed the IEEE Xplore web search functionality [#2789](https://github.com/JabRef/jabref/issues/2789) - We fixed an error in the CrossRef fetcher that occurred if one of the fetched entries had no title +- We fixed an issue that prevented new entries to be automatically assigned to the currently selected group [#2783](https://github.com/JabRef/jabref/issues/2783). +- We fixed a bug that only allowed parsing positive timezones from a FileAnnotation [#2839](https://github.com/JabRef/jabref/issues/22839) +- We fixed a bug that did not allow the correct re-export of the MS-Office XML field `msbib-accessed` with a different date format [#2859](https://github.com/JabRef/jabref/issues/2859). + ### Removed diff --git a/LICENSE.md b/LICENSE.md index 5a78e5477f3..8ae99528256 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,26 +1,21 @@ -The MIT License (MIT) -===================== +MIT License Copyright © 2003-2016 [JabRef Authors](https://github.com/JabRef/jabref/blob/master/AUTHORS) -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the “Software”), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/build.gradle b/build.gradle index ce8a296a86f..dd9b49ef43b 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,7 @@ install4j { repositories { + mavenLocal() jcenter() maven { url "https://oss.sonatype.org/content/groups/public" } maven { url "https://repo.eclipse.org/content/repositories/paho-snapshots/" } @@ -113,6 +114,7 @@ dependencies { compile 'de.codecentric.centerdevice:javafxsvg:1.2.1' compile 'org.controlsfx:controlsfx:8.40.12' compile 'org.fxmisc.easybind:easybind:1.0.3' + compile 'net.corda:jfx:0.11.0' compile 'org.fxmisc.flowless:flowless:0.5.2' compile 'de.jensd:fontawesomefx-materialdesignfont:1.7.22-4' diff --git a/external-libraries.txt b/external-libraries.txt index eb8ad861aa7..182d1431c1e 100644 --- a/external-libraries.txt +++ b/external-libraries.txt @@ -131,12 +131,17 @@ URL: http://fxexperience.com/controlsfx/ License: BSD-3-Clause Id: org.fx.misc.easybin:easybind -Projekt: EasyBind +Project: EasyBind URL: https://github.com/TomasMikula/EasyBind License: BSD-2-Clause +Id: net.corda:jfx +Project: Corda +URL: https://github.com/corda/corda/tree/master/client/jfx +License: Apache-2.0 + Id: org.fxmisc.flowless:flowless -Projekt: Flowless +Project: Flowless URL: https://github.com/TomasMikula/Flowless License: BSD-2-Clause @@ -151,7 +156,7 @@ URL: https://github.com/google/gson License: Apache-2.0 Id: de.jensd:fontawesomefx-materialdesignfont -Projekt: FontAwesomeFX +Project: FontAwesomeFX URL: https://bitbucket.org/Jerady/fontawesomefx License: Apache-2.0 diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index 1715352d0f3..b7fc538f6df 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -26,7 +26,6 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.TimerTask; import java.util.stream.Collectors; import javax.swing.AbstractAction; @@ -37,7 +36,6 @@ import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; -import javax.swing.tree.TreePath; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; @@ -69,8 +67,6 @@ import org.jabref.gui.filelist.FileListEntry; import org.jabref.gui.filelist.FileListTableModel; import org.jabref.gui.groups.GroupAddRemoveDialog; -import org.jabref.gui.groups.GroupSelector; -import org.jabref.gui.groups.GroupTreeNodeViewModel; import org.jabref.gui.importer.actions.AppendDatabaseAction; import org.jabref.gui.journals.AbbreviateAction; import org.jabref.gui.journals.UnabbreviateAction; @@ -1313,9 +1309,6 @@ public void actionPerformed(ActionEvent e) { @Override public void keyPressed(KeyEvent e) { final int keyCode = e.getKeyCode(); - final TreePath path = frame.getGroupSelector().getSelectionPath(); - final GroupTreeNodeViewModel node = path == null ? null : (GroupTreeNodeViewModel) path - .getLastPathComponent(); if (e.isControlDown()) { switch (keyCode) { @@ -1479,7 +1472,6 @@ public void showEntry(final BibEntry be) { showEntryEditor(entryEditor); newEntryShowing(be); - setEntryEditorEnabled(true); // Make sure it is enabled. } /** @@ -1905,10 +1897,6 @@ public BibDatabaseContext getBibDatabaseContext() { return this.bibDatabaseContext; } - public GroupSelector getGroupSelector() { - return frame.getGroupSelector(); - } - public boolean isUpdatedExternally() { return updatedExternally; } @@ -2121,68 +2109,18 @@ public void searchAndOpen() { } private class GroupTreeListener { - - private final Runnable task = new Runnable() { - - @Override - public void run() { - // Update group display (for example to reflect that the number of contained entries has changed) - frame.getGroupSelector().revalidateGroups(); - } - }; - - /** - * Only access when you have the lock of the task instance - * - * Guarded by "task" - */ - private TimerTask timerTask = new TimerTask() { - - @Override - public void run() { - task.run(); - } - }; - @Subscribe public void listen(EntryAddedEvent addedEntryEvent) { // if the added entry is an undo don't add it to the current group if (addedEntryEvent.getEntryEventSource() == EntryEventSource.UNDO) { - scheduleUpdate(); return; } // Automatically add new entry to the selected group (or set of groups) - if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP) - && frame.getGroupSelector().getToggleAction().isSelected()) { + if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)) { final List entries = Collections.singletonList(addedEntryEvent.getBibEntry()); - final TreePath[] selection = frame.getGroupSelector().getGroupsTree().getSelectionPaths(); - if (selection != null) { - // it is possible that the user selected nothing. Therefore, checked for "!= null" - for (final TreePath tree : selection) { - ((GroupTreeNodeViewModel) tree.getLastPathComponent()).addEntriesToGroup(entries); - } - } - SwingUtilities.invokeLater(() -> BasePanel.this.getGroupSelector().valueChanged(null)); - } - - scheduleUpdate(); - } - - private void scheduleUpdate() { - // This is a quickfix/dirty hack. - // a better solution would be using RxJava or something reactive instead - // nevertheless it works correctly - synchronized (task) { - timerTask.cancel(); - timerTask = new TimerTask() { - - @Override - public void run() { - task.run(); - } - }; - JabRefExecutorService.INSTANCE.submit(timerTask, 200); + Globals.stateManager.getSelectedGroup(bibDatabaseContext).forEach( + selectedGroup -> selectedGroup.addEntriesToGroup(entries)); } } } diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index f12e7ff22c7..27b6ceced3a 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -91,7 +91,7 @@ import org.jabref.gui.exporter.SaveDatabaseAction; import org.jabref.gui.externalfiletype.ExternalFileTypeEditor; import org.jabref.gui.groups.EntryTableTransferHandler; -import org.jabref.gui.groups.GroupSelector; +import org.jabref.gui.groups.GroupSidePane; import org.jabref.gui.help.AboutAction; import org.jabref.gui.help.HelpAction; import org.jabref.gui.importer.ImportCustomizationDialog; @@ -462,7 +462,7 @@ public void actionPerformed(ActionEvent e) { private PushToApplications pushApplications; private GeneralFetcher generalFetcher; private OpenOfficePanel openOfficePanel; - private GroupSelector groupSelector; + private GroupSidePane groupSidePane; private int previousTabCount = -1; private JMenu newSpec; @@ -632,7 +632,7 @@ public void windowClosing(WindowEvent e) { currentBasePanel.getPreviewPanel().updateLayout(); - groupSelector.getToggleAction().setSelected(sidePaneManager.isComponentVisible(GroupSelector.class)); + groupSidePane.getToggleAction().setSelected(sidePaneManager.isComponentVisible(GroupSidePane.class)); previewToggle.setSelected(Globals.prefs.getPreviewPreferences().isPreviewPanelEnabled()); generalFetcher.getToggleAction().setSelected(sidePaneManager.isComponentVisible(GeneralFetcher.class)); openOfficePanel.getToggleAction().setSelected(sidePaneManager.isComponentVisible(OpenOfficeSidePanel.class)); @@ -720,11 +720,11 @@ public void setWindowTitle() { private void initSidePane() { sidePaneManager = new SidePaneManager(this); - groupSelector = new GroupSelector(this, sidePaneManager); + groupSidePane = new GroupSidePane(this, sidePaneManager); openOfficePanel = new OpenOfficePanel(this, sidePaneManager); generalFetcher = new GeneralFetcher(this, sidePaneManager); - sidePaneManager.register(groupSelector); + sidePaneManager.register(groupSidePane); } /** @@ -1153,10 +1153,10 @@ private void fillMenu() { } mb.add(search); - groups.add(new JCheckBoxMenuItem(groupSelector.getToggleAction())); + groups.add(new JCheckBoxMenuItem(groupSidePane.getToggleAction())); if (prefs.getBoolean(JabRefPreferences.GROUP_SIDEPANE_VISIBLE)) { - sidePaneManager.register(groupSelector); - sidePaneManager.show(GroupSelector.class); + sidePaneManager.register(groupSidePane); + sidePaneManager.show(GroupSidePane.class); } groups.addSeparator(); @@ -1178,7 +1178,7 @@ private void fillMenu() { view.addSeparator(); view.add(new JCheckBoxMenuItem(toggleToolbar)); view.add(new JCheckBoxMenuItem(enableToggle(generalFetcher.getToggleAction()))); - view.add(new JCheckBoxMenuItem(groupSelector.getToggleAction())); + view.add(new JCheckBoxMenuItem(groupSidePane.getToggleAction())); view.add(new JCheckBoxMenuItem(togglePreview)); view.add(showPdvViewer); view.add(getNextPreviewStyleAction()); @@ -1377,7 +1377,7 @@ private void createToolBar() { previewToggle = new JToggleButton(togglePreview); tlb.addJToggleButton(previewToggle); - tlb.addJToggleButton(new JToggleButton(groupSelector.getToggleAction())); + tlb.addJToggleButton(new JToggleButton(groupSidePane.getToggleAction())); tlb.addSeparator(); @@ -1404,7 +1404,7 @@ private void initActions() { openDatabaseOnlyActions.addAll(Arrays.asList(manageSelectors, mergeDatabaseAction, newSubDatabaseAction, save, copyPreview, saveAs, saveSelectedAs, saveSelectedAsPlain, editModeAction, undo, redo, cut, deleteEntry, copy, paste, mark, markSpecific, unmark, unmarkAll, rankSubMenu, editEntry, selectAll, copyKey, copyCiteKey, copyKeyAndTitle, copyKeyAndLink, editPreamble, editStrings, - groupSelector.getToggleAction(), makeKeyAction, normalSearch, generalFetcher.getToggleAction(), mergeEntries, cleanupEntries, exportToClipboard, replaceAll, + groupSidePane.getToggleAction(), makeKeyAction, normalSearch, generalFetcher.getToggleAction(), mergeEntries, cleanupEntries, exportToClipboard, replaceAll, sendAsEmail, downloadFullText, lookupIdentifiers, writeXmpAction, openOfficePanel.getToggleAction(), findUnlinkedFiles, addToGroup, removeFromGroup, moveToGroup, autoLinkFile, resolveDuplicateKeys, openUrl, openFolder, openFile, togglePreview, dupliCheck, autoSetFile, newEntryAction, newSpec, customizeAction, plainTextImport, getMassSetField(), getManageKeywords(), @@ -1918,10 +1918,6 @@ public SidePaneManager getSidePaneManager() { return sidePaneManager; } - public GroupSelector getGroupSelector() { - return groupSelector; - } - public void setPreviewToggle(boolean enabled) { previewToggle.setSelected(enabled); } diff --git a/src/main/java/org/jabref/gui/MappedList.java b/src/main/java/org/jabref/gui/MappedList.java deleted file mode 100644 index ca43019229d..00000000000 --- a/src/main/java/org/jabref/gui/MappedList.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.jabref.gui; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import javafx.collections.ListChangeListener.Change; -import javafx.collections.ObservableList; -import javafx.collections.transformation.TransformationList; - -/** - * Mapped view of a {@link ObservableList}. - * - * It is a planned to include a similar version of this class in the Java core, see - * https://bugs.openjdk.java.net/browse/JDK-8091967 - * Until it is available in Java, we use a own implementation. - * Source code taken from - * https://gist.github.com/TomasMikula/8883719#file-mappedlist-java-L1 - * - * @param source type - * @param target type - */ -public class MappedList extends TransformationList { - - private final Function mapper; - - public MappedList(ObservableList source, Function mapper) { - super(source); - this.mapper = mapper; - } - - @Override - public int getSourceIndex(int index) { - return index; - } - - @Override - public F get(int index) { - return mapper.apply(getSource().get(index)); - } - - @Override - public int size() { - return getSource().size(); - } - - @Override - protected void sourceChanged(Change c) { - fireChange(new Change(this) { - - @Override - public boolean wasAdded() { - return c.wasAdded(); - } - - @Override - public boolean wasRemoved() { - return c.wasRemoved(); - } - - @Override - public boolean wasReplaced() { - return c.wasReplaced(); - } - - @Override - public boolean wasUpdated() { - return c.wasUpdated(); - } - - @Override - public boolean wasPermutated() { - return c.wasPermutated(); - } - - @Override - public int getPermutation(int i) { - return c.getPermutation(i); - } - - @Override - protected int[] getPermutation() { - // This method is only called by the superclass methods - // wasPermutated() and getPermutation(int), which are - // both overriden by this class. There is no other way - // this method can be called. - throw new AssertionError("Unreachable code"); - } - - @Override - public List getRemoved() { - ArrayList res = new ArrayList<>(c.getRemovedSize()); - for (E e: c.getRemoved()) { - res.add(mapper.apply(e)); - } - return res; - } - - @Override - public int getFrom() { - return c.getFrom(); - } - - @Override - public int getTo() { - return c.getTo(); - } - - @Override - public boolean next() { - return c.next(); - } - - @Override - public void reset() { - c.reset(); - } - }); - } -} diff --git a/src/main/java/org/jabref/gui/StateManager.java b/src/main/java/org/jabref/gui/StateManager.java index 399e6edab66..c09a7024372 100644 --- a/src/main/java/org/jabref/gui/StateManager.java +++ b/src/main/java/org/jabref/gui/StateManager.java @@ -7,8 +7,8 @@ import javafx.beans.binding.Bindings; import javafx.beans.property.ObjectProperty; -import javafx.beans.property.ReadOnlyObjectProperty; -import javafx.beans.property.ReadOnlyObjectWrapper; +import javafx.beans.property.ReadOnlyListProperty; +import javafx.beans.property.ReadOnlyListWrapper; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -33,21 +33,21 @@ public class StateManager { private final ObjectProperty> activeDatabase = new SimpleObjectProperty<>(Optional.empty()); - private final ReadOnlyObjectWrapper> activeGroup = new ReadOnlyObjectWrapper<>(Optional.empty()); + private final ReadOnlyListWrapper activeGroups = new ReadOnlyListWrapper<>(FXCollections.observableArrayList()); private final ObservableList selectedEntries = FXCollections.observableArrayList(); - private final ObservableMap selectedGroups = FXCollections.observableHashMap(); + private final ObservableMap> selectedGroups = FXCollections.observableHashMap(); public StateManager() { MonadicBinding currentDatabase = EasyBind.map(activeDatabase, database -> database.orElse(null)); - activeGroup.bind(EasyBind.map(Bindings.valueAt(selectedGroups, currentDatabase), Optional::ofNullable)); + activeGroups.bind(Bindings.valueAt(selectedGroups, currentDatabase)); } public ObjectProperty> activeDatabaseProperty() { return activeDatabase; } - public ReadOnlyObjectProperty> activeGroupProperty() { - return activeGroup.getReadOnlyProperty(); + public ReadOnlyListProperty activeGroupProperty() { + return activeGroups.getReadOnlyProperty(); } public ObservableList getSelectedEntries() { @@ -58,16 +58,17 @@ public void setSelectedEntries(List newSelectedEntries) { selectedEntries.setAll(newSelectedEntries); } - public void setSelectedGroup(BibDatabaseContext database, GroupTreeNode newSelectedGroup) { - Objects.requireNonNull(newSelectedGroup); - selectedGroups.put(database, newSelectedGroup); + public void setSelectedGroups(BibDatabaseContext database, List newSelectedGroups) { + Objects.requireNonNull(newSelectedGroups); + selectedGroups.put(database, FXCollections.observableArrayList(newSelectedGroups)); } - public Optional getSelectedGroup(BibDatabaseContext database) { - return Optional.ofNullable(selectedGroups.get(database)); + public ObservableList getSelectedGroup(BibDatabaseContext database) { + ObservableList selectedGroupsForDatabase = selectedGroups.get(database); + return selectedGroupsForDatabase != null ? selectedGroupsForDatabase : FXCollections.observableArrayList(); } - public void clearSelectedGroup(BibDatabaseContext database) { + public void clearSelectedGroups(BibDatabaseContext database) { selectedGroups.remove(database); } diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index f4d1de6e529..1248848e91a 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -80,6 +80,7 @@ import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.undo.UndoableKeyChange; import org.jabref.gui.undo.UndoableRemoveEntry; +import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.component.CheckBoxMessage; import org.jabref.gui.util.component.VerticalLabelUI; import org.jabref.logic.TypedBibEntry; @@ -239,7 +240,7 @@ public EntryEditor(JabRefFrame frame, BasePanel panel, BibEntry entry) { tabbed.setSelectedIndex(sourceIndex); } - updateAllFields(); + DefaultTaskExecutor.runInJavaFXThread(() -> setEntry(entry)); } private static String getSourceString(BibEntry entry, BibDatabaseMode type) throws IOException { @@ -456,6 +457,17 @@ public BibEntry getEntry() { return entry; } + /** + * Sets all the text areas according to the shown entry. + */ + private void setEntry(BibEntry entry) { + for (Object tab : tabs) { + if (tab instanceof EntryEditorTab) { + ((EntryEditorTab) tab).setEntry(entry); + } + } + } + public BibDatabase getDatabase() { return panel.getDatabase(); } @@ -713,19 +725,6 @@ public boolean isEnabled() { return source.isEnabled(); } - /** - * Sets the enabled status of all text fields of the entry editor. - */ - @Override - public void setEnabled(boolean enabled) { - for (Object tab : tabs) { - if (tab instanceof EntryEditorTab) { - ((EntryEditorTab) tab).setEnabled(enabled); - } - } - source.setEnabled(enabled); - } - /** * Makes sure the current edit is stored. */ @@ -899,17 +898,6 @@ private void setField(String fieldName, String newFieldData) { } } - /** - * Sets all the text areas according to the shown entry. - */ - private void updateAllFields() { - for (Object tab : tabs) { - if (tab instanceof EntryEditorTab) { - ((EntryEditorTab) tab).setEntry(entry); - } - } - } - public void updateAllContentSelectors() { if (!contentSelectors.isEmpty()) { for (FieldContentSelector contentSelector : contentSelectors) { @@ -1103,7 +1091,6 @@ public void stateChanged(ChangeEvent event) { } if (activeTab instanceof EntryEditorTab) { - ((EntryEditorTab) activeTab).updateAll(); activateVisible(); } diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditorTab.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditorTab.java index ea20743f872..e127930c9a0 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditorTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditorTab.java @@ -1,24 +1,18 @@ package org.jabref.gui.entryeditor; -import java.awt.AWTKeyStroke; import java.awt.Component; -import java.awt.KeyboardFocusManager; -import java.awt.event.FocusListener; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.stream.Stream; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; -import javax.swing.KeyStroke; import javafx.embed.swing.JFXPanel; import javafx.scene.Node; @@ -36,8 +30,6 @@ import org.jabref.gui.FXDialogService; import org.jabref.gui.GUIGlobals; import org.jabref.gui.JabRefFrame; -import org.jabref.gui.autocompleter.AutoCompleteListener; -import org.jabref.gui.fieldeditors.FieldEditor; import org.jabref.gui.fieldeditors.FieldEditorFX; import org.jabref.gui.fieldeditors.FieldEditors; import org.jabref.gui.fieldeditors.FieldNameLabel; @@ -58,7 +50,6 @@ class EntryEditorTab { private final List fields; private final EntryEditor parent; private final Map editors = new LinkedHashMap<>(); - private final FocusListener fieldListener = new EntryEditorTabFocusListener(this); private final String tabTitle; private final JabRefFrame frame; private final BasePanel basePanel; @@ -256,15 +247,11 @@ private String getPrompt(String field) { return ""; } - private BibEntry getEntry() { - return entry; - } - public void setEntry(BibEntry entry) { try { updating = true; for (FieldEditorFX editor : editors.values()) { - DefaultTaskExecutor.runInJavaFXThread(() -> editor.bindToEntry(entry)); + editor.bindToEntry(entry); } this.entry = entry; } finally { @@ -272,41 +259,11 @@ public void setEntry(BibEntry entry) { } } - private boolean isFieldModified(FieldEditor fieldEditor) { - String text = fieldEditor.getText().trim(); - - if (text.isEmpty()) { - return getEntry().hasField(fieldEditor.getFieldName()); - } else { - return !Optional.of(text).equals(getEntry().getField(fieldEditor.getFieldName())); - } - } - - public void markIfModified(FieldEditor fieldEditor) { - // Only mark as changed if not already is and the field was indeed modified - if (!updating && !basePanel.isModified() && isFieldModified(fieldEditor)) { - markBaseChanged(); - } - } - - private void markBaseChanged() { - basePanel.markBaseChanged(); - } - /** * Only sets the activeField variable but does not focus it. *

* If you want to focus it call {@link #focus()} afterwards. */ - // TODO: Reenable or delete this - //public void setActive(FieldEditor fieldEditor) { - // activeField = fieldEditor; - //} - - //public FieldEditor getActive() { - // return activeField; - //} - public void setActive(String fieldName) { if (editors.containsKey(fieldName)) { activeField = editors.get(fieldName); @@ -323,13 +280,6 @@ public void focus() { } } - /** - * Reset all fields from the data in the BibEntry. - */ - public void updateAll() { - setEntry(getEntry()); - } - public boolean updateField(String field, String content) { if (!editors.containsKey(field)) { return false; @@ -358,15 +308,6 @@ public boolean updateField(String field, String content) { return true; } - public void setEnabled(boolean enabled) { - /* - // TODO: Reenable this - for (FieldEditor editor : editors.values()) { - editor.setEnabled(enabled); - } - */ - } - public Component getPane() { return panel; } @@ -402,40 +343,4 @@ private void setupKeyBindings(final InputMap inputMap, final ActionMap actionMap inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.PREVIOUS_TAB), "prevtab"); actionMap.put("prevtab", this.frame.prevTab); } - - /** - * Set up key bindings and focus listener for the FieldEditor. - * - * @param component - */ - private void setupJTextComponent(final JComponent component, final AutoCompleteListener autoCompleteListener) { - - // Here we add focus listeners to the component. The funny code is because we need - // to guarantee that the AutoCompleteListener - if used - is called before fieldListener - // on a focus lost event. The AutoCompleteListener is responsible for removing any - // current suggestion when focus is lost, and this must be done before fieldListener - // stores the current edit. Swing doesn't guarantee the order of execution of event - // listeners, so we handle this by only adding the AutoCompleteListener and telling - // it to call fieldListener afterwards. If no AutoCompleteListener is used, we - // add the fieldListener normally. - if (autoCompleteListener == null) { - component.addFocusListener(fieldListener); - } else { - component.addKeyListener(autoCompleteListener); - component.addFocusListener(autoCompleteListener); - autoCompleteListener.setNextFocusListener(fieldListener); - } - - setupKeyBindings(component.getInputMap(JComponent.WHEN_FOCUSED), component.getActionMap()); - - Set keys = new HashSet<>( - component.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)); - keys.clear(); - keys.add(AWTKeyStroke.getAWTKeyStroke("pressed TAB")); - component.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys); - keys = new HashSet<>(component.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)); - keys.clear(); - keys.add(KeyStroke.getKeyStroke("shift pressed TAB")); - component.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys); - } } diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditorTabFocusListener.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditorTabFocusListener.java deleted file mode 100644 index c0b0bcfe299..00000000000 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditorTabFocusListener.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.jabref.gui.entryeditor; - -import java.awt.Component; -import java.awt.Rectangle; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; - -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.JTextComponent; - -import org.jabref.gui.fieldeditors.FieldEditor; - - -/** - * Focus listener that fires the storeFieldAction when a TextArea loses focus. - */ -class EntryEditorTabFocusListener implements FocusListener { - - /** - * The EntryEditorTab this FocusListener is currently tied to - */ - private final EntryEditorTab entryEditorTab; - /** The component this DocumentListener is currently tied to */ - private JTextComponent textComponent; - /** The listener which gets tied to each TextComponent (and removed) */ - private DocumentListener documentListener; - - - public EntryEditorTabFocusListener(final EntryEditorTab entryEditorTab) { - this.entryEditorTab = entryEditorTab; - } - - @Override - public void focusGained(FocusEvent event) { - synchronized (this) { - if (textComponent != null) { - textComponent.getDocument().removeDocumentListener(documentListener); - textComponent = null; - documentListener = null; - } - - if (event.getSource() instanceof JTextComponent) { - textComponent = (JTextComponent) event.getSource(); - documentListener = new DocumentListener() { - private void fire() { - if (textComponent.isFocusOwner()) { - entryEditorTab.markIfModified((FieldEditor) textComponent); - } - } - - @Override - public void changedUpdate(DocumentEvent e) { - fire(); - } - - @Override - public void insertUpdate(DocumentEvent e) { - fire(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - fire(); - } - }; - textComponent.getDocument().addDocumentListener(documentListener); - - // Makes the vertical scroll panel view follow the focus - Component component = textComponent.getParent().getParent(); - if (component instanceof JScrollPane) { - JScrollPane scrollPane = (JScrollPane) component; - Component scrollPaneParent = scrollPane.getParent(); - if (scrollPaneParent instanceof JPanel) { - JPanel panel = (JPanel) scrollPaneParent; - Rectangle bounds = scrollPane.getBounds(); - panel.scrollRectToVisible(bounds); - } - } - - } - } - // TODO: Reenable this - //entryEditorTab.setActive((FieldEditor) event.getSource()); - } - - @Override - public void focusLost(FocusEvent event) { - synchronized (this) { - if (textComponent != null) { - textComponent.getDocument().removeDocumentListener(documentListener); - textComponent = null; - documentListener = null; - } - } - if (!event.isTemporary()) { - entryEditorTab.getParent().updateField(event.getSource()); - } - } - -} diff --git a/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java b/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java index 596a7f9eac2..2cc348f9e76 100644 --- a/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java +++ b/src/main/java/org/jabref/gui/errorconsole/ErrorConsoleViewModel.java @@ -16,7 +16,6 @@ import org.jabref.gui.AbstractViewModel; import org.jabref.gui.ClipBoardManager; import org.jabref.gui.DialogService; -import org.jabref.gui.MappedList; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.logic.l10n.Localization; import org.jabref.logic.logging.LogMessages; @@ -27,6 +26,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.http.client.utils.URIBuilder; import org.apache.logging.log4j.core.LogEvent; +import org.fxmisc.easybind.EasyBind; public class ErrorConsoleViewModel extends AbstractViewModel { private static final Log LOGGER = LogFactory.getLog(ErrorConsoleViewModel.class); @@ -42,7 +42,7 @@ public ErrorConsoleViewModel(DialogService dialogService, ClipBoardManager clipB this.dialogService = Objects.requireNonNull(dialogService); this.clipBoardManager = Objects.requireNonNull(clipBoardManager); this.buildInfo = Objects.requireNonNull(buildInfo); - ObservableList eventViewModels = new MappedList<>(LogMessages.getInstance().getMessages(), LogEventViewModel::new); + ObservableList eventViewModels = EasyBind.map(LogMessages.getInstance().getMessages(), LogEventViewModel::new); allMessagesData = new ReadOnlyListWrapper<>(eventViewModels); } diff --git a/src/main/java/org/jabref/gui/groups/DroppingMouseLocation.java b/src/main/java/org/jabref/gui/groups/DroppingMouseLocation.java new file mode 100644 index 00000000000..e946facdcf7 --- /dev/null +++ b/src/main/java/org/jabref/gui/groups/DroppingMouseLocation.java @@ -0,0 +1,10 @@ +package org.jabref.gui.groups; + +/** + * The mouse location within the cell when the dropping gesture occurs. + */ +enum DroppingMouseLocation { + BOTTOM, + CENTER, + TOP +} diff --git a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index a73496975cb..4e1b85993a2 100644 --- a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -67,7 +67,7 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state .sorted((group1, group2) -> group1.getDisplayName().compareToIgnoreCase(group2.getDisplayName())) .collect(Collectors.toCollection(FXCollections::observableArrayList)); } else { - children = EasyBind.map(groupNode.getChildren(), this::toViewModel); + children = BindingsHelper.mapBacked(groupNode.getChildren(), this::toViewModel); } hasChildren = new SimpleBooleanProperty(); hasChildren.bind(Bindings.isNotEmpty(children)); @@ -254,6 +254,51 @@ public void moveTo(GroupNodeViewModel target) { //panel.getUndoManager().addEdit(new UndoableMoveGroup(this.groupsRoot, moveChange)); //panel.markBaseChanged(); //frame.output(Localization.lang("Moved group \"%0\".", node.getNode().getGroup().getName())); + } + + public void moveTo(GroupTreeNode target, int targetIndex) { + getGroupNode().moveTo(target, targetIndex); + } + + public Optional getParent() { + return groupNode.getParent(); + } + + public void draggedOn(GroupNodeViewModel target, DroppingMouseLocation mouseLocation) { + Optional targetParent = target.getParent(); + if (targetParent.isPresent()) { + int targetIndex = target.getPositionInParent(); + + // In case we want to move an item in the same parent + // and the item is moved down, we need to adjust the target index + if (targetParent.equals(getParent())) { + int sourceIndex = this.getPositionInParent(); + if (sourceIndex < targetIndex) { + targetIndex--; + } + } + + // Different actions depending on where the user releases the drop in the target row + // Bottom + top -> insert source row before / after this row + // Center -> add as child + switch (mouseLocation) { + case BOTTOM: + this.moveTo(targetParent.get(), targetIndex + 1); + break; + case CENTER: + this.moveTo(target); + break; + case TOP: + this.moveTo(targetParent.get(), targetIndex); + break; + } + } else { + // No parent = root -> just add + this.moveTo(target); + } + } + private int getPositionInParent() { + return groupNode.getPositionInParent(); } } diff --git a/src/main/java/org/jabref/gui/groups/GroupSelector.java b/src/main/java/org/jabref/gui/groups/GroupSelector.java deleted file mode 100644 index c5ff928e176..00000000000 --- a/src/main/java/org/jabref/gui/groups/GroupSelector.java +++ /dev/null @@ -1,637 +0,0 @@ -package org.jabref.gui.groups; - -import java.awt.BorderLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Enumeration; -import java.util.List; -import java.util.Optional; - -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JMenu; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JScrollPane; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingUtilities; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; -import javax.swing.undo.AbstractUndoableEdit; -import javax.swing.undo.CompoundEdit; - -import javafx.application.Platform; -import javafx.embed.swing.JFXPanel; -import javafx.scene.Scene; -import javafx.scene.layout.StackPane; - -import org.jabref.Globals; -import org.jabref.gui.BasePanel; -import org.jabref.gui.IconTheme; -import org.jabref.gui.JabRefFrame; -import org.jabref.gui.SidePaneComponent; -import org.jabref.gui.SidePaneManager; -import org.jabref.gui.help.HelpAction; -import org.jabref.gui.keyboard.KeyBinding; -import org.jabref.gui.maintable.MainTableDataModel; -import org.jabref.logic.groups.DefaultGroupsFactory; -import org.jabref.logic.help.HelpFile; -import org.jabref.logic.l10n.Localization; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.groups.AllEntriesGroup; -import org.jabref.model.groups.GroupTreeNode; -import org.jabref.model.groups.event.GroupUpdatedEvent; -import org.jabref.model.metadata.MetaData; -import org.jabref.model.search.SearchMatcher; -import org.jabref.preferences.JabRefPreferences; - -import com.google.common.eventbus.Subscribe; - -/** - * The whole UI component holding the groups tree and the buttons - */ -public class GroupSelector extends SidePaneComponent implements TreeSelectionListener { - - protected final JabRefFrame frame; - private final GroupsTree groupsTree; - private final JPopupMenu groupsContextMenu = new JPopupMenu(); - private final JPopupMenu settings = new JPopupMenu(); - 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 autoAssignGroup = new JCheckBoxMenuItem( - Localization.lang("Automatically assign new entry to selected groups")); - private final JMenu sortSubmenu = new JMenu(Localization.lang("Sort alphabetically")); - private final NodeAction sortDirectSubgroupsPopupAction = new SortDirectSubgroupsAction(); - private final NodeAction sortAllSubgroupsPopupAction = new SortAllSubgroupsAction(); - private final ToggleAction toggleAction; - private DefaultTreeModel groupsTreeModel; - private GroupTreeNodeViewModel groupsRoot; - - /** - * The first element for each group defines which field to use for the quicksearch. The next two define the name and - * regexp for the group. - */ - public GroupSelector(JabRefFrame frame, SidePaneManager manager) { - super(manager, IconTheme.JabRefIcon.TOGGLE_GROUPS.getIcon(), Localization.lang("Groups")); - - Globals.stateManager.activeGroupProperty() - .addListener((observable, oldValue, newValue) -> updateShownEntriesAccordingToSelectedGroups(newValue)); - - toggleAction = new ToggleAction(Localization.menuTitle("Toggle groups interface"), - Localization.lang("Toggle groups interface"), - Globals.getKeyPrefs().getKey(KeyBinding.TOGGLE_GROUPS_INTERFACE), - IconTheme.JabRefIcon.TOGGLE_GROUPS); - - this.frame = frame; - - 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())); - - JRadioButtonMenuItem highlCb = new JRadioButtonMenuItem(Localization.lang("Highlight"), false); - if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_FLOAT_SELECTIONS)) { - - floatCb.setSelected(true); - highlCb.setSelected(false); - } else { - highlCb.setSelected(true); - floatCb.setSelected(false); - } - JRadioButtonMenuItem orCb = new JRadioButtonMenuItem(Localization.lang("Union"), false); - if (Globals.prefs.getBoolean(JabRefPreferences.GROUP_INTERSECT_SELECTIONS)) { - andCb.setSelected(true); - orCb.setSelected(false); - } else { - orCb.setSelected(true); - andCb.setSelected(false); - } - - autoAssignGroup.addChangeListener( - event -> Globals.prefs.putBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP, autoAssignGroup.isSelected())); - - invCb.setSelected(Globals.prefs.getBoolean(JabRefPreferences.GROUP_INVERT_SELECTIONS)); - autoAssignGroup.setSelected(Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); - - JButton openSettings = new JButton(IconTheme.JabRefIcon.PREFERENCES.getSmallIcon()); - settings.add(andCb); - settings.add(orCb); - settings.addSeparator(); - settings.add(invCb); - settings.addSeparator(); - settings.add(autoAssignGroup); - openSettings.addActionListener(e -> { - if (!settings.isVisible()) { - JButton src = (JButton) e.getSource(); - autoAssignGroup.setSelected(Globals.prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); - settings.show(src, 0, openSettings.getHeight()); - } - }); - - JButton helpButton = new HelpAction(Localization.lang("Help on groups"), HelpFile.GROUP) - .getHelpButton(); - Insets butIns = new Insets(0, 0, 0, 0); - helpButton.setMargin(butIns); - openSettings.setMargin(butIns); - andCb.addActionListener(e -> valueChanged(null)); - orCb.addActionListener(e -> valueChanged(null)); - invCb.addActionListener(e -> valueChanged(null)); - floatCb.addActionListener(e -> valueChanged(null)); - highlCb.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") + ""); - 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(); - bgr.add(andCb); - bgr.add(orCb); - ButtonGroup visMode = new ButtonGroup(); - visMode.add(floatCb); - visMode.add(highlCb); - - JPanel rootPanel = new JPanel(); - GridBagLayout gbl = new GridBagLayout(); - rootPanel.setLayout(gbl); - - GridBagConstraints con = new GridBagConstraints(); - con.fill = GridBagConstraints.BOTH; - con.weightx = 1; - con.gridwidth = 1; - con.gridy = 0; - - con.gridx = 0; - - con.gridx = 1; - - con.gridx = 2; - gbl.setConstraints(openSettings, con); - rootPanel.add(openSettings); - - con.gridx = 3; - con.gridwidth = GridBagConstraints.REMAINDER; - gbl.setConstraints(helpButton, con); - rootPanel.add(helpButton); - - groupsTree = new GroupsTree(this); - groupsTree.addTreeSelectionListener(this); - - JScrollPane groupsTreePane = new JScrollPane(groupsTree, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, - ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - groupsTreePane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - groupsTreePane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - con.gridwidth = GridBagConstraints.REMAINDER; - con.weighty = 1; - con.gridx = 0; - con.gridwidth = 4; - con.gridy = 1; - gbl.setConstraints(groupsTreePane, con); - rootPanel.add(groupsTreePane); - - add(rootPanel, BorderLayout.CENTER); - groupsTree.setBorder(BorderFactory.createEmptyBorder(5, 10, 0, 0)); - this.setTitle(Localization.lang("Groups")); - definePopup(); - - setGroups(GroupTreeNode.fromGroup(DefaultGroupsFactory.getAllEntriesGroup())); - - JFXPanel groupsPane = new JFXPanel(); - add(groupsPane); - // Execute on JavaFX Application Thread - Platform.runLater(() -> { - StackPane root = new StackPane(); - root.getChildren().addAll(new GroupTreeView().getView()); - Scene scene = new Scene(root); - groupsPane.setScene(scene); - }); - } - - 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.addSeparator(); - sortSubmenu.add(sortDirectSubgroupsPopupAction); - sortSubmenu.add(sortAllSubgroupsPopupAction); - groupsContextMenu.add(sortSubmenu); - groupsContextMenu.addSeparator(); - groupsTree.addMouseListener(new MouseAdapter() { - - @Override - public void mousePressed(MouseEvent e) { - if (e.isPopupTrigger()) { - showPopup(e); - } - } - - @Override - public void mouseReleased(MouseEvent e) { - if (e.isPopupTrigger()) { - showPopup(e); - } - } - - @Override - public void mouseClicked(MouseEvent e) { - TreePath path = groupsTree.getPathForLocation(e.getPoint().x, e.getPoint().y); - if (path == null) { - return; - } - GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) path.getLastPathComponent(); - // the root node is "AllEntries" and cannot be edited - if (node.getNode().isRoot()) { - return; - } - if ((e.getClickCount() == 2) && (e.getButton() == MouseEvent.BUTTON1)) { // edit - //editGroupAction.actionPerformed(null); // dummy event - } - } - }); - // be sure to remove a possible border highlight when the popup menu - // disappears - groupsContextMenu.addPopupMenuListener(new PopupMenuListener() { - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - // nothing to do - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - groupsTree.setHighlightBorderCell(null); - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - groupsTree.setHighlightBorderCell(null); - } - }); - } - - private void showPopup(MouseEvent e) { - final TreePath path = groupsTree.getPathForLocation(e.getPoint().x, e.getPoint().y); - sortSubmenu.setEnabled(path != null); - if (path != null) { // some path dependent enabling/disabling - GroupTreeNodeViewModel node = (GroupTreeNodeViewModel) path.getLastPathComponent(); - sortDirectSubgroupsPopupAction.setNode(node); - sortAllSubgroupsPopupAction.setNode(node); - groupsTree.setHighlightBorderCell(node); - if (node.canBeEdited()) { - //editGroupPopupAction.setEnabled(false); - //addGroupPopupAction.setEnabled(false); - //removeGroupAndSubgroupsPopupAction.setEnabled(false); - //removeGroupKeepSubgroupsPopupAction.setEnabled(false); - } else { - //editGroupPopupAction.setEnabled(true); - //addGroupPopupAction.setEnabled(true); - //addGroupPopupAction.setNode(node); - //removeGroupAndSubgroupsPopupAction.setEnabled(true); - //removeGroupKeepSubgroupsPopupAction.setEnabled(true); - } - sortSubmenu.setEnabled(!node.isLeaf()); - //removeSubgroupsPopupAction.setEnabled(!node.isLeaf()); - // add/remove entries to/from group - List selection = frame.getCurrentBasePanel().getSelectedEntries(); - if (!selection.isEmpty()) { - if (node.canAddEntries(selection)) { - //addToGroup.setEnabled(true); - } - if (node.canRemoveEntries(selection)) { - //removeFromGroup.setEnabled(true); - } - } - } else { - sortDirectSubgroupsPopupAction.setNode(null); - sortAllSubgroupsPopupAction.setNode(null); - } - groupsContextMenu.show(groupsTree, e.getPoint().x, e.getPoint().y); - } - - @Override - public void valueChanged(TreeSelectionEvent e) { - if (panel == null) { - return; // ignore this event (happens for example if the file was closed) - } - /* - if (getLeafsOfSelection().stream().allMatch(GroupTreeNodeViewModel::isAllEntriesGroup)) { - panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); - if (showOverlappingGroups.isSelected()) { - groupsTree.setOverlappingGroups(Collections.emptyList()); - } - frame.output(Localization.lang("Displaying no groups") + "."); - return; - } - */ - updateShownEntriesAccordingToSelectedGroups(); - } - - private void updateShownEntriesAccordingToSelectedGroups() { - updateShownEntriesAccordingToSelectedGroups(Globals.stateManager.activeGroupProperty().get()); - /*final MatcherSet searchRules = MatcherSets - .build(andCb.isSelected() ? MatcherSets.MatcherType.AND : MatcherSets.MatcherType.OR); - - for (GroupTreeNodeViewModel node : getLeafsOfSelection()) { - SearchMatcher searchRule = node.getNode().getSearchMatcher(); - searchRules.addRule(searchRule); - } - SearchMatcher searchRule = invCb.isSelected() ? new NotMatcher(searchRules) : searchRules; - GroupingWorker worker = new GroupingWorker(searchRule); - worker.getWorker().run(); - worker.getCallBack().update(); - */ - } - - private void updateShownEntriesAccordingToSelectedGroups(Optional selectedGroup) { - if (!selectedGroup.isPresent()) { - // No selected group, nothing to do - return; - } - SearchMatcher searchRule = selectedGroup.get().getSearchMatcher(); - GroupingWorker worker = new GroupingWorker(searchRule); - worker.run(); - worker.update(); - } - - private GroupTreeNodeViewModel getFirstSelectedNode() { - TreePath path = groupsTree.getSelectionPath(); - if (path != null) { - return (GroupTreeNodeViewModel) path.getLastPathComponent(); - } - return null; - } - - /** - * Revalidate the groups tree (e.g. after the data stored in the model has been changed) and maintain the current - * selection and expansion state. - */ - public void revalidateGroups() { - if (SwingUtilities.isEventDispatchThread()) { - revalidateGroups(null); - } else { - SwingUtilities.invokeLater(() -> revalidateGroups(null)); - } - } - - /** - * Revalidate the groups tree (e.g. after the data stored in the model has been changed) and maintain the current - * selection and expansion state. - * - * @param node If this is non-null, the view is scrolled to make it visible. - */ - 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. - * - * @param node If this is non-null, the view is scrolled to make it visible. - */ - private void revalidateGroups(TreePath[] selectionPaths, Enumeration expandedNodes, - GroupTreeNodeViewModel node) { - groupsTree.clearSelection(); - if (selectionPaths != null) { - groupsTree.setSelectionPaths(selectionPaths); - } - // tree is completely collapsed here - if (expandedNodes != null) { - while (expandedNodes.hasMoreElements()) { - groupsTree.expandPath(expandedNodes.nextElement()); - } - } - groupsTree.revalidate(); - if (node != null) { - groupsTree.scrollPathToVisible(node.getTreePath()); - } - } - - @Override - public void componentOpening() { - valueChanged(null); - Globals.prefs.putBoolean(JabRefPreferences.GROUP_SIDEPANE_VISIBLE, Boolean.TRUE); - } - - @Override - public int getRescalingWeight() { - return 1; - } - - @Override - public void componentClosing() { - if (panel != null) { // panel may be null if no file is open any more - panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); - } - getToggleAction().setSelected(false); - Globals.prefs.putBoolean(JabRefPreferences.GROUP_SIDEPANE_VISIBLE, Boolean.FALSE); - } - - private void setGroups(GroupTreeNode groupsRoot) { - // We ignore the set group since this is handled via JavaFX - this.groupsRoot = new GroupTreeNodeViewModel(new GroupTreeNode(DefaultGroupsFactory.getAllEntriesGroup())); - //this.groupsRoot = new GroupTreeNodeViewModel(groupsRoot); - groupsTreeModel = new DefaultTreeModel(this.groupsRoot); - this.groupsRoot.subscribeToDescendantChanged(groupsTreeModel::nodeStructureChanged); - groupsTree.setModel(groupsTreeModel); - } - - /** - * Adds the specified node as a child of the current root. The group contained in newGroups must not be of - * type AllEntriesGroup, since every tree has exactly one AllEntriesGroup (its root). The newGroups are - * inserted directly, i.e. they are not deepCopy()'d. - */ - public void addGroups(GroupTreeNode newGroups, CompoundEdit ce) { - // TODO: This shouldn't be a method of GroupSelector - - // paranoia: ensure that there are never two instances of AllEntriesGroup - if (newGroups.getGroup() instanceof AllEntriesGroup) { - return; // this should be impossible anyway - } - newGroups.moveTo(groupsRoot.getNode()); - UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(groupsRoot, - new GroupTreeNodeViewModel(newGroups), UndoableAddOrRemoveGroup.ADD_NODE); - ce.addEdit(undo); - } - - public TreePath getSelectionPath() { - return groupsTree.getSelectionPath(); - } - - public void concludeAssignment(AbstractUndoableEdit undo, GroupTreeNode node, int assignedEntries) { - if (undo == null) { - frame.output(Localization.lang("The group \"%0\" already contains the selection.", - node.getGroup().getName())); - return; - } - panel.getUndoManager().addEdit(undo); - panel.markBaseChanged(); - panel.updateEntryEditorIfShowing(); - final String groupName = node.getGroup().getName(); - if (assignedEntries == 1) { - frame.output(Localization.lang("Assigned 1 entry to group \"%0\".", groupName)); - } else { - frame.output(Localization.lang("Assigned %0 entries to group \"%1\".", String.valueOf(assignedEntries), - groupName)); - } - } - - private GroupTreeNodeViewModel getGroupTreeRoot() { - return groupsRoot; - } - - private Enumeration getExpandedPaths() { - return groupsTree.getExpandedDescendants(groupsRoot.getTreePath()); - } - - /** - * panel may be null to indicate that no file is currently open. - */ - @Override - public void setActiveBasePanel(BasePanel panel) { - super.setActiveBasePanel(panel); - if (panel == null) { // hide groups - frame.getSidePaneManager().hide(GroupSelector.class); - return; - } - MetaData metaData = panel.getBibDatabaseContext().getMetaData(); - if (metaData.getGroups().isPresent()) { - setGroups(metaData.getGroups().get()); - } else { - GroupTreeNode newGroupsRoot = GroupTreeNode - .fromGroup(DefaultGroupsFactory.getAllEntriesGroup()); - metaData.setGroups(newGroupsRoot); - setGroups(newGroupsRoot); - } - - metaData.registerListener(this); - - synchronized (getTreeLock()) { - validateTree(); - } - } - - public GroupsTree getGroupsTree() { - return this.groupsTree; - } - - @Subscribe - public void listen(GroupUpdatedEvent updateEvent) { - setGroups(updateEvent.getMetaData().getGroups().orElse(null)); - } - - @Override - public void grabFocus() { - groupsTree.grabFocus(); - } - - @Override - public ToggleAction getToggleAction() { - return toggleAction; - } - - class GroupingWorker { - - private final SearchMatcher matcher; - - public GroupingWorker(SearchMatcher matcher) { - this.matcher = matcher; - } - - public void run() { - for (BibEntry entry : panel.getDatabase().getEntries()) { - boolean hit = matcher.isMatch(entry); - entry.setGroupHit(hit); - } - } - - public void update() { - // Show the result in the chosen way: - 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); - - frame.output(Localization.lang("Updated group selection") + "."); - } - } - - private abstract class NodeAction extends AbstractAction { - - private GroupTreeNodeViewModel node; - - public NodeAction(String s) { - super(s); - } - - public void setNode(GroupTreeNodeViewModel node) { - this.node = node; - } - - /** - * Returns the node to use in this action. If a node has been set explicitly (via setNode), it is returned. - * Otherwise, the first node in the current selection is returned. If all this fails, null is returned. - */ - public GroupTreeNodeViewModel getNodeToUse() { - if (node != null) { - return node; - } - return getFirstSelectedNode(); - } - } - - private class SortDirectSubgroupsAction extends NodeAction { - - public SortDirectSubgroupsAction() { - super(Localization.lang("Immediate subgroups")); - } - - @Override - public void actionPerformed(ActionEvent ae) { - final GroupTreeNodeViewModel node = getNodeToUse(); - final UndoableModifySubtree undo = new UndoableModifySubtree(getGroupTreeRoot(), node, - Localization.lang("sort subgroups")); - groupsTree.sort(node, false); - panel.getUndoManager().addEdit(undo); - panel.markBaseChanged(); - frame.output(Localization.lang("Sorted immediate subgroups.")); - } - } - - private class SortAllSubgroupsAction extends NodeAction { - - public SortAllSubgroupsAction() { - super(Localization.lang("All subgroups (recursively)")); - } - - @Override - public void actionPerformed(ActionEvent ae) { - final GroupTreeNodeViewModel node = getNodeToUse(); - final UndoableModifySubtree undo = new UndoableModifySubtree(getGroupTreeRoot(), node, - Localization.lang("sort subgroups")); - groupsTree.sort(node, true); - panel.getUndoManager().addEdit(undo); - panel.markBaseChanged(); - frame.output(Localization.lang("Sorted all subgroups recursively.")); - } - } -} diff --git a/src/main/java/org/jabref/gui/groups/GroupSidePane.java b/src/main/java/org/jabref/gui/groups/GroupSidePane.java new file mode 100644 index 00000000000..6123a99920d --- /dev/null +++ b/src/main/java/org/jabref/gui/groups/GroupSidePane.java @@ -0,0 +1,122 @@ +package org.jabref.gui.groups; + +import java.util.List; + +import javafx.application.Platform; +import javafx.embed.swing.JFXPanel; +import javafx.scene.Scene; +import javafx.scene.layout.StackPane; + +import org.jabref.Globals; +import org.jabref.gui.BasePanel; +import org.jabref.gui.IconTheme; +import org.jabref.gui.JabRefFrame; +import org.jabref.gui.SidePaneComponent; +import org.jabref.gui.SidePaneManager; +import org.jabref.gui.keyboard.KeyBinding; +import org.jabref.gui.maintable.MainTableDataModel; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.groups.GroupTreeNode; +import org.jabref.model.search.matchers.MatcherSet; +import org.jabref.model.search.matchers.MatcherSets; +import org.jabref.preferences.JabRefPreferences; + +/** + * The groups side pane. + * This class is just a Swing wrapper around the JavaFX implementation {@link GroupTreeView}. + */ +public class GroupSidePane extends SidePaneComponent { + + protected final JabRefFrame frame; + private final ToggleAction toggleAction; + + /** + * The first element for each group defines which field to use for the quicksearch. The next two define the name and + * regexp for the group. + */ + public GroupSidePane(JabRefFrame frame, SidePaneManager manager) { + super(manager, IconTheme.JabRefIcon.TOGGLE_GROUPS.getIcon(), Localization.lang("Groups")); + + Globals.stateManager.activeGroupProperty() + .addListener((observable, oldValue, newValue) -> updateShownEntriesAccordingToSelectedGroups(newValue)); + + toggleAction = new ToggleAction(Localization.menuTitle("Toggle groups interface"), + Localization.lang("Toggle groups interface"), + Globals.getKeyPrefs().getKey(KeyBinding.TOGGLE_GROUPS_INTERFACE), + IconTheme.JabRefIcon.TOGGLE_GROUPS); + + this.frame = frame; + + this.setTitle(Localization.lang("Groups")); + + JFXPanel groupsPane = new JFXPanel(); + add(groupsPane); + // Execute on JavaFX Application Thread + Platform.runLater(() -> { + StackPane root = new StackPane(); + root.getChildren().addAll(new GroupTreeView().getView()); + Scene scene = new Scene(root); + groupsPane.setScene(scene); + }); + } + + private void updateShownEntriesAccordingToSelectedGroups(List selectedGroups) { + if (selectedGroups == null || selectedGroups.isEmpty()) { + // No selected group, nothing to do + return; + } + + final MatcherSet searchRules = MatcherSets.build( + Globals.prefs.getBoolean(JabRefPreferences.GROUP_INTERSECT_SELECTIONS) ? MatcherSets.MatcherType.AND : MatcherSets.MatcherType.OR); + + for (GroupTreeNode node : selectedGroups) { + searchRules.addRule(node.getSearchMatcher()); + } + + GroupingWorker worker = new GroupingWorker(frame, panel); + worker.run(searchRules); + worker.update(); + } + + @Override + public void componentOpening() { + Globals.prefs.putBoolean(JabRefPreferences.GROUP_SIDEPANE_VISIBLE, Boolean.TRUE); + } + + @Override + public int getRescalingWeight() { + return 1; + } + + @Override + public void componentClosing() { + if (panel != null) { // panel may be null if no file is open any more + panel.getMainTable().getTableModel().updateGroupingState(MainTableDataModel.DisplayOption.DISABLED); + } + getToggleAction().setSelected(false); + Globals.prefs.putBoolean(JabRefPreferences.GROUP_SIDEPANE_VISIBLE, Boolean.FALSE); + } + + @Override + public void setActiveBasePanel(BasePanel panel) { + super.setActiveBasePanel(panel); + if (panel == null) { // hide groups + frame.getSidePaneManager().hide(GroupSidePane.class); + return; + } + + synchronized (getTreeLock()) { + validateTree(); + } + } + + @Override + public void grabFocus() { + + } + + @Override + public ToggleAction getToggleAction() { + return toggleAction; + } +} diff --git a/src/main/java/org/jabref/gui/groups/GroupTree.css b/src/main/java/org/jabref/gui/groups/GroupTree.css index d0d7859dbfc..7a46b16a4bb 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTree.css +++ b/src/main/java/org/jabref/gui/groups/GroupTree.css @@ -34,6 +34,24 @@ -fx-font-size: 12px; } +.tree-table-row-cell:dragOver-bottom { + -fx-border-color: #eea82f; + -fx-border-width: 0 0 2 0; + -fx-padding: 0 0 -2 0; +} + +.tree-table-row-cell:dragOver-center { + -fx-border-color: #eea82f; + -fx-border-width: 2 2 2 2; + -fx-padding: -2 -2 -2 -2; +} + +.tree-table-row-cell:dragOver-top { + -fx-border-color: #eea82f; + -fx-border-width: 2 0 0 0; + -fx-padding: -2 0 0 0; +} + .tree-table-row-cell:sub > .tree-table-cell { -fx-padding: 0.20em 0em 0.20em 0em; } diff --git a/src/main/java/org/jabref/gui/groups/GroupTree.fxml b/src/main/java/org/jabref/gui/groups/GroupTree.fxml index 322ae5140d8..1d994c8f11c 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTree.fxml +++ b/src/main/java/org/jabref/gui/groups/GroupTree.fxml @@ -14,8 +14,8 @@

- - + diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeController.java b/src/main/java/org/jabref/gui/groups/GroupTreeController.java index 471f2c1a2f2..1d1d58c2534 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeController.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeController.java @@ -2,17 +2,22 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.List; import java.util.Optional; +import java.util.function.Consumer; +import java.util.stream.Collectors; import javax.inject.Inject; import javafx.beans.property.ObjectProperty; +import javafx.collections.ObservableList; import javafx.css.PseudoClass; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.ContextMenu; import javafx.scene.control.Control; import javafx.scene.control.MenuItem; +import javafx.scene.control.SelectionMode; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.TextField; import javafx.scene.control.TreeItem; @@ -20,6 +25,7 @@ import javafx.scene.control.TreeTableRow; import javafx.scene.control.TreeTableView; import javafx.scene.input.ClipboardContent; +import javafx.scene.input.DragEvent; import javafx.scene.input.Dragboard; import javafx.scene.input.TransferMode; import javafx.scene.layout.StackPane; @@ -55,15 +61,37 @@ public class GroupTreeController extends AbstractController @Inject private DialogService dialogService; @Inject private TaskExecutor taskExecutor; + private static void removePseudoClasses(TreeTableRow row, PseudoClass... pseudoClasses) { + for (PseudoClass pseudoClass : pseudoClasses) { + row.pseudoClassStateChanged(pseudoClass, false); + } + } + @FXML public void initialize() { viewModel = new GroupTreeViewModel(stateManager, dialogService, taskExecutor); + // Set-up groups tree + groupTree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); + // Set-up bindings - groupTree.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> viewModel - .selectedGroupProperty().setValue(newValue != null ? newValue.getValue() : null)); - viewModel.selectedGroupProperty().addListener((observable, oldValue, newValue) -> getTreeItemByValue(newValue) - .ifPresent(treeItem -> groupTree.getSelectionModel().select(treeItem))); + Consumer> updateSelectedGroups = + (newSelectedGroups) -> newSelectedGroups.forEach(this::selectNode); + Consumer>> updateViewModel = + (newSelectedGroups) -> { + if (newSelectedGroups == null) { + viewModel.selectedGroupsProperty().clear(); + } else { + viewModel.selectedGroupsProperty().setAll(newSelectedGroups.stream().map(TreeItem::getValue).collect(Collectors.toList())); + } + }; + BindingsHelper.bindContentBidirectional( + groupTree.getSelectionModel().getSelectedItems(), + viewModel.selectedGroupsProperty(), + updateSelectedGroups, + updateViewModel + ); + viewModel.filterTextProperty().bind(searchField.textProperty()); groupTree.rootProperty().bind( @@ -120,6 +148,11 @@ public void initialize() { // Set pseudo-classes to indicate if row is root or sub-item ( > 1 deep) PseudoClass rootPseudoClass = PseudoClass.getPseudoClass("root"); PseudoClass subElementPseudoClass = PseudoClass.getPseudoClass("sub"); + + // Pseudo-classes for drag and drop + PseudoClass dragOverBottom = PseudoClass.getPseudoClass("dragOver-bottom"); + PseudoClass dragOverCenter = PseudoClass.getPseudoClass("dragOver-center"); + PseudoClass dragOverTop = PseudoClass.getPseudoClass("dragOver-top"); groupTree.setRowFactory(treeTable -> { TreeTableRow row = new TreeTableRow<>(); row.treeItemProperty().addListener((ov, oldTreeItem, newTreeItem) -> { @@ -162,9 +195,25 @@ public void initialize() { Dragboard dragboard = event.getDragboard(); if ((event.getGestureSource() != row) && row.getItem().acceptableDrop(dragboard)) { event.acceptTransferModes(TransferMode.MOVE, TransferMode.LINK); + + removePseudoClasses(row, dragOverBottom, dragOverCenter, dragOverTop); + switch (getDroppingMouseLocation(row, event)) { + case BOTTOM: + row.pseudoClassStateChanged(dragOverBottom, true); + break; + case CENTER: + row.pseudoClassStateChanged(dragOverCenter, true); + break; + case TOP: + row.pseudoClassStateChanged(dragOverTop, true); + break; + } } event.consume(); }); + row.setOnDragExited(event -> { + removePseudoClasses(row, dragOverBottom, dragOverCenter, dragOverTop); + }); row.setOnDragDropped(event -> { Dragboard dragboard = event.getDragboard(); @@ -174,7 +223,7 @@ public void initialize() { Optional source = viewModel.rootGroupProperty().get() .getChildByPath(pathToSource); if (source.isPresent()) { - source.get().moveTo(row.getItem()); + source.get().draggedOn(row.getItem(), getDroppingMouseLocation(row, event)); success = true; } } @@ -196,6 +245,11 @@ public void initialize() { setupClearButtonField(searchField); } + private void selectNode(GroupNodeViewModel value) { + getTreeItemByValue(value) + .ifPresent(treeItem -> groupTree.getSelectionModel().select(treeItem)); + } + private Optional> getTreeItemByValue(GroupNodeViewModel value) { return getTreeItemByValue(groupTree.getRoot(), value); } @@ -253,6 +307,22 @@ private ContextMenu createContextMenuForGroup(GroupNodeViewModel group) { menu.getItems().add(new SeparatorMenuItem()); menu.getItems().add(sortAlphabetically); + // TODO: Disable some actions under certain conditions + //if (group.canBeEdited()) { + //editGroupPopupAction.setEnabled(false); + //addGroupPopupAction.setEnabled(false); + //removeGroupAndSubgroupsPopupAction.setEnabled(false); + //removeGroupKeepSubgroupsPopupAction.setEnabled(false); + //} else { + //editGroupPopupAction.setEnabled(true); + //addGroupPopupAction.setEnabled(true); + //addGroupPopupAction.setNode(node); + //removeGroupAndSubgroupsPopupAction.setEnabled(true); + //removeGroupKeepSubgroupsPopupAction.setEnabled(true); + //} + //sortSubmenu.setEnabled(!node.isLeaf()); + //removeSubgroupsPopupAction.setEnabled(!node.isLeaf()); + return menu; } @@ -273,4 +343,17 @@ private void setupClearButtonField(CustomTextField customTextField) { LOGGER.error("Failed to decorate text field with clear button", ex); } } + + /** + * Determines where the mouse is in the given row. + */ + private DroppingMouseLocation getDroppingMouseLocation(TreeTableRow row, DragEvent event) { + if ((row.getHeight() * 0.25) > event.getY()) { + return DroppingMouseLocation.TOP; + } else if ((row.getHeight() * 0.75) < event.getY()) { + return DroppingMouseLocation.BOTTOM; + } else { + return DroppingMouseLocation.CENTER; + } + } } diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index adab6abb7dd..c505280e705 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -5,15 +5,20 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Predicate; +import java.util.stream.Collectors; import javax.swing.SwingUtilities; import javafx.application.Platform; import javafx.beans.binding.Bindings; +import javafx.beans.property.ListProperty; import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleListProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; @@ -30,16 +35,16 @@ public class GroupTreeViewModel extends AbstractViewModel { private final ObjectProperty rootGroup = new SimpleObjectProperty<>(); - private final ObjectProperty selectedGroup = new SimpleObjectProperty<>(); + private final ListProperty selectedGroups = new SimpleListProperty<>(FXCollections.observableArrayList()); 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 Optional currentDatabase; private final Comparator compAlphabetIgnoreCase = (GroupTreeNode v1, GroupTreeNode v2) -> v1 .getName() .compareToIgnoreCase(v2.getName()); + private Optional currentDatabase; public GroupTreeViewModel(StateManager stateManager, DialogService dialogService, TaskExecutor taskExecutor) { this.stateManager = Objects.requireNonNull(stateManager); @@ -49,7 +54,7 @@ public GroupTreeViewModel(StateManager stateManager, DialogService dialogService // Register listener stateManager.activeDatabaseProperty() .addListener((observable, oldValue, newValue) -> onActiveDatabaseChanged(newValue)); - selectedGroup.addListener((observable, oldValue, newValue) -> onSelectedGroupChanged(newValue)); + selectedGroups.addListener((observable, oldValue, newValue) -> onSelectedGroupChanged(newValue)); // Set-up bindings filterPredicate @@ -63,8 +68,8 @@ public ObjectProperty rootGroupProperty() { return rootGroup; } - public ObjectProperty selectedGroupProperty() { - return selectedGroup; + public ListProperty selectedGroupsProperty() { + return selectedGroups; } public ObjectProperty> filterPredicateProperty() { @@ -79,7 +84,7 @@ public StringProperty filterTextProperty() { * Gets invoked if the user selects a different group. * We need to notify the {@link StateManager} about this change so that the main table gets updated. */ - private void onSelectedGroupChanged(GroupNodeViewModel newValue) { + private void onSelectedGroupChanged(ObservableList newValue) { if (!currentDatabase.equals(stateManager.activeDatabaseProperty().getValue())) { // Switch of database occurred -> do nothing return; @@ -87,9 +92,9 @@ private void onSelectedGroupChanged(GroupNodeViewModel newValue) { currentDatabase.ifPresent(database -> { if (newValue == null) { - stateManager.clearSelectedGroup(database); + stateManager.clearSelectedGroups(database); } else { - stateManager.setSelectedGroup(database, newValue.getGroupNode()); + stateManager.setSelectedGroups(database, newValue.stream().map(GroupNodeViewModel::getGroupNode).collect(Collectors.toList())); } }); } @@ -114,9 +119,10 @@ private void onActiveDatabaseChanged(Optional newDatabase) { .orElse(GroupNodeViewModel.getAllEntriesGroup(newDatabase.get(), stateManager, taskExecutor)); rootGroup.setValue(newRoot); - stateManager.getSelectedGroup(newDatabase.get()).ifPresent( - selectedGroup -> this.selectedGroup.setValue( - new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup))); + this.selectedGroups.setAll( + stateManager.getSelectedGroup(newDatabase.get()).stream() + .map(selectedGroup -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup)) + .collect(Collectors.toList())); } currentDatabase = newDatabase; @@ -251,6 +257,21 @@ public void addSelectedEntries(GroupNodeViewModel group) { // NamedCompound undoAll = new NamedCompound(Localization.lang("change assignment of entries")); // if (!undoAdd.isEmpty()) { undo.addEdit(UndoableChangeEntriesOfGroup.getUndoableEdit(node, undoAdd)); } // panel.getUndoManager().addEdit(undoAll); + + // TODO Display massages + //if (undo == null) { + // frame.output(Localization.lang("The group \"%0\" already contains the selection.", + // node.getGroup().getName())); + // return; + //} + // panel.getUndoManager().addEdit(undo); + // final String groupName = node.getGroup().getName(); + // if (assignedEntries == 1) { + // frame.output(Localization.lang("Assigned 1 entry to group \"%0\".", groupName)); + // } else { + // frame.output(Localization.lang("Assigned %0 entries to group \"%1\".", String.valueOf(assignedEntries), + // groupName)); + //} } public void removeSelectedEntries(GroupNodeViewModel group) { diff --git a/src/main/java/org/jabref/gui/groups/GroupingWorker.java b/src/main/java/org/jabref/gui/groups/GroupingWorker.java new file mode 100644 index 00000000000..6ce158e0fba --- /dev/null +++ b/src/main/java/org/jabref/gui/groups/GroupingWorker.java @@ -0,0 +1,42 @@ +package org.jabref.gui.groups; + +import org.jabref.Globals; +import org.jabref.gui.BasePanel; +import org.jabref.gui.JabRefFrame; +import org.jabref.gui.maintable.MainTableDataModel; +import org.jabref.logic.l10n.Localization; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.search.SearchMatcher; +import org.jabref.preferences.JabRefPreferences; + +class GroupingWorker { + + private final JabRefFrame frame; + private final BasePanel panel; + + public GroupingWorker(JabRefFrame frame, BasePanel panel) { + this.frame = frame; + this.panel = panel; + } + + public void run(SearchMatcher matcher) { + for (BibEntry entry : panel.getDatabase().getEntries()) { + boolean hit = matcher.isMatch(entry); + entry.setGroupHit(hit); + } + } + + public void update() { + // Show the result in the chosen way: + 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); + + frame.output(Localization.lang("Updated group selection") + "."); + } +} diff --git a/src/main/java/org/jabref/gui/groups/GroupsTree.java b/src/main/java/org/jabref/gui/groups/GroupsTree.java deleted file mode 100644 index e95ea812bc5..00000000000 --- a/src/main/java/org/jabref/gui/groups/GroupsTree.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.jabref.gui.groups; - -import javax.swing.JTree; -import javax.swing.ToolTipManager; -import javax.swing.tree.TreeSelectionModel; - -public class GroupsTree extends JTree { - - private final GroupTreeCellRenderer localCellRenderer = new GroupTreeCellRenderer(); - - /** - * @param groupSelector the parent UI component - */ - public GroupsTree(GroupSelector groupSelector) { - setCellRenderer(localCellRenderer); - setFocusable(false); - setToggleClickCount(0); - ToolTipManager.sharedInstance().registerComponent(this); - setShowsRootHandles(false); - getSelectionModel().setSelectionMode( - TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); - this.setFocusable(true); - - } - - /** Highlights the specified cell or disables highlight if cell == null */ - public void setHighlightBorderCell(GroupTreeNodeViewModel node) { - localCellRenderer.setHighlightBorderCell(node); - repaint(); - } - - /** Sort immediate children of the specified node alphabetically. */ - public void sort(GroupTreeNodeViewModel node, boolean recursive) { - node.sortChildrenByName(recursive); - } -} diff --git a/src/main/java/org/jabref/gui/groups/UndoableModifyGroup.java b/src/main/java/org/jabref/gui/groups/UndoableModifyGroup.java index 91802ff907b..c4b67ddc683 100644 --- a/src/main/java/org/jabref/gui/groups/UndoableModifyGroup.java +++ b/src/main/java/org/jabref/gui/groups/UndoableModifyGroup.java @@ -9,7 +9,7 @@ class UndoableModifyGroup extends AbstractUndoableJabRefEdit { - private final GroupSelector groupSelector; + private final GroupSidePane groupSidePane; private final AbstractGroup m_oldGroupBackup; private final AbstractGroup m_newGroupBackup; private final GroupTreeNode m_groupsRootHandle; @@ -23,9 +23,9 @@ class UndoableModifyGroup extends AbstractUndoableJabRefEdit { * The new group to replace the one currently stored in node * . */ - public UndoableModifyGroup(GroupSelector gs, GroupTreeNodeViewModel groupsRoot, - GroupTreeNodeViewModel node, AbstractGroup newGroup) { - groupSelector = gs; + public UndoableModifyGroup(GroupSidePane gs, GroupTreeNodeViewModel groupsRoot, + GroupTreeNodeViewModel node, AbstractGroup newGroup) { + groupSidePane = gs; m_oldGroupBackup = node.getNode().getGroup().deepCopy(); m_newGroupBackup = newGroup.deepCopy(); m_pathToNode = node.getNode().getIndexedPathFromRoot(); @@ -43,7 +43,6 @@ public void undo() { //TODO: NULL m_groupsRootHandle.getDescendant(m_pathToNode).get().setGroup( m_oldGroupBackup.deepCopy()); - groupSelector.revalidateGroups(); } @Override @@ -51,6 +50,5 @@ public void redo() { super.redo(); m_groupsRootHandle.getDescendant(m_pathToNode).get().setGroup( m_newGroupBackup.deepCopy()); - groupSelector.revalidateGroups(); } } diff --git a/src/main/java/org/jabref/gui/importer/actions/AppendDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/AppendDatabaseAction.java index e976fd6cd59..baae05a96f7 100644 --- a/src/main/java/org/jabref/gui/importer/actions/AppendDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/AppendDatabaseAction.java @@ -6,6 +6,7 @@ import java.util.List; import javax.swing.JOptionPane; +import javax.swing.undo.CompoundEdit; import org.jabref.Globals; import org.jabref.JabRefExecutorService; @@ -26,12 +27,14 @@ import org.jabref.logic.util.FileExtensions; import org.jabref.logic.util.UpdateField; import org.jabref.model.database.BibDatabase; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.KeyCollisionException; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibtexString; import org.jabref.model.groups.AllEntriesGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; +import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.metadata.ContentSelector; import org.jabref.model.metadata.MetaData; import org.jabref.preferences.JabRefPreferences; @@ -53,82 +56,29 @@ public AppendDatabaseAction(JabRefFrame frame, BasePanel panel) { this.panel = panel; } - @Override - public void action() { - - filesToOpen.clear(); - final MergeDialog md = new MergeDialog(frame, Localization.lang("Append library"), true); - md.setLocationRelativeTo(panel); - md.setVisible(true); - if (md.isOkPressed()) { - - FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() - .withDefaultExtension(FileExtensions.BIBTEX_DB) - .withInitialDirectory(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)) - .build(); - DialogService ds = new FXDialogService(); - - List chosen = DefaultTaskExecutor - .runInJavaFXThread(() -> ds.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration)); - if (chosen.isEmpty()) { - return; - } - filesToOpen.addAll(chosen); - - // Run the actual open in a thread to prevent the program - // locking until the file is loaded. - JabRefExecutorService.INSTANCE.execute( - () -> openIt(md.importEntries(), md.importStrings(), md.importGroups(), md.importSelectorWords())); - - } - - } + private static void mergeFromBibtex(BasePanel panel, ParserResult parserResult, boolean importEntries, + boolean importStrings, boolean importGroups, boolean importSelectorWords) throws KeyCollisionException { - private void openIt(boolean importEntries, boolean importStrings, boolean importGroups, - boolean importSelectorWords) { - if (filesToOpen.isEmpty()) { - return; - } - for (Path file : filesToOpen) { - try { - Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, file.getParent().toString()); - // Should this be done _after_ we know it was successfully opened? - ParserResult pr = OpenDatabase.loadDatabase(file.toFile(), - Globals.prefs.getImportFormatPreferences()); - AppendDatabaseAction.mergeFromBibtex(frame, panel, pr, importEntries, importStrings, importGroups, - importSelectorWords); - panel.output(Localization.lang("Imported from library") + " '" + file + "'"); - } catch (IOException | KeyCollisionException ex) { - LOGGER.warn("Could not open database", ex); - JOptionPane.showMessageDialog(panel, ex.getMessage(), Localization.lang("Open library"), - JOptionPane.ERROR_MESSAGE); - } - } - } - - private static void mergeFromBibtex(JabRefFrame frame, BasePanel panel, ParserResult pr, boolean importEntries, - boolean importStrings, boolean importGroups, boolean importSelectorWords) throws KeyCollisionException { - - BibDatabase fromDatabase = pr.getDatabase(); + BibDatabase fromDatabase = parserResult.getDatabase(); List appendedEntries = new ArrayList<>(); List originalEntries = new ArrayList<>(); BibDatabase database = panel.getDatabase(); NamedCompound ce = new NamedCompound(Localization.lang("Append library")); - MetaData meta = pr.getMetaData(); + MetaData meta = parserResult.getMetaData(); if (importEntries) { // Add entries boolean overwriteOwner = Globals.prefs.getBoolean(JabRefPreferences.OVERWRITE_OWNER); boolean overwriteTimeStamp = Globals.prefs.getBoolean(JabRefPreferences.OVERWRITE_TIME_STAMP); for (BibEntry originalEntry : fromDatabase.getEntries()) { - BibEntry be = (BibEntry) originalEntry.clone(); - UpdateField.setAutomaticFields(be, overwriteOwner, overwriteTimeStamp, + BibEntry entry = (BibEntry) originalEntry.clone(); + UpdateField.setAutomaticFields(entry, overwriteOwner, overwriteTimeStamp, Globals.prefs.getUpdateFieldPreferences()); - database.insertEntry(be); - appendedEntries.add(be); + database.insertEntry(entry); + appendedEntries.add(entry); originalEntries.add(originalEntry); - ce.addEdit(new UndoableInsertEntry(database, be, panel)); + ce.addEdit(new UndoableInsertEntry(database, entry, panel)); } } @@ -156,10 +106,7 @@ private static void mergeFromBibtex(JabRefFrame frame, BasePanel panel, ParserRe } } - // groupsSelector is always created, even when no groups - // have been defined. therefore, no check for null is - // required here - frame.getGroupSelector().addGroups(newGroups, ce); + addGroups(newGroups, ce); }); } @@ -173,4 +120,77 @@ private static void mergeFromBibtex(JabRefFrame frame, BasePanel panel, ParserRe panel.getUndoManager().addEdit(ce); panel.markBaseChanged(); } + + /** + * Adds the specified node as a child of the current root. The group contained in newGroups must not be of + * type AllEntriesGroup, since every tree has exactly one AllEntriesGroup (its root). The newGroups are + * inserted directly, i.e. they are not deepCopy()'d. + */ + private static void addGroups(GroupTreeNode newGroups, CompoundEdit ce) { + + // paranoia: ensure that there are never two instances of AllEntriesGroup + if (newGroups.getGroup() instanceof AllEntriesGroup) { + return; // this should be impossible anyway + } + + Globals.stateManager.getActiveDatabase() + .map(BibDatabaseContext::getMetaData) + .flatMap(MetaData::getGroups) + .ifPresent(newGroups::moveTo); + + //UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(groupsRoot, + // new GroupTreeNodeViewModel(newGroups), UndoableAddOrRemoveGroup.ADD_NODE); + //ce.addEdit(undo); + } + + @Override + public void action() { + filesToOpen.clear(); + final MergeDialog dialog = new MergeDialog(frame, Localization.lang("Append library"), true); + dialog.setLocationRelativeTo(panel); + dialog.setVisible(true); + if (dialog.isOkPressed()) { + + FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() + .withDefaultExtension(FileExtensions.BIBTEX_DB) + .withInitialDirectory(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)) + .build(); + DialogService dialogService = new FXDialogService(); + + List chosen = DefaultTaskExecutor + .runInJavaFXThread(() -> dialogService.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration)); + if (chosen.isEmpty()) { + return; + } + filesToOpen.addAll(chosen); + + // Run the actual open in a thread to prevent the program + // locking until the file is loaded. + JabRefExecutorService.INSTANCE.execute( + () -> openIt(dialog.importEntries(), dialog.importStrings(), dialog.importGroups(), dialog.importSelectorWords())); + } + } + + private void openIt(boolean importEntries, boolean importStrings, boolean importGroups, + boolean importSelectorWords) { + if (filesToOpen.isEmpty()) { + return; + } + for (Path file : filesToOpen) { + try { + Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, file.getParent().toString()); + // Should this be done _after_ we know it was successfully opened? + ParserResult parserResult = OpenDatabase.loadDatabase(file.toFile(), + Globals.prefs.getImportFormatPreferences()); + AppendDatabaseAction.mergeFromBibtex(panel, parserResult, importEntries, importStrings, importGroups, + importSelectorWords); + panel.output(Localization.lang("Imported from library") + " '" + file + "'"); + } catch (IOException | KeyCollisionException ex) { + LOGGER.warn("Could not open database", ex); + JOptionPane.showMessageDialog(panel, ex.getMessage(), Localization.lang("Open library"), + JOptionPane.ERROR_MESSAGE); + } + } + } + } diff --git a/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java b/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java index 6b6cd35e365..061fe5719ed 100644 --- a/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java +++ b/src/main/java/org/jabref/gui/preftabs/GroupsPrefsTab.java @@ -9,6 +9,7 @@ import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JRadioButton; import javax.swing.JTextField; import org.jabref.logic.l10n.Localization; @@ -23,6 +24,9 @@ class GroupsPrefsTab extends JPanel implements PrefsTab { 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 JRadioButton multiSelectionModeIntersection = new JRadioButton(Localization.lang("Intersection")); + private final JRadioButton multiSelectionModeUnion = new JRadioButton(Localization.lang("Union")); + private final JTextField groupingField = new JTextField(20); private final JTextField keywordSeparator = new JTextField(2); @@ -49,8 +53,15 @@ public void focusLost(FocusEvent e) { hideMode.add(grayOut); hideMode.add(hideNonHits); + ButtonGroup multiSelectionMode = new ButtonGroup(); + multiSelectionMode.add(multiSelectionModeIntersection); + multiSelectionMode.add(multiSelectionModeUnion); + multiSelectionModeIntersection.setToolTipText(Localization.lang("Display only entries belonging to all selected groups.")); + multiSelectionModeUnion.setToolTipText(Localization.lang("Display all entries belonging to one or more of the selected groups.")); + + FormLayout layout = new FormLayout("9dlu, pref", //500px", - "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, 3dlu, p, 3dlu, p"); DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.appendSeparator(Localization.lang("View")); builder.nextLine(); @@ -64,6 +75,14 @@ public void focusLost(FocusEvent e) { builder.nextLine(); builder.nextLine(); builder.nextColumn(); + builder.append(multiSelectionModeIntersection); + builder.nextLine(); + builder.nextLine(); + builder.nextColumn(); + builder.append(multiSelectionModeUnion); + builder.nextLine(); + builder.nextLine(); + builder.nextColumn(); builder.append(autoAssignGroup); builder.nextLine(); builder.nextLine(); @@ -95,6 +114,7 @@ public void setValues() { groupingField.setText(prefs.get(JabRefPreferences.GROUPS_DEFAULT_FIELD)); keywordSeparator.setText(prefs.get(JabRefPreferences.KEYWORD_SEPARATOR)); autoAssignGroup.setSelected(prefs.getBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP)); + multiSelectionModeIntersection.setSelected(prefs.getBoolean(JabRefPreferences.GROUP_INTERSECT_SELECTIONS)); } @Override @@ -103,6 +123,7 @@ public void storeSettings() { prefs.put(JabRefPreferences.GROUPS_DEFAULT_FIELD, groupingField.getText().trim()); prefs.putBoolean(JabRefPreferences.AUTO_ASSIGN_GROUP, autoAssignGroup.isSelected()); prefs.put(JabRefPreferences.KEYWORD_SEPARATOR, keywordSeparator.getText()); + prefs.putBoolean(JabRefPreferences.GROUP_INTERSECT_SELECTIONS, multiSelectionModeIntersection.isSelected()); } @Override diff --git a/src/main/java/org/jabref/gui/preftabs/PreferencesDialog.java b/src/main/java/org/jabref/gui/preftabs/PreferencesDialog.java index fa880318a9a..156bbe872b1 100644 --- a/src/main/java/org/jabref/gui/preftabs/PreferencesDialog.java +++ b/src/main/java/org/jabref/gui/preftabs/PreferencesDialog.java @@ -256,10 +256,18 @@ private void storeAllSettings() { MainTable.updateRenderers(); GUIGlobals.updateEntryEditorColors(); frame.setupAllTables(); - frame.getGroupSelector().revalidateGroups(); // icons may have changed frame.output(Localization.lang("Preferences recorded.")); } + public void setValues() { + // Update all field values in the tabs: + int count = main.getComponentCount(); + Component[] comps = main.getComponents(); + for (int i = 0; i < count; i++) { + ((PrefsTab) comps[i]).setValues(); + } + } + class OkAction extends AbstractAction { public OkAction() { @@ -303,15 +311,6 @@ public void actionPerformed(ActionEvent e) { } } - public void setValues() { - // Update all field values in the tabs: - int count = main.getComponentCount(); - Component[] comps = main.getComponents(); - for (int i = 0; i < count; i++) { - ((PrefsTab) comps[i]).setValues(); - } - } - class CancelAction extends AbstractAction { public CancelAction() { diff --git a/src/main/java/org/jabref/gui/util/BindingsHelper.java b/src/main/java/org/jabref/gui/util/BindingsHelper.java index f2158a065f4..88ca45210af 100644 --- a/src/main/java/org/jabref/gui/util/BindingsHelper.java +++ b/src/main/java/org/jabref/gui/util/BindingsHelper.java @@ -18,6 +18,9 @@ import javafx.css.PseudoClass; import javafx.scene.Node; +import net.corda.client.jfx.utils.MappedList; + + /** * Helper methods for javafx binding. * Some methods are taken from https://bugs.openjdk.java.net/browse/JDK-8134679 @@ -56,6 +59,18 @@ public String getName() { pseudoClassState.bind(condition); } + /** + * Creates a new list in which each element is converted using the provided mapping. + * All changes to the underlying list are propagated to the converted list. + * + * In contrast to {@link org.fxmisc.easybind.EasyBind#map(ObservableList, Function)}, + * the items are converted when the are inserted (and at the initialization) instead of when they are accessed. + * Thus the initial CPU overhead and memory consumption is higher but the access to list items is quicker. + */ + public static ObservableList mapBacked(ObservableList source, Function mapper) { + return new MappedList<>(source, mapper::apply); + } + /** * Binds propertA bidirectional to propertyB using the provided map functions to convert between them. */ @@ -86,14 +101,33 @@ public static void bindBidirectional(ObservableValue propertyA, Observ propertyB.addListener(binding.getChangeListenerB()); } - public static void bindContentBidirectional(ListProperty listProperty, Property property, Function, B> mapToB, Function> mapToList) { - final BidirectionalListBinding binding = new BidirectionalListBinding<>(listProperty, property, mapToB, mapToList); + public static void bindContentBidirectional(ObservableList propertyA, ListProperty propertyB, Consumer> updateA, Consumer> updateB) { + bindContentBidirectional( + propertyA, + (ObservableValue>) propertyB, + updateA, + updateB); + } + + public static void bindContentBidirectional(ObservableList propertyA, ObservableValue propertyB, Consumer updateA, Consumer> updateB) { + final BidirectionalListBinding binding = new BidirectionalListBinding<>(propertyA, propertyB, updateA, updateB); // use property as initial source - listProperty.setAll(mapToList.apply(property.getValue())); + updateA.accept(propertyB.getValue()); + + propertyA.addListener(binding); + propertyB.addListener(binding); + } - listProperty.addListener(binding); - property.addListener(binding); + public static void bindContentBidirectional(ListProperty listProperty, Property property, Function, B> mapToB, Function> mapToList) { + Consumer updateList = newValueB -> listProperty.setAll(mapToList.apply(newValueB)); + Consumer> updateB = newValueList -> property.setValue(mapToB.apply(newValueList)); + + bindContentBidirectional( + listProperty, + property, + updateList, + updateB); } private static class BidirectionalBinding { @@ -139,17 +173,17 @@ private void updateLocked(Consumer update, T oldValue, T newValue) { private static class BidirectionalListBinding implements ListChangeListener, ChangeListener { - private final ListProperty listProperty; - private final Property property; - private final Function, B> mapToB; - private final Function> mapToList; + private final ObservableList listProperty; + private final ObservableValue property; + private final Consumer updateA; + private final Consumer> updateB; private boolean updating = false; - public BidirectionalListBinding(ListProperty listProperty, Property property, Function, B> mapToB, Function> mapToList) { + public BidirectionalListBinding(ObservableList listProperty, ObservableValue property, Consumer updateA, Consumer> updateB) { this.listProperty = listProperty; this.property = property; - this.mapToB = mapToB; - this.mapToList = mapToList; + this.updateA = updateA; + this.updateB = updateB; } @Override @@ -157,7 +191,7 @@ public void changed(ObservableValue observable, B oldValue, B newVa if (!updating) { try { updating = true; - listProperty.setAll(mapToList.apply(newValue)); + updateA.accept(newValue); } finally { updating = false; } @@ -169,7 +203,7 @@ public void onChanged(Change c) { if (!updating) { try { updating = true; - property.setValue(mapToB.apply(listProperty.getValue())); + updateB.accept(listProperty); } finally { updating = false; } diff --git a/src/main/java/org/jabref/gui/util/RecursiveTreeItem.java b/src/main/java/org/jabref/gui/util/RecursiveTreeItem.java index e6f15fb2caf..1117f9dad36 100644 --- a/src/main/java/org/jabref/gui/util/RecursiveTreeItem.java +++ b/src/main/java/org/jabref/gui/util/RecursiveTreeItem.java @@ -70,28 +70,28 @@ private void addChildrenListener(T value) { children = new FilteredList<>(childrenFactory.call(value)); children.predicateProperty().bind(Bindings.createObjectBinding(() -> this::showNode, filter)); - children.forEach(this::addAsChild); + addAsChildren(children, 0); children.addListener((ListChangeListener) change -> { while (change.next()) { if (change.wasRemoved()) { change.getRemoved().forEach(t-> { - final List> itemsToRemove = RecursiveTreeItem.this.getChildren().stream().filter(treeItem -> treeItem.getValue().equals(t)).collect(Collectors.toList()); - - RecursiveTreeItem.this.getChildren().removeAll(itemsToRemove); + final List> itemsToRemove = getChildren().stream().filter(treeItem -> treeItem.getValue().equals(t)).collect(Collectors.toList()); + getChildren().removeAll(itemsToRemove); }); } if (change.wasAdded()) { - change.getAddedSubList().forEach(this::addAsChild); + addAsChildren(change.getAddedSubList(), change.getFrom()); } } }); } - private boolean addAsChild(T child) { - return RecursiveTreeItem.this.getChildren().add(new RecursiveTreeItem<>(child, getGraphic(), childrenFactory, expandedProperty, filter)); + private void addAsChildren(List children, int startIndex) { + List> treeItems = children.stream().map(child -> new RecursiveTreeItem<>(child, getGraphic(), childrenFactory, expandedProperty, filter)).collect(Collectors.toList()); + getChildren().addAll(startIndex, treeItems); } private boolean showNode(T t) { diff --git a/src/main/java/org/jabref/logic/importer/WebFetchers.java b/src/main/java/org/jabref/logic/importer/WebFetchers.java index a0ca5f0cfd3..628ebb41953 100644 --- a/src/main/java/org/jabref/logic/importer/WebFetchers.java +++ b/src/main/java/org/jabref/logic/importer/WebFetchers.java @@ -14,6 +14,7 @@ import org.jabref.logic.importer.fetcher.GoogleScholar; import org.jabref.logic.importer.fetcher.GvkFetcher; import org.jabref.logic.importer.fetcher.IsbnFetcher; +import org.jabref.logic.importer.fetcher.LibraryOfCongress; import org.jabref.logic.importer.fetcher.MathSciNet; import org.jabref.logic.importer.fetcher.MedlineFetcher; import org.jabref.logic.importer.fetcher.TitleFetcher; @@ -88,6 +89,7 @@ public static List getIdBasedFetchers(ImportFormatPreferences im list.add(new TitleFetcher(importFormatPreferences)); list.add(new MathSciNet(importFormatPreferences)); list.add(new CrossRef()); + list.add(new LibraryOfCongress()); list.sort(Comparator.comparing(WebFetcher::getName)); return list; } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java b/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java index f3ecdc21700..d8a50a9d333 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystem.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Objects; +import org.jabref.logic.cleanup.MoveFieldCleanup; import org.jabref.logic.formatter.bibtexfields.ClearFormatter; import org.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter; import org.jabref.logic.formatter.bibtexfields.RemoveBracesFormatter; @@ -154,8 +155,9 @@ public void doPostCleanup(BibEntry entry) { new FieldFormatterCleanup(FieldName.TITLE, new RemoveBracesFormatter()).cleanup(entry); new FieldFormatterCleanup(FieldName.AUTHOR, new NormalizeNamesFormatter()).cleanup(entry); - // Remove url to ADS page + // Remove ADS note new FieldFormatterCleanup("adsnote", new ClearFormatter()).cleanup(entry); - new FieldFormatterCleanup("adsurl", new ClearFormatter()).cleanup(entry); + // Move adsurl to url field + new MoveFieldCleanup("adsurl", FieldName.URL).cleanup(entry); } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/LibraryOfCongress.java b/src/main/java/org/jabref/logic/importer/fetcher/LibraryOfCongress.java new file mode 100644 index 00000000000..60ca3bc13d8 --- /dev/null +++ b/src/main/java/org/jabref/logic/importer/fetcher/LibraryOfCongress.java @@ -0,0 +1,34 @@ +package org.jabref.logic.importer.fetcher; + +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; + +import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.importer.IdBasedParserFetcher; +import org.jabref.logic.importer.Parser; +import org.jabref.logic.importer.fileformat.ModsImporter; + +import org.apache.http.client.utils.URIBuilder; + +/** + * Fetcher for the Library of Congress Control Number (LCCN) using https://lccn.loc.gov/ + */ +public class LibraryOfCongress implements IdBasedParserFetcher { + + @Override + public String getName() { + return "Library of Congress"; + } + + @Override + public URL getURLForID(String identifier) throws URISyntaxException, MalformedURLException, FetcherException { + URIBuilder uriBuilder = new URIBuilder("https://lccn.loc.gov/" + identifier + "/mods"); + return uriBuilder.build().toURL(); + } + + @Override + public Parser getParser() { + return new ModsImporter(); + } +} diff --git a/src/main/java/org/jabref/logic/importer/fileformat/ModsImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/ModsImporter.java index 2708b05ae20..325683a2326 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/ModsImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/ModsImporter.java @@ -2,7 +2,11 @@ import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,6 +21,8 @@ import javax.xml.bind.Unmarshaller; import org.jabref.logic.importer.Importer; +import org.jabref.logic.importer.ParseException; +import org.jabref.logic.importer.Parser; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.importer.fileformat.mods.AbstractDefinition; import org.jabref.logic.importer.fileformat.mods.DateDefinition; @@ -61,7 +67,7 @@ * More details about the format can be found here http://www.loc.gov/standards/mods/.
* The newest xml schema can also be found here www.loc.gov/standards/mods/mods-schemas.html.. */ -public class ModsImporter extends Importer { +public class ModsImporter extends Importer implements Parser { private static final Log LOGGER = LogFactory.getLog(ModsImporter.class); private static final String KEYWORD_SEPARATOR = JabRefPreferences.getInstance().getImportFormatPreferences() @@ -476,4 +482,13 @@ public String getDescription() { return "Importer for the MODS format"; } + @Override + public List parseEntries(InputStream inputStream) throws ParseException { + try { + return importDatabase(new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))).getDatabase().getEntries(); + } catch (IOException e) { + LOGGER.error(e.getLocalizedMessage(), e); + } + return Collections.emptyList(); + } } diff --git a/src/main/java/org/jabref/logic/msbib/MSBibEntry.java b/src/main/java/org/jabref/logic/msbib/MSBibEntry.java index 7e1cb3d2758..2155ee5a56f 100644 --- a/src/main/java/org/jabref/logic/msbib/MSBibEntry.java +++ b/src/main/java/org/jabref/logic/msbib/MSBibEntry.java @@ -10,6 +10,7 @@ import org.jabref.model.entry.Author; import org.jabref.model.entry.AuthorList; +import org.jabref.model.entry.Date; import org.jabref.model.strings.StringUtil; import org.w3c.dom.Document; @@ -26,14 +27,6 @@ */ class MSBibEntry { - /** - * Allows 20.3-2007|||20/3- 2007 etc. - * (\d{1,2})\s?[.,-/]\s?(\d{1,2})\s?[.,-/]\s?(\d{2,4}) - * 1-2 DIGITS SPACE SEPERATOR SPACE 1-2 DIGITS SPACE SEPERATOR SPACE 2-4 DIGITS - */ - private static final Pattern DATE_PATTERN = Pattern - .compile("(\\d{1,2})\\s*[.,-/]\\s*(\\d{1,2})\\s*[.,-/]\\s*(\\d{2,4})"); - // MSBib fields and values public Map fields = new HashMap<>(); public List authors; @@ -165,22 +158,11 @@ private void populateFromXml(Element entry) { String dayAccessed = getXmlElementTextContent("DayAccessed", entry); String yearAccessed = getXmlElementTextContent("YearAccessed", entry); - StringBuilder sbDateAccesed = new StringBuilder(); - if (monthAccessed != null) { - sbDateAccesed.append(monthAccessed); - sbDateAccesed.append(' '); - } - if (dayAccessed != null) { - sbDateAccesed.append(dayAccessed); - sbDateAccesed.append(", "); - } - if (yearAccessed != null) { - sbDateAccesed.append(yearAccessed); - } - dateAccessed = sbDateAccesed.toString().trim(); - if (dateAccessed.isEmpty() || ",".equals(dateAccessed)) { - dateAccessed = null; - } + Optional parsedDateAcessed = Date.parse(Optional.ofNullable(yearAccessed), + Optional.ofNullable(monthAccessed), + Optional.ofNullable(dayAccessed)); + + parsedDateAcessed.map(Date::getNormalized).ifPresent(date -> dateAccessed = date); NodeList nodeLst = entry.getElementsByTagNameNS("*", "Author"); if (nodeLst.getLength() > 0) { @@ -262,15 +244,7 @@ public Element getEntryDom(Document document) { addField(document, rootNode, entry.getKey(), entry.getValue()); } - // based on bibtex content - if (dateAccessed != null) { - Matcher matcher = DATE_PATTERN.matcher(dateAccessed); - if (matcher.matches() && (matcher.groupCount() >= 3)) { - addField(document, rootNode, "Month" + "Accessed", matcher.group(1)); - addField(document, rootNode, "Day" + "Accessed", matcher.group(2)); - addField(document, rootNode, "Year" + "Accessed", matcher.group(3)); - } - } + Optional.ofNullable(dateAccessed).ifPresent(field -> addDateAcessedFields(document, rootNode)); Element allAuthors = document.createElementNS(MSBibDatabase.NAMESPACE, MSBibDatabase.PREFIX + "Author"); @@ -361,6 +335,23 @@ private void addAuthor(Document document, Element allAuthors, String entryName, } + private void addDateAcessedFields(Document document, Element rootNode) { + Optional parsedDateAcesseField = Date.parse(dateAccessed); + parsedDateAcesseField.flatMap(Date::getYear).map(accYear -> accYear.toString()).ifPresent(yearAccessed -> { + addField(document, rootNode, "Year" + "Accessed", yearAccessed); + }); + + parsedDateAcesseField.flatMap(Date::getMonth) + .map(accMonth -> accMonth.getTwoDigitNumber()).ifPresent(monthAcessed -> { + addField(document, rootNode, "Month" + "Accessed", monthAcessed); + + }); + parsedDateAcesseField.flatMap(Date::getDay).map(accDay -> accDay.toString()).ifPresent(dayAccessed -> { + addField(document, rootNode, "Day" + "Accessed", dayAccessed); + }); + + } + private void addAddress(Document document, Element parent, String addressToSplit) { if (addressToSplit == null) { return; diff --git a/src/main/java/org/jabref/model/entry/Date.java b/src/main/java/org/jabref/model/entry/Date.java index 5b4db035bfd..08bb3d7f552 100644 --- a/src/main/java/org/jabref/model/entry/Date.java +++ b/src/main/java/org/jabref/model/entry/Date.java @@ -31,21 +31,25 @@ public Date(TemporalAccessor date) { * The code is essentially taken from http://stackoverflow.com/questions/4024544/how-to-parse-dates-in-multiple-formats-using-simpledateformat. */ public static Optional parse(String dateString) { - List formatStrings = Arrays.asList("uuuu-M-d", "uuuu-M", "d-M-uuuu", "M/uu", "M/uuuu", "MMMM d, uuuu", "MMMM, uuuu", + Objects.requireNonNull(dateString); + List formatStrings = Arrays.asList("uuuu-M-d", "uuuu-M", "d-M-uuuu", "M/uu", "M/uuuu", "MMMM d, uuuu", + "MMMM, uuuu", "d.M.uuuu", "uuuu.M.d", "uuuu"); - for (String formatString : formatStrings) { - try { - TemporalAccessor parsedDate = DateTimeFormatter.ofPattern(formatString).parse(dateString); - return Optional.of(new Date(parsedDate)); - } catch (DateTimeParseException ignored) { - // Ignored + + for (String formatString : formatStrings) { + try { + TemporalAccessor parsedDate = DateTimeFormatter.ofPattern(formatString).parse(dateString); + return Optional.of(new Date(parsedDate)); + } catch (DateTimeParseException ignored) { + // Ignored + } } - } return Optional.empty(); } - public static Optional parse(Optional yearValue, Optional monthValue, Optional dayValue) { + public static Optional parse(Optional yearValue, Optional monthValue, + Optional dayValue) { Optional year = yearValue.flatMap(Date::convertToInt).map(Year::of); Optional month = monthValue.flatMap(Month::parse); Optional day = dayValue.flatMap(Date::convertToInt); @@ -107,8 +111,12 @@ public TemporalAccessor toTemporalAccessor() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } Date date1 = (Date) o; return Objects.equals(getYear(), date1.getYear()) && Objects.equals(getMonth(), date1.getMonth()) && diff --git a/src/main/java/org/jabref/model/pdf/FileAnnotation.java b/src/main/java/org/jabref/model/pdf/FileAnnotation.java index 1c09eaaa78e..79e478b946c 100644 --- a/src/main/java/org/jabref/model/pdf/FileAnnotation.java +++ b/src/main/java/org/jabref/model/pdf/FileAnnotation.java @@ -12,7 +12,7 @@ public class FileAnnotation { private final static int ABBREVIATED_ANNOTATION_NAME_LENGTH = 45; private static final String DATE_TIME_STRING = "^D:\\d{14}$"; - private static final String DATE_TIME_STRING_WITH_TIME_ZONE = "^D:\\d{14}\\+.+"; + private static final String DATE_TIME_STRING_WITH_TIME_ZONE = "^D:\\d{14}.+"; private static final String ANNOTATION_DATE_FORMAT = "yyyyMMddHHmmss"; private final String author; diff --git a/src/main/java/org/jabref/model/util/TreeCollector.java b/src/main/java/org/jabref/model/util/TreeCollector.java index 2955774bc1f..28614f4d448 100644 --- a/src/main/java/org/jabref/model/util/TreeCollector.java +++ b/src/main/java/org/jabref/model/util/TreeCollector.java @@ -40,7 +40,7 @@ private TreeCollector(Function> getChildren, BiConsumer addChil } public static > TreeCollector mergeIntoTree(BiPredicate equivalence) { - return new TreeCollector( + return new TreeCollector<>( TreeNode::getChildren, (parent, child) -> child.moveTo(parent), equivalence); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 946001eef94..4ffcccd55cd 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -185,9 +185,7 @@ public class JabRefPreferences implements PreferencesService { public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CA = "editorEMACSkeyBindingsRebindCA"; public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CF = "editorEMACSkeyBindingsRebindCF"; public static final String GROUPS_DEFAULT_FIELD = "groupsDefaultField"; - public static final String GROUP_INVERT_SELECTIONS = "groupInvertSelections"; public static final String GROUP_INTERSECT_SELECTIONS = "groupIntersectSelections"; - public static final String GROUP_FLOAT_SELECTIONS = "groupFloatSelections"; public static final String KEYWORD_SEPARATOR = "groupKeywordSeparator"; public static final String AUTO_ASSIGN_GROUP = "autoAssignGroup"; public static final String LIST_OF_FILE_COLUMNS = "listOfFileColumns"; @@ -568,9 +566,7 @@ private JabRefPreferences() { defaults.put(EDITOR_EMACS_KEYBINDINGS_REBIND_CF, Boolean.TRUE); defaults.put(AUTO_COMPLETE, Boolean.FALSE); AutoCompletePreferences.putDefaults(defaults); - defaults.put(GROUP_FLOAT_SELECTIONS, Boolean.TRUE); - defaults.put(GROUP_INTERSECT_SELECTIONS, Boolean.TRUE); - defaults.put(GROUP_INVERT_SELECTIONS, Boolean.FALSE); + defaults.put(GROUP_INTERSECT_SELECTIONS, Boolean.FALSE); defaults.put(GROUPS_DEFAULT_FIELD, FieldName.KEYWORDS); defaults.put(AUTO_ASSIGN_GROUP, Boolean.TRUE); defaults.put(KEYWORD_SEPARATOR, ", "); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index b2cd3e0416c..395756a5870 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Alle_posterne_af_d All_fields=Alle_felter -All_subgroups_(recursively)=Alle_undergrupper_(rekursivt) - Always_reformat_BIB_file_on_save_and_export= A_SAX_exception_occurred_while_parsing_'%0'\:=En_SAXException_forekom_ved_læsning_af_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Vis_kommandolinjehjælp Display_only_entries_belonging_to_all_selected_groups.=Vis_kun_poster_indeholdt_i_alle_valgte_grupper. Display_version=Vis_versionsnummer -Displaying_no_groups=Viser_ingen_grupper - Do_not_abbreviate_names=Forkort_ikke_navn Do_not_automatically_set=Sæt_ikke_links_automatisk @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Genererede_BibTeX-nøgle_for Generating_BibTeX_key_for=Genererer_BibTeX-nøgle_for Get_fulltext= -Gray_out_entries_not_in_group_selection=Skraver_poster_udenfor_valgte_grupper - Gray_out_non-hits=Skraver_ikke-træffere Groups=Gruppering @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Har_du_valgt_korrekt_pakke-sti? Help=Hjælp -Help_on_groups=Hjælp_om_grupper - Help_on_key_patterns=Hjælp_om_nøglegenerering Help_on_regular_expression_search=Hjælp_om_søgning_med_regulære_udtryk @@ -612,8 +604,6 @@ Icon=Ikon Ignore=Ignorer -Immediate_subgroups=Nærmeste_undergrupper - Import=Importer Import_and_keep_old_entry=Importer_og_behold_den_gamle_post @@ -671,8 +661,6 @@ Invalid_date_format=Ugyldigt_datoformat Invalid_URL=Ugyldig_URL -Inverted=Inverteret - Online_help= JabRef_preferences=JabRef-indstillinger @@ -760,7 +748,6 @@ modify_group=ændre_gruppe Move_down=Flyt_ned -Move_entries_in_group_selection_to_the_top=Flyt_poster_i_valgte_grupper_til_toppen Move_external_links_to_'file'_field=Flyt_eksterne_links_til_'file'-feltet move_group=flyt_gruppe @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Vis_dialog_for_at_bekræfte_sletn Show_description=Vis_beskrivelse -Show_entries_not_in_group_selection=Vis_poster_udenfor_valgte_grupper - Show_file_column=Vis_'file'-kolonne Show_last_names_only=Vis_kun_efternavn @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Sprang_over_-_PDF-filen_findes_ikke Skipped_entry.=Sprang_over_post. -Sort_alphabetically=Sorter_alfabetisk - -sort_subgroups=sorter_undergrupper - -Sorted_all_subgroups_recursively.=Sorterede_alle_undergrupper_rekursivt. - -Sorted_immediate_subgroups.=Sorterede_nærmeste_undergrupper. - source_edit=redigering_af_kilde Special_name_formatters=Specielle_navneformateringer diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 9ac956f6419..1067d4340df 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Alle_Einträge_die All_fields=Alle_Felder -All_subgroups_(recursively)=Alle_Untergruppen_(rekursiv) - Always_reformat_BIB_file_on_save_and_export=Formatiere_BIB_Datei_immer_neu_beim_Exportieren A_SAX_exception_occurred_while_parsing_'%0'\:=Beim_Parsen_von_'%0'_ist_eine_SAX-Exception_aufgetreten\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Zeige_Kommandozeilenhilfe Display_only_entries_belonging_to_all_selected_groups.=Nur_Einträge_anzeigen,_die_zu_allen_ausgewählten_Gruppen_gehören. Display_version=Version_anzeigen -Displaying_no_groups=Keine_Gruppen_anzeigen - Do_not_abbreviate_names=Namen_nicht_abkürzen Do_not_automatically_set=Nicht_automatisch_zuordnen @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=BibTeX-Key_erzeugt_für Generating_BibTeX_key_for=Erzeuge_BibTeX-Key_für Get_fulltext=Hole_Volltext -Gray_out_entries_not_in_group_selection=Einträge_ausblenden,_die_nicht_in_der_Gruppenauswahl_sind - Gray_out_non-hits=Nicht-Treffer_grau_einfärben Groups=Gruppen @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Habe_Sie_den_richtigen_Klassenpfad_gew Help=Hilfe -Help_on_groups=Hilfe_zu_Gruppen - Help_on_key_patterns=Hilfe_zu_BibTeX-Key-Mustern Help_on_regular_expression_search=Hilfe_zur_Suche_mit_regulärem_Ausdruck @@ -612,8 +604,6 @@ Icon=Icon Ignore=Ignorieren -Immediate_subgroups=Direkte_Untergruppen - Import=Importieren Import_and_keep_old_entry=Importieren_und_alten_Eintrag_behalten @@ -671,8 +661,6 @@ Invalid_date_format=Ungültiges_Datumsformat Invalid_URL=Ungültige_URL -Inverted=Invertiert - Online_help=Online_Hilfe JabRef_preferences=JabRef_Einstellungen @@ -760,7 +748,6 @@ modify_group=Gruppe_bearbeiten Move_down=Nach_unten -Move_entries_in_group_selection_to_the_top=Sortiere_Einträge_der_Gruppenauswahl_nach_oben Move_external_links_to_'file'_field=Externe_Links_in_das_Feld_'file'_verschieben move_group=Gruppe_verschieben @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Dialog_zum_Löschen_von_Einträge Show_description=Beschreibung_anzeigen -Show_entries_not_in_group_selection=Zeige_Einträge,_die_nicht_in_der_Gruppenauswahl_sind - Show_file_column=Datei-Spalte_anzeigen Show_last_names_only=Zeige_nur_Nachnamen @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Übersprungen_-_PDF_exisitert_nicht Skipped_entry.=Eintrag_übersprungen. -Sort_alphabetically=Alphabetisch_sortieren - -sort_subgroups=Untergruppen_sortieren - -Sorted_all_subgroups_recursively.=Alle_Untergruppen_rekursiv_sortiert. - -Sorted_immediate_subgroups.=Alle_direkten_Untergruppen_sortiert. - source_edit=Quelltextbearbeitung Special_name_formatters=Spezielle_Namens-Formatierer diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index bb2264f24cd..11385b6ee24 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=All_entries_of_thi All_fields=All_fields -All_subgroups_(recursively)=All_subgroups_(recursively) - Always_reformat_BIB_file_on_save_and_export=Always_reformat_BIB_file_on_save_and_export A_SAX_exception_occurred_while_parsing_'%0'\:=A_SAX_exception_occurred_while_parsing_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Display_help_on_command_line_options Display_only_entries_belonging_to_all_selected_groups.=Display_only_entries_belonging_to_all_selected_groups. Display_version=Display_version -Displaying_no_groups=Displaying_no_groups - Do_not_abbreviate_names=Do_not_abbreviate_names Do_not_automatically_set=Do_not_automatically_set @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Generated_BibTeX_key_for Generating_BibTeX_key_for=Generating_BibTeX_key_for Get_fulltext=Get_fulltext -Gray_out_entries_not_in_group_selection=Gray_out_entries_not_in_group_selection - Gray_out_non-hits=Gray_out_non-hits Groups=Groups @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Have_you_chosen_the_correct_package_pa Help=Help -Help_on_groups=Help_on_groups - Help_on_key_patterns=Help_on_key_patterns Help_on_regular_expression_search=Help_on_regular_expression_search @@ -612,8 +604,6 @@ Icon=Icon Ignore=Ignore -Immediate_subgroups=Immediate_subgroups - Import=Import Import_and_keep_old_entry=Import_and_keep_old_entry @@ -671,8 +661,6 @@ Invalid_date_format=Invalid_date_format Invalid_URL=Invalid_URL -Inverted=Inverted - Online_help=Online_help JabRef_preferences=JabRef_preferences @@ -760,7 +748,6 @@ modify_group=modify_group Move_down=Move_down -Move_entries_in_group_selection_to_the_top=Move_entries_in_group_selection_to_the_top Move_external_links_to_'file'_field=Move_external_links_to_'file'_field move_group=move_group @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Show_confirmation_dialog_when_del Show_description=Show_description -Show_entries_not_in_group_selection=Show_entries_not_in_group_selection - Show_file_column=Show_file_column Show_last_names_only=Show_last_names_only @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Skipped_-_PDF_does_not_exist Skipped_entry.=Skipped_entry. -Sort_alphabetically=Sort_alphabetically - -sort_subgroups=sort_subgroups - -Sorted_all_subgroups_recursively.=Sorted_all_subgroups_recursively. - -Sorted_immediate_subgroups.=Sorted_immediate_subgroups. - source_edit=source_edit Special_name_formatters=Special_name_formatters diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 8ddc2b2ed6c..45c5bd953ac 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Todas_las_entradas All_fields=Todos_los_campos -All_subgroups_(recursively)=Todos_los_subgrupos(Recursivamente) - Always_reformat_BIB_file_on_save_and_export=Siempre_reformatear_el_fichero_BIB_al_guardar_y_exportar A_SAX_exception_occurred_while_parsing_'%0'\:=Ocurrió_una_Excepción_SAX_mientras_se_analizaba_la_sintaxis_de_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Mosrar_ayuda_en_las_opciones_de_línea_de_c Display_only_entries_belonging_to_all_selected_groups.=Mostrar_sólo_entradas_pertenecientes_a_todos_los_grupos_seleccionados. Display_version=Mostrar_versión -Displaying_no_groups=No_se_muestran_grupos - Do_not_abbreviate_names=No_abreviar_nombres Do_not_automatically_set=No_establecer_automáticamente @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Generar_clabe_BibTeX_para Generating_BibTeX_key_for=Generarando_clave_BibTeX_para Get_fulltext=Obtener_texto_completo -Gray_out_entries_not_in_group_selection=Poner_en_gris_entradas_que_no_estén_en_el_grupo_de_selección - Gray_out_non-hits=Poner_en_gris_los_no_encontrados Groups=Grupos @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=¿Ha_escogido_la_ruta_de_paquetes_corr Help=Ayuda -Help_on_groups=Ayuda_sobre_grupos - Help_on_key_patterns=Ayuda_sobre_patrones_de_teclas Help_on_regular_expression_search=Ayuda_sobre_búsqueda_mediante_expresión_regular @@ -612,8 +604,6 @@ Icon=Icono Ignore=Ignorar -Immediate_subgroups=Subgrupos_inmediatos - Import=Importar Import_and_keep_old_entry=Importar_y_conservar_entrada_antigua @@ -671,8 +661,6 @@ Invalid_date_format=Formato_de_fecha_no_válido Invalid_URL=URL_no_válida -Inverted=Invertido - Online_help=Ayuda_online JabRef_preferences=Preferencias_de_JabRef @@ -760,7 +748,6 @@ modify_group=Modificar_grupo Move_down=Mover_hacia_abajo -Move_entries_in_group_selection_to_the_top=Mover_entradas_en_el_grupo_seleccionado_al_inicio Move_external_links_to_'file'_field=Mover_enlaces_externos_al_campo_'archivo' move_group=Mover_grupo @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Mostra_diálogo_de_confirmación_ Show_description=Mostrar_descripción -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_last_names_only=Mostrar_sólo_apellidos @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Omitido_-_No_existe_el_PDF Skipped_entry.=Entrada_omitida. -Sort_alphabetically=Ordenar_alfabéticamente - -sort_subgroups=ordenar_subgrupos - -Sorted_all_subgroups_recursively.=Ordenar_todos_los_subgrupos_recursivamente. - -Sorted_immediate_subgroups.=Subgrupos_inmediatos_ordenados. - source_edit=editar_fuente Special_name_formatters=Formateadores_con_nombre_especial diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index ddbe5713999..77fef62ff50 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?= All_fields= -All_subgroups_(recursively)= - Always_reformat_BIB_file_on_save_and_export= A_SAX_exception_occurred_while_parsing_'%0'\:= @@ -352,8 +350,6 @@ Display_help_on_command_line_options= Display_only_entries_belonging_to_all_selected_groups.= Display_version= -Displaying_no_groups= - Do_not_abbreviate_names= Do_not_automatically_set= @@ -577,8 +573,6 @@ Generated_BibTeX_key_for= Generating_BibTeX_key_for= Get_fulltext= -Gray_out_entries_not_in_group_selection= - Gray_out_non-hits= Groups= @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?= Help= -Help_on_groups= - Help_on_key_patterns= Help_on_regular_expression_search= @@ -612,8 +604,6 @@ Icon= Ignore= -Immediate_subgroups= - Import= Import_and_keep_old_entry= @@ -671,8 +661,6 @@ Invalid_date_format= Invalid_URL= -Inverted= - Online_help= JabRef_preferences= @@ -760,7 +748,6 @@ modify_group= Move_down= -Move_entries_in_group_selection_to_the_top= Move_external_links_to_'file'_field= move_group= @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries= Show_description= -Show_entries_not_in_group_selection= - Show_file_column= Show_last_names_only= @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist= Skipped_entry.= -Sort_alphabetically= - -sort_subgroups= - -Sorted_all_subgroups_recursively.= - -Sorted_immediate_subgroups.= - source_edit= Special_name_formatters= diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 94f0d637875..c9c63d16c23 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Toutes_les_entrée All_fields=Tous_les_champs -All_subgroups_(recursively)=Tous_les_sous-groupes_(récursivement) - Always_reformat_BIB_file_on_save_and_export=Toujours_remettre_en_forme_les_fichiers_BIB_lors_de_l'enregistrement_et_de_l'exportation A_SAX_exception_occurred_while_parsing_'%0'\:=Une_exception_SAX_est_survenue_pendant_le_traitement_de_'%0'_\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Afficher_l'aide_sur_les_options_de_la_ligne Display_only_entries_belonging_to_all_selected_groups.=Afficher_uniquement_les_entrées_appartenant_à_tous_les_groupes_sélectionnés. Display_version=Afficher_la_version -Displaying_no_groups=Pas_de_groupes_à_afficher - Do_not_abbreviate_names=Ne_pas_abréger_les_noms Do_not_automatically_set=Ne_pas_définir_automatiquement. @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Création_terminée_de_la_clef_BibTeX_pour Generating_BibTeX_key_for=Création_en_cours_d'une_clef_BibTeX_pour Get_fulltext=Obtenir_le_document -Gray_out_entries_not_in_group_selection=Griser_les_entrées_hors_de_la_sélection - Gray_out_non-hits=Griser_les_entrées_non_correspondantes Groups=Groupes @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Avez-vous_choisi_le_bon_chemin_pour_le Help=Aide -Help_on_groups=Aide_sur_les_groupes - Help_on_key_patterns=Aide_sur_le_paramétrage_des_clefs Help_on_regular_expression_search=Aide_sur_la_recherche_d'une_expression_régulière @@ -612,8 +604,6 @@ Icon=Icône Ignore=Ignorer -Immediate_subgroups=Uniquement_les_sous-groupes_directs - Import=Importer Import_and_keep_old_entry=Importer_et_conserver_l'ancienne_entrée @@ -671,8 +661,6 @@ Invalid_date_format=Format_de_date_invalide Invalid_URL=URL_invalide -Inverted=Complémentaire - Online_help=Aide_en_ligne JabRef_preferences=Préférences_pour_JabRef @@ -760,7 +748,6 @@ modify_group=Modifier_le_groupe 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 Move_external_links_to_'file'_field=Déplacer_les_liens_externes_vers_le_champ_'fichier' move_group=déplacer_le_groupe @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Demander_une_confirmation_lors_de Show_description=Montrer_la_description -Show_entries_not_in_group_selection=Montrer_les_entrées_non_sélectionnées - Show_file_column=Afficher_la_colonne_Fichier Show_last_names_only=Afficher_uniquement_les_noms_propres @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Omis_-_Le_PDF_n'existe_pas Skipped_entry.=Entrée_omise -Sort_alphabetically=Classer_alphabétiquement - -sort_subgroups=trier_les_sous-groupes - -Sorted_all_subgroups_recursively.=Tous_les_sous-groupes_récursivement_triés. - -Sorted_immediate_subgroups.=Sous-groupes_directs_triés. - source_edit=édition_du_source Special_name_formatters=Formateurs_de_nom_spéciaux diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties index 63b8a115ce5..5cf62453596 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_in.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Semua_entri_tipe_i All_fields=Semua_bidang -All_subgroups_(recursively)=Semua_anak_grup_(rekursif) - Always_reformat_BIB_file_on_save_and_export= A_SAX_exception_occurred_while_parsing_'%0'\:=SAXException_terjadi_ketika_mengurai_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Tampilkan_bantuan_pada_opsi_perindah_baris Display_only_entries_belonging_to_all_selected_groups.=Tampilkan_entri_hanya_yang_ada_di_grup_pilihan. Display_version=Tampilkan_versi -Displaying_no_groups=Grup_tidak_ditampilkan - Do_not_abbreviate_names=Jangan_singkat_nama Do_not_automatically_set=Jangan_pengaturan_otomatis @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Kunci_BibTeX_dibuat_untuk Generating_BibTeX_key_for=Membuat_kunci_BibTeX_untuk Get_fulltext= -Gray_out_entries_not_in_group_selection=Kelabukan_entri_yang_tidak_dalam_pilihan_grup - Gray_out_non-hits=Kelabukan_non-hits Groups=Grup @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Apakah_anda_sudah_memilih_lokasi_paket Help=Bantuan -Help_on_groups=Bantuan_untuk_grup - Help_on_key_patterns=Bantuan_untuk_pola_kunci Help_on_regular_expression_search=Bantuan_untuk_Pencarian_Ekspresi_Reguler @@ -612,8 +604,6 @@ Icon=Ikon Ignore=Abaikan -Immediate_subgroups=sub-grup_seketika - Import=Impor Import_and_keep_old_entry=Impor_dan_pertahankan_entri_lama @@ -671,8 +661,6 @@ Invalid_date_format=Format_hari_salah Invalid_URL=URL_salah -Inverted=Dibalik - Online_help= JabRef_preferences=Preferensi_JabRef @@ -760,7 +748,6 @@ modify_group=memodifikasi_grup Move_down=Pindah_kebawah -Move_entries_in_group_selection_to_the_top=Pindah_entri_dalam_grup_pilihan_ke_atas Move_external_links_to_'file'_field=Pindah_tautan_eksternal_ke_bidang_'berkas' move_group=pindah_grup @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Tampilkan_dialog_konfirmasi_jika_ Show_description=Tampilkan_deskripsi -Show_entries_not_in_group_selection=Tampilkan_entri_tidak_dalam_pilihan_grup - Show_file_column=Tampilkan_kolom_berkas Show_last_names_only=Tampil_hanya_nama_belakang @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Dilompati_-_PDF_tidak_ada Skipped_entry.=Entri_dilompati. -Sort_alphabetically=Urut_alfabet - -sort_subgroups=urut_sub-grup - -Sorted_all_subgroups_recursively.=Diurutkan_semua_sub-grup_secara_rekursif - -Sorted_immediate_subgroups.=Diurutkan_sub-grup_seketika. - source_edit=sunting_sumber Special_name_formatters=Pemformat_Nama_Spesial diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 8d9727cb899..f7251d8f8a4 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Tutte_le_voci_di_q All_fields=Tutti_i_campi -All_subgroups_(recursively)=Tutti_i_sottogruppi_(ricorsivamente) - Always_reformat_BIB_file_on_save_and_export=Riformatta_sempre_il_file_BIB_quando_salvi_o_esporti A_SAX_exception_occurred_while_parsing_'%0'\:=Eccezione_SAX_durante_l'analisi_di_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Mostra_l'aiuto_sulle_opzioni_della_riga_di_ Display_only_entries_belonging_to_all_selected_groups.=Mostra_solo_le_voci_appartenenti_a_tutti_i_gruppi_selezionati. Display_version=Versione -Displaying_no_groups=Nessun_gruppo_da_visualizzare - Do_not_abbreviate_names=Non_abbreviare_i_nomi Do_not_automatically_set=Non_effettuare_definizioni_automatiche @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Generata_la_chiave_BibTeX_per Generating_BibTeX_key_for=Generazione_in_corso_della_chiave_BibTeX_per Get_fulltext=Prendi_testo_completo -Gray_out_entries_not_in_group_selection=Evidenzia_in_grigio_le_voci_fuori_dai_gruppi_selezionati - Gray_out_non-hits=Disattiva_le_voci_non_corrispondenti Groups=Gruppi @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Il_classpath_è_corretto? Help=Aiuto -Help_on_groups=Aiuto_sui_gruppi - Help_on_key_patterns=Aiuto_sulla_composizione_delle_chiavi Help_on_regular_expression_search=Aiuto_sulla_ricerca_di_un'espressione_regolare @@ -612,8 +604,6 @@ Icon=Icona Ignore=Ignora -Immediate_subgroups=Sottogruppi_diretti - Import=Importa Import_and_keep_old_entry=Importa_e_mantieni_le_vecchie_voci @@ -671,8 +661,6 @@ Invalid_date_format=Formato_data_non_valido Invalid_URL=URL_non_valido -Inverted=Complementare - Online_help=Help_online JabRef_preferences=Preferenze_JabRef @@ -760,7 +748,6 @@ modify_group=modifica_gruppo Move_down=Sposta_in_giù -Move_entries_in_group_selection_to_the_top=Sposta_le_voci_selezionate_in_su Move_external_links_to_'file'_field=Sposta_i_collegamenti_esterni_nel_campo_'file' move_group=sposta_gruppo @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Chiedere_conferma_della_cancellaz Show_description=Mostra_descrizione -Show_entries_not_in_group_selection=Mostra_le_voci_non_comprese_nei_gruppi_selezionati - Show_file_column=Visualizza_la_colonna_File Show_last_names_only=Mostra_solo_i_cognomi @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Saltato_-_Il_file_PDF_non_esiste Skipped_entry.=Voce_saltata -Sort_alphabetically=Ordina_alfabeticamente - -sort_subgroups=ordina_i_sottogruppi - -Sorted_all_subgroups_recursively.=Ordina_tutti_i_sottogruppi_ricorsivamente. - -Sorted_immediate_subgroups.=Ordinati_i_sottogruppi_immediati. - source_edit=modifica_sorgente Special_name_formatters=Formattazioni_speciali_dei_nomi diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 5cf62087ac7..5c9ea80343c 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=この型の項目 All_fields=全フィールド -All_subgroups_(recursively)=全下層グループ(再帰的に) - Always_reformat_BIB_file_on_save_and_export=保存・書出の際、つねにBIBファイルを再整形する A_SAX_exception_occurred_while_parsing_'%0'\:=「%0」を解析中にSAX例外エラーが発生しました\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=コマンドラインオプションに関 Display_only_entries_belonging_to_all_selected_groups.=選択したグループ全てに属する項目のみ表示する。 Display_version=バージョンを表示 -Displaying_no_groups=グループを表示しない - Do_not_abbreviate_names=名前を略さない Do_not_automatically_set=自動設定しない @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=以下の項目のBibTeX鍵を生成しました\: Generating_BibTeX_key_for=以下の項目のBibTeX鍵を生成しています\: Get_fulltext=フルテキストを得る -Gray_out_entries_not_in_group_selection=グループ選択にない項目を淡色化する - Gray_out_non-hits=合致しないものを淡色化 Groups=グループ @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=正しいパッケージパスを選 Help=ヘルプ -Help_on_groups=グループに関するヘルプ - Help_on_key_patterns=キーパターンに関するヘルプ Help_on_regular_expression_search=正規表現検索に関するヘルプ @@ -612,8 +604,6 @@ Icon=アイコン Ignore=無視 -Immediate_subgroups=直下の下層グループ - Import=読み込み Import_and_keep_old_entry=読み込みを行い、旧項目は維持 @@ -671,8 +661,6 @@ Invalid_date_format=無効な日付書式です Invalid_URL=無効なURLです -Inverted=否定 - Online_help=オンラインヘルプ JabRef_preferences=JabRefの設定 @@ -760,7 +748,6 @@ modify_group=グループを修正 Move_down=下げる -Move_entries_in_group_selection_to_the_top=グループ選択中の項目を上に移動 Move_external_links_to_'file'_field=外部リンクを「ファイル」フィールドに移動 move_group=グループを移動 @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=項目を削除する際に確認 Show_description=説明を表示 -Show_entries_not_in_group_selection=グループ選択に「ない」項目を表示する - Show_file_column=ファイル列を表示 Show_last_names_only=姓のみを表示する @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=跳ばしました_-_PDFが存在しません Skipped_entry.=項目を跳ばしました。 -Sort_alphabetically=アルファベット順に整序 - -sort_subgroups=下層グループを整序 - -Sorted_all_subgroups_recursively.=下層グループをすべて再帰的に整序しました。 - -Sorted_immediate_subgroups.=直下の下層グループを整序しました。 - source_edit=ソースの編集 Special_name_formatters=名前の整形の定義 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index ce725f8b4ea..df337381b16 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?= All_fields=Alle_velden -All_subgroups_(recursively)=Alle_subgroepen_(recursief) - Always_reformat_BIB_file_on_save_and_export= A_SAX_exception_occurred_while_parsing_'%0'\:= @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Toon_help_over_commandline_opties Display_only_entries_belonging_to_all_selected_groups.=Toon_alleen_entries_die_tot_alle_geselecteerde_groepen_behoren. Display_version=Display_versie -Displaying_no_groups=Geen_groepen_tonend - Do_not_abbreviate_names=Namen_niet_afkorten Do_not_automatically_set=Niet_automatisch_instellen @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Gegenereerde_BibTeX-sleutel_voor Generating_BibTeX_key_for=BibTeX-sleutel_aan_het_genereren_voor Get_fulltext= -Gray_out_entries_not_in_group_selection=Maak_entries_die_niet_in_de_groep_selectie_zitten_grijs - Gray_out_non-hits=Maak_niet_gevonden_items_grijs Groups=Groepen @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Heeft_u_het_correcte_pakket_pad_gekoze Help=Help -Help_on_groups=Help_over_groepen - Help_on_key_patterns=Help_over_sleutelpatronen Help_on_regular_expression_search=Help_over_Regular_Expression_Zoekopdracht @@ -612,8 +604,6 @@ Icon= Ignore=Negeren -Immediate_subgroups=Directe_subgroepen - Import=Importeren Import_and_keep_old_entry=Importeren_en_oude_entry_behouden @@ -671,8 +661,6 @@ Invalid_date_format=Ongeldig_datumformaat Invalid_URL=Ongeldige_URL -Inverted=Ge\u00efnverteerd - Online_help= JabRef_preferences=JabRef_instellingen @@ -760,7 +748,6 @@ modify_group=wijzig_groep Move_down=Verplaats_naar_beneden -Move_entries_in_group_selection_to_the_top=Verplaats_entries_in_de_groep_selectie_naar_de_top Move_external_links_to_'file'_field= move_group=verplaats_groep @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Toon_bevestigingsdialoog_bij_verw Show_description=Toon_beschrijving -Show_entries_not_in_group_selection=Toon_entries_die_zich_niet_in_de_groep_selectie_bevinden - Show_file_column= Show_last_names_only=Toon_enkel_laatste_namen @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Overgeslagen_-_PDF_bestaat_niet Skipped_entry.=Overgeslagen_entry. -Sort_alphabetically=Alphabetisch_sorteren - -sort_subgroups=subgroepen_sorteren - -Sorted_all_subgroups_recursively.=Alle_subgroepen_recursief_gesorteerd. - -Sorted_immediate_subgroups.=Onmiddellijke_subgroepen_sorteren. - source_edit=broncode_aanpassen Special_name_formatters= diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index 2e4512a0b40..98619ebcb9b 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Alle_enhetene_av_d All_fields=Alle_felter -All_subgroups_(recursively)=Alle_undergrupper_(rekursivt) - Always_reformat_BIB_file_on_save_and_export= A_SAX_exception_occurred_while_parsing_'%0'\:=En_SAXException_forekom_ved_lesing_av_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Vis_kommandolinjehjelp Display_only_entries_belonging_to_all_selected_groups.=Vis_kun_enheter_inneholdt_i_alle_valgte_grupper. Display_version=Vis_versjonsnummer -Displaying_no_groups=Viser_ingen_grupper - Do_not_abbreviate_names=Ikke_forkort_navn Do_not_automatically_set=Ikke_sett_linker_automatisk @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Genererte_BibTeX-n\u00f8kkel_for Generating_BibTeX_key_for=Genererer_BibTeX-n\u00f8kkel_for Get_fulltext= -Gray_out_entries_not_in_group_selection=Skraver_enheter_utenfor_valgte_grupper - Gray_out_non-hits=Vis_ikke-treff_i-gr\u00e5tt Groups=Gruppering @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Har_du_valgt_riktig_pakkenavn? Help=Hjelp -Help_on_groups=Hjelp_om_grupper - Help_on_key_patterns=Hjelp_om_n\u00f8kkelgenerering Help_on_regular_expression_search=Hjelp_for_s\u00f8k_med_regul\u00e6ruttrykk @@ -612,8 +604,6 @@ Icon=Ikon Ignore=Ignorer -Immediate_subgroups=N\u00e6rmeste_undergrupper - Import=Importer Import_and_keep_old_entry=Importer_og_behold_den_gamle_enheten @@ -671,8 +661,6 @@ Invalid_date_format=Ugyldig_datoformat Invalid_URL=Ugyldig_URL -Inverted=Invertert - Online_help= JabRef_preferences=JabRef-oppsett @@ -760,7 +748,6 @@ modify_group=endre_gruppe Move_down=Flytt_ned -Move_entries_in_group_selection_to_the_top=Flytt_enheter_i_valgte_grupper_\u00f8verst Move_external_links_to_'file'_field=Flytt_eksterne_linker_til_'file'-feltet move_group=flytt_gruppe @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Vis_dialog_for_\u00e5_bekrefte_sl Show_description=Vis_beskrivelse -Show_entries_not_in_group_selection=Vis_enheter_utenfor_valgte_grupper - Show_file_column=Vis_'file'-kolonne Show_last_names_only=Vis_bare_etternavn @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Hoppet_over_-_PDF-filen_finnes_ikke Skipped_entry.=Hoppet_over_enhet. -Sort_alphabetically=Sorter_alfabetisk - -sort_subgroups=sorter_undergrupper - -Sorted_all_subgroups_recursively.=Sorterte_alle_undergrupper_rekursivt. - -Sorted_immediate_subgroups.=Sorterte_n\u00e6rmeste_undergrupper. - source_edit=redigering_av_kilde Special_name_formatters=Spesielle_navneformaterere diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 9a1a4f4be10..1c324798b14 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Todas_as_referênc All_fields=Todos_os_campos -All_subgroups_(recursively)=Todos_os_subgrupos_(recursivamente) - Always_reformat_BIB_file_on_save_and_export= A_SAX_exception_occurred_while_parsing_'%0'\:=Uma_exceção_ocorreu_durante_a_análise_de_'%0' @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Exibir_ajuda_para_opções_de_linha_de_coma Display_only_entries_belonging_to_all_selected_groups.=Exibir_apenas_referências_pertencentes_aos_grupos_selecionados. Display_version=Exibir_versão -Displaying_no_groups=Nenhum_grupo_sendo_exibido - Do_not_abbreviate_names=Não_abreviar_nomes Do_not_automatically_set=Não_definir_automaticamente @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Chave_BibTeX_gerada_para Generating_BibTeX_key_for=Gerando_chave_BibTeX_para Get_fulltext= -Gray_out_entries_not_in_group_selection=Esmaecer_referências_fora_da_seleção_do_grupo - Gray_out_non-hits=Esmaecer_referências_não_encontradas Groups=Grupos @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Você_escolheu_o_caminho_de_pacote_cor Help=Ajuda -Help_on_groups=Ajuda_sobre_grupos - Help_on_key_patterns=Ajuda_sobre_modelos_de_chave Help_on_regular_expression_search=Ajuda_sobre_busca_por_expressão_regular @@ -612,8 +604,6 @@ Icon=Ícone Ignore=Ignorar -Immediate_subgroups=Subgrupos_imediatos - Import=Importar Import_and_keep_old_entry=Importar_e_manter_referências_antigas @@ -671,8 +661,6 @@ Invalid_date_format=Formato_de_data_inválido Invalid_URL=URL_inválida -Inverted=invertido - Online_help= JabRef_preferences=Preferências_do_JabRef @@ -760,7 +748,6 @@ modify_group=Modificar_grupo Move_down=Mover_para_baixo -Move_entries_in_group_selection_to_the_top=Mover_referências_nos_grupos_selecionados_para_o_topo Move_external_links_to_'file'_field=Mover_links_externos_para_o_campo_'arquivo' move_group=mover_grupo @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Exibir_diálogo_de_confirmação_ Show_description=Exibir_descrição -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_last_names_only=Exibir_apenas_últimos_nomes @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Omitido_-_O_PDF_não_existe Skipped_entry.=Referência_omitida. -Sort_alphabetically=Ordenar_alfabeticamente - -sort_subgroups=ordenar_subgrupos - -Sorted_all_subgroups_recursively.=Todos_os_grupos_foram_recursivamente_ordenados. - -Sorted_immediate_subgroups.=Grupos_imediatos_ordenados. - source_edit=edição_de_fonte Special_name_formatters=Formatadores_de_nome_espepciais diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 7d1ca0bcb38..289c44321d5 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Все_запис All_fields=Все_поля -All_subgroups_(recursively)=Все_подгруппы_(рекурсивно) - Always_reformat_BIB_file_on_save_and_export=Всегда_преобразовывать_формат_файла_BIB_при_сохранении_и_экспорте A_SAX_exception_occurred_while_parsing_'%0'\:=Исключение_SAX_при_анализе_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Отображать_справку_по_п Display_only_entries_belonging_to_all_selected_groups.=Отображать_только_записи,_принадлежащие_всем_выбранным_группам. Display_version=Отобразить_сведения_о_версии -Displaying_no_groups=Без_отображения_групп - Do_not_abbreviate_names=Не_сокращать_названия Do_not_automatically_set=Без_автоопределения @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Создать_ключ_BibTeX_для Generating_BibTeX_key_for=Создание_ключа_BibTeX_для Get_fulltext=Получить_весь_текст -Gray_out_entries_not_in_group_selection=Деактивировать_записи,_не_выделенные_в_группу - Gray_out_non-hits=Деактивировать_неподходящие Groups=Группы @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Проверьте_правильно Help=Справка -Help_on_groups=Справка_по_группам - Help_on_key_patterns=Справка_по_шаблонам_ключей Help_on_regular_expression_search=Справка_по_поиску_с_помощью_регулярных_выражений @@ -612,8 +604,6 @@ Icon=Значок Ignore=Пропуск -Immediate_subgroups=Непосредственные_подгруппы - Import=Импорт Import_and_keep_old_entry=Импорт_с_сохранением_старой_записи @@ -671,8 +661,6 @@ Invalid_date_format=Недопустимый_формат_даты Invalid_URL=Недопустимый_URL-адрес -Inverted=Обратный - Online_help=Онлайн-справка JabRef_preferences=Пользовательские_настройки_JabRef @@ -760,7 +748,6 @@ modify_group=модифицировать_группу Move_down=Переместить_вниз -Move_entries_in_group_selection_to_the_top=Переместить_выделенные_записи_вверх Move_external_links_to_'file'_field=Переместить_внешние_ссылки_в_поле_'файл' move_group=переместить_группу @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Запрос_подтвержде Show_description=Показать_описание -Show_entries_not_in_group_selection=Показать_записи_не_выбранные_в_группе - Show_file_column=Показать_столбец_Файл Show_last_names_only=Показать_только_фамилии @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Пропущено_-_PDF_не_существует Skipped_entry.=Запись_пропущена. -Sort_alphabetically=Сортировка_в_алфавитном_порядке - -sort_subgroups=сортировка_подгрупп - -Sorted_all_subgroups_recursively.=Все_подгруппы_с_рекурсивной_сортировкой. - -Sorted_immediate_subgroups.=Непосредственные_подгруппы_с_сортировкой. - source_edit=изменение_источника Special_name_formatters=Особые_программы_форматирования_имени diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index ed60d53fdab..83bd5391554 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Alla_poster_av_den All_fields=Alla_fält -All_subgroups_(recursively)=Alla_undergrupper_(rekursivt) - Always_reformat_BIB_file_on_save_and_export=Formattera_alltid_om_BIB-filen_vid_när_den_sparas_eller_exporteras A_SAX_exception_occurred_while_parsing_'%0'\:=Ett_SAX-undantag_inträffade_när_'%0'_tolkades\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Visa_hjälp_för_kommandoradsalternativ Display_only_entries_belonging_to_all_selected_groups.=Visa_bara_poster_som_ingår_i_alla_valda_grupper. Display_version=Visa_version -Displaying_no_groups=Visar_inga_grupper - Do_not_abbreviate_names=Förkorta_ej_namn Do_not_automatically_set=Sätt_ej_automatiskt @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Genererade_BibTeX-nycklar_för Generating_BibTeX_key_for=Genererar_BibTeX-nycklar_för Get_fulltext=Hämta_dokument -Gray_out_entries_not_in_group_selection=Skugga_poster_som_inte_är_med_i_en_grupp - Gray_out_non-hits=Skugga_icke-träffar Groups=Grupper @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Har_du_valt_rätt_sökväg_till_pakete Help=Hjälp -Help_on_groups=Hjälp_för_grupper - Help_on_key_patterns=Hjälp_för_nyckelmönster Help_on_regular_expression_search=Hjälp_för_sökning_med_reguljära_uttryck @@ -612,8 +604,6 @@ Icon=Ikon Ignore=Ignorera -Immediate_subgroups= - Import=Importera Import_and_keep_old_entry=Importera_och_behåll_gammal_post @@ -671,8 +661,6 @@ Invalid_date_format=Ogiltigt_datumformat Invalid_URL=Ogiltig_URL -Inverted=Omvänd - Online_help=Onlinehjälp JabRef_preferences=Inställningar_för_JabRef @@ -760,7 +748,6 @@ modify_group=ändra_grupp Move_down=Flytta_nedåt -Move_entries_in_group_selection_to_the_top= Move_external_links_to_'file'_field=Flytta_externa_länkar_till_'file'-fältet move_group=flytta_grupp @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Visa_bekräftelseruta_när_poster Show_description=Visa_beskrivning -Show_entries_not_in_group_selection=Visa_poster_som_inte_är_i_vald_grupp - Show_file_column=Visa_filkolumn Show_last_names_only=Visa_bara_efternamn @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Hoppade_över_-_PDF_fanns_ej Skipped_entry.=Hoppade_över_post. -Sort_alphabetically=Sortera_i_bokstavsordning - -sort_subgroups=sortera_undergrupper - -Sorted_all_subgroups_recursively.=Sorterade_alla_undergrupper_rekursivt. - -Sorted_immediate_subgroups.= - source_edit=ändring_av_källkod Special_name_formatters=Speciella_format_för_namn diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 703f9fc0e2b..877afdaed70 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Bu_türeden_tüm_g All_fields=Tüm_alanlar -All_subgroups_(recursively)=Tüm_alt-gruplar_(özyinelemeli) - Always_reformat_BIB_file_on_save_and_export=Kaydetme_ve_dışa_aktarmada_BIB_dosyasını_her_zaman_yeniden_biçemle A_SAX_exception_occurred_while_parsing_'%0'\:='%0'_ayrıştırılırken_bir_SAXİstisnası_oluştu\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Komut_satırı_seçenekleri_hakkındaki_yar Display_only_entries_belonging_to_all_selected_groups.=Yalnızca_seçili_tüm_gruplara_ait_girdileri_göster. Display_version=Sürümü_göster -Displaying_no_groups=Gruplar_gösterilmiyor - Do_not_abbreviate_names=İsimleri_kısaltma Do_not_automatically_set=Otomatik_kurma @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Şunun_için_BibTeX_anahtarı_oluşturuldu Generating_BibTeX_key_for=Şunun_için_BibTeX_anahtarı_oluşturuluyor Get_fulltext=Tammetni_getir -Gray_out_entries_not_in_group_selection=Grup_seçiminde_olmayan_girdileri_grileştir - Gray_out_non-hits=İsabet_almayanları_grileştir Groups=Gruplar @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Doğru_paket_yolunu_seçtiniz_mi? Help=Yardım -Help_on_groups=Gruplar_hakkında_yardım - Help_on_key_patterns=Tuş_desenleri_hakkında_yardım Help_on_regular_expression_search=Düzenli_İfade_Arama_hakkında_yardım @@ -612,8 +604,6 @@ Icon=Simge Ignore=Yoksay -Immediate_subgroups=Bir_sonraki_altgruplar - Import=İçe_aktar Import_and_keep_old_entry=İçe_aktar_ve_eski_girdiyi_koru @@ -671,8 +661,6 @@ Invalid_date_format=Geçersiz_tarih_biçemi Invalid_URL=Geçersiz_URL -Inverted=Ters_çevrilmiş - Online_help=Çevrimiçi_yardım JabRef_preferences=JabRef_tercihler @@ -760,7 +748,6 @@ modify_group=grubu_değiştir Move_down=Aşağı_taşı -Move_entries_in_group_selection_to_the_top=Grup_seçimindeki_girdileri_en_üste_taşı Move_external_links_to_'file'_field=Harici_linkleri_'dosya'_alanına_taşı move_group=grubu_taşı @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Girdileri_silerken_onaylama_ileti Show_description=Açıklamayı_göster -Show_entries_not_in_group_selection=Girdileri_grup_seçiminde_gösterme - Show_file_column=Dosya_sütununu_göster Show_last_names_only=Yalnızca_soyadları_göster @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Atlandı_-_PDF_mevcut_değil Skipped_entry.=Girdi_atlandı. -Sort_alphabetically=Alfabetik_sırala - -sort_subgroups=altgrupları_sırala - -Sorted_all_subgroups_recursively.=Tüm_altgruplar_özyineli_sıralandı. - -Sorted_immediate_subgroups.=En_yakın_altgruplar_sıralandı. - source_edit=kaynak_düzenle Special_name_formatters=Özel_Ad_Biçemleyicileri diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 365cc9fa218..d54a9d3d6eb 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=Tất_cả_các_m All_fields=Tất_cả_các_dữ_liệu -All_subgroups_(recursively)=Tất_cả_các_nhóm_con_(đệ_quy) - Always_reformat_BIB_file_on_save_and_export= A_SAX_exception_occurred_while_parsing_'%0'\:=Một_lỗi_SAXException_xảy_ra_khi_đang_phân_tách_'%0'\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=Trình_bày_trợ_giúp_ở_các_tùy_chọ Display_only_entries_belonging_to_all_selected_groups.=Chỉ_trình_bày_các_mục_thuộc_về_tất_cả_các_nhóm_được_chọn. Display_version=Trình_bày_phiên_bản -Displaying_no_groups=Không_trình_bày_các_nhóm - Do_not_abbreviate_names=Không_viết_tắt_tên Do_not_automatically_set=Không_thiết_lập_tự_động @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=Khóa_BibTeX_được_tạo_ra_cho Generating_BibTeX_key_for=Đang_tạo_khóa_BibTeX_cho Get_fulltext=Nhập_toàn_văn_bản -Gray_out_entries_not_in_group_selection=Tô_xám_các_mục_không_thuộc_phép_chọn_nhóm - Gray_out_non-hits=Tô_xám_các_mục_không_gặp Groups=Các_nhóm @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=Bạn_đã_chọn_đường_dẫn_gói Help=Trợ_giúp -Help_on_groups=Trợ_giúp_về_nhóm - Help_on_key_patterns=Trợ_giúp_về_các_kiểu_khóa Help_on_regular_expression_search=Trợ_giúp_về_tìm_kiếm_bằng_biểu_thức_chính_tắc @@ -612,8 +604,6 @@ Icon=Biểu_tượng Ignore=Bỏ_qua -Immediate_subgroups=Các_nhóm_con_sát_nhau - Import=Nhập Import_and_keep_old_entry=Nhập_và_giữ_mục_cũ @@ -671,8 +661,6 @@ Invalid_date_format=Định_dạng_ngày_không_hợp_lệ Invalid_URL=URL_không_hợp_lệ -Inverted=Đảo_ngược - Online_help=Trợ_giúp_trực_tuyến JabRef_preferences=Các_tùy_thích_JabRef @@ -760,7 +748,6 @@ modify_group=điều_chỉnh_nhóm 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 Move_external_links_to_'file'_field=Chuyển_các_liên_kết_ngoài_vào_dữ_liệu_'file' move_group=chuyển_nhóm @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=Hiển_thị_hộp_thoại_xác_n Show_description=Hiển_thị_mô_tả -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_last_names_only=Chỉ_hiển_thị_Họ @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=Bỏ_qua_-_tập_tin_PDF_không_tồn_tại Skipped_entry.=Mục_bị_bỏ_qua. -Sort_alphabetically=Xếp_theo_thứ_tự_ABC - -sort_subgroups=Xếp_thứ_tự_các_nhóm_con - -Sorted_all_subgroups_recursively.=Xếp_thứ_tự_tất_cả_các_nhóm_con_theo_cách_đệ_quy. - -Sorted_immediate_subgroups.=Các_nhóm_con_cạnh_nhau_được_xếp_thứ_tự. - source_edit=chỉnh_sửa_nguồn Special_name_formatters=Các_trình_định_dạng_tên_đặc_biệt diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties index f176aebf8db..da9d7a22384 100644 --- a/src/main/resources/l10n/JabRef_zh.properties +++ b/src/main/resources/l10n/JabRef_zh.properties @@ -80,8 +80,6 @@ All_entries_of_this_type_will_be_declared_typeless._Continue?=所有此类型记 All_fields=所有域 -All_subgroups_(recursively)=所有子分组(递归地) - Always_reformat_BIB_file_on_save_and_export=当保存和导出时重新格式化_BIB_文件 A_SAX_exception_occurred_while_parsing_'%0'\:=当解析'%0'时发生了一个_SAXException\: @@ -352,8 +350,6 @@ Display_help_on_command_line_options=用命令行选项显示帮助 Display_only_entries_belonging_to_all_selected_groups.=只显示属于所有选中分组的记录,即显示选中分组的交集。 Display_version=显示版本 -Displaying_no_groups=非分组视图 - Do_not_abbreviate_names=不要缩写姓名 Do_not_automatically_set=不要自动设置 @@ -577,8 +573,6 @@ Generated_BibTeX_key_for=已生成_BibTeX_键——为 Generating_BibTeX_key_for=正在生成_BibTeX_键——为 Get_fulltext=获取全文 -Gray_out_entries_not_in_group_selection=灰色显示未选中记录 - Gray_out_non-hits=置灰未选中 Groups=分组 @@ -587,8 +581,6 @@ Have_you_chosen_the_correct_package_path?=您选择了正确的包路径吗? Help=帮助 -Help_on_groups=分组帮助 - Help_on_key_patterns=键表达式帮助 Help_on_regular_expression_search=正则表达式搜索帮助 @@ -612,8 +604,6 @@ Icon=图标 Ignore=忽略 -Immediate_subgroups=直接子分组 - Import=导入 Import_and_keep_old_entry=导入且保存旧记录 @@ -671,8 +661,6 @@ Invalid_date_format=非法的日期格式 Invalid_URL=非法的_URL -Inverted=补集 - Online_help=在线帮助 JabRef_preferences=JabRef_首选项 @@ -760,7 +748,6 @@ modify_group=修改分组 Move_down=下移 -Move_entries_in_group_selection_to_the_top=移动选中分组的记录到顶部 Move_external_links_to_'file'_field=移动外部链接到_'file'_域 move_group=移动分组 @@ -1117,8 +1104,6 @@ Show_confirmation_dialog_when_deleting_entries=删除多条记录时发出警告 Show_description=显示描述 -Show_entries_not_in_group_selection=显示那些在选中分组中的记录 - Show_file_column=显示“文件”列 Show_last_names_only=只显示“姓_(Lastname)” @@ -1140,14 +1125,6 @@ Skipped_-_PDF_does_not_exist=跳过-PDF_不存在 Skipped_entry.=已跳过记录 -Sort_alphabetically=按字母表排序 - -sort_subgroups=排序子分组 - -Sorted_all_subgroups_recursively.=递归排序所有子分组。 - -Sorted_immediate_subgroups.=完成排序直接子分组。 - source_edit=源代码编辑 Special_name_formatters=特殊的姓名格式化器 diff --git a/src/main/resources/l10n/Menu_el.properties b/src/main/resources/l10n/Menu_el.properties new file mode 100644 index 00000000000..65889232211 --- /dev/null +++ b/src/main/resources/l10n/Menu_el.properties @@ -0,0 +1,125 @@ +Abbreviate_journal_names_(ISO)=Συντομογραφίες_ονομάτων_περιοδικών_(ISO) +Abbreviate_journal_names_(MEDLINE)=Συντομογραφίες_ονομάτων_περιοδικών_(MEDLINE) +About_JabRef=&Σχετικά_με_το_JabRef +Append_database=&Σύναψη_βάση_δεδομένων +Autogenerate_BibTeX_keys=&Autogenerate_BibTeX_keys +Close_database=&Κλείσιμο_βάσης_δεδομένων +Copy=Αντιγραφή +Copy_\\cite{BibTeX_key}=Αντιγραφή_\\c&ite{BibTeX_key} +Copy_BibTeX_key=Αντιγραφή&BibTeX_key +Customize_entry_types=&Προσαρμογή_τύπου_καταχώρησης +Cut=&Αποκοπή +Database_properties=Ιδιότητες_βασης_δεδομένων +Edit=&Επεξεργασία +# Bibtex +Edit_entry=&Επεξεργασία_καταχώρησης +Edit_preamble=Επεξεργασία_&preamble +Edit_strings=Επεξεργασία_&strings +Export=&Εξαγωγή +Export_selected_entries_to_clipboard=&Εξαγωγή_επιλεγμένων_καταχωρήσεων_στο_clipboard + +# Menu names +File=&Φάκελος +Find_duplicates=&Εύρεση_διπλότυπων +Help=&Βοήθεια +Highlight_groups_matching_all_selected_entries=Υπογράμμιση_ομάδων_που_ταιριάζουν_ολές_τις_επιλεγμένες_καταχωρήσεις +Highlight_groups_matching_any_selected_entry=Υπογράμμιση_ομάδων_που_ταιριάζουν_οποιαδήποτε_επιλεγμένη_καταχωρήση +Disable_highlight_groups_matching_entries=Απενεργοποίηση_υπογράμμισης_ομάδων_αντιστοιχούμενων_καταχωρήσεων + +# Help +Online_help=Online_βοήθεια +Donate_to_JabRef=Δωρεά_στο_JabRef +Manage_content_selectors=Διαχείριση&Επιλογείς_Περιεχομένου +Manage_custom_exports=&Διαχείριση_Εξαγωγής_Προτιμήσεων +Manage_custom_imports=Διαχείριση_Προτιμήσεων_&Εισαγωγών +Manage_journal_abbreviations=Διαχείριση_&συντομογραφιών_περιοδικών +Mark_entries=&Επισύμανση_καταχωρήσεων +# File menu +New_%0_database=&Νέα_%0_βάση_δεδομένων +# Menu BibTeX (BibTeX) +New_entry=&Νέα_καταχώρηση +New_entry_by_type...=&Νέα_καταχώρηση_ανα_τύπο... +New_entry_from_plain_text=&Νέα_καταχώρηση_από_plain_κείμενο +New_subdatabase_based_on_AUX_file=Nέα_subdatabase_βασισμένη_σε_αρχείο_AU&X +# View +Next_tab=&Επόμενη_καρτέλα +Open_database=&Άνοιγμα_βάσης_δεδομένων +Open_URL_or_DOI=Άνοιγμα_&URL_ή_DOI +Open_terminal_here=Open_terminal_here +Options=&Επιλογές +Paste=&Επικόλληση +# Options +Preferences=&Προτιμήσεις +Previous_tab=&Προηγούμενη_καρτέλα +Quit=&Έξοδος +Recent_files=&Πρόσφατα_αρχεία +Redo=&Επαναφορά +Replace_string=&Αντικατάσταση_string +Save_database=&Αποθήκευση_database +Save_database_as...=Αποθήκευση_βάσης_δεδομένων_ως... +Save_selected_as...=Αποθήκεση_επιλεγμένου_ως... +# Tools +Search=&Αναζήτηση +Select_all=Επιλογή_&όλων +Set_up_general_fields=Ρύθμιση&γενικών_πεδίων +Show_error_console=Προβολή_κονσόλας_λαθών +Sort_tabs=&Σύντομες_καρτέλες +Switch_preview_layout=&Αλλαγή_προεπισκόπησης_layout +# Export menu +Toggle_entry_preview=&Toggle_entry_preview +Toggle_groups_interface=Toggle_&groups_interface +Tools=&Εργαλεία +Unabbreviate_journal_names=Ονόματα_περιοδικών_χωρίς_συντομογραφία +# Edit +Undo=&Αναίρεση +Mark_specific_color=Επισύμανση_συγκεκριμένου_χρώματος +Unmark_all=Απεπιλογή_όλων +Unmark_entries=Απεπιλογή_καταχωρήσεων +View=&Προβολή +Import_into_new_database=Εισαγωγή_σε_νέα_βάση_δεδομένων +Import_into_current_database=Εισαγωγή_σε_υπάρχουσα_βάση_δεδομένων + +Switch_to_%0_mode=Αλλαγή_%0_κατάστασης +Push_entries_to_external_application_(%0)=Push_entries_to_external_application_(%0) +Write_XMP-metadata_to_PDFs=Εγγραφή_XMP-μεταδεδομένων_σε_PDF + +Export_selected_entries=Εξαγωγή_επιλεγμένων_καταχωρήσεων + +Save_all=Αποθήκευση_όλων + +Manage_external_file_types=Διαχείριση_εξωτερικού_τυπου_αρχείων + +Open_file=Άνοιγμα_αρχείου + +Connect_to_external_SQL_database=Σύνδεση_σε_εξωτερική_βάση_SQL +Export_to_external_SQL_database=Εξαγωγή_σε_εξωτερική_βάση_SQL +Import_from_external_SQL_database=Εισαγωγή_σε_εξωτερική_βάση_SQL +Focus_entry_table=Επικεντρωμένη_εισαγωγή_πίνακα + +Increase_table_font_size=&Μεγένθυση_γραμματοσειράς_πίνακα +Decrease_table_font_size=&Σμίκρυνση_γραμματοσειράς_πίνακα +Forward=Επόμενο +Back=Πίσω + +Look_up_full_text_document=Εύρεση_πλήρες_κειμένο_εγγράφου +Set/clear/rename_fields=Ρύθμιση/καθαρισμός/μετονομασία_πεδίων + +Resolve_duplicate_BibTeX_keys=Resolve_διπλότυπων_BibTeX_keys +Copy_BibTeX_key_and_title=Αντιγραφή_BibTeX_και_τίτλου + +Cleanup_entries=Καθαρισμός_καταχωρήσεων +Manage_keywords=Διαχείριση_λέξεων_κλειδιών +Merge_entries=Συγχώνευση_καταχωρήσεων +Open_folder=Άνοιγμα_φακέλου +Find_unlinked_files...=Εύρεση_αποσυνδεμένων_αρχείων... +Hide/show_toolbar=Απόκρυψη/προβολή_εργαλειοθήκης + +Fork_me_on_GitHub=Fork_me_on_GitHub +Save_selected_as_plain_BibTeX...=Αποθήκευση_επιλεγμένου_ως_plain_BibTeX... + +Groups=Ομάδες +Delete_entry=Διαγραφή_καταχώρησης +Check_integrity=Έλεγχος_συνοχής + +Quality=Ποιότητα +Online_help_forum=Online_forum_βοήθειας diff --git a/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java b/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java index cb8801ed880..c1956a7e5e7 100644 --- a/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java +++ b/src/test/java/org/jabref/gui/groups/GroupNodeViewModelTest.java @@ -1,5 +1,7 @@ package org.jabref.gui.groups; +import java.util.Arrays; + import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -87,7 +89,71 @@ public void treeOfAutomaticKeywordGroupIsCombined() throws Exception { assertEquals(expected, groupViewModel.getChildren()); } + @Test + public void draggedOnTopOfGroupAddsBeforeIt() throws Exception { + GroupNodeViewModel rootViewModel = getViewModelForGroup(new WordKeywordGroup("root", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true)); + WordKeywordGroup groupA = new WordKeywordGroup("A", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true); + WordKeywordGroup groupB = new WordKeywordGroup("B", GroupHierarchyType.INCLUDING, "keywords", "A > B", true, ',', true); + WordKeywordGroup groupC = new WordKeywordGroup("C", GroupHierarchyType.INCLUDING, "keywords", "A > B > B1", true, ',', true); + GroupNodeViewModel groupAViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupA)); + GroupNodeViewModel groupBViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupB)); + GroupNodeViewModel groupCViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupC)); + + groupCViewModel.draggedOn(groupBViewModel, DroppingMouseLocation.TOP); + + assertEquals(Arrays.asList(groupAViewModel, groupCViewModel, groupBViewModel), rootViewModel.getChildren()); + } + + @Test + public void draggedOnBottomOfGroupAddsAfterIt() throws Exception { + GroupNodeViewModel rootViewModel = getViewModelForGroup(new WordKeywordGroup("root", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true)); + WordKeywordGroup groupA = new WordKeywordGroup("A", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true); + WordKeywordGroup groupB = new WordKeywordGroup("B", GroupHierarchyType.INCLUDING, "keywords", "A > B", true, ',', true); + WordKeywordGroup groupC = new WordKeywordGroup("C", GroupHierarchyType.INCLUDING, "keywords", "A > B > B1", true, ',', true); + GroupNodeViewModel groupAViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupA)); + GroupNodeViewModel groupBViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupB)); + GroupNodeViewModel groupCViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupC)); + + groupCViewModel.draggedOn(groupAViewModel, DroppingMouseLocation.BOTTOM); + + assertEquals(Arrays.asList(groupAViewModel, groupCViewModel, groupBViewModel), rootViewModel.getChildren()); + } + + @Test + public void draggedOnBottomOfGroupAddsAfterItWhenSourceGroupWasBefore() throws Exception { + GroupNodeViewModel rootViewModel = getViewModelForGroup(new WordKeywordGroup("root", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true)); + WordKeywordGroup groupA = new WordKeywordGroup("A", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true); + WordKeywordGroup groupB = new WordKeywordGroup("B", GroupHierarchyType.INCLUDING, "keywords", "A > B", true, ',', true); + WordKeywordGroup groupC = new WordKeywordGroup("C", GroupHierarchyType.INCLUDING, "keywords", "A > B > B1", true, ',', true); + GroupNodeViewModel groupAViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupA)); + GroupNodeViewModel groupBViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupB)); + GroupNodeViewModel groupCViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupC)); + + groupAViewModel.draggedOn(groupBViewModel, DroppingMouseLocation.BOTTOM); + + assertEquals(Arrays.asList(groupBViewModel, groupAViewModel, groupCViewModel), rootViewModel.getChildren()); + } + + @Test + public void draggedOnTopOfGroupAddsBeforeItWhenSourceGroupWasBefore() throws Exception { + GroupNodeViewModel rootViewModel = getViewModelForGroup(new WordKeywordGroup("root", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true)); + WordKeywordGroup groupA = new WordKeywordGroup("A", GroupHierarchyType.INCLUDING, "keywords", "A", true, ',', true); + WordKeywordGroup groupB = new WordKeywordGroup("B", GroupHierarchyType.INCLUDING, "keywords", "A > B", true, ',', true); + WordKeywordGroup groupC = new WordKeywordGroup("C", GroupHierarchyType.INCLUDING, "keywords", "A > B > B1", true, ',', true); + GroupNodeViewModel groupAViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupA)); + GroupNodeViewModel groupBViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupB)); + GroupNodeViewModel groupCViewModel = getViewModelForGroup(rootViewModel.addSubgroup(groupC)); + + groupAViewModel.draggedOn(groupCViewModel, DroppingMouseLocation.TOP); + + assertEquals(Arrays.asList(groupBViewModel, groupAViewModel, groupCViewModel), rootViewModel.getChildren()); + } + private GroupNodeViewModel getViewModelForGroup(AbstractGroup group) { return new GroupNodeViewModel(databaseContext, stateManager, taskExecutor, group); } + + private GroupNodeViewModel getViewModelForGroup(GroupTreeNode group) { + return new GroupNodeViewModel(databaseContext, stateManager, taskExecutor, group); + } } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/LibraryOfCongressTest.java b/src/test/java/org/jabref/logic/importer/fetcher/LibraryOfCongressTest.java new file mode 100644 index 00000000000..4ee2dca2d8c --- /dev/null +++ b/src/test/java/org/jabref/logic/importer/fetcher/LibraryOfCongressTest.java @@ -0,0 +1,34 @@ +package org.jabref.logic.importer.fetcher; + +import java.util.Optional; + +import org.jabref.model.entry.BibEntry; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class LibraryOfCongressTest { + + private LibraryOfCongress fetcher = new LibraryOfCongress(); + + @Test + public void performSearchById() throws Exception { + BibEntry expected = new BibEntry(); + expected.setField("address", "Burlington, MA"); + expected.setField("author", "West, Matthew"); + expected.setField("isbn", "0123751063 (pbk.)"); + expected.setField("issuance", "monographic"); + expected.setField("keywords", "Database design, Data structures (Computer science)"); + expected.setField("language", "eng"); + expected.setField("lccn", "2010045158"); + expected.setField("note", "Matthew West., Includes index."); + expected.setField("oclc", "ocn665135773"); + expected.setField("publisher", "Morgan Kaufmann"); + expected.setField("source", "DLC"); + expected.setField("title", "Developing high quality data models"); + expected.setField("year", "2011"); + + assertEquals(Optional.of(expected), fetcher.performSearchById("2010045158")); + } +} diff --git a/src/test/java/org/jabref/model/TreeNodeTest.java b/src/test/java/org/jabref/model/TreeNodeTest.java index 841dfaeab29..cff784ef02b 100644 --- a/src/test/java/org/jabref/model/TreeNodeTest.java +++ b/src/test/java/org/jabref/model/TreeNodeTest.java @@ -172,6 +172,36 @@ public void moveToInSameLevelAddsAtEnd() { assertEquals(Arrays.asList(child2, child1), root.getChildren()); } + @Test + public void moveToInSameLevelWhenNodeWasBeforeTargetIndex() { + TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); + TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock(); + TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock(); + TreeNodeTestData.TreeNodeMock child3 = new TreeNodeTestData.TreeNodeMock(); + root.addChild(child1); + root.addChild(child2); + root.addChild(child3); + + child1.moveTo(root, 1); + + assertEquals(Arrays.asList(child2, child1, child3), root.getChildren()); + } + + @Test + public void moveToInSameLevelWhenNodeWasAfterTargetIndex() { + TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); + TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock(); + TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock(); + TreeNodeTestData.TreeNodeMock child3 = new TreeNodeTestData.TreeNodeMock(); + root.addChild(child1); + root.addChild(child2); + root.addChild(child3); + + child3.moveTo(root, 1); + + assertEquals(Arrays.asList(child1, child3, child2), root.getChildren()); + } + @Test public void getPathFromRootInSimpleTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); diff --git a/src/test/java/org/jabref/model/entry/DateTest.java b/src/test/java/org/jabref/model/entry/DateTest.java index 5c55cc92179..3192ef78554 100644 --- a/src/test/java/org/jabref/model/entry/DateTest.java +++ b/src/test/java/org/jabref/model/entry/DateTest.java @@ -14,4 +14,9 @@ public void parseCorrectlyDayMonthYearDate() throws Exception { Date expected = new Date(LocalDate.of(2014, 6, 19)); assertEquals(Optional.of(expected), Date.parse("19-06-2014")); } + + @Test(expected = NullPointerException.class) + public void parseDateNull() { + assertEquals(Optional.empty(), Date.parse(null)); + } } diff --git a/src/test/java/org/jabref/model/pdf/FileAnnotationTest.java b/src/test/java/org/jabref/model/pdf/FileAnnotationTest.java new file mode 100644 index 00000000000..054f3d99d95 --- /dev/null +++ b/src/test/java/org/jabref/model/pdf/FileAnnotationTest.java @@ -0,0 +1,32 @@ +package org.jabref.model.pdf; + +import java.time.LocalDateTime; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +public class FileAnnotationTest { + + @Test + public void testParseDateMinusBeforeTimezone() { + String dateString = "D:20170512224019-03'00'"; + LocalDateTime date = FileAnnotation.extractModifiedTime(dateString); + assertEquals(LocalDateTime.of(2017, 05, 12, 22, 40, 19), date); + } + + @Test + public void testParseDatePlusBeforeTimezone() { + String dateString = "D:20170512224019+03'00'"; + LocalDateTime date = FileAnnotation.extractModifiedTime(dateString); + assertEquals(LocalDateTime.of(2017, 05, 12, 22, 40, 19), date); + } + + @Test + public void testParseDateNoTimezone() { + String dateString = "D:20170512224019"; + LocalDateTime date = FileAnnotation.extractModifiedTime(dateString); + assertEquals(LocalDateTime.of(2017, 05, 12, 22, 40, 19), date); + } +} diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest1.xml b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest1.xml index 960fd22d6b3..d92aaaa3a05 100644 --- a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest1.xml +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTest1.xml @@ -24,8 +24,8 @@ 10 abb 1000 -12 -10 +10 +12 2015 5 diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDateAcessed.bib b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDateAcessed.bib new file mode 100644 index 00000000000..bc4edda355f --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDateAcessed.bib @@ -0,0 +1,12 @@ +% Encoding: UTF-8 + +@Article{Testa, + author = {Sam and jason}, + title = {Test}, + journaltitle = {Test}, + year = {2012}, + date = {2016}, + msbib-accessed = {2015-12-12}, +} + +@Comment{jabref-meta: databaseType:biblatex;} diff --git a/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDateAcessed.xml b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDateAcessed.xml new file mode 100644 index 00000000000..03524e8a072 --- /dev/null +++ b/src/test/resources/org/jabref/logic/exporter/MsBibExportFormatTestDateAcessed.xml @@ -0,0 +1,27 @@ + + + +2012 +article +JournalArticle +2015-12-12 +Test +Testa +2015 +12 +12 + + + + +Sam + + +jason + + + + +Test + +