From ff72b06b537d18c4b4e2a7f2a1c4f5845151512c Mon Sep 17 00:00:00 2001 From: github actions Date: Mon, 6 Apr 2020 19:37:22 +0000 Subject: [PATCH 01/23] Squashed 'src/main/resources/csl-styles/' changes from 900e4d515c..88726cb64d 88726cb64d Update Rhinology (#4672) git-subtree-dir: src/main/resources/csl-styles git-subtree-split: 88726cb64d5a7d1471b9bd96f818ea32785bcd91 --- rhinology.csl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rhinology.csl b/rhinology.csl index a4f25b60942..2b3176f5a67 100644 --- a/rhinology.csl +++ b/rhinology.csl @@ -186,7 +186,7 @@ - + From 4d8d69755994dba6f6464c2a222870f88051ea2e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2020 08:53:43 +0200 Subject: [PATCH 02/23] Bump bcprov-jdk15on from 1.64 to 1.65 (#6256) Bumps [bcprov-jdk15on](https://github.com/bcgit/bc-java) from 1.64 to 1.65. - [Release notes](https://github.com/bcgit/bc-java/releases) - [Changelog](https://github.com/bcgit/bc-java/blob/master/docs/releasenotes.html) - [Commits](https://github.com/bcgit/bc-java/commits) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 512c5e3fd98..97521b206d2 100644 --- a/build.gradle +++ b/build.gradle @@ -120,7 +120,7 @@ dependencies { implementation group: 'org.apache.tika', name: 'tika-core', version: '1.24' // required for reading write-protected PDFs - see https://github.com/JabRef/jabref/pull/942#issuecomment-209252635 - implementation 'org.bouncycastle:bcprov-jdk15on:1.64' + implementation 'org.bouncycastle:bcprov-jdk15on:1.65' implementation 'commons-cli:commons-cli:1.4' From 7f1b57bd48392463a2bd17a3d6bfe89066d9fa78 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2020 08:53:54 +0200 Subject: [PATCH 03/23] Bump classgraph from 4.8.66 to 4.8.68 (#6255) Bumps [classgraph](https://github.com/classgraph/classgraph) from 4.8.66 to 4.8.68. - [Release notes](https://github.com/classgraph/classgraph/releases) - [Commits](https://github.com/classgraph/classgraph/compare/classgraph-4.8.66...classgraph-4.8.68) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 97521b206d2..d65e8de2437 100644 --- a/build.gradle +++ b/build.gradle @@ -200,7 +200,7 @@ dependencies { implementation 'com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:0.61.0' implementation 'com.vladsch.flexmark:flexmark-ext-gfm-tasklist:0.61.0' - testImplementation 'io.github.classgraph:classgraph:4.8.66' + testImplementation 'io.github.classgraph:classgraph:4.8.68' testImplementation 'org.junit.jupiter:junit-jupiter:5.6.1' testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.6.1' testImplementation 'org.junit.platform:junit-platform-launcher:1.6.1' From d829dfeca0c17767a423c298ef530d38f019576f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2020 08:54:07 +0200 Subject: [PATCH 04/23] Bump unirest-java from 3.7.00 to 3.7.01 (#6253) Bumps [unirest-java](https://github.com/Kong/unirest-java) from 3.7.00 to 3.7.01. - [Release notes](https://github.com/Kong/unirest-java/releases) - [Changelog](https://github.com/Kong/unirest-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/Kong/unirest-java/compare/v3.7.00...v3.7.01) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d65e8de2437..ec6c6e93d17 100644 --- a/build.gradle +++ b/build.gradle @@ -171,7 +171,7 @@ dependencies { implementation 'org.controlsfx:controlsfx:11.0.1' implementation 'org.jsoup:jsoup:1.13.1' - implementation 'com.konghq:unirest-java:3.7.00' + implementation 'com.konghq:unirest-java:3.7.01' implementation 'org.slf4j:slf4j-api:2.0.0-alpha1' implementation group: 'org.apache.logging.log4j', name: 'log4j-jcl', version: '3.0.0-SNAPSHOT' From 46e27cdbcf79aeb8a255770ff4c6458ab5da0661 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2020 08:54:27 +0200 Subject: [PATCH 05/23] Bump postgresql from 42.2.11 to 42.2.12 (#6254) Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.2.11 to 42.2.12. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.2.11...REL42.2.12) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ec6c6e93d17..04c82de94b8 100644 --- a/build.gradle +++ b/build.gradle @@ -144,7 +144,7 @@ dependencies { implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.6.0' - implementation 'org.postgresql:postgresql:42.2.11' + implementation 'org.postgresql:postgresql:42.2.12' implementation ('com.oracle.ojdbc:ojdbc10:19.3.0.0') { // causing module issues From 8968ccfd5d39d66a080ef0b6c6bbd4e8b0a7d543 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Wed, 8 Apr 2020 06:25:57 +0200 Subject: [PATCH 06/23] JDK14 switch - and checkstyle skipping (#6250) Suggestion by https://stackoverflow.com/a/61071633/873282 --- config/checkstyle/checkstyle.xml | 5 +++ .../layout/format/AuthorAndsReplacer.java | 36 ++++++++----------- .../jabref/logic/layout/format/Ordinal.java | 23 +++++------- 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index e57c9dd8bc2..6905dd174a1 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -8,6 +8,11 @@ + + + + + diff --git a/src/main/java/org/jabref/logic/layout/format/AuthorAndsReplacer.java b/src/main/java/org/jabref/logic/layout/format/AuthorAndsReplacer.java index bf4be2b51f4..52531b47466 100644 --- a/src/main/java/org/jabref/logic/layout/format/AuthorAndsReplacer.java +++ b/src/main/java/org/jabref/logic/layout/format/AuthorAndsReplacer.java @@ -18,28 +18,22 @@ public String format(String fieldText) { return null; } String[] authors = fieldText.split(" and "); - String s; - - switch (authors.length) { - case 1: - //Does nothing; - s = authors[0]; - break; - case 2: - s = authors[0] + " & " + authors[1]; - break; - default: - int i; - int x = authors.length; - StringBuilder sb = new StringBuilder(); - - for (i = 0; i < (x - 2); i++) { - sb.append(authors[i]).append("; "); + //CHECKSTYLE:OFF + String s = switch (authors.length) { + case 1 -> authors[0]; // just no action + case 2 -> authors[0] + " & " + authors[1]; + default -> { + int i; + int x = authors.length; + StringBuilder sb = new StringBuilder(); + for (i = 0; i < (x - 2); i++) { + sb.append(authors[i]).append("; "); + } + sb.append(authors[i]).append(" & ").append(authors[i + 1]); + yield sb.toString(); } - sb.append(authors[i]).append(" & ").append(authors[i + 1]); - s = sb.toString(); - break; - } + }; + //CHECKSTYLE:ON return s; diff --git a/src/main/java/org/jabref/logic/layout/format/Ordinal.java b/src/main/java/org/jabref/logic/layout/format/Ordinal.java index 5587828634e..85290643e79 100644 --- a/src/main/java/org/jabref/logic/layout/format/Ordinal.java +++ b/src/main/java/org/jabref/logic/layout/format/Ordinal.java @@ -23,21 +23,14 @@ public String format(String fieldText) { while (m.find()) { String result = m.group(1); int value = Integer.parseInt(result); - String ordinalString; - switch (value) { - case 1: - ordinalString = "st"; - break; - case 2: - ordinalString = "nd"; - break; - case 3: - ordinalString = "rd"; - break; - default: - ordinalString = "th"; - break; - } + //CHECKSTYLE:OFF + String ordinalString = switch (value) { + case 1 -> "st"; + case 2 -> "nd"; + case 3 -> "rd"; + default -> "th"; + }; + //CHECKSTYLE:ON m.appendReplacement(sb, result + ordinalString); } m.appendTail(sb); From bdc5739b69148bcdb77259f3a303d518ea5b21f2 Mon Sep 17 00:00:00 2001 From: systemoperator <3658393+systemoperator@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:44:43 +0200 Subject: [PATCH 07/23] Entry editor: Add more tooltips and wrap tooltips if necessary (#6239) * wrap tooltips if necessary * adding additional entry field tooltips (including SpecialFields) * small changes * ISRN added * small changes * descriptions adapted * English localization extended --- .../gui/fieldeditors/FieldNameLabel.java | 96 ++++++++++++++++++- src/main/resources/l10n/JabRef_en.properties | 41 +++++++- 2 files changed, 133 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java b/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java index 91b48f52721..ea4526faa1f 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/FieldNameLabel.java @@ -4,10 +4,12 @@ import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.Tooltip; +import javafx.stage.Screen; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.InternalField; +import org.jabref.model.entry.field.SpecialField; import org.jabref.model.entry.field.StandardField; import org.jabref.model.strings.StringUtil; @@ -22,8 +24,11 @@ public FieldNameLabel(Field field) { String description = getDescription(field); if (StringUtil.isNotBlank(description)) { - Tooltip tooltip = new Tooltip(); - tooltip.setText(description); + Screen currentScreen = Screen.getPrimary(); + double maxWidth = currentScreen.getBounds().getWidth(); + Tooltip tooltip = new Tooltip(description); + tooltip.setMaxWidth(maxWidth * 2 / 3); + tooltip.setWrapText(true); this.setTooltip(tooltip); } } @@ -32,18 +37,29 @@ public String getDescription(Field field) { if (field.isStandardField()) { StandardField standardField = (StandardField) field; switch (standardField) { + case ABSTRACT: + return Localization.lang("This field is intended for recording abstracts, to be printed by a special bibliography style."); case ADDENDUM: return Localization.lang("Miscellaneous bibliographic data usually printed at the end of the entry."); case AFTERWORD: return Localization.lang("Author(s) of an afterword to the work."); + case ANNOTATION: + case ANNOTE: + return Localization.lang("This field may be useful when implementing a style for annotated bibliographies."); case ANNOTATOR: return Localization.lang("Author(s) of annotations to the work."); case AUTHOR: return Localization.lang("Author(s) of the work."); + case BOOKSUBTITLE: + return Localization.lang("Subtitle related to the \"Booktitle\"."); case BOOKTITLE: return Localization.lang("Title of the main publication this work is part of."); + case BOOKTITLEADDON: + return Localization.lang("Annex to the \"Booktitle\", to be printed in a different font."); case CHAPTER: return Localization.lang("Chapter or section or any other unit of a work."); + case COMMENT: + return Localization.lang("Comment to this entry."); case COMMENTATOR: return Localization.lang("Author(s) of a commentary to the work.") + "\n" + Localization.lang("Note that this field is intended for commented editions which have a commentator in addition to the author. If the work is a stand-alone commentary, the commentator should be given in the author field."); @@ -55,6 +71,20 @@ public String getDescription(Field field) { return Localization.lang("Edition of a printed publication."); case EDITOR: return Localization.lang("Editor(s) of the work or the main publication, depending on the type of the entry."); + case EDITORA: + return Localization.lang("Secondary editor performing a different editorial role, such as compiling, redacting, etc."); + case EDITORB: + return Localization.lang("Another secondary editor performing a different role."); + case EDITORC: + return Localization.lang("Another secondary editor performing a different role."); + case EDITORTYPE: + return Localization.lang("Type of editorial role performed by the \"Editor\"."); + case EDITORATYPE: + return Localization.lang("Type of editorial role performed by the \"Editora\"."); + case EDITORBTYPE: + return Localization.lang("Type of editorial role performed by the \"Editorb\"."); + case EDITORCTYPE: + return Localization.lang("Type of editorial role performed by the \"Editorc\"."); case EID: return Localization.lang("Electronic identifier of a work.") + "\n" + Localization.lang("This field may replace the pages field for journals deviating from the classic pagination scheme of printed journals by only enumerating articles or papers and not pages."); @@ -79,6 +109,8 @@ public String getDescription(Field field) { case FILE: case PDF: return Localization.lang("Link(s) to a local PDF or other document of the work."); + case FOREWORD: + return Localization.lang("Author(s) of a foreword to the work."); case HOWPUBLISHED: return Localization.lang("Publication notice for unusual publications which do not fit into any of the common categories."); case INSTITUTION: @@ -88,6 +120,10 @@ public String getDescription(Field field) { return Localization.lang("Author(s) of an introduction to the work."); case ISBN: return Localization.lang("International Standard Book Number of a book."); + case ISRN: + return Localization.lang("International Standard Technical Report Number of a technical report."); + case ISSN: + return Localization.lang("International Standard Serial Number of a periodical."); case ISSUE: return Localization.lang("Issue of a journal.") + "\n" + Localization.lang("This field is intended for journals whose individual issues are identified by a designation such as \"Spring\" or \"Summer\" rather than the month or a number. Integer ranges and short designators are better written to the number field."); @@ -95,41 +131,67 @@ public String getDescription(Field field) { return Localization.lang("Subtitle of a specific issue of a journal or other periodical."); case ISSUETITLE: return Localization.lang("Title of a specific issue of a journal or other periodical."); + case JOURNALSUBTITLE: + return Localization.lang("Subtitle of a journal, a newspaper, or some other periodical."); case JOURNALTITLE: case JOURNAL: return Localization.lang("Name of a journal, a newspaper, or some other periodical."); case LABEL: return Localization.lang("Designation to be used by the citation style as a substitute for the regular label if any data required to generate the regular label is missing."); + case LANGUAGE: + return Localization.lang("Language(s) of the work. Languages may be specified literally or as localisation keys."); case LIBRARY: return Localization.lang("Information such as a library name and a call number."); case LOCATION: case ADDRESS: - return Localization.lang("The place(s) of publication, i. e., the location of the publisher or institution, depending on the entry type."); + return Localization.lang("Place(s) of publication, i. e., the location of the publisher or institution, depending on the entry type."); + case MAINSUBTITLE: + return Localization.lang("Subtitle related to the \"Maintitle\"."); case MAINTITLE: return Localization.lang("Main title of a multi-volume book, such as \"Collected Works\"."); + case MAINTITLEADDON: + return Localization.lang("Annex to the \"Maintitle\", to be printed in a different font."); case MONTH: return Localization.lang("Publication month."); + case NAMEADDON: + return Localization.lang("Addon to be printed immediately after the author name in the bibliography."); case NOTE: return Localization.lang("Miscellaneous bibliographic data which does not fit into any other field."); case NUMBER: return Localization.lang("Number of a journal or the volume/number of a book in a series."); case ORGANIZATION: return Localization.lang("Organization(s) that published a manual or an online resource, or sponsored a conference."); + case ORIGDATE: + return Localization.lang("If the work is a translation, a reprint, or something similar, the publication date of the original edition."); + case ORIGLANGUAGE: + return Localization.lang("If the work is a translation, the language(s) of the original work."); case PAGES: return Localization.lang("One or more page numbers or page ranges.") + "\n" + Localization.lang("If the work is published as part of another one, such as an article in a journal or a collection, this field holds the relevant page range in that other work. It may also be used to limit the reference to a specific part of a work (a chapter in a book, for example). For papers in electronic journals with anon-classical pagination setup the eid field may be more suitable."); case PAGETOTAL: return Localization.lang("Total number of pages of the work."); + case PAGINATION: + return Localization.lang("Pagination of the work. The key should be given in the singular form."); + case PART: + return Localization.lang("Number of a partial volume. This field applies to books only, not to journals. It may be used when a logical volume consists of two or more physical ones."); case PUBLISHER: return Localization.lang("Name(s) of the publisher(s)."); case PUBSTATE: return Localization.lang("Publication state of the work, e. g., \"in press\"."); case SERIES: return Localization.lang("Name of a publication series, such as \"Studies in...\", or the number of a journal series."); + case SHORTTITLE: + return Localization.lang("Title in an abridged form."); case SUBTITLE: return Localization.lang("Subtitle of the work."); case TITLE: return Localization.lang("Title of the work."); + case TITLEADDON: + return Localization.lang("Annex to the \"Title\", to be printed in a different font."); + case TRANSLATOR: + return Localization.lang("Translator(s) of the \"Title\" or \"Booktitle\", depending on the entry type. If the translator is identical to the \"Editor\", the standard styles will automatically concatenate these fields in the bibliography."); + case TYPE: + return Localization.lang("Type of a \"Manual\", \"Patent\", \"Report\", or \"Thesis\"."); case URL: return Localization.lang("URL of an online publication."); case URLDATE: @@ -144,17 +206,45 @@ public String getDescription(Field field) { return Localization.lang("Total number of volumes of a multi-volume work."); case YEAR: return Localization.lang("Year of publication."); + case CROSSREF: + return Localization.lang("This field holds an entry key for the cross-referencing feature. Child entries with a \"Crossref\" field inherit data from the parent entry specified in the \"Crossref\" field."); + case GENDER: + return Localization.lang("Gender of the author or gender of the editor, if there is no author."); case KEYWORDS: return Localization.lang("Separated list of keywords."); + case RELATED: + return Localization.lang("Citation keys of other entries which have a relationship to this entry."); + case XREF: + return Localization.lang("This field is an alternative cross-referencing mechanism. It differs from \"Crossref\" in that the child entry will not inherit any data from the parent entry specified in the \"Xref\" field."); } } else if (field instanceof InternalField) { InternalField internalField = (InternalField) field; switch (internalField) { + case OWNER: + return Localization.lang("Owner/creator of this entry."); + case TIMESTAMP: + return Localization.lang("Timestamp of this entry, when it has been created or last modified."); case KEY_FIELD: return Localization.lang("Key by which the work may be cited."); case GROUPS: return Localization.lang("Name(s) of the (manual) groups the entry belongs to."); } + } else if (field instanceof SpecialField) { + SpecialField specialField = (SpecialField) field; + switch (specialField) { + case PRINTED: + return Localization.lang("User-specific printed flag, in case the entry has been printed."); + case PRIORITY: + return Localization.lang("User-specific priority."); + case QUALITY: + return Localization.lang("User-specific quality flag, in case its quality is assured."); + case RANKING: + return Localization.lang("User-specific ranking."); + case READ_STATUS: + return Localization.lang("User-specific read status."); + case RELEVANCE: + return Localization.lang("User-specific relevance flag, in case the entry is relevant."); + } } return ""; } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 7c7dca115eb..24d8e4649e2 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2140,7 +2140,7 @@ Revision\ number\ of\ a\ piece\ of\ software,\ a\ manual,\ etc.=Revision number Separated\ list\ of\ keywords.=Separated list of keywords. Subtitle\ of\ a\ specific\ issue\ of\ a\ journal\ or\ other\ periodical.=Subtitle of a specific issue of a journal or other periodical. Subtitle\ of\ the\ work.=Subtitle of the work. -The\ place(s)\ of\ publication,\ i.\ e.,\ the\ location\ of\ the\ publisher\ or\ institution,\ depending\ on\ the\ entry\ type.=The place(s) of publication, i. e., the location of the publisher or institution, depending on the entry type. +Place(s)\ of\ publication,\ i.\ e.,\ the\ location\ of\ the\ publisher\ or\ institution,\ depending\ on\ the\ entry\ type.=Place(s) of publication, i. e., the location of the publisher or institution, depending on the entry type. This\ could\ be\ a\ section\ of\ an\ archive,\ a\ path\ indicating\ a\ service,\ a\ classification\ of\ some\ sort.=This could be a section of an archive, a path indicating a service, a classification of some sort. This\ field\ is\ intended\ for\ journals\ whose\ individual\ issues\ are\ identified\ by\ a\ designation\ such\ as\ "Spring"\ or\ "Summer"\ rather\ than\ the\ month\ or\ a\ number.\ Integer\ ranges\ and\ short\ designators\ are\ better\ written\ to\ the\ number\ field.=This field is intended for journals whose individual issues are identified by a designation such as "Spring" or "Summer" rather than the month or a number. Integer ranges and short designators are better written to the number field. This\ field\ may\ replace\ the\ pages\ field\ for\ journals\ deviating\ from\ the\ classic\ pagination\ scheme\ of\ printed\ journals\ by\ only\ enumerating\ articles\ or\ papers\ and\ not\ pages.=This field may replace the pages field for journals deviating from the classic pagination scheme of printed journals by only enumerating articles or papers and not pages. @@ -2155,6 +2155,45 @@ Type\ of\ the\ eprint\ identifier,\ e.\ g.,\ the\ name\ of\ the\ archive,\ repos URL\ of\ an\ online\ publication.=URL of an online publication. Volume\ of\ a\ multi-volume\ book\ or\ a\ periodical.=Volume of a multi-volume book or a periodical. Year\ of\ publication.=Year of publication. +This\ field\ is\ intended\ for\ recording\ abstracts,\ to\ be\ printed\ by\ a\ special\ bibliography\ style.=This field is intended for recording abstracts, to be printed by a special bibliography style. +This\ field\ may\ be\ useful\ when\ implementing\ a\ style\ for\ annotated\ bibliographies.=This field may be useful when implementing a style for annotated bibliographies. +Subtitle\ related\ to\ the\ "Booktitle".=Subtitle related to the "Booktitle". +Annex\ to\ the\ "Booktitle",\ to\ be\ printed\ in\ a\ different\ font.=Annex to the "Booktitle", to be printed in a different font. +Comment\ to\ this\ entry.=Comment to this entry. +Secondary\ editor\ performing\ a\ different\ editorial\ role,\ such\ as\ compiling,\ redacting,\ etc.=Secondary editor performing a different editorial role, such as compiling, redacting, etc. +Another\ secondary\ editor\ performing\ a\ different\ role.=Another secondary editor performing a different role. +Type\ of\ editorial\ role\ performed\ by\ the\ "Editor".=Type of editorial role performed by the "Editor". +Type\ of\ editorial\ role\ performed\ by\ the\ "Editora".=Type of editorial role performed by the "Editora". +Type\ of\ editorial\ role\ performed\ by\ the\ "Editorb".=Type of editorial role performed by the "Editorb". +Type\ of\ editorial\ role\ performed\ by\ the\ "Editorc".=Type of editorial role performed by the "Editorc". +Author(s)\ of\ a\ foreword\ to\ the\ work.=Author(s) of a foreword to the work. +International\ Standard\ Technical\ Report\ Number\ of\ a\ technical\ report.=International Standard Technical Report Number of a technical report. +International\ Standard\ Serial\ Number\ of\ a\ periodical.=International Standard Serial Number of a periodical. +Subtitle\ of\ a\ journal,\ a\ newspaper,\ or\ some\ other\ periodical.=Subtitle of a journal, a newspaper, or some other periodical. +Language(s)\ of\ the\ work.\ Languages\ may\ be\ specified\ literally\ or\ as\ localisation\ keys.=Language(s) of the work. Languages may be specified literally or as localisation keys. +Subtitle\ related\ to\ the\ "Maintitle".=Subtitle related to the "Maintitle". +Annex\ to\ the\ "Maintitle",\ to\ be\ printed\ in\ a\ different\ font.=Annex to the "Maintitle", to be printed in a different font. +Addon\ to\ be\ printed\ immediately\ after\ the\ author\ name\ in\ the\ bibliography.=Addon to be printed immediately after the author name in the bibliography. +If\ the\ work\ is\ a\ translation,\ a\ reprint,\ or\ something\ similar,\ the\ publication\ date\ of\ the\ original\ edition.=If the work is a translation, a reprint, or something similar, the publication date of the original edition. +If\ the\ work\ is\ a\ translation,\ the\ language(s)\ of\ the\ original\ work.=If the work is a translation, the language(s) of the original work. +Pagination\ of\ the\ work.\ The\ key\ should\ be\ given\ in\ the\ singular\ form.=Pagination of the work. The key should be given in the singular form. +Number\ of\ a\ partial\ volume.\ This\ field\ applies\ to\ books\ only,\ not\ to\ journals.\ It\ may\ be\ used\ when\ a\ logical\ volume\ consists\ of\ two\ or\ more\ physical\ ones.=Number of a partial volume. This field applies to books only, not to journals. It may be used when a logical volume consists of two or more physical ones. +Title\ in\ an\ abridged\ form.=Title in an abridged form. +Annex\ to\ the\ "Title",\ to\ be\ printed\ in\ a\ different\ font.=Annex to the "Title", to be printed in a different font. +Translator(s)\ of\ the\ "Title"\ or\ "Booktitle",\ depending\ on\ the\ entry\ type.\ If\ the\ translator\ is\ identical\ to\ the\ "Editor",\ the\ standard\ styles\ will\ automatically\ concatenate\ these\ fields\ in\ the\ bibliography.=Translator(s) of the "Title" or "Booktitle", depending on the entry type. If the translator is identical to the "Editor", the standard styles will automatically concatenate these fields in the bibliography. +Type\ of\ a\ "Manual",\ "Patent",\ "Report",\ or\ "Thesis".=Type of a "Manual", "Patent", "Report", or "Thesis". +This\ field\ holds\ an\ entry\ key\ for\ the\ cross-referencing\ feature.\ Child\ entries\ with\ a\ "Crossref"\ field\ inherit\ data\ from\ the\ parent\ entry\ specified\ in\ the\ "Crossref"\ field.=This field holds an entry key for the cross-referencing feature. Child entries with a "Crossref" field inherit data from the parent entry specified in the "Crossref" field. +Gender\ of\ the\ author\ or\ gender\ of\ the\ editor,\ if\ there\ is\ no\ author.=Gender of the author or gender of the editor, if there is no author. +Citation\ keys\ of\ other\ entries\ which\ have\ a\ relationship\ to\ this\ entry.=Citation keys of other entries which have a relationship to this entry. +This\ field\ is\ an\ alternative\ cross-referencing\ mechanism.\ It\ differs\ from\ "Crossref"\ in\ that\ the\ child\ entry\ will\ not\ inherit\ any\ data\ from\ the\ parent\ entry\ specified\ in\ the\ "Xref"\ field.=This field is an alternative cross-referencing mechanism. It differs from "Crossref" in that the child entry will not inherit any data from the parent entry specified in the "Xref" field. +Owner/creator\ of\ this\ entry.=Owner/creator of this entry. +Timestamp\ of\ this\ entry,\ when\ it\ has\ been\ created\ or\ last\ modified.=Timestamp of this entry, when it has been created or last modified. +User-specific\ printed\ flag,\ in\ case\ the\ entry\ has\ been\ printed.=User-specific printed flag, in case the entry has been printed. +User-specific\ priority.=User-specific priority. +User-specific\ quality\ flag,\ in\ case\ its\ quality\ is\ assured.=User-specific quality flag, in case its quality is assured. +User-specific\ ranking.=User-specific ranking. +User-specific\ read\ status.=User-specific read status. +User-specific\ relevance\ flag,\ in\ case\ the\ entry\ is\ relevant.=User-specific relevance flag, in case the entry is relevant. Remove\ formatter\ for\ %0=Remove formatter for %0 Remove\ formatter\ '%0'=Remove formatter '%0' From 037102f4fe6fef66cf88522cf0b71b107554db0c Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 10 Apr 2020 17:29:29 +0200 Subject: [PATCH 08/23] Use https everywhere --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21ab436819e..9470e7343bd 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ An explanation of donation possibilities and usage of donations is available at [![Join the chat at https://gitter.im/JabRef/jabref](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/JabRef/jabref?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![OpenHub](https://www.openhub.net/p/jabref/widgets/project_thin_badge.gif)](https://www.openhub.net/p/jabref) -> Not a programmer? [Learn how to help.](http://contribute.jabref.org) +> Not a programmer? [Learn how to help.](https://contribute.jabref.org) Want to be part of a free and open-source project that tens of thousands of scientists use every day? Check out the ways you can contribute, below: From 478569968b1364ca373e1ebcb42dec0736be10cb Mon Sep 17 00:00:00 2001 From: github actions Date: Fri, 10 Apr 2020 15:45:35 +0000 Subject: [PATCH 09/23] Squashed 'src/main/resources/csl-styles/' changes from 88726cb64d..db54e5655d MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit db54e5655d Update CONTRIBUTING.md 2f16a9bbe0 Update CONTRIBUTING.md 4cd05ba3d2 Create associacao-brasileira-de-normas-tecnicas-ufrgs-footnote-ibid.csl (#4369) 4d4655ec70 Update instituto-brasileiro-de-informacao-em-ciencia-e-tecnologia-abn… (#4684) 59482650cd Update instituto-brasileiro-de-informacao-em-ciencia-e-tecnologia-abn… (#4683) f8b744c2e4 Create aberdeen-university-school-of-education-harvard.csl (#4685) 807930a3a3 Update trabajos-de-prehistoria.csl (#4680) c25709f615 Update society-for-american-archaeology.csl (#4681) 86f888afc0 Update archeosciences.csl (#4682) 99c4fd322b Create sylwan.csl (#4678) d9ba2dedaf Update equine-veterinary-education.csl (#4677) 7d306592bc Update equine-veterinary-education.csl (#4675) 9a7791fd2d Update equine-veterinary-education.csl (#4674) 0a46235dd6 Create norois.csl (#4673) git-subtree-dir: src/main/resources/csl-styles git-subtree-split: db54e5655db93458e241e237f96e2e5883baa63d --- CONTRIBUTING.md | 16 +- archeosciences.csl | 136 +-- ...tecnicas-ufrgs-note-initials-with-ibid.csl | 949 ++++++++++++++++++ equine-veterinary-education.csl | 125 ++- ...-em-ciencia-e-tecnologia-abnt-initials.csl | 425 ++++---- ...nformacao-em-ciencia-e-tecnologia-abnt.csl | 429 ++++---- norois.csl | 525 ++++++++++ society-for-american-archaeology.csl | 38 +- sylwan.csl | 597 +++++++++++ trabajos-de-prehistoria.csl | 8 +- ...f-aberdeen-school-of-education-harvard.csl | 383 +++++++ 11 files changed, 3043 insertions(+), 588 deletions(-) create mode 100644 associacao-brasileira-de-normas-tecnicas-ufrgs-note-initials-with-ibid.csl create mode 100644 norois.csl create mode 100644 sylwan.csl create mode 100644 university-of-aberdeen-school-of-education-harvard.csl diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6b4d0986f8b..3b06aea71fb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ To submit a style, please follow the following steps (for locale files, follow t #### 1. Check that your style meets all our [style requirements](https://github.com/citation-style-language/styles/wiki/Style-Requirements) -#### 2. [Validate](https://github.com/citation-style-language/styles/wiki/Validation) your style against the CSL schema, and correct any validation errors +#### 2. [Validate](https://validator.citationstyles.org/) your style against the CSL schema, and correct any validation errors #### 3. Create a pull request @@ -33,7 +33,7 @@ To start, create a GitHub account and sign in. ##### 3b. Submitting changes to an existing style 1. Visit https://github.com/citation-style-language/styles and find the style you wish to change (dependent styles are stored in the [dependent](https://github.com/citation-style-language/styles/tree/master/dependent) subdirectory). - To search by file name press "t" (this activates GitHub’s [File Finder](https://github.com/blog/793-introducing-the-file-finder)) and start typing. + To search the repository by file name, click the "Find file" button or press t to activate GitHub’s [file finder](https://help.github.com/en/github/searching-for-information-on-github/finding-files-on-github) and start typing. 2. Click on the style name, which will bring you to a page like https://github.com/citation-style-language/styles/blob/master/apa.csl. 3. Click the edit icon (in the shape of a pencil). This opens a code editor in which you can make your changes (you can for example copy and paste your modified style into this window). @@ -52,30 +52,30 @@ We often request you to make some changes to your pull request. Don't create a new pull request right away if your original submission has issues. It's much easier for us if you update your original pull request instead. -After you create a pull request, our @csl-bot will first automatically run a number of tests to check whether your style validates and follows our style requirements. +After you create a pull request, our [@csl-bot](https://github.com/csl-bot) will first automatically run a number of tests to check whether your style validates and follows our style requirements. These tests usually finish within a few minutes. -If there are problems, @csl-bot will give a link to the test report, which contains the identified errors. +If there are problems, [@csl-bot](https://github.com/csl-bot) will leave a comment with the identified errors. If you have trouble understanding these errors, please post a comment in the pull request and ask for help. -We also have a handful of volunteers who review pull requests, usually within a day or two. +We also have a handful of volunteers who review pull requests, usually within a week or two. To update your pull request: 1. Visit the "Files changed" tab of your pull request. -2. Click the edit (pencil) icon at the top-right of your style. +2. Click the ellipsis button at the top-right of your style, and select "Edit file" in the ellipsis menu. 3. Make your changes, and click the "Commit changes" button. Any changes made this way will automatically appear in the pull request, and each commit will trigger a new test report. Once we are satisfied, we will **merge** your pull request. -This can take hours or days, depending on how busy we are, and on how much back and forth is needed to get your style in acceptable shape. +This can take days or weeks, depending on how busy we are, and on how much back and forth is needed to get your style in acceptable shape. #### 5. Make additional changes after merging Once a pull request has been merged, it can no longer be used to submit further changes. So, if you wish to make additional changes, just create a new pull request. -Please always start from the latest version of the style from our repository, because we often perform maintenance on the repository styles. +Please always start from the latest version of the style from our repository, because we may have performed maintenance on your style or accepted corrections from other contributors. ## Asking for help diff --git a/archeosciences.csl b/archeosciences.csl index 3e47dcbde9e..d5da8f3f69f 100644 --- a/archeosciences.csl +++ b/archeosciences.csl @@ -1,6 +1,6 @@ diff --git a/equine-veterinary-education.csl b/equine-veterinary-education.csl index 5ca3be5962b..d98416158a0 100644 --- a/equine-veterinary-education.csl +++ b/equine-veterinary-education.csl @@ -1,52 +1,50 @@ - diff --git a/instituto-brasileiro-de-informacao-em-ciencia-e-tecnologia-abnt-initials.csl b/instituto-brasileiro-de-informacao-em-ciencia-e-tecnologia-abnt-initials.csl index a11d1a84189..b01dad805cd 100644 --- a/instituto-brasileiro-de-informacao-em-ciencia-e-tecnologia-abnt-initials.csl +++ b/instituto-brasileiro-de-informacao-em-ciencia-e-tecnologia-abnt-initials.csl @@ -1,7 +1,7 @@ - diff --git a/society-for-american-archaeology.csl b/society-for-american-archaeology.csl index c4bf3bd173f..a92dd15abc6 100644 --- a/society-for-american-archaeology.csl +++ b/society-for-american-archaeology.csl @@ -1,10 +1,13 @@ - diff --git a/trabajos-de-prehistoria.csl b/trabajos-de-prehistoria.csl index 7cd53900036..08b707b343a 100644 --- a/trabajos-de-prehistoria.csl +++ b/trabajos-de-prehistoria.csl @@ -15,7 +15,7 @@ 0082-5638 1988-3218 - 2020-04-04T11:24:49+00:00 + 2020-04-09T10:37:35+00:00 This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License @@ -109,7 +109,7 @@ - + @@ -127,11 +127,11 @@ - + - + diff --git a/university-of-aberdeen-school-of-education-harvard.csl b/university-of-aberdeen-school-of-education-harvard.csl new file mode 100644 index 00000000000..2e719634880 --- /dev/null +++ b/university-of-aberdeen-school-of-education-harvard.csl @@ -0,0 +1,383 @@ + + From d4396ce4de0c796a6b40b1b63351a011c715594d Mon Sep 17 00:00:00 2001 From: Grzegorz Popiel Date: Fri, 10 Apr 2020 21:26:45 +0200 Subject: [PATCH 10/23] Fix sort by priority (#6222) (#6265) * Fix sort by priority (#6222) * Change in CHANGELOG. --- CHANGELOG.md | 1 + .../gui/maintable/MainTableColumnFactory.java | 5 ++++ .../comparator/PriorityFieldComparator.java | 27 +++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/main/java/org/jabref/gui/util/comparator/PriorityFieldComparator.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c49eaed2b1..7b63f3508ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve ### Fixed +- We fixed an issue where sort by priority was broken. [#6222](https://github.com/JabRef/jabref/issues/6222) - We fixed an issue where opening a library from the recent libraries menu was not possible. [#5939](https://github.com/JabRef/jabref/issues/5939) - We fixed an issue with inconsistent capitalization of file extensions when downloading files [#6115](https://github.com/JabRef/jabref/issues/6115) - We fixed the display of language and encoding in the preferences dialog. [#6130](https://github.com/JabRef/jabref/pull/6130) diff --git a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java index bde67b260aa..a821e343d01 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java +++ b/src/main/java/org/jabref/gui/maintable/MainTableColumnFactory.java @@ -38,6 +38,7 @@ import org.jabref.gui.specialfields.SpecialFieldsPreferences; import org.jabref.gui.util.OptionalValueTableCellFactory; import org.jabref.gui.util.ValueTableCellFactory; +import org.jabref.gui.util.comparator.PriorityFieldComparator; import org.jabref.gui.util.comparator.RankingFieldComparator; import org.jabref.gui.util.comparator.ReadStatusFieldComparator; import org.jabref.logic.l10n.Localization; @@ -316,6 +317,10 @@ private TableColumn column.setComparator(new ReadStatusFieldComparator()); } + if (specialField == SpecialField.PRIORITY) { + column.setComparator(new PriorityFieldComparator()); + } + column.setSortable(true); return column; diff --git a/src/main/java/org/jabref/gui/util/comparator/PriorityFieldComparator.java b/src/main/java/org/jabref/gui/util/comparator/PriorityFieldComparator.java new file mode 100644 index 00000000000..d9ab62e1cc3 --- /dev/null +++ b/src/main/java/org/jabref/gui/util/comparator/PriorityFieldComparator.java @@ -0,0 +1,27 @@ +package org.jabref.gui.util.comparator; + +import java.util.Comparator; +import java.util.Optional; + +import org.jabref.gui.specialfields.SpecialFieldValueViewModel; + +public class PriorityFieldComparator implements Comparator> { + + @Override + public int compare(Optional val1, Optional val2) { + if (val1.isPresent()) { + if (val2.isPresent()) { + return val1.get().getValue().compareTo(val2.get().getValue()); + } else { + return -1; + } + } else { + if (val2.isPresent()) { + return 1; + } else { + return 0; + } + } + } + +} From 1c724f26742ba832c610e5795bc30e35fa0de2b7 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sat, 11 Apr 2020 11:49:00 +0200 Subject: [PATCH 11/23] Improve calculation of matched entries upon change (#6268) Instead of recalculating the number of matched entries for every group (which means `#groups * #entries` operations) now a change triggers a more intelligent re-calculation which needs at maximum `#groups` operations. This gives a huge boost and makes editing entries smooth even for large databases with many groups. --- CHANGELOG.md | 5 +- .../jabref/gui/groups/GroupNodeViewModel.java | 52 ++++++++++++++----- .../java/org/jabref/model/entry/BibEntry.java | 4 +- .../jabref/model/groups/GroupTreeNode.java | 18 ++++--- .../model/groups/GroupTreeNodeTest.java | 48 ++++++++--------- 5 files changed, 77 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b63f3508ca..6df019fe891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,12 +27,13 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve ### Fixed +- We greatly improved the performance of the overall application and many operations. [#5071](https://github.com/JabRef/jabref/issues/5071) - We fixed an issue where sort by priority was broken. [#6222](https://github.com/JabRef/jabref/issues/6222) - We fixed an issue where opening a library from the recent libraries menu was not possible. [#5939](https://github.com/JabRef/jabref/issues/5939) -- We fixed an issue with inconsistent capitalization of file extensions when downloading files [#6115](https://github.com/JabRef/jabref/issues/6115) +- We fixed an issue with inconsistent capitalization of file extensions when downloading files. [#6115](https://github.com/JabRef/jabref/issues/6115) - We fixed the display of language and encoding in the preferences dialog. [#6130](https://github.com/JabRef/jabref/pull/6130) - We fixed an issue where search full-text documents downloaded files with same name, overwriting existing files. [#6174](https://github.com/JabRef/jabref/pull/6174) -- We fixe an issue where custom jstyles for Open/LibreOffice where not saved correctly [#6170](https://github.com/JabRef/jabref/issues/6170) +- We fixe an issue where custom jstyles for Open/LibreOffice where not saved correctly. [#6170](https://github.com/JabRef/jabref/issues/6170) ### Removed diff --git a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java index a20278ae64f..4f40d4bb670 100644 --- a/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java @@ -8,8 +8,8 @@ import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.IntegerBinding; import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.property.SimpleIntegerProperty; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; @@ -28,7 +28,6 @@ import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.groups.DefaultGroupsFactory; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; -import org.jabref.logic.util.DelayTaskThrottler; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -50,7 +49,7 @@ public class GroupNodeViewModel { private final BibDatabaseContext databaseContext; private final StateManager stateManager; private final GroupTreeNode groupNode; - private final SimpleIntegerProperty hits; + private final ObservableList matchedEntries = FXCollections.observableArrayList(); private final SimpleBooleanProperty hasChildren; private final SimpleBooleanProperty expandedProperty = new SimpleBooleanProperty(); private final BooleanBinding anySelectedEntriesMatched; @@ -58,7 +57,6 @@ public class GroupNodeViewModel { private final TaskExecutor taskExecutor; private final CustomLocalDragboard localDragBoard; private final ObservableList entriesList; - private final DelayTaskThrottler throttler; public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager stateManager, TaskExecutor taskExecutor, GroupTreeNode groupNode, CustomLocalDragboard localDragBoard) { this.databaseContext = Objects.requireNonNull(databaseContext); @@ -82,8 +80,7 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state } hasChildren = new SimpleBooleanProperty(); hasChildren.bind(Bindings.isNotEmpty(children)); - hits = new SimpleIntegerProperty(0); - calculateNumberOfMatches(); + updateMatchedEntries(); expandedProperty.set(groupNode.getGroup().isExpanded()); expandedProperty.addListener((observable, oldValue, newValue) -> groupNode.getGroup().setExpanded(newValue)); @@ -91,7 +88,6 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state // The wrapper created by the FXCollections will set a weak listener on the wrapped list. This weak listener gets garbage collected. Hence, we need to maintain a reference to this list. entriesList = databaseContext.getDatabase().getEntries(); entriesList.addListener(this::onDatabaseChanged); - throttler = taskExecutor.createThrottler(1000); ObservableList selectedEntriesMatchStatus = EasyBind.map(stateManager.getSelectedEntries(), groupNode::matches); anySelectedEntriesMatched = BindingsHelper.any(selectedEntriesMatchStatus, matched -> matched); @@ -157,8 +153,8 @@ public String getDescription() { return groupNode.getGroup().getDescription().orElse(""); } - public SimpleIntegerProperty getHits() { - return hits; + public IntegerBinding getHits() { + return Bindings.size(matchedEntries); } @Override @@ -184,7 +180,7 @@ public String toString() { ", children=" + children + ", databaseContext=" + databaseContext + ", groupNode=" + groupNode + - ", hits=" + hits + + ", matchedEntries=" + matchedEntries + '}'; } @@ -222,16 +218,44 @@ public GroupTreeNode getGroupNode() { * Gets invoked if an entry in the current database changes. */ private void onDatabaseChanged(ListChangeListener.Change change) { - throttler.schedule(this::calculateNumberOfMatches); + while (change.next()) { + if (change.wasPermutated()) { + // Nothing to do, as permutation doesn't change matched entries + } else if (change.wasUpdated()) { + for (BibEntry changedEntry : change.getList().subList(change.getFrom(), change.getTo())) { + if (groupNode.matches(changedEntry)) { + if (!matchedEntries.contains(changedEntry)) { + matchedEntries.add(changedEntry); + } + } else { + matchedEntries.remove(changedEntry); + } + } + } else { + for (BibEntry removedEntry : change.getRemoved()) { + matchedEntries.remove(removedEntry); + } + for (BibEntry addedEntry : change.getAddedSubList()) { + if (groupNode.matches(addedEntry)) { + if (!matchedEntries.contains(addedEntry)) { + matchedEntries.add(addedEntry); + } + } + } + } + } } - private void calculateNumberOfMatches() { + private void updateMatchedEntries() { // We calculate the new hit value // We could be more intelligent and try to figure out the new number of hits based on the entry change // for example, a previously matched entry gets removed -> hits = hits - 1 BackgroundTask - .wrap(() -> groupNode.calculateNumberOfMatches(databaseContext.getDatabase())) - .onSuccess(hits::setValue) + .wrap(() -> groupNode.findMatches(databaseContext.getDatabase())) + .onSuccess(entries -> { + matchedEntries.clear(); + matchedEntries.addAll(entries); + }) .executeWith(taskExecutor); } diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index d4c69cdfcdd..db66d82b3c6 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -528,8 +528,8 @@ public Optional setField(Field field, String value, EntriesEventSou changed = true; - fields.put(field, value.intern()); invalidateFieldCache(field); + fields.put(field, value.intern()); FieldChange change = new FieldChange(this, field, oldValue, value); if (isNewField) { @@ -574,8 +574,8 @@ public Optional clearField(Field field, EntriesEventSource eventSou changed = true; - fields.remove(field); invalidateFieldCache(field); + fields.remove(field); FieldChange change = new FieldChange(this, field, oldValue.get(), null); eventBus.post(new FieldAddedOrRemovedEvent(change, eventSource)); diff --git a/src/main/java/org/jabref/model/groups/GroupTreeNode.java b/src/main/java/org/jabref/model/groups/GroupTreeNode.java index f0f0b9d4745..85795e36194 100644 --- a/src/main/java/org/jabref/model/groups/GroupTreeNode.java +++ b/src/main/java/org/jabref/model/groups/GroupTreeNode.java @@ -218,24 +218,26 @@ public GroupTreeNode copyNode() { } /** - * Determines the number of entries in the specified list which are matched by this group. + * Determines the entries in the specified list which are matched by this group. + * * @param entries list of entries to be searched - * @return number of hits + * @return matched entries */ - public long calculateNumberOfMatches(List entries) { + public List findMatches(List entries) { SearchMatcher matcher = getSearchMatcher(); return entries.stream() .filter(matcher::isMatch) - .count(); + .collect(Collectors.toList()); } /** - * Determines the number of entries in the specified database which are matched by this group. + * Determines the entries in the specified database which are matched by this group. + * * @param database database to be searched - * @return number of hits + * @return matched entries */ - public long calculateNumberOfMatches(BibDatabase database) { - return calculateNumberOfMatches(database.getEntries()); + public List findMatches(BibDatabase database) { + return findMatches(database.getEntries()); } /** diff --git a/src/test/java/org/jabref/model/groups/GroupTreeNodeTest.java b/src/test/java/org/jabref/model/groups/GroupTreeNodeTest.java index 36fb12c924c..05886e41c76 100644 --- a/src/test/java/org/jabref/model/groups/GroupTreeNodeTest.java +++ b/src/test/java/org/jabref/model/groups/GroupTreeNodeTest.java @@ -95,7 +95,7 @@ private static AbstractGroup getExplict(String name) { * A */ /* - public GroupTreeNode getNodeAsChild(TreeNodeMock root) { + GroupTreeNode getNodeAsChild(TreeNodeMock root) { root.addChild(new TreeNodeMock()); root.addChild(new TreeNodeMock()); TreeNodeMock node = new TreeNodeMock(); @@ -109,7 +109,7 @@ public static GroupTreeNode getRoot() { } @BeforeEach - public void setUp() throws Exception { + void setUp() throws Exception { entries.clear(); entry = new BibEntry(); entries.add(entry); @@ -118,7 +118,7 @@ public void setUp() throws Exception { } /* - public GroupTreeNode getNodeInComplexTree() { + GroupTreeNode getNodeInComplexTree() { return getNodeInComplexTree(new TreeNodeMock()); } */ @@ -128,14 +128,14 @@ private GroupTreeNode getNodeInSimpleTree() { } @Test - public void getSearchRuleForIndependentGroupReturnsGroupAsMatcher() { + void getSearchRuleForIndependentGroupReturnsGroupAsMatcher() { GroupTreeNode node = GroupTreeNode .fromGroup(new ExplicitGroup("node", GroupHierarchyType.INDEPENDENT, ',')); assertEquals(node.getGroup(), node.getSearchMatcher()); } @Test - public void getSearchRuleForRefiningGroupReturnsParentAndGroupAsMatcher() { + void getSearchRuleForRefiningGroupReturnsParentAndGroupAsMatcher() { GroupTreeNode parent = GroupTreeNode .fromGroup( new ExplicitGroup("parent", GroupHierarchyType.INDEPENDENT, ',')); @@ -149,7 +149,7 @@ public void getSearchRuleForRefiningGroupReturnsParentAndGroupAsMatcher() { } @Test - public void getSearchRuleForIncludingGroupReturnsGroupOrSubgroupAsMatcher() { + void getSearchRuleForIncludingGroupReturnsGroupOrSubgroupAsMatcher() { GroupTreeNode node = GroupTreeNode.fromGroup(new ExplicitGroup("node", GroupHierarchyType.INCLUDING, ',')); GroupTreeNode child = node.addSubgroup(new ExplicitGroup("child", GroupHierarchyType.INDEPENDENT, ',')); @@ -160,48 +160,48 @@ public void getSearchRuleForIncludingGroupReturnsGroupOrSubgroupAsMatcher() { } @Test - public void numberOfHitsReturnsZeroForEmptyList() throws Exception { - assertEquals(0, getNodeInSimpleTree().calculateNumberOfMatches(Collections.emptyList())); + void findMatchesReturnsEmptyForEmptyList() throws Exception { + assertEquals(Collections.emptyList(), getNodeInSimpleTree().findMatches(Collections.emptyList())); } @Test - public void numberOfHitsMatchesOneEntry() throws Exception { + void findMatchesOneEntry() throws Exception { GroupTreeNode parent = getNodeInSimpleTree(); GroupTreeNode node = parent.addSubgroup( new WordKeywordGroup("node", GroupHierarchyType.INDEPENDENT, StandardField.AUTHOR, "author2", true, ',', false)); - assertEquals(1, node.calculateNumberOfMatches(entries)); + assertEquals(1, node.findMatches(entries).size()); } @Test - public void numberOfHitsMatchesMultipleEntries() throws Exception { + void findMatchesMultipleEntries() throws Exception { GroupTreeNode parent = getNodeInSimpleTree(); GroupTreeNode node = parent.addSubgroup( new WordKeywordGroup("node", GroupHierarchyType.INDEPENDENT, StandardField.AUTHOR, "author1", true, ',', false)); - assertEquals(2, node.calculateNumberOfMatches(entries)); + assertEquals(2, node.findMatches(entries).size()); } @Test - public void numberOfHitsWorksForRefiningGroups() throws Exception { + void findMatchesWorksForRefiningGroups() throws Exception { GroupTreeNode grandParent = getNodeInSimpleTree(); GroupTreeNode parent = grandParent.addSubgroup( new WordKeywordGroup("node", GroupHierarchyType.INDEPENDENT, StandardField.AUTHOR, "author2", true, ',', false)); GroupTreeNode node = parent.addSubgroup( new WordKeywordGroup("node", GroupHierarchyType.REFINING, StandardField.AUTHOR, "author1", true, ',', false)); - assertEquals(1, node.calculateNumberOfMatches(entries)); + assertEquals(1, node.findMatches(entries).size()); } @Test - public void numberOfHitsWorksForHierarchyOfIndependentGroups() throws Exception { + void findMatchesWorksForHierarchyOfIndependentGroups() throws Exception { GroupTreeNode grandParent = getNodeInSimpleTree(); GroupTreeNode parent = grandParent.addSubgroup( new WordKeywordGroup("node", GroupHierarchyType.INDEPENDENT, StandardField.AUTHOR, "author2", true, ',', false)); GroupTreeNode node = parent.addSubgroup( new WordKeywordGroup("node", GroupHierarchyType.INDEPENDENT, StandardField.AUTHOR, "author1", true, ',', false)); - assertEquals(2, node.calculateNumberOfMatches(entries)); + assertEquals(2, node.findMatches(entries).size()); } @Test - public void setGroupChangesUnderlyingGroup() throws Exception { + void setGroupChangesUnderlyingGroup() throws Exception { GroupTreeNode node = getNodeInSimpleTree(); AbstractGroup newGroup = new ExplicitGroup("NewGroup", GroupHierarchyType.INDEPENDENT, ','); @@ -211,7 +211,7 @@ public void setGroupChangesUnderlyingGroup() throws Exception { } @Test - public void setGroupAddsPreviousAssignmentsExplicitToExplicit() throws Exception { + void setGroupAddsPreviousAssignmentsExplicitToExplicit() throws Exception { ExplicitGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, ','); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); @@ -223,7 +223,7 @@ public void setGroupAddsPreviousAssignmentsExplicitToExplicit() throws Exception } @Test - public void setGroupWithFalseDoesNotAddsPreviousAssignments() throws Exception { + void setGroupWithFalseDoesNotAddsPreviousAssignments() throws Exception { ExplicitGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, ','); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); @@ -235,7 +235,7 @@ public void setGroupWithFalseDoesNotAddsPreviousAssignments() throws Exception { } @Test - public void setGroupAddsOnlyPreviousAssignments() throws Exception { + void setGroupAddsOnlyPreviousAssignments() throws Exception { ExplicitGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, ','); assertFalse(oldGroup.isMatch(entry)); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); @@ -247,7 +247,7 @@ public void setGroupAddsOnlyPreviousAssignments() throws Exception { } @Test - public void setGroupExplicitToSearchDoesNotKeepPreviousAssignments() throws Exception { + void setGroupExplicitToSearchDoesNotKeepPreviousAssignments() throws Exception { ExplicitGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, ','); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); @@ -259,7 +259,7 @@ public void setGroupExplicitToSearchDoesNotKeepPreviousAssignments() throws Exce } @Test - public void setGroupExplicitToExplicitIsRenameAndSoRemovesPreviousAssignment() throws Exception { + void setGroupExplicitToExplicitIsRenameAndSoRemovesPreviousAssignment() throws Exception { ExplicitGroup oldGroup = new ExplicitGroup("OldGroup", GroupHierarchyType.INDEPENDENT, ','); oldGroup.add(entry); GroupTreeNode node = GroupTreeNode.fromGroup(oldGroup); @@ -271,7 +271,7 @@ public void setGroupExplicitToExplicitIsRenameAndSoRemovesPreviousAssignment() t } @Test - public void getChildByPathFindsCorrectChildInSecondLevel() throws Exception { + void getChildByPathFindsCorrectChildInSecondLevel() throws Exception { GroupTreeNode root = getRoot(); GroupTreeNode child = getNodeInSimpleTree(root); @@ -279,7 +279,7 @@ public void getChildByPathFindsCorrectChildInSecondLevel() throws Exception { } @Test - public void getPathSimpleTree() throws Exception { + void getPathSimpleTree() throws Exception { GroupTreeNode node = getNodeInSimpleTree(); assertEquals("ExplicitParent > ExplicitNode", node.getPath()); From 771af5dc2a45a2cfeeb48d1f2286424292238595 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 12 Apr 2020 13:37:35 +0200 Subject: [PATCH 12/23] Improve performance (#6270) * Improve performance - Cache latex free field values for display in the main table - Only access preferences once for how to display names (instead of for every entry again) - Update search async only after 400ms without typing * Fix tests --- .idea/runConfigurations/JabRef_Main.xml | 3 + src/main/java/org/jabref/gui/BasePanel.java | 4 +- .../gui/maintable/BibEntryTableViewModel.java | 2 +- .../org/jabref/gui/maintable/FieldColumn.java | 55 +----- .../gui/maintable/MainTableNameFormatter.java | 31 ++-- .../jabref/gui/search/GlobalSearchBar.java | 9 +- .../gui/util/ValueTableCellFactory.java | 6 +- .../java/org/jabref/model/entry/BibEntry.java | 51 +++--- .../BibtexKeyGeneratorTest.java | 148 +++++++-------- .../org/jabref/model/entry/BibEntryTest.java | 170 +++++++++--------- 10 files changed, 220 insertions(+), 259 deletions(-) diff --git a/.idea/runConfigurations/JabRef_Main.xml b/.idea/runConfigurations/JabRef_Main.xml index 70f04ee246c..4a1ef684c65 100644 --- a/.idea/runConfigurations/JabRef_Main.xml +++ b/.idea/runConfigurations/JabRef_Main.xml @@ -4,6 +4,9 @@