From 646135731bc0607719b64b6b9406f4f13362aeb5 Mon Sep 17 00:00:00 2001 From: leaf-soba Date: Fri, 6 Sep 2024 15:41:19 +0800 Subject: [PATCH 001/324] Rename "Show 'Ai Chat' tab" to "Show tab 'AI Chat'" (#11709) solve #11708 --- .../jabref/gui/preferences/entryeditor/EntryEditorTab.fxml | 4 ++-- src/main/resources/l10n/JabRef_en.properties | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/entryeditor/EntryEditorTab.fxml b/src/main/java/org/jabref/gui/preferences/entryeditor/EntryEditorTab.fxml index 664e5ee0b79..c95c261f7ac 100644 --- a/src/main/java/org/jabref/gui/preferences/entryeditor/EntryEditorTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/entryeditor/EntryEditorTab.fxml @@ -32,8 +32,8 @@ - - + + diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index b105285632a..5ff0d0364d7 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2524,8 +2524,8 @@ AI=AI AI\ chat=AI chat I\ agree=I agree Privacy\ notice=Privacy notice -Show\ 'AI\ Chat'\ tab=Show 'AI Chat' tab -Show\ 'AI\ Summary'\ tab=Show 'AI Summary' tab +Show\ tab\ 'AI\ Chat'=Show tab 'AI Chat' +Show\ tab\ 'AI\ Summary'=Show tab 'AI Summary' Submit=Submit Unable\ to\ chat=Unable to chat Clear\ chat\ history=Clear chat history From 4e5715c44fdb18fbcb5c4cc28b435c08668c6d2b Mon Sep 17 00:00:00 2001 From: Christoph Date: Fri, 6 Sep 2024 20:17:46 +0200 Subject: [PATCH 002/324] New Crowdin updates (#11711) * New translations jabref_en.properties (French) * New translations jabref_en.properties (Polish) * New translations jabref_en.properties (Portuguese, Brazilian) * New translations jabref_en.properties (Spanish) * New translations jabref_en.properties (Arabic) * New translations jabref_en.properties (Danish) * New translations jabref_en.properties (German) * New translations jabref_en.properties (Greek) * New translations jabref_en.properties (Finnish) * New translations jabref_en.properties (Italian) * New translations jabref_en.properties (Japanese) * New translations jabref_en.properties (Korean) * New translations jabref_en.properties (Dutch) * New translations jabref_en.properties (Norwegian) * New translations jabref_en.properties (Portuguese) * New translations jabref_en.properties (Russian) * New translations jabref_en.properties (Swedish) * New translations jabref_en.properties (Turkish) * New translations jabref_en.properties (Ukrainian) * New translations jabref_en.properties (Chinese Simplified) * New translations jabref_en.properties (Chinese Traditional) * New translations jabref_en.properties (Vietnamese) * New translations jabref_en.properties (Indonesian) * New translations jabref_en.properties (Persian) * New translations jabref_en.properties (Tagalog) --- src/main/resources/l10n/JabRef_ar.properties | 13 ---- src/main/resources/l10n/JabRef_da.properties | 23 ------- src/main/resources/l10n/JabRef_de.properties | 69 ++++++++----------- src/main/resources/l10n/JabRef_el.properties | 33 --------- src/main/resources/l10n/JabRef_es.properties | 33 --------- src/main/resources/l10n/JabRef_fa.properties | 15 ---- src/main/resources/l10n/JabRef_fi.properties | 12 ---- src/main/resources/l10n/JabRef_fr.properties | 60 ++++++---------- src/main/resources/l10n/JabRef_id.properties | 27 -------- src/main/resources/l10n/JabRef_it.properties | 60 ++++++---------- src/main/resources/l10n/JabRef_ja.properties | 33 --------- src/main/resources/l10n/JabRef_ko.properties | 33 --------- src/main/resources/l10n/JabRef_nl.properties | 35 ---------- src/main/resources/l10n/JabRef_no.properties | 23 ------- src/main/resources/l10n/JabRef_pl.properties | 55 ++++++--------- src/main/resources/l10n/JabRef_pt.properties | 32 --------- .../resources/l10n/JabRef_pt_BR.properties | 60 ++++++---------- src/main/resources/l10n/JabRef_ru.properties | 33 --------- src/main/resources/l10n/JabRef_sv.properties | 28 -------- src/main/resources/l10n/JabRef_tl.properties | 27 -------- src/main/resources/l10n/JabRef_tr.properties | 35 ---------- src/main/resources/l10n/JabRef_uk.properties | 21 ------ src/main/resources/l10n/JabRef_vi.properties | 23 ------- .../resources/l10n/JabRef_zh_CN.properties | 35 ---------- .../resources/l10n/JabRef_zh_TW.properties | 22 ------ 25 files changed, 111 insertions(+), 729 deletions(-) diff --git a/src/main/resources/l10n/JabRef_ar.properties b/src/main/resources/l10n/JabRef_ar.properties index 5f59728ba20..996ce6bf593 100644 --- a/src/main/resources/l10n/JabRef_ar.properties +++ b/src/main/resources/l10n/JabRef_ar.properties @@ -1,16 +1,11 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=غير قادر على رصد التغييرات في الملفات. المرجو إغلاق الملفات و البرنامج وإعادة تشغيله. قد تواجه بعض الأخطاء و المشاكل إذا واصلت هذه الجلسة. - - - %0/%1\ entries=%0/%1 مرجع Export\ operation\ finished\ successfully.=انتهاء عملية التصدير بنجاح. Reveal\ in\ File\ Explorer=فتح في متصفح الملفات - - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=اختصر أسماء المجلات المختارة (الإختصار الإفتراضي) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=اختصر أسماء المجلات المختارة (اختصار بدون نقط) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=اختصر أسماء المجلات المختارة (أقصر اختصار فريد و غير متكرر) @@ -49,9 +44,6 @@ Add\ entry\ manually=إنشاء مرجع يدويًا All\ entries=جميع المراجع -and=و - - Application=التطبيق @@ -81,8 +73,6 @@ Cancel=إلغاء - - Change\ case=غيّر حجم الأحرف Change\ entry\ type=تغيير نوع المرجع @@ -254,7 +244,6 @@ Import\ preferences\ from\ file=استيراد الإعدادات من ملف - JabRef\ preferences=إعدادات JabRef @@ -304,7 +293,6 @@ no\ library\ generated=لم يتم توليد المكتبة - Open\ library=فتح المكتبة @@ -418,7 +406,6 @@ Show\ required\ fields=إظهار الحقول المطلوبة -the\ field\ %0=الحقل %0 diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 92419952631..296ce587c92 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1,17 +1,6 @@ -%0\ contains\ the\ regular\ expression\ %1=%0 indeholder regulærudtrykket %1 -%0\ contains\ the\ term\ %1=%0 indeholder udtrykket %1 -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 indeholder ikke regulærudtrykket %1 -%0\ doesn't\ contain\ the\ term\ %1=%0 indeholder ikke udtrykket %1 - - - - -%0\ matches\ the\ regular\ expression\ %1=%0 matcher regulærudtrykket %1 - -%0\ matches\ the\ term\ %1=%0 matcher udtrykket %1 Abbreviate\ names=Forkort navn @@ -56,10 +45,6 @@ The\ label\ of\ the\ string\ cannot\ contain\ the\ '\#'\ character.=Navnet på s All\ entries=Alle poster -and=og - -any\ field\ that\ matches\ the\ regular\ expression\ %0=ethvert felt som matcher regulærudtrykket %0 - Appearance=Udseende Application=Applikation @@ -94,10 +79,6 @@ Cancel=Annuller -case\ insensitive=skelner ikke mellem store og små bogstaver - -case\ sensitive=skelner mellem store og små bogstaver - Case\ sensitive=Skeln mellem store og små bogstaver change\ assignment\ of\ entries=ændre tildeling af poster @@ -332,7 +313,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Uafhængig gruppe\: Vis kun denne gruppes poster - Invalid\ URL=Ugyldig URL @@ -404,8 +384,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Ingen tidsskriftsnavne kunne forkort No\ journal\ names\ could\ be\ unabbreviated.=Ingen tidsskriftsnavne kunne ekspanderes. -not=ikke - not\ found=ikke fundet Nothing\ to\ redo=Ingenting at gentage @@ -610,7 +588,6 @@ New\ BibTeX\ sublibrary=Ny BibTeX-dellibrary Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Skifter mellem fuldt og forkortet tidsskriftsnavn hvis navnet er kendt. -the\ field\ %0=feltet %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Gruppen "%0" indeholder allerede de valgte poster. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Output-indstillingen er afhængig af en gyldig import-indstilling. diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index c10d966d9b8..b3ae803b34e 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Dateiänderungen können nicht überwacht werden. Bitte schließen Sie Dateien und Prozesse und starten Sie neu. Es kann zu Fehlern kommen, wenn Sie diese Sitzung fortsetzen. -%0\ contains\ the\ regular\ expression\ %1=%0 enthält den regulären Ausdruck %1 - -%0\ contains\ the\ term\ %1=%0 enthalten den Ausdruck %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 nicht den regulären Ausdruck %1 enthält - -%0\ doesn't\ contain\ the\ term\ %1=%0 nicht den Ausdruck %1 enthält %0/%1\ entries=%0/%1 Einträge @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Exportvorgang erfolgreich abgeschloss Reveal\ in\ File\ Explorer=Im Datei-Explorer anzeigen -%0\ matches\ the\ regular\ expression\ %1=%0 exakt dem regulären Ausdruck %1 entspricht - -%0\ matches\ the\ term\ %1=%0 exakt dem Ausdruck %1 entspricht - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Zeitschriftennamen der ausgewählten Einträge abkürzen (Standard-Abkürzung) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Zeitschriftentitel der ausgewählten Einträge abkürzen (Ohne-Punkte-Abkürzung) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Zeitschriftennamen der ausgewählten Einträge abkürzen (Kürzestmögliche eindeutige Abkürzung) @@ -89,10 +78,6 @@ All\ entries=Alle Einträge Also\ remove\ subgroups=Auch Untergruppen entfernen -and=und - -any\ field\ that\ matches\ the\ regular\ expression\ %0=ein beliebiges Feld, auf das der reguläre Ausdruck %0 passt, - Appearance=Erscheinungsbild Application=Anwendung @@ -136,10 +121,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Gruppe kann nicht ers Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Ordner kann nicht geöffnet werden, da die Datei ein Website-Link ist. -case\ insensitive=Groß-/Kleinschreibung wird nicht unterschieden - -case\ sensitive=Groß-/Kleinschreibung wird unterschieden - Case\ sensitive=Groß-/Kleinschreibung change\ assignment\ of\ entries=Änderung der zugewiesenen Einträge @@ -503,10 +484,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Unabhängige Gruppen\: Nur die Einträge dieser Gruppe anzeigen I\ Agree=Ich stimme zu -Indexing\ PDF\ files=PDF-Dateien indexieren -Indexing\ for\ %0=Indizierung von %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 von %1 verknüpfte Dateien zum Index hinzugefügt - Invalid\ URL=Ungültige URL Online\ help=Online Hilfe @@ -621,8 +598,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Es konnten keine Zeitschriftentitel No\ journal\ names\ could\ be\ unabbreviated.=Das Aufheben der Abkürzung konnte bei keiner Zeitschrift durchgeführt werden. -not=nicht - not\ found=davon nicht gefunden Nothing\ to\ redo=Wiederholen nicht möglich @@ -833,8 +808,6 @@ Fulltext\ search=Volltextsuche Help\ on\ regular\ expression\ search=Hilfe zur Suche mit regulärem Ausdruck Searching\ for\ duplicates...=Suche nach doppelten Einträgen... Searching\ for\ files=Suche nach Dateien -The\ search\ is\ case-insensitive.=Bei der Suche wird die Groß- und Kleinschreibung nicht berücksichtigt. -The\ search\ is\ case-sensitive.=Bei der Suche wird die Groß- und Kleinschreibung berücksichtigt. Use\ regular\ expression\ search=Suche mit regulärem Ausdruck benutzen search\ expression=Suchausdruck Free\ search\ expression=Freier Suchausdruck @@ -847,17 +820,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Bitte öffnen Sie ei Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Bitte geben Sie einen Feldnamen ein, um nach Schlüsselwörtern zu suchen. No\ results\ found.=Keine Ergebnisse gefunden. Found\ %0\ results.=%0 Ergebnisse gefunden. -Invalid\ regular\ expression=Ungültiger regulärer Ausdruck -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Diese Suche enthält Einträge, die in einem beliebigen Feld den regulären Ausdruck %0 enthalten -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Diese Suche enthält Einträge, die in einem beliebigen Feld den Begriff %0 enthalten -This\ search\ contains\ entries\ in\ which=Diese Suche enthält Einträge, in denen Empty\ search\ ID=Leere Such-ID The\ given\ search\ ID\ was\ empty.=Die übergebene Such-ID ist leer. Clear\ search=Suche zurücksetzen Search\ document\ identifier\ online=Suche online nach Dokumentenbezeichner Search\ for\ unlinked\ local\ files=Suche nach nicht verlinkten Dateien Search\ full\ text\ documents\ online=Suche Volltextdokumente online -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Tipp\:\n\nUm alle Felder nach Smith zu durchsuchen, geben Sie ein\:\nSmith\n\nUm das Feld author nach Smith und das Feld title nach electrical zu durchsuchen, geben Sie ein\:\nauthor\=Smith and title\=electrical Search\ term\ is\ empty.=Suchbegriff ist leer. Invalid\ regular\ expression.=Ungültiger regulärer Ausdruck. Searching\ for\ a\ keyword=Suche nach einem Schlüsselwort @@ -944,7 +912,6 @@ New\ BibTeX\ sublibrary=Neue BibTeX-Teilbibliothek Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Wechselt zwischen vollem und abgekürztem Zeitschriftentitel falls bekannt. -the\ field\ %0=das Feld %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Die Gruppe "%0" enthält bereits diese Auswahl. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Die Ausgabe-Option beruht auf einer gültigen Import-Option. @@ -2442,6 +2409,7 @@ Entry\ types=Eintragstypen Others=Andere Recommended=Empfohlen +Define\ study\ parameters=Studienparameter definieren Authors\ and\ Title=Autoren und Titel Catalog=Katalog Catalogs=Kataloge @@ -2474,10 +2442,8 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Alle verknüpfte Rebuild\ fulltext\ search\ index=Volltext-Suchindex neu erstellen Rebuild\ fulltext\ search\ index\ for\ current\ library?=Volltext-Suchindex für die aktuelle Bibliothek neu erstellen? Rebuilding\ fulltext\ search\ index...=Volltext-Suchindex wird neu erstellt... -Failed\ to\ access\ fulltext\ search\ index=Zugriff auf Volltext-Suchindex fehlgeschlagen Found\ match\ in\ %0=Treffer gefunden in %0 On\ page\ %0=Auf Seite %0 -Found\ matches\ in\ Annotations\:=Treffer in Notizen gefunden\: Fetcher\ cannot\ be\ tested\!=Der Fetcher kann nicht getestet werden\! Fetcher\ unknown\!=Fetcher unbekannt\! @@ -2544,8 +2510,6 @@ AI=KI AI\ chat=KI-Chat I\ agree=Ich stimme zu Privacy\ notice=Hinweis zum Datenschutz -Show\ 'AI\ Chat'\ tab=Registerkarte 'KI-Chat' anzeigen -Show\ 'AI\ Summary'\ tab=Registerkarte 'KI-Zusammenfassung' anzeigen Submit=Absenden Unable\ to\ chat=Chat nicht möglich Clear\ chat\ history=Chatverlauf löschen @@ -2562,7 +2526,6 @@ Please\ provide\ a\ non-empty\ and\ unique\ citation\ key\ for\ this\ entry.=Bit RAG\ -\ maximum\ results\ count=RAG - maximale Anzahl von Ergebnissen RAG\ -\ minimum\ score=RAG - Mindestpunktzahl RAG\ max\ results\ count\ must\ be\ greater\ than\ 0=RAG maximale Anzahl von Ergebnissen muss größer als 0 sein -RAG\ min\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1= Clear\ embeddings\ cache=Einbettungs-Cache löschen Clear\ embeddings\ cache\ for\ current\ library?=Einbettungs-Cache für die aktuelle Bibliothek löschen? Clearing\ embeddings\ cache...=Lösche Einbettungs Cache... @@ -2586,6 +2549,8 @@ An\ error\ occurred\ while\ building\ the\ embedding\ model=Beim Erstellen des E Embedding\ model\ is\ not\ set\ up=Einbettungsmodell ist nicht eingerichtet AI\ summary=KI-Zusammenfassung Regenerate=Regenerieren +The\ path\ of\ the\ current\ library\ is\ not\ set,\ but\ it\ is\ required\ for\ summarization=Der Pfad der aktuellen Bibliothek ist nicht gesetzt, aber für die Zusammenfassung erforderlich +Enable\ AI\ functionality\ (summary\ generation\ and\ chatting)\ in\ JabRef=Aktivieren Sie KI-Funktionen (Zusammenfassungserstellung und Chatten) in JabRef Customize\ expert\ settings=Experteneinstellungen anpassen These\ parameters\ affect\ how\ the\ AI\ will\ answer\ your\ questions.=Diese Parameter beeinflussen, wie die KI Ihre Fragen beantworten wird. Chat\ with\ AI\ about\ content\ of\ attached\ file(s)=Mit der KI über den Inhalt angehängter Datei(en) chatten @@ -2622,6 +2587,30 @@ Estimated\ time\ left\:\ approx.\ 2\ minutes.=Geschätzte verbleibende Zeit\: ca Estimated\ time\ left\:\ more\ than\ 2\ minutes.=Geschätzte verbleibende Zeit\: mehr als 2 Minuten. You\ find\ information\ about\ the\ privacy\ policy\ here.=Hier finden Sie Informationen über die Datenschutzerklärung. The\ size\ of\ the\ embedding\ model\ could\ be\ smaller\ than\ written\ in\ the\ list.=Die Größe des Einbettungsmodells könnte kleiner sein als in der Liste angegeben. +Embedding\ model\ has\ to\ be\ provided=Einbettungsmodell muss angegeben werden +After\ the\ file\ will\ be\ ingested,\ you\ will\ be\ able\ to\ chat\ with\ it.=Nachdem die Datei verarbeitet wurde, können Sie mit ihr chatten. +Could\ not\ find\ path\ for\ a\ linked\ file\ '%0'\ while\ generating\ embeddings.=Pfad für eine verknüpfte Datei '%0' konnte während der Erstellung von Einbettungen nicht gefunden werden. +File\ %0\ could\ not\ be\ ingested=Datei %0 konnte nicht verarbeitet werden +File\ %0\ is\ currently\ being\ processed=Datei %0 wird derzeit verarbeitet +File\ %0\ is\ not\ a\ PDF\ file=Die Datei %0 ist keine PDF-Datei +Generating\ embeddings\ for\ file\ '%0'=Erstelle Einbettungen für Datei '%0' +Notifications=Benachrichtigungen +Only\ PDF\ files\ can\ be\ used\ for\ chatting=Nur PDF-Dateien können zum Chatten verwendet werden +The\ chat\ history\ will\ not\ be\ stored\ in\ next\ sessions=Der Chatverlauf wird nicht in den nächsten Sitzungen gespeichert +Unable\ to\ generate\ embeddings\ for\ file\ '%0',\ because\ JabRef\ was\ unable\ to\ extract\ text\ from\ the\ file=Konnte keine Einbettungen für Datei %0 generieren, da JabRef während der Verarbeitung des Eintrags den Text nicht extrahieren konnte +Chat\ with\ group=Mit Gruppe chatten +Unable\ to\ chat\ with\ group=Chat mit Gruppe nicht möglich +Waiting\ for\ AI\ reply...=Warte auf KI-Antwort... +An\ error\ occurred\ while\ opening\ chat\ history\ storage.\ Chat\ history\ of\ entries\ and\ groups\ will\ not\ be\ stored\ in\ the\ next\ session.=Beim Öffnen des Speichers des Chat-Verlaufs ist ein Fehler aufgetreten. Der Chat-Verlauf von Einträgen und Gruppen wird in der nächsten Sitzung nicht gespeichert. +An\ error\ occurred\ while\ opening\ summary\ storage.\ Summaries\ of\ entries\ will\ not\ be\ stored\ in\ the\ next\ session.=Beim Öffnen des Zusammenfassungsspeichers ist ein Fehler aufgetreten. Zusammenfassungen von Einträgen werden in der nächsten Sitzung nicht gespeichert. +An\ error\ occurred\ while\ opening\ the\ embeddings\ cache\ file.\ Embeddings\ will\ not\ be\ stored\ in\ the\ next\ session.=Beim Öffnen der Cache-Datei für die Einbettungen ist ein Fehler aufgetreten. Einbettungen werden nicht in der nächsten Sitzung gespeichert. +An\ error\ occurred\ while\ opening\ the\ fully\ ingested\ documents\ cache\ file.\ Fully\ ingested\ documents\ will\ not\ be\ stored\ in\ the\ next\ session.=Beim Öffnen der Zwischenspeicherdatei für vollständig verarbeiteten Dokument ist ein Fehler aufgetreten. Vollständig verarbeitete Dokumente werden in der nächsten Sitzung nicht gespeichert. +Invalid\ citation\ key\ for\ %0\ (%1)=Ungültiger Zitationsschlüssel für %0 (%1) +No\ citation\ key\ for\ %0=Kein Zitationsschlüssel für %0 +Please\ attach\ at\ least\ one\ PDF\ file\ to\ enable\ summarization\ of\ PDF\ file(s).=Bitte fügen Sie mindestens eine PDF-Datei an, um die Zusammenfassung von PDF-Datei(en) zu aktivieren. +Unable\ to\ generate\ summary=Zusammenfassung kann nicht erstellt werden +Group\ %0=Gruppe %0 +AI\ chat\ with\ %0=KI-Chat mit %0 Generating\ embeddings\ for\ %0=Erstelle Einbettungen für %0 Link=Link @@ -2638,7 +2627,6 @@ Left\ Entry=Linker Eintrag Merge\ %0=%0 zusammenführen Right\ Entry=Rechter Eintrag Unmerge\ %0=%0 trennen -plain\ text=Klartext The\ %0s\ are\ the\ same.\ However,\ the\ order\ of\ field\ content\ differs=Die %0s sind identisch. Die Reihenfolge der Feldinhalte ist jedoch unterschiedlich @@ -2705,6 +2693,8 @@ Access\ denied.\ You\ are\ not\ authorized\ to\ access\ this\ resource.\ Please\ Access\ denied.\ You\ do\ not\ have\ permission\ to\ access\ this\ resource.\ Please\ contact\ the\ administrator\ for\ assistance\ or\ try\ a\ different\ action.=Zugriff verweigert. Sie haben keine Berechtigung, auf diese Ressource zuzugreifen. Bitte wenden Sie sich an den Administrator oder versuchen Sie eine andere Aktion. The\ requested\ resource\ could\ not\ be\ found.\ It\ seems\ that\ the\ file\ you\ are\ trying\ to\ download\ is\ not\ available\ or\ has\ been\ moved.\ Please\ verify\ the\ URL\ and\ try\ again.\ If\ you\ believe\ this\ is\ an\ error,\ please\ contact\ the\ administrator\ for\ further\ assistance.=Die angeforderte Ressource konnte nicht gefunden werden. Es scheint, dass die Datei, die Sie herunterladen möchten, nicht verfügbar oder verschoben wurde. Bitte überprüfen Sie die URL und versuchen Sie es erneut. Wenn Sie glauben, dass dies ein Fehler ist, kontaktieren Sie bitte den Administrator für weitere Hilfe. Something\ is\ wrong\ on\ JabRef\ side.\ Please\ check\ the\ URL\ and\ try\ again.=Auf der JabRef-Seite stimmt etwas nicht. Bitte überprüfen Sie die URL und versuchen Sie es erneut. +Error\ downloading\ from\ URL.\ Cause\ is\ likely\ the\ server\ side.\nPlease\ try\ again\ later\ or\ contact\ the\ server\ administrator.=Fehler beim Herunterladen von der URL. Ursache ist wahrscheinlich serverseitig.\nBitte versuchen Sie es später noch einmal oder kontaktieren Sie den Serveradministrator. +Please\ check\ the\ URL\ and\ try\ again.\nURL\:\ %0\nDetails\:\ %1=Bitte überprüfen Sie die URL und versuchen Sie es erneut.\nURL\: %0\nDetails\: %1 Finished=Abgeschlossen Finished\ writing\ metadata\ for\ library\ %0\ (%1\ succeeded,\ %2\ skipped,\ %3\ errors).=Das Schreiben von Metadaten für die Bibliothek %0 ist abgeschlossen (%1 erfolgreich, %2 übersprungen, %3 Fehler). @@ -2731,6 +2721,7 @@ Help\ on\ external\ applications=Hilfe zu externen Anwendungen Identifier-based\ Web\ Search=Identifikator-basierte Websuche Related\ articles=ähnliche Dokumente +Show\ tab\ 'Related\ articles'=Zeige Reiter 'Ähnliche Dokumente' Pushing\ citations\ to\ TeXShop\ is\ only\ possible\ on\ macOS\!=Zitate in TeXShop zu übertragen ist nur auf macOS möglich\! diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index 6d9b8cd044b..9fdc68de6f4 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Δεν είναι δυνατή η παρακολούθηση αλλαγών των αρχείων. Παρακαλούμε κλείστε τα αρχεία και τις διεργασίες και κάντε επανεκκίνηση. Ενδέχεται να αντιμετωπίσετε σφάλματα εάν συνεχίσετε με την τρέχουσα συνεδρία. -%0\ contains\ the\ regular\ expression\ %1=%0 περιέχει την συνήθη έκφραση %1 - -%0\ contains\ the\ term\ %1=%0 περιέχει τον όρο %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 δεν περιέχει την συνήθη έκφραση %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 δεν περιέχει τον όρο %1 %0/%1\ entries=%0/%1 καταχωρήσεις @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Η διαδικασία εξαγωγ Reveal\ in\ File\ Explorer=Εμφάνιση στον Εξερευνητή Αρχείων -%0\ matches\ the\ regular\ expression\ %1=%0 ταιριάζει την συνήθη έκφραση %1 - -%0\ matches\ the\ term\ %1=%0 ταιριάζει τον όρο %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Σύντμηση ονομάτων περιοδικών για τις επιλεγμένες καταχωρήσεις (ΠΡΟΕΠΙΛΕΓΜΕΝΗ σύντμηση) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Σύντμηση ονομάτων περιοδικών για τις επιλεγμένες καταχωρήσεις (σύντμηση ΧΩΡΙΣ ΤΕΛΕΙΕΣ) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Σύντμηση ονομάτων περιοδικών για τις επιλεγμένες καταχωρήσεις (ΣΥΝΟΜΟΤΕΡΗ ΜΟΝΑΔΙΚΗ συντομογραφία) @@ -79,10 +68,6 @@ All\ entries=Όλες entries Also\ remove\ subgroups=Αφαιρέστε επίσης τις υποομάδες -and=και - -any\ field\ that\ matches\ the\ regular\ expression\ %0=οποιοδήποτε πεδίο που ταιριάζει με την κανονική έκφραση (regular expression) %0 - Appearance=Εμφάνιση Application=Εφαρμογή @@ -125,10 +110,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Δεν είναι δ Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Δεν είναι δυνατό το άνοιγμα του φακέλου, καθώς το αρχείο είναι ένας διαδικτυακός σύνδεσμος. -case\ insensitive=χωρίς διάκριση πεζών - κεφαλαίων - -case\ sensitive=διάκριση πεζών - κεφαλαίων - Case\ sensitive=Διάκριση πεζών - κεφαλαίων change\ assignment\ of\ entries=αλλαγή ανάθεσης των καταχωρήσεων @@ -424,9 +405,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Ανεξάρτητη ομάδα\: Όταν επιλεχθεί αυτό, προβάλλονται οι καταχωρήσεις μόνο αυτής της ομάδας I\ Agree=Συμφωνώ -Indexing\ for\ %0=Ευρετήριο για %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 από %1 συνδεδεμένα αρχεία προστέθηκαν στο ευρετήριο - Invalid\ URL=Μη έγκυρη διεύθυνση URL Online\ help=Online βοήθεια @@ -517,8 +495,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Δεν ήταν δυνατή η σύ No\ journal\ names\ could\ be\ unabbreviated.=Δεν ήταν δυνατή η αναίρεση της σύντμησης ονομάτων περιοδικών. -not=δεν - not\ found=δεν βρέθηκε Nothing\ to\ redo=Καμία ενέργεια προς επανάληψη @@ -716,8 +692,6 @@ Fulltext\ search=Αναζήτηση πλήρους κειμένου Help\ on\ regular\ expression\ search=Βοήθεια για την αναζήτηση κανονικών εκφράσεων Searching\ for\ duplicates...=Αναζήτηση για διπλότυπα... Searching\ for\ files=Αναζήτηση για αρχεία -The\ search\ is\ case-insensitive.=Η αναζήτηση δε διαχωρίζει τα πεζά από τα κεφαλαία γράμματα. -The\ search\ is\ case-sensitive.=Η αναζήτηση διαχωρίζει τα πεζά από τα κεφαλαία γράμματα. Use\ regular\ expression\ search=Χρήση αναζήτησης κανονικής έκφρασης search\ expression=έκφραση αναζήτησης Free\ search\ expression=Ελεύθερη αναζήτηση έκφρασης @@ -730,17 +704,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Παρακαλώ α Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Παρακαλούμε εισάγετε ένα όνομα πεδίου για να αναζητήσετε μια λέξη-κλειδί. No\ results\ found.=Δε βρέθηκαν αποτελέσματα. Found\ %0\ results.=Βρέθηκαν %0 αποτελέσματα. -Invalid\ regular\ expression=Μη έγκυρη κανονική έκφραση -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Αυτή η αναζήτηση περιέχει καταχωρήσεις στις οποίες οποιοδήποτε πεδίο θα περιέχει την κανονική έκφραση %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Αυτή η αναζήτηση περιέχει καταχωρήσεις στις οποίες οποιοδήποτε πεδίο θα περιέχει τον όρο %0 -This\ search\ contains\ entries\ in\ which=Αυτή η αναζήτηση περιέχει καταχωρήσεις στις οποίες Empty\ search\ ID=Κενό ID αναζήτησης The\ given\ search\ ID\ was\ empty.=Το δεδομένο ID αναζήτησης ήταν κενό. Clear\ search=Εκκαθάριση αναζήτησης Search\ document\ identifier\ online=Αναζήτηση αναγνωριστικού του εγγράφου διαδικτυακά Search\ for\ unlinked\ local\ files=Αναζήτηση για μη συνδεδεμένα τοπικά αρχεία Search\ full\ text\ documents\ online=Αναζήτηση εγγράφων πλήρους κειμένου διαδικτυακά -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Υπόδειξη\:\n\nΓια την αναζήτηση όλων των πεδίων για Smith, πληκτρολογήστε\:\nsmith\n\nΓια την αναζήτηση του πεδίου author για Smith και το πεδίο title για electrical, πληκτρολογήστε\:\nauthor\=Smith and title\=electrical Search\ term\ is\ empty.=Ο όρος αναζήτησης είναι κενός. Invalid\ regular\ expression.=Μη έγκυρη κανονική έκφραση. Searching\ for\ a\ keyword=Αναζήτηση λέξης-κλειδιού σε εξέλιξη @@ -813,7 +782,6 @@ New\ BibTeX\ sublibrary=Νέα υπο-βιβλιοθήκη BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Εναλλαγή από πλήρες ή συντετμημένο όνομα περιοδικού, εάν το όνομα του περιοδικού είναι άγνωστο. -the\ field\ %0=το πεδίο %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Η ομάδα "%0" περιέχει ήδη την επιλογή. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Η επιλογή εξόδου εξαρτάται από μια έγκυρη επιλογή εισαγωγής. @@ -1779,7 +1747,6 @@ Link=Σύνδεση (Note\:\ If\ original\ entries\ lack\ keywords\ to\ qualify\ for\ the\ new\ group\ configuration,\ confirming\ here\ will\ add\ them)=(Σημείωση\: Εάν από τις αρχικές καταχωρήσεις λείπουν λέξεις-κλειδιά που να πληρούν τις προϋποθέσεις για τη νέα διαμόρφωση της ομάδας, η επιβεβαίωση εδώ θα τις προσθέσει) -plain\ text=απλό κείμενο diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 7c4aa8258c9..fa623b1d75d 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=No es posible supervisar los cambios en los archivos. Cierre los archivos y procesos y reinicie. Puede que se produzcan errores si continúa con esta sesión. -%0\ contains\ the\ regular\ expression\ %1=%0 contiene la expresión regular %1 - -%0\ contains\ the\ term\ %1=%0 contiene el término %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 no contiene la expresión regular %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 no contiene el término %1 %0/%1\ entries=%0/%1 entradas @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=La operación de exportación ha fina Reveal\ in\ File\ Explorer=Mostrar en Explorador de Archivos -%0\ matches\ the\ regular\ expression\ %1=%0 coincidencias con la Expresión Regular %1 - -%0\ matches\ the\ term\ %1=%0 coincidencias con el término %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Abreviar nombres de revistas de las entradas seleccionadas (abreviatura DEFAULT) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Abreviar nombres de revistas de las entradas seleccionadas (abreviatura DOTLESS) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Abreviar nombres de revistas de las entradas seleccionadas (abreviatura SHORTEST UNIQUE) @@ -89,10 +78,6 @@ All\ entries=Todas las entradas Also\ remove\ subgroups=Quitar subgrupos también -and=y - -any\ field\ that\ matches\ the\ regular\ expression\ %0=cualquier campo que satisfaga la Expresión Regular %0 - Appearance=Aspecto Application=Aplicación @@ -135,10 +120,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=No se puede crear el Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=No se puede abrir la carpeta porque el archivo es un enlace en línea. -case\ insensitive=insensible al uso de mayúsculas/minúsculas - -case\ sensitive=sensible al uso de mayúsculas/minúsculas - Case\ sensitive=Sensible al uso de mayúsculas/minúsculas change\ assignment\ of\ entries=Cambiar asignación de entradas @@ -457,9 +438,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Grupo independiente\: ver sólo las entradas de este grupo cuando esté seleccionado. I\ Agree=Acepto -Indexing\ for\ %0=Indización para %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 de %1 archivos enlazados añadidos al índice - Invalid\ URL=URL no válida Online\ help=Ayuda online @@ -569,8 +547,6 @@ No\ journal\ names\ could\ be\ abbreviated.=No se pudieron abreviar nombres de r No\ journal\ names\ could\ be\ unabbreviated.=No se pudieron expandir nombres de revistas. -not=no - not\ found=no encontrado Nothing\ to\ redo=Nada que rehacer @@ -771,8 +747,6 @@ Fulltext\ search=Búsqueda de texto completo Help\ on\ regular\ expression\ search=Ayuda sobre búsqueda mediante expresión regular Searching\ for\ duplicates...=Buscando duplicados... Searching\ for\ files=Buscando archivos -The\ search\ is\ case-insensitive.=La búsqueda no distingue mayúsculas y minúsculas. -The\ search\ is\ case-sensitive.=La búsqueda distingue mayúsculas y minúsculas. Use\ regular\ expression\ search=Usar búsqueda de expresión regular search\ expression=expresión de búsqueda Free\ search\ expression=Expresión de búsqueda libre @@ -785,17 +759,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Abra o cree una nuev Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Introduzca un nombre de campo para buscar una palabra clave. No\ results\ found.=No se encontraron resultados. Found\ %0\ results.=Se encontraron %0 resultados. -Invalid\ regular\ expression=Expresión regular inválida -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Esta búsqueda contiene entradas en las cuales cualquier campo contiene la expresión regular %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Esta búsqueda contiene entradas en las cuales cualquier campo contiene el término %0 -This\ search\ contains\ entries\ in\ which=Esta búsqueda contiene entradas en las cuales Empty\ search\ ID=Vaciar ID de búsqueda The\ given\ search\ ID\ was\ empty.=La ID de búsqueda está vacía. Clear\ search=Limpiar búsqueda Search\ document\ identifier\ online=Buscar online un identificador de documento Search\ for\ unlinked\ local\ files=Buscar archivos locales desenlazados Search\ full\ text\ documents\ online=Buscar online documentos de texto completos -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Consejo\:\n\nPara buscar Pedro en todos los campos, escriba\:\npedro\n\nPara buscar Pedro en el campo author y eléctrico en el campo title, escriba\:\nauthor\=Pedro and title\=eléctrico Search\ term\ is\ empty.=El término de búsqueda está vacío. Invalid\ regular\ expression.=Expresión regular inválida. Searching\ for\ a\ keyword=Buscando palabras clave @@ -875,7 +844,6 @@ New\ BibTeX\ sublibrary=Nueva biblioteca secundaria BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Cambia entre nombre completo y abreviado de la revista si se conoce el nombre de la revista. -the\ field\ %0=el campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=El grupo "%0" ya contiene la selección. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=La opción de salida depende de una opción de importación válida. @@ -2415,7 +2383,6 @@ Left\ Entry=Entrada izquierda Merge\ %0=Combinar %0 Right\ Entry=Entrada derecha Unmerge\ %0=Descombinar %0 -plain\ text=texto plano Keep\ existing\ entry=Mantener entrada existente diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 39272445844..2901bb40930 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -1,11 +1,5 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=قادر به نمايش تغيير پرونده نمی باشد. لطفا پرونده ها و فرايند ها را بسته و شروع دوباره كنيد. در صورت ادامه ممكن است با خطاهایی مواجه شويد. -%0\ contains\ the\ term\ %1=%0 شامل اين واژه %1 - - - - - @@ -42,9 +36,6 @@ String\ constants=ثابت های رشته -and=و - - Appearance=ظاهر @@ -72,10 +63,6 @@ Cannot\ create\ group=نمی‌توان گروه را ایجاد کرد Cannot\ create\ group.\ Please\ create\ a\ library\ first.=نمی‌توان گروه را ایجاد کرد. لطفاً ابتدا كتابخانه را ايجاد كنيد. -case\ insensitive=غیر حساس به کوچکی و بزرگی حروف - -case\ sensitive=حساس به کوچکی و بزرگی حروف - Case\ sensitive=حساس به کوچکی و بزرگی حروف @@ -267,8 +254,6 @@ Will\ write\ metadata\ to\ the\ PDFs\ linked\ from\ selected\ entries.=فراد - - diff --git a/src/main/resources/l10n/JabRef_fi.properties b/src/main/resources/l10n/JabRef_fi.properties index 6ca3071f083..5850a7ae7c7 100644 --- a/src/main/resources/l10n/JabRef_fi.properties +++ b/src/main/resources/l10n/JabRef_fi.properties @@ -1,10 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Tiedostojen muutoksia ei voi seurata. Sulje tiedostot ja prosessit ja käynnistä uudelleen. Saatat kohdata virheitä, jos jatkat tätä istuntoa. -%0\ contains\ the\ regular\ expression\ %1=%0 sisältää säännöllisen lausekkeen %1 - - - - - @@ -446,12 +440,6 @@ About\ JabRef=Tietoja JabRef - - - - - - diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index cd56446d7bc..379b261e014 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Impossible de surveiller les changements de fichiers. Veuillez fermer les fichiers et les traitements puis redémarrer. Vous pourriez rencontrer des erreurs si vous continuez avec cette session. -%0\ contains\ the\ regular\ expression\ %1=%0 contient l'expression régulière %1 - -%0\ contains\ the\ term\ %1=%0 contient le terme %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 ne contient pas l'expression régulière %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 ne contient pas le terme %1 %0/%1\ entries=%0/%1 entrées @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=L'opération d'export s'est terminée Reveal\ in\ File\ Explorer=Montrer dans l'explorateur de fichiers -%0\ matches\ the\ regular\ expression\ %1=%0 correspond à l'expression régulière %1 - -%0\ matches\ the\ term\ %1=%0 correspond au terme %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Abréger les noms de journaux des entrées sélectionnées (abréviation par DÉFAUT) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Abréger les noms de journaux des entrées sélectionnées (abréviation SANS POINT) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Abréger les noms de journaux des entrées sélectionnées (abréviation UNIQUE LA PLUS COURTE) @@ -89,10 +78,6 @@ All\ entries=Toutes les entrées Also\ remove\ subgroups=Supprimer aussi les sous-groupes -and=et - -any\ field\ that\ matches\ the\ regular\ expression\ %0=tout champ qui correspond à l'expression régulière %0 - Appearance=Aspect Application=Logiciel @@ -136,10 +121,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Impossible de créer Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Impossible d'ouvrir le dossier car le fichier est un lien en ligne. -case\ insensitive=insensible à la casse - -case\ sensitive=sensible à la casse - Case\ sensitive=Sensible à la casse change\ assignment\ of\ entries=changer l'assignation des entrées @@ -288,6 +269,10 @@ Dynamically\ group\ entries\ by\ searching\ a\ field\ for\ a\ keyword=Grouper dy Each\ line\ must\ be\ of\ the\ following\ form\:\ 'tab\:field1;field2;...;fieldN'.=Chaque ligne doit être au format suivant \: 'tab\:field1;field2;...;fieldN'. +Search\ groups\ migration\ of\ %0=Migration des groupes de recherche à %0 +The\ search\ groups\ syntax\ is\ outdated.\ Do\ you\ want\ to\ migrate\ to\ the\ new\ syntax?= La syntaxe des groupes de recherche est obsolète. Voulez-vous migrer vers la nouvelle syntaxe ? +Migrate=Migrer +Keep\ as\ is=Garder tel quel Edit=Édition Edit\ file\ type=Modifier le type de fichier @@ -503,10 +488,13 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Groupe indépendant \: quand sélectionné, affiche uniquement les entrées de ce groupe I\ Agree=J’accepte -Indexing\ PDF\ files=Indexation des fichiers PDF -Indexing\ for\ %0=Indexation de %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 sur %1 fichiers liés ajoutés à l'index - +Score=Résultat +Indexing\ bib\ fields\ for\ %0=Indexation des champs bib à %0 +Indexing\ PDF\ files\ for\ %0=Indexation des fichiers PDF à %0 +%0\ of\ %1\ entries\ added\ to\ the\ index.=%0 sur %1 entrées ajoutées à l'index. +%0\ of\ %1\ entries\ removed\ from\ the\ index.=%0 of %1 entrées supprimées de l'index. +Indexing\ %0.\ %1\ of\ %2\ files\ added\ to\ the\ index.=Indexation de %0. %1 sur %2 fichiers ajoutés à l'index. +Removing\ entries\ from\ index\ for\ %0=Suppression des entrées de l'index à %0 Invalid\ URL=URL invalide Online\ help=Aide en ligne @@ -621,8 +609,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Aucun nom de journal n'a pu être ab No\ journal\ names\ could\ be\ unabbreviated.=Aucun nom de journal n'a pu être développé. -not=non - not\ found=non trouvé Nothing\ to\ redo=Rien à répéter @@ -822,6 +808,7 @@ Character\ encoding\ '%0'\ is\ not\ supported.=L'encodage de caractères '%0' n' Filter\ search\ results=Filtrer les résultats de recherche Filter\ by\ groups=Filtrer par groupes Invert\ groups=Inverser les groupes +Match\ score=Résultat de la correspondance Scroll\ to\ previous\ match\ category=Défiler vers la catégorie de correspondance précédente Scroll\ to\ next\ match\ category=Défiler vers la catégorie de correspondance suivante Search=Recherche @@ -833,8 +820,6 @@ Fulltext\ search=Recherche dans les documents Help\ on\ regular\ expression\ search=Aide sur la recherche d'une expression régulière Searching\ for\ duplicates...=Recherche des doublons en cours... Searching\ for\ files=Recherche de fichiers... -The\ search\ is\ case-insensitive.=La recherche est insensible à la casse. -The\ search\ is\ case-sensitive.=La recherche est sensible à la casse. Use\ regular\ expression\ search=Utiliser l'expression régulière pour la recherche search\ expression=expression de recherche Free\ search\ expression=Expression de recherche libre @@ -847,17 +832,13 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Veuillez ouvrir ou c Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Veuillez entrer le nom du champ dans lequel chercher un mot-clef. No\ results\ found.=Aucun résultat trouvé. Found\ %0\ results.=%0 résultats trouvés. -Invalid\ regular\ expression=Expression régulière invalide -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Cette recherche renvoie des entrées pour lesquelles au moins un champ contient l'expression régulière %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Cette recherche renvoie des entrées pour lesquelles au moins un champ contient le terme %0 -This\ search\ contains\ entries\ in\ which=Cette recherche renvoie des entrées pour lesquelles Empty\ search\ ID=Identifiant de recherche vide The\ given\ search\ ID\ was\ empty.=L'Identifiant de recherche entré était vide. Clear\ search=Effacer la recherche Search\ document\ identifier\ online=Rechercher en ligne l'identifiant d'un document Search\ for\ unlinked\ local\ files=Rechercher localement des fichiers non liés Search\ full\ text\ documents\ online=Rechercher en ligne des textes intégraux -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Astuce \:\n\nPour rechercher Smith dans tous les champs, entrer \:\nSmith\n\nPour rechercher Smith dans le champ author et electrical dans le champ title, entrer\:\nauthor\=Smith and title\=electrical +Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\:Smith\ AND\ title\:electrical=Astuce \:\n\nPour rechercher Smith dans tous les champs , entrez \:\nforgeron\n\nPour rechercher Smith dans le champ author et électrique dans le champ titre entrez \:\nauthor\:Smith AND title\:électrique Search\ term\ is\ empty.=Le terme de recherche est vide. Invalid\ regular\ expression.=Expression régulière invalide. Searching\ for\ a\ keyword=Recherche d'un mot-clef @@ -944,7 +925,6 @@ New\ BibTeX\ sublibrary=Nouveau sous-fichier BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Bascule entre les noms de journaux développés et abrégés si le nom de journal est connu. -the\ field\ %0=le champ %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Le groupe « %0 » contient déjà la sélection. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=L'option de sortie dépend d'une option d'importation valide. @@ -2475,10 +2455,9 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Indexer automati Rebuild\ fulltext\ search\ index=Reconstruire l'index de recherche sur les documents Rebuild\ fulltext\ search\ index\ for\ current\ library?=Reconstruire l'index de recherche sur les documents pour le fichier courant ? Rebuilding\ fulltext\ search\ index...=Reconstruction de l'index de recherche sur les documents... -Failed\ to\ access\ fulltext\ search\ index=Échec de l'accès à l'index de recherche sur les documents Found\ match\ in\ %0=Correspondance trouvée dans %0 On\ page\ %0=Sur la page %0 -Found\ matches\ in\ Annotations\:=Correspondances trouvées dans les annotations \: +Found\ matches\ in\ annotations\:=Correspondances trouvées dans les annotations \: Fetcher\ cannot\ be\ tested\!=L'outil de collecte ne peut pas être testé \! Fetcher\ unknown\!=Outil de collecte inconnu \! @@ -2545,8 +2524,8 @@ AI=IA AI\ chat=Tchat IA I\ agree=J'accepte Privacy\ notice=Déclaration de confidentialité -Show\ 'AI\ Chat'\ tab=Afficher l'onglet 'Tchat IA' -Show\ 'AI\ Summary'\ tab=Afficher l'onglet 'Résumé IA' +Show\ tab\ 'AI\ Chat'=Afficher l'onglet 'Tchat IA' +Show\ tab\ 'AI\ Summary'=Afficher l'onglet 'Résumé IA' Submit=Envoyer Unable\ to\ chat=Tchat indisponible Clear\ chat\ history=Effacer l'historique du tchat @@ -2563,7 +2542,6 @@ Please\ provide\ a\ non-empty\ and\ unique\ citation\ key\ for\ this\ entry.=Veu RAG\ -\ maximum\ results\ count=RAG - nombre maximum de résultats RAG\ -\ minimum\ score=RAG - score minimal RAG\ max\ results\ count\ must\ be\ greater\ than\ 0=Le nombre maximum de résultats RAG doit être supérieur à 0 -RAG\ min\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Le score minimum de RAG doit être compris entre 0 et 1 Clear\ embeddings\ cache=Effacer le cache des intégrations Clear\ embeddings\ cache\ for\ current\ library?=Effacer le cache des intégrations pour le fichier actuel ? Clearing\ embeddings\ cache...=Effacement du cache des intégrations... @@ -2637,7 +2615,7 @@ Only\ PDF\ files\ can\ be\ used\ for\ chatting=Seuls les fichiers PDF peuvent ê The\ chat\ history\ will\ not\ be\ stored\ in\ next\ sessions=L'historique des tchats ne sera pas stocké lors des prochaines sessions Unable\ to\ generate\ embeddings\ for\ file\ '%0',\ because\ JabRef\ was\ unable\ to\ extract\ text\ from\ the\ file=Impossible de générer des intégrations pour le fichier '%0', car JabRef n'a pas pu extraire de texte de ce fichier Chat\ with\ group=Tchater avec le groupe -No\ database\ is\ set.=Aucune base de données n'est définie. +No\ library\ is\ selected.=Aucun fichier sélectionné. Unable\ to\ chat\ with\ group=Impossible de tchatter avec le groupe Waiting\ for\ AI\ reply...=En attente de réponse de l'IA... An\ error\ occurred\ while\ opening\ chat\ history\ storage.\ Chat\ history\ of\ entries\ and\ groups\ will\ not\ be\ stored\ in\ the\ next\ session.=Une erreur s'est produite lors de l'ouverture du stockage de l'historique du tchats. L'historique des entrées et des groupes de tchat ne sera pas stocké lors de la prochaine session. @@ -2651,6 +2629,9 @@ Unable\ to\ generate\ summary=Impossible de générer le résumé Group\ %0=Groupe %0 AI\ chat\ with\ %0=Tchat IA avec %0 Generating\ embeddings\ for\ %0=Générer des intégrations pour %0 +RAG\ minimum\ score\ must\ be\ a\ number=Le score minimum de RAG doit être un nombre +RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Le score minimum de RAG doit être compris entre 0 et 1 +Temperature\ must\ be\ a\ number=La température doit être un nombre Link=Lien Source\ URL=URL de la source @@ -2666,7 +2647,6 @@ Left\ Entry=Entrée de gauche Merge\ %0=Fusionner %0 Right\ Entry=Entrée de droite Unmerge\ %0=Annuler la fusion %0 -plain\ text=texte brut The\ %0s\ are\ the\ same.\ However,\ the\ order\ of\ field\ content\ differs=Les %0s sont les mêmes. Cependant, l'ordre du contenu du champ est différent diff --git a/src/main/resources/l10n/JabRef_id.properties b/src/main/resources/l10n/JabRef_id.properties index beccccc6b3d..6692e127384 100644 --- a/src/main/resources/l10n/JabRef_id.properties +++ b/src/main/resources/l10n/JabRef_id.properties @@ -1,21 +1,10 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Tidak dapat memantau perubahan file. Silakan tutup file dan proses dan mulai ulang program. Anda mungkin mengalami error/malfungsi jika melanjutkan sesi ini. -%0\ contains\ the\ regular\ expression\ %1=%0 mengandung Ekspresi Reguler %1 - -%0\ contains\ the\ term\ %1=% mengandung istilah %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 tidak mengandung Ekspresi Reguler %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 tidak mengandung istilah %1 Export\ operation\ finished\ successfully.=Operasi eksport file selesai dengan sukses. Reveal\ in\ File\ Explorer=Buka di File Explorer -%0\ matches\ the\ regular\ expression\ %1=%0 sesuai dengan Ekspresi Reguler %1 - -%0\ matches\ the\ term\ %1=%0 sesuai dengan istilah %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Buat singkatan nama jurnal dari entri pilihan (singkatan BAWAAN) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Buat singkatan nama jurnal dari entri yang dipilih (singkatan DOTLESS) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Buat singkatan nama jurnal dari entri yang dipilih (singkatan PALING SINGKAT dan UNIK) @@ -74,10 +63,6 @@ All\ entries=Semua entri Also\ remove\ subgroups=Juga Hapus sub-grup -and=dan - -any\ field\ that\ matches\ the\ regular\ expression\ %0=bidang yang sesuai dengan ekspresi reguler %0 - Appearance=Penampilan Application=Aplikasi @@ -120,10 +105,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Tidak dapat membuat g Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Tidak dapat membuka folder karena file tersebut adalah tautan online. -case\ insensitive=huruf besar kecil tidak penting - -case\ sensitive=memperhitungkan huruf besar kecil - Case\ sensitive=Huruf besar kecil tidak penting change\ assignment\ of\ entries=merubah penugasan entri @@ -376,7 +357,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Grup bebas\: Ketika dipilih, lihat hanya entri grup ini I\ Agree=Saya Setuju - Invalid\ URL=URL salah Online\ help=Bantuan online @@ -452,8 +432,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Tidak ada nama jurnal yang bisa disi No\ journal\ names\ could\ be\ unabbreviated.=Tidak ada ada nama jurnal yang bisa dipanjangkan. -not=tidak - not\ found=tidak ditemukan Nothing\ to\ redo=Tidak ada yang dibatalkan @@ -627,9 +605,6 @@ Please\ enter\ a\ search\ string=Tuliskan string pencarian Please\ open\ or\ start\ a\ new\ library\ before\ searching=Buka atau jalankan basisdata yang baru sebelum mencari No\ results\ found.=Tidak menemukan hasil pencarian. Found\ %0\ results.=Menemukan %0 hasil pencarian. -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Pencarian ini berisi entri di mana setiap bidang mengandung ekspresi reguler %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Pencarian ini berisi entri di mana setiap bidang mengandung ekspresi reguler %0 -This\ search\ contains\ entries\ in\ which=Pencarian ini berisi entri yang Empty\ search\ ID=ID pencarian kosong The\ given\ search\ ID\ was\ empty.=ID pencarian yang diberikan kosong. @@ -686,7 +661,6 @@ New\ BibTeX\ sublibrary=Anak basisdata BibTeX baru Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Menukar antara nama jurnal penuh dan singkatan jika nama jurnal diketahui. -the\ field\ %0=bidang %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Grup "%0" sudah mengandung pilihan. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Pilihan keluaran tergantung dari pilihan impor yang sah. @@ -1539,7 +1513,6 @@ Delete\ text=Hapus teks Link=Tautan -plain\ text=teks biasa diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 9dd80ebd214..5c45d339556 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Impossibile monitorare le modifiche ai file. Si prega di chiudere i file e i processi e riavviare. Si possono riscontrare errori continuando con questa sessione. -%0\ contains\ the\ regular\ expression\ %1=%0 contiene l'espressione regolare %1 - -%0\ contains\ the\ term\ %1=%0 contiene il termine %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 non contiene l'espressione regolare %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 non contiene il termine %1 %0/%1\ entries=%0/%1 voci @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=L'operazione di esportazione si è co Reveal\ in\ File\ Explorer=Mostra nel File Explorer -%0\ matches\ the\ regular\ expression\ %1=%0 corrisponde all'espressione regolare %1 - -%0\ matches\ the\ term\ %1=%0 corrisponde al termine %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Abbrevia i nomi delle riviste delle voci selezionate (abbreviazione predefinita) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Abbrevia i nomi delle riviste delle voci selezionate (abbreviazione DOTLESS) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Abbrevia i nomi dei giornali delle voci selezionate (più corta abbreviazione univoca) @@ -89,10 +78,6 @@ All\ entries=Tutte le voci Also\ remove\ subgroups=Rimuovi anche sottogruppi -and=e - -any\ field\ that\ matches\ the\ regular\ expression\ %0=qualsiasi campo che corrisponda all'espressione regolare %0 - Appearance=Aspetto Application=Applicazione @@ -136,10 +121,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Impossibile creare il Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Impossibile aprire la cartella perché il file è un link online. -case\ insensitive=non distingue maiuscole e minuscole - -case\ sensitive=distingue maiuscole e minuscole - Case\ sensitive=Distingue maiuscole e minuscole change\ assignment\ of\ entries=modifica l'assegnazione delle voci @@ -288,6 +269,10 @@ Dynamically\ group\ entries\ by\ searching\ a\ field\ for\ a\ keyword=Raggruppa Each\ line\ must\ be\ of\ the\ following\ form\:\ 'tab\:field1;field2;...;fieldN'.=Ogni riga deve essere nella seguente forma\: 'tab\:field1;field2;...;fieldN'. +Search\ groups\ migration\ of\ %0=Migrazione di gruppi di ricerca di %0 +The\ search\ groups\ syntax\ is\ outdated.\ Do\ you\ want\ to\ migrate\ to\ the\ new\ syntax?= La sintassi dei gruppi di ricerca è obsoleta. Vuoi migrare alla nuova sintassi? +Migrate=Migra +Keep\ as\ is=Mantieni com'è Edit=Modifica Edit\ file\ type=Modifica il tipo di file @@ -503,10 +488,13 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Gruppo indipendente\: Quando selezionato, mostra solo le voci di questo gruppo I\ Agree=Accetto -Indexing\ PDF\ files=Indicizzazione file PDF -Indexing\ for\ %0=Indicizzazione per %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 di %1 file collegati aggiunti all'indice - +Score=Punteggio +Indexing\ bib\ fields\ for\ %0=Indicizzazione dei campi bib per %0 +Indexing\ PDF\ files\ for\ %0=Indicizzazione dei file PDF per %0 +%0\ of\ %1\ entries\ added\ to\ the\ index.=%0 di %1 voci aggiunte all'indice. +%0\ of\ %1\ entries\ removed\ from\ the\ index.=%0 di %1 voci rimosse dall'indice. +Indexing\ %0.\ %1\ of\ %2\ files\ added\ to\ the\ index.=Indicizzazione %0. %1 di %2 file aggiunti all'indice. +Removing\ entries\ from\ index\ for\ %0=Rimozione delle voci dall'indice per %0 Invalid\ URL=URL non valido Online\ help=Aiuto online @@ -621,8 +609,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Nessun nome di rivista può essere a No\ journal\ names\ could\ be\ unabbreviated.=Nessuna abbreviazione di rivista può essere estesa. -not=non - not\ found=non trovato Nothing\ to\ redo=Niente da ripetere @@ -822,6 +808,7 @@ Character\ encoding\ '%0'\ is\ not\ supported.=La codifica dei caratteri '%0' no Filter\ search\ results=Filtra i risultati della ricerca Filter\ by\ groups=Filtra per gruppo Invert\ groups=Inverti i gruppi +Match\ score=Punteggio della partita Scroll\ to\ previous\ match\ category=Scorri alla categoria di corrispondenza precedente Scroll\ to\ next\ match\ category=Scorri alla categoria di corrispondenza successiva Search=Ricerca @@ -833,8 +820,6 @@ Fulltext\ search=Ricerca su tutto il testo Help\ on\ regular\ expression\ search=Aiuto sulla ricerca di un'espressione regolare Searching\ for\ duplicates...=Ricerca di duplicati in corso... Searching\ for\ files=Ricerca dei file -The\ search\ is\ case-insensitive.=La ricerca non distingue maiuscole e minuscole. -The\ search\ is\ case-sensitive.=La ricerca distingue maiuscole e minuscole. Use\ regular\ expression\ search=Ricerca l'espressione regolare search\ expression=espressione di ricerca Free\ search\ expression=Espressione di ricerca libera @@ -847,17 +832,13 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Aprire o creare una Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Inserisci un nome di campo per cercare una parola chiave. No\ results\ found.=Nessun risultato trovato. Found\ %0\ results.=Trovati %0 risultati. -Invalid\ regular\ expression=Espressione regolare non valida -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Questa ricerca contiene occorrenze in cui qualsiasi campo contiene l'espressione regolare %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Questa ricerca contiene occorrenze in cui qualsiasi campo contiene il termine %0 -This\ search\ contains\ entries\ in\ which=Questa ricerca contiene occorrenze in cui Empty\ search\ ID=ID della ricerca vuoto The\ given\ search\ ID\ was\ empty.=L'ID della ricerca usato era vuoto. Clear\ search=Cancella ricerca Search\ document\ identifier\ online=Cerca l'identificatore del documento online Search\ for\ unlinked\ local\ files=Cerca file locali non collegati Search\ full\ text\ documents\ online=Cerca documenti di testo online -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Suggerimento\:\n\nPer cercare tutti i campi per Smith, enter\:\nsmith\n\nPer cercare il campo author per Smith e il campo title per electrical, enter\:\nauthor\=Smith and title\=electrical +Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\:Smith\ AND\ title\:electrical=Suggerimento\:\n\nPer cercare tutti i campi per Smith, enter\:\nsmith\n\nPer cercare il campo author per Smith e il campo title per electrical, enter\:\nauthor\=Smith and title\=electrical Search\ term\ is\ empty.=Il termine di ricerca è vuoto. Invalid\ regular\ expression.=Espressione regolare non valida. Searching\ for\ a\ keyword=Ricerca per parole chiave @@ -944,7 +925,6 @@ New\ BibTeX\ sublibrary=Nuova sottolibreria BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Alterna nomi completi e nomi abbreviati per le riviste delle quali è noto il nome. -the\ field\ %0=il campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Il gruppo "%0" contiene già la selezione. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=L'opzione di output dipende da una opzione di importazione valida. @@ -2475,10 +2455,9 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Indicizza automa Rebuild\ fulltext\ search\ index=Ricostruisci l'indice di ricerca su tutto il testo Rebuild\ fulltext\ search\ index\ for\ current\ library?=Ricostruisci l'indice di ricerca su tutto il testo per la libreria corrente? Rebuilding\ fulltext\ search\ index...=Ricostruzione indice di ricerca su tutto il testo... -Failed\ to\ access\ fulltext\ search\ index=Accesso all'indice di ricerca su tutto il testo non riuscito Found\ match\ in\ %0=Corrispondenza trovata in %0 On\ page\ %0=A pagina %0 -Found\ matches\ in\ Annotations\:=Trovate corrispondenze nelle annotazioni\: +Found\ matches\ in\ annotations\:=Trovate corrispondenze nelle annotazioni\: Fetcher\ cannot\ be\ tested\!=Il raccoglitore non può essere testato\! Fetcher\ unknown\!=Raccoglitore sconosciuto\! @@ -2545,8 +2524,8 @@ AI=Intelligenza Artificiale AI\ chat=Chat AI I\ agree=Sono d`accordo Privacy\ notice=Informativa sulla privacy -Show\ 'AI\ Chat'\ tab=Mostra la scheda 'Chat AI' -Show\ 'AI\ Summary'\ tab=Mostra la scheda 'Riepilogo AI' +Show\ tab\ 'AI\ Chat'=Mostra la scheda 'Chat AI' +Show\ tab\ 'AI\ Summary'=Mostra la scheda 'Riepilogo AI' Submit=Invia Unable\ to\ chat=Impossibile chattare Clear\ chat\ history=Cancella la cronologia della chat @@ -2563,7 +2542,6 @@ Please\ provide\ a\ non-empty\ and\ unique\ citation\ key\ for\ this\ entry.=Si RAG\ -\ maximum\ results\ count=RAG - numero massimo di risultati RAG\ -\ minimum\ score=RAG - punteggio minimo RAG\ max\ results\ count\ must\ be\ greater\ than\ 0=Il conteggio massimo dei risultati di RAG deve essere maggiore di 0 -RAG\ min\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Il punteggio minimo di RAG deve essere maggiore di 0 e minore di 1 Clear\ embeddings\ cache=Cancella la cache degli incorporamenti Clear\ embeddings\ cache\ for\ current\ library?=Cancellare la cache degli incorporamenti per la corrente libreria? Clearing\ embeddings\ cache...=Cancellazione della cache degli incorporamenti... @@ -2603,7 +2581,7 @@ Only\ PDF\ files\ can\ be\ used\ for\ chatting=Solo i file PDF possono essere ut The\ chat\ history\ will\ not\ be\ stored\ in\ next\ sessions=La cronologia della chat non verrà memorizzata nelle sessioni successive Unable\ to\ generate\ embeddings\ for\ file\ '%0',\ because\ JabRef\ was\ unable\ to\ extract\ text\ from\ the\ file=Impossibile generare incorporazioni per il file '%0', perché JabRef non è stato in grado di estrarre il testo dal file Chat\ with\ group=Chatta con il gruppo -No\ database\ is\ set.=Nessun database è impostato. +No\ library\ is\ selected.=Nessuna libreria è selezionata. Unable\ to\ chat\ with\ group=Impossibile chattare con il gruppo Waiting\ for\ AI\ reply...=In attesa della risposta dell'AI... An\ error\ occurred\ while\ opening\ chat\ history\ storage.\ Chat\ history\ of\ entries\ and\ groups\ will\ not\ be\ stored\ in\ the\ next\ session.=Si è verificato un errore durante l'apertura della cronologia chat. La cronologia delle chat delle voci e dei gruppi non verrà memorizzata nella prossima sessione. @@ -2617,6 +2595,9 @@ Unable\ to\ generate\ summary=Impossibile generare riassunto Group\ %0=Gruppo %0 AI\ chat\ with\ %0=Chat AI con %0 Generating\ embeddings\ for\ %0=Generazione di incorporamenti per %0 +RAG\ minimum\ score\ must\ be\ a\ number=Il punteggio minimo di RAG deve essere un numero +RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Il punteggio minimo di RAG deve essere maggiore di 0 e minore di 1 +Temperature\ must\ be\ a\ number=La temperatura deve essere un numero Link=Collegamento Source\ URL=URL di origine @@ -2632,7 +2613,6 @@ Left\ Entry=Voce Sinistra Merge\ %0=Unisci %0 Right\ Entry=Voce Destra Unmerge\ %0=Separa %0 -plain\ text=Testo semplice The\ %0s\ are\ the\ same.\ However,\ the\ order\ of\ field\ content\ differs=Gli %0s sono gli stessi. Tuttavia, l'ordine del contenuto del campo differisce diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 040d21890a3..8c2787d36d0 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=ファイルの変更を監視できません。ファイルとプロセスを閉じて、再起動してください。このセッションのまま続行すると、エラーが発生する恐れがあります。 -%0\ contains\ the\ regular\ expression\ %1=%0には,正規表現%1が含まれています - -%0\ contains\ the\ term\ %1=%0には,用語%1が含まれています - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0には,正規表現%1が含まれていません - -%0\ doesn't\ contain\ the\ term\ %1=%0には,用語%1が含まれていません %0/%1\ entries=%1 項目中 %0 項目 @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=書き出し操作は正常に終了 Reveal\ in\ File\ Explorer=ファイルエクスプローラーで表示 -%0\ matches\ the\ regular\ expression\ %1=%0は正規表現%1に一致します - -%0\ matches\ the\ term\ %1=%0は項目%1に一致します - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=選択項目の学術誌名を短縮形にします(既定の短縮形) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=選択項目の学術誌名を短縮形にします(ピリオドなし短縮形) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=選択項目の学術誌名を短縮形にします(重複のない最も簡素な短縮形) @@ -80,10 +69,6 @@ All\ entries=全項目 Also\ remove\ subgroups=下層グループも削除 -and=および - -any\ field\ that\ matches\ the\ regular\ expression\ %0=正規表現%0に一致するフィールドすべて - Appearance=外観 Application=アプリケーション @@ -126,10 +111,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=グループを作成 Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=ファイルがオンラインリンクであるためフォルダを開くことができません。 -case\ insensitive=大小文字を区別しない - -case\ sensitive=大小文字を区別 - Case\ sensitive=大小文字を区別 change\ assignment\ of\ entries=項目の割り当てを変更 @@ -437,9 +418,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=独立グループ:このグループの項目のみを表示 I\ Agree=同意する -Indexing\ for\ %0=%0 をインデックス化中 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%1 個のリンクされたファイルのうち %0 個がインデックスに追加されました - Invalid\ URL=無効なURLです Online\ help=オンラインヘルプ @@ -535,8 +513,6 @@ No\ journal\ names\ could\ be\ abbreviated.=学術誌名を短縮形にするこ No\ journal\ names\ could\ be\ unabbreviated.=学術誌名を非短縮形にすることができませんでした. -not=非 - not\ found=見つかりません Nothing\ to\ redo=繰り返すべきものがありません @@ -744,17 +720,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=検索前にライ Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=キーワード検索をするフィールド名を入力してください. No\ results\ found.=検出されませんでした. Found\ %0\ results.=%0件検出しました. -Invalid\ regular\ expression=正規表現が不正 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=この検索結果は,フィールドのうちどれかに正規表現%0が含まれている項目を表示します. -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=この検索結果は,フィールドのうちどれかに用語%0が含まれている項目を表示します. -This\ search\ contains\ entries\ in\ which=この検索結果は下記のものを表示; Empty\ search\ ID=検索IDが空 The\ given\ search\ ID\ was\ empty.=提示された検索IDが空です. Clear\ search=検索を消去 Search\ document\ identifier\ online=文書IDをオンライン検索 Search\ for\ unlinked\ local\ files=未リンクのローカルファイルを検索 Search\ full\ text\ documents\ online=文書本体をオンライン検索 -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=ヒント\:\n\n全フィールドで Smith を検索するには,\n smith と入力します.\n\nauthor フィールドに Smithtitle フィールドに electrical を指定して検索するには,author\=Smith and title\=electrical と入力します。 Search\ term\ is\ empty.=検索キーワードが空です. Invalid\ regular\ expression.=正規表現が不正です. Searching\ for\ a\ keyword=キーワード検索 @@ -827,7 +798,6 @@ New\ BibTeX\ sublibrary=新規BibTeX下層ライブラリ Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=学術誌名が既知の場合は,完全な学術誌名と短縮形を切り替える. -the\ field\ %0=フィールド%0 The\ group\ "%0"\ already\ contains\ the\ selection.=グループ「%0」には既に選択したものが含まれています. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=この出力オプションは,有効な読み込みオプションに依存します. @@ -2273,10 +2243,8 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=リンクした Rebuild\ fulltext\ search\ index=全文検索インデックスを再構築 Rebuild\ fulltext\ search\ index\ for\ current\ library?=現在のライブラリの全文検索インデックスを再構築しますか? Rebuilding\ fulltext\ search\ index...=全文検索インデックスを再構築しています... -Failed\ to\ access\ fulltext\ search\ index=全文検索インデックスへのアクセスに失敗しました Found\ match\ in\ %0=%0 で一致が見つかりました On\ page\ %0=%0 ページ -Found\ matches\ in\ Annotations\:=注釈で一致するものが見つかりました: Fetcher\ cannot\ be\ tested\!=取得子をテストすることができません! Fetcher\ unknown\!=不明な取得子です! @@ -2344,7 +2312,6 @@ Do\ not\ assign=割り当てない Left\ Entry=左側の項目 Right\ Entry=右側の項目 -plain\ text=平文 diff --git a/src/main/resources/l10n/JabRef_ko.properties b/src/main/resources/l10n/JabRef_ko.properties index 7b89b8f2df1..9599e486a08 100644 --- a/src/main/resources/l10n/JabRef_ko.properties +++ b/src/main/resources/l10n/JabRef_ko.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=파일 변경을 모니터링할 수 없습니다. 파일 및 프로세스를 닫고 다시 시작하십시오. 이 세션을 계속 진행하면 오류가 발생할 수 있습니다. -%0\ contains\ the\ regular\ expression\ %1=%0 정규식을 포함합니다 %1 - -%0\ contains\ the\ term\ %1=%0 용어을 포함한다%1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0에 정규식 %1이 포함되어 있지 않습니다 - -%0\ doesn't\ contain\ the\ term\ %1=%0은 %1이라는 용어를 포함하지 않습니다 %0/%1\ entries=%0/%1 항목 @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Eksporditoiming on edukalt lõpule vi Reveal\ in\ File\ Explorer=파일 탐색기에 표시 -%0\ matches\ the\ regular\ expression\ %1=%0은 정규식 %1와 일치합니다. - -%0\ matches\ the\ term\ %1=%0은 항목 %1 와 일치합니다. - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=선택한 항목의 저널 이름 약어(DEFAULT약어) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=선택한 항목의 저널명 약어(DOTLESS 약어) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=선택한 항목의 저널 이름 약어(SHORTEST UNIQUE 약어) @@ -75,10 +64,6 @@ All\ entries=모든 항목 Also\ remove\ subgroups=하위 그룹을 제거합니다 -and=그리고 - -any\ field\ that\ matches\ the\ regular\ expression\ %0=정규식 %0과 일치하는 필드 - Appearance=모양 Application=신청 @@ -121,10 +106,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=그룹을 만들 수 Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=파일이 온라인 링크이므로 폴더를 열 수 없습니다. -case\ insensitive=대/소문자를 구분하지 않음 - -case\ sensitive=대/소문자 구분 - Case\ sensitive=대/소문자 구분 change\ assignment\ of\ entries=항목 할당 변경 @@ -417,9 +398,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=독립 그룹\: 선택하면 이 그룹의 항목만 봅니다. I\ Agree=동의함 -Indexing\ for\ %0=%0에 대한 인덱싱 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=인덱스에 연결된 파일 %1개 중 %0개 추가됨 - Invalid\ URL=유효하지 않은 URL Online\ help=온라인 도움말 @@ -506,8 +484,6 @@ No\ journal\ names\ could\ be\ abbreviated.=저널 이름은 축약할 수 없 No\ journal\ names\ could\ be\ unabbreviated.=저널 이름을 축약할 수 없습니다. -not=아니다 - not\ found=찾을 수 없습니다. Nothing\ to\ redo=다시 실행할 작업이 없습니다. @@ -707,17 +683,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=검색전에 새 라 Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=키워드를 검색하려면 필드 이름을 입력하세요. No\ results\ found.=검색 결과가 없습니다 Found\ %0\ results.=검색 결과 %0개 -Invalid\ regular\ expression=유효하지 않은 정규식 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=이 검색에는 정규식 %0이 포함된 필드가 포함되어 있습니다. -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=이 검색에는 어떤 필드에 %0 용어가 포함된 항목이 포함되어 있습니다. -This\ search\ contains\ entries\ in\ which=이 검색에는 다음 항목이 포함되어 있습니다. Empty\ search\ ID=탐색 ID 없음 The\ given\ search\ ID\ was\ empty.=주어진 탐색 ID가 없습니다 Clear\ search=검색 초기화 Search\ document\ identifier\ online=온라인에서 문서 식별자 검색 Search\ for\ unlinked\ local\ files=연결 해제된 로컬 파일 검색 Search\ full\ text\ documents\ online=온라인에서 전체 텍스트 문서 검색 -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=힌트\:\n\n모든 영역에서 Smith를 검색하고 싶다면 smith 라고 입력하세요.\n\n작가 영역에서 Smith를 검색하고 싶거나 \n제목 영역에서 electrical를 검색하고 싶다면\nauthor\=Smith and title\=electrical라고 입력하세요 Search\ term\ is\ empty.=검색어가 비어 있습니다. Invalid\ regular\ expression.=잘못된 정규 표현식입니다. Searching\ for\ a\ keyword=키워드 검색 @@ -782,7 +753,6 @@ New\ BibTeX\ sublibrary=새 BibTeX 서브라이브러리 Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=저널 이름을 알고 있는 경우 전체 저널 이름과 약식 저널 이름 사이를 전환합니다. -the\ field\ %0=필드 %0 The\ group\ "%0"\ already\ contains\ the\ selection.=그룹 "%0"에 이미 선택 항목이 포함되어 있습니다. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=출력 옵션은 유효한 가져오기 옵션에 따라 다릅니다. @@ -2158,10 +2128,8 @@ Select\ directory=디렉토리를 선택 Rebuild\ fulltext\ search\ index=전체 텍스트 검색 색인 재구축 Rebuild\ fulltext\ search\ index\ for\ current\ library?=현재 라이브러리에 대한 전체 텍스트 검색 인덱스를 다시 작성하시겠습니까? Rebuilding\ fulltext\ search\ index...=전체 텍스트 검색 색인 재구축 중... -Failed\ to\ access\ fulltext\ search\ index=전체 텍스트 검색 색인에 액세스하지 못했습니다. Found\ match\ in\ %0=%0에서 일치하는 항목을 찾았습니다. On\ page\ %0=페이지 %0 -Found\ matches\ in\ Annotations\:=주석에서 일치하는 항목을 찾았습니다. Character\ by\ character=한 문자씩 @@ -2183,7 +2151,6 @@ Word\ by\ word=한 단어씩 Link=링크 -plain\ text=일반 텍스트 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index bd607a19df4..906ab442817 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Kan bestandswijzigingen niet bijhouden. Sluit bestanden en processen en start opnieuw. U kan fouten tegenkomen als u verder gaat met deze sessie. -%0\ contains\ the\ regular\ expression\ %1=%0 bevat de reguliere expressie %1 - -%0\ contains\ the\ term\ %1=%0 bevat de term %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 bevat de reguliere espressie %1 niet - -%0\ doesn't\ contain\ the\ term\ %1=%0 bevat de term %1 niet %0/%1\ entries=%0/%1 items @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Export actie succesvol afgerond. Reveal\ in\ File\ Explorer=Toon in Verkenner -%0\ matches\ the\ regular\ expression\ %1=%0 komt overeen met de standaard-uitdruk %1 - -%0\ matches\ the\ term\ %1=%0 komt overeen met de term %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Kort tijdschriftnamen van de geselecteerde items af (DEFAULT afkorting) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Kort tijdschriftnamen van de geselecteerde items af (DOTLESS afkorting) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Kort tijdschriftnamen van de geselecteerde items af (SHORTEST UNIQUE afkorting) @@ -84,10 +73,6 @@ All\ entries=Alle items Also\ remove\ subgroups=Ook subgroepen verwijderen -and=en - -any\ field\ that\ matches\ the\ regular\ expression\ %0=elk veld dat overeenkomt met de reguliere expressie %0 - Appearance=Uiterlijk Application=Programma @@ -130,10 +115,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Kan groep niet maken. Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Kan map niet openen omdat het bestand een online link is. -case\ insensitive=hoofdletter ongevoelig - -case\ sensitive=hoofdlettergevoelig - Case\ sensitive=Hoofdlettergevoelig change\ assignment\ of\ entries=verandering toewijzing van invoergegevens @@ -444,9 +425,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Onafhankelijke groep\: Wanneer geselecteerd, toon enkel de invoergegevens van deze groep I\ Agree=Ik ga akkoord -Indexing\ for\ %0=Indexeren voor %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 van %1 gelinkte bestanden toegevoegd aan de index - Invalid\ URL=Ongeldige URL Online\ help=Online hulp @@ -556,8 +534,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Er konden geen tijdschriftnamen afge No\ journal\ names\ could\ be\ unabbreviated.=Geen afkortingen van tijdschriftnamen konden ongedaan gemaakt worden. -not=niet - not\ found=niet gevonden Nothing\ to\ redo=Niets om te herstellen @@ -758,8 +734,6 @@ Fulltext\ search=Zoeken in de volledige tekst Help\ on\ regular\ expression\ search=Help over Reguliere Expressie Zoekopdracht Searching\ for\ duplicates...=Aan het zoeken naar duplicaten... Searching\ for\ files=Zoeken naar bestanden -The\ search\ is\ case-insensitive.=De zoekopdracht is hoofdletterongevoelig. -The\ search\ is\ case-sensitive.=De zoekopdracht is hoofdlettergevoelig. Use\ regular\ expression\ search=Gebruik Reguliere Expressie Zoekopdracht search\ expression=zoek expressie Free\ search\ expression=Vrije zoekexpressie @@ -772,17 +746,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Open of begin een ni Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Voer een veldnaam in om te zoeken naar een trefwoord. No\ results\ found.=Geen resultaten gevonden. Found\ %0\ results.=%0 resultaten gevonden. -Invalid\ regular\ expression=Ongeldige reguliere expressie -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Deze zoekopdracht bevat invoergegevens waarin elk veld de reguliere expressie %0 bevat -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Deze zoekopdracht bevat invoergegevens waarin elk veld de term %0 bevat -This\ search\ contains\ entries\ in\ which=Deze zoekopdracht bevat invoergegevens waarin Empty\ search\ ID=Leeg zoek ID The\ given\ search\ ID\ was\ empty.=Het opgegeven zoek ID was leeg. Clear\ search=Wis zoekopdracht Search\ document\ identifier\ online=Online document-id zoeken Search\ for\ unlinked\ local\ files=Zoeken naar niet-gekoppelde lokale bestanden Search\ full\ text\ documents\ online=Zoek volledige tekstdocumenten online -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Hint\:\n\nOm alle velden te doorzoeken voor Smith, voer in\:\nsmith\n\nOm het veld author voor Smith en het veld title voor electrical te zoeken, voer in\:\nauthor\=Smith and title\=electrical Search\ term\ is\ empty.=Zoekterm is leeg. Invalid\ regular\ expression.=Ongeldige reguliere expressie. Searching\ for\ a\ keyword=Zoeken naar een trefwoord @@ -858,7 +827,6 @@ New\ BibTeX\ sublibrary=Nieuwe BibTeX subblibliotheek Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Schakelt tussen volledige en afgekorte tijdschriftnaam als het tijdschrift gekend is. -the\ field\ %0=het veld %0 The\ group\ "%0"\ already\ contains\ the\ selection.=De groep "%0" bevat reeds de selectie. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=De uitvoeroptie is afhankelijk van een geldige importeeroptie. @@ -2345,10 +2313,8 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Indexeer automat Rebuild\ fulltext\ search\ index=Volledige tekst zoekindex opnieuw opbouwen Rebuild\ fulltext\ search\ index\ for\ current\ library?=Volledige tekst zoekindex opnieuw aanmaken voor huidige bibliotheek? Rebuilding\ fulltext\ search\ index...=Volledige tekst zoekindex opnieuw opbouwen... -Failed\ to\ access\ fulltext\ search\ index=Toegang tot volledige zoekindex mislukt Found\ match\ in\ %0=Overeenkomst gevonden in %0 On\ page\ %0=Op pagina %0 -Found\ matches\ in\ Annotations\:=Overeenkomsten gevonden in annotaties\: Fetcher\ cannot\ be\ tested\!=Fetcher kan niet worden getest\! Fetcher\ unknown\!=Fetcher onbekend\! @@ -2424,7 +2390,6 @@ Left\ Entry=Linker Invoer Merge\ %0=Voeg %0 samen Right\ Entry=Rechter Invoer Unmerge\ %0=Samenvoegen ongedaan maken %0 -plain\ text=onopgemaakte tekst The\ %0s\ are\ the\ same.\ However,\ the\ order\ of\ field\ content\ differs=De %0s zijn hetzelfde. De volgorde van de veldinhoud verschilt echter diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index ef9c7af227c..f1a5bf336f6 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1,17 +1,6 @@ -%0\ contains\ the\ regular\ expression\ %1=%0 inneholder regulæruttrykket %1 -%0\ contains\ the\ term\ %1=%0 inneholder uttrykket %1 -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 inneholder ikke regulæruttrykket %1 -%0\ doesn't\ contain\ the\ term\ %1=%0 inneholder ikke uttrykket %1 - - - - -%0\ matches\ the\ regular\ expression\ %1=%0 matcher regulæruttrykket %1 - -%0\ matches\ the\ term\ %1=%0 matcher uttrykket %1 Abbreviate\ names=Forkort navn @@ -58,10 +47,6 @@ The\ label\ of\ the\ string\ cannot\ contain\ the\ '\#'\ character.=Navnet på s All\ entries=Alle enheter -and=og - -any\ field\ that\ matches\ the\ regular\ expression\ %0=ethvert felt som matcher regulæruttrykket %0 - Appearance=Utseende Application=Applikasjon @@ -98,10 +83,6 @@ Cannot\ create\ group=Kan ikke opprette gruppe Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Kan ikke opprette gruppe. Vennligst opprett et bibliotek først. -case\ insensitive=skiller ikke mellom store og små bokstaver - -case\ sensitive=skiller mellom store og små bokstaver - Case\ sensitive=Skill store og små bokstaver change\ assignment\ of\ entries=endre tilordning av oppføringer @@ -348,7 +329,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Uavhengig gruppe\: Vis bare denne gruppens enheter I\ Agree=Jeg godtar - Invalid\ URL=Ugyldig URL Online\ help=Online hjelp @@ -423,8 +403,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Ingen journalnavn kunne forkortes. No\ journal\ names\ could\ be\ unabbreviated.=Ingen journalnavn kunne ekspanderes. -not=ikke - not\ found=ikke funnet Nothing\ to\ redo=Ingenting å gjenta @@ -649,7 +627,6 @@ New\ BibTeX\ sublibrary=Nytt BibTeX-delbibiliotek Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Bytter mellom fullt og forkortet journalnavn dersom navnet er kjent. -the\ field\ %0=feltet %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Gruppen "%0" inneholder allerede de valgte enhetene. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Lagre-operasjonen er avhengig av en gyldig import-operasjon. diff --git a/src/main/resources/l10n/JabRef_pl.properties b/src/main/resources/l10n/JabRef_pl.properties index bf6deb0d720..cf265d2535d 100644 --- a/src/main/resources/l10n/JabRef_pl.properties +++ b/src/main/resources/l10n/JabRef_pl.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Nie można monitorować zmian plików. Zamknij pliki i procesy i uruchom ponownie. Jeśli będziesz kontynuować sesję, możesz napotkać błędy. -%0\ contains\ the\ regular\ expression\ %1=%0 zawiera wyrażenie regularne %1 - -%0\ contains\ the\ term\ %1=%0 zawiera frazę %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 nie zawiera wyrażenia regularnego %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 nie zawiera frazy %1 %0/%1\ entries=%0/%1 wpisów @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Operacja eksportu zakończona pomyśl Reveal\ in\ File\ Explorer=Pokaż w Eksploratorze plików -%0\ matches\ the\ regular\ expression\ %1=%0 pasuje do wyrażenia regularnego %1 - -%0\ matches\ the\ term\ %1=%0 pasuje do frazy %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Skróć nazwy czasopism dla wybranych wpisów (skrót DEFAULT) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Skróć nazwy czasopism dla wybranych wpisów (skrót DOTLESS) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Skróć nazwy czasopism dla wybranych wpisów (skrót SHORTEST UNIQUE) @@ -76,10 +65,6 @@ All\ entries=Wszystkie wpisy Also\ remove\ subgroups=Usuń również podgrupy -and=i - -any\ field\ that\ matches\ the\ regular\ expression\ %0=dowolne pole pasujące do wyrażenia regularnego %0 - Appearance=Wygląd Application=Aplikacja @@ -123,10 +108,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Nie można utworzyć Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Nie można otworzyć folderu ponieważ plik jest zasobem online. -case\ insensitive=ignoruj wielkość liter - -case\ sensitive=rozróżniaj wielkość liter - Case\ sensitive=Rozróżniaj wielkość liter change\ assignment\ of\ entries=zmień przypisanie wpisów @@ -463,9 +444,6 @@ Importer\ class=Klasa importera I\ Agree=Wyrażam zgodę -Indexing\ PDF\ files=Indeksowanie plików PDF -Indexing\ for\ %0=Indeksowanie dla %0 - Invalid\ URL=Nieprawidłowy URL Online\ help=Pomoc online @@ -579,8 +557,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Nie udało się skrócić żadnego t No\ journal\ names\ could\ be\ unabbreviated.=Nie udało się rozwinąć skróconego tytułu żadnego czasopisma. -not=nie - not\ found=nie znaleziono Nothing\ to\ redo=Brak zmian do powtórki @@ -787,8 +763,6 @@ Fulltext\ search=Wyszukiwanie pełnotekstowe Help\ on\ regular\ expression\ search=Pomoc przy wyszukiwaniu wyrażenia regularnego Searching\ for\ duplicates...=Wyszukiwanie duplikatów... Searching\ for\ files=Szukanie plików -The\ search\ is\ case-insensitive.=Wyszukiwanie nie rozróżnia wielkość liter. -The\ search\ is\ case-sensitive.=Wyszukiwanie rozróżnia wielkość liter. Use\ regular\ expression\ search=Użyj wyszukiwania wyrażenia regularnego search\ expression=szukaj wyrażenia Free\ search\ expression=Wyrażenie wyszukiwania @@ -801,10 +775,6 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Proszę otworzyć lu Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Wprowadź nazwę pola, aby wyszukać słowo kluczowe. No\ results\ found.=Nie znaleziono wyników. Found\ %0\ results.=Znaleziono %0 wyników. -Invalid\ regular\ expression=Nieprawidłowe wyrażenie regularne -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=To wyszukiwanie zawiera wpisy, w których każde pole zawiera wyrażenie regularne %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=To wyszukiwanie zawiera wpisy, w których dowolne pole zawiera wyrażenie %0 -This\ search\ contains\ entries\ in\ which=To wyszukiwanie zawiera wpisy, w których Empty\ search\ ID=Pusty identyfikator wyszukiwania The\ given\ search\ ID\ was\ empty.=Podany identyfikator wyszukiwania był pusty. Clear\ search=Wyczyść wyszukiwanie @@ -889,7 +859,6 @@ This\ feature\ generates\ a\ new\ library\ based\ on\ the\ list\ of\ references\ New\ BibTeX\ sublibrary=Nowa pod-biblioteka BibTeX -the\ field\ %0=pole %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Grupa "%0" już zawiera ten wybór. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Opcja wyjścia zależy od prawidłowej opcji importu. @@ -1746,8 +1715,8 @@ AI=Sztuczna inteligencja AI\ chat=Czat AI I\ agree=Zgadzam się Privacy\ notice=Informacja o ochronie prywatności -Show\ 'AI\ Chat'\ tab=Pokaż zakładkę 'Czat AI' -Show\ 'AI\ Summary'\ tab=Pokaż zakładkę „Podsumowanie AI” +Show\ tab\ 'AI\ Chat'=Pokaż zakładkę 'Czat AI' +Show\ tab\ 'AI\ Summary'=Pokaż zakładkę „Podsumowanie AI” Submit=Prześlij Unable\ to\ chat=Nie można czatować Clear\ chat\ history=Wyczyść historię @@ -1781,7 +1750,26 @@ Estimated\ time\ left\:\ approx.\ 2\ minutes.=Pozostały szacowany czas\: około Estimated\ time\ left\:\ more\ than\ 2\ minutes.=Pozostały szacowany czas\: ponad 2 minuty. You\ find\ information\ about\ the\ privacy\ policy\ here.=Tutaj znajdziesz informacje o polityce prywatności. Embedding\ model\ has\ to\ be\ provided=Należy podać model osadzania +Could\ not\ find\ path\ for\ a\ linked\ file\ '%0'\ while\ generating\ embeddings.=Nie udało się znaleźć ścieżki połączonego pliku '%0' podczas generowania osadzeń. +File\ %0\ is\ currently\ being\ processed=Plik %0 jest obecnie przetwarzany +File\ %0\ is\ not\ a\ PDF\ file=Plik %0 nie jest plikiem PDF +Generating\ embeddings\ for\ file\ '%0'=Generowanie osadzeń dla pliku '%0' +Notifications=Powiadomienia +Only\ PDF\ files\ can\ be\ used\ for\ chatting=Tylko pliki PDF mogą być używane do czatowania +The\ chat\ history\ will\ not\ be\ stored\ in\ next\ sessions=Historia czatu nie będzie przechowywana w kolejnych sesjach +Unable\ to\ generate\ embeddings\ for\ file\ '%0',\ because\ JabRef\ was\ unable\ to\ extract\ text\ from\ the\ file=Nie można wygenerować osadzeń dla pliku '%0', ponieważ JabRef nie był w stanie wyodrębnić tekstu z pliku +Chat\ with\ group=Czat z grupą +No\ library\ is\ selected.=Nie wybrano biblioteki. +Unable\ to\ chat\ with\ group=Nie można czatować z grupą +Waiting\ for\ AI\ reply...=Oczekiwanie na odpowiedź AI... +Invalid\ citation\ key\ for\ %0\ (%1)=Nieprawidłowy klucz cytowania dla %0 (%1) +No\ citation\ key\ for\ %0=Nie znaleziono klucza cytowania dla %0 +Please\ attach\ at\ least\ one\ PDF\ file\ to\ enable\ summarization\ of\ PDF\ file(s).=W celu umożliwienia podsumowania plików PDF, proszę załączyć przynajmniej jeden plik PDF. +Group\ %0=Grupa %0 Generating\ embeddings\ for\ %0=Generowanie osadzeń dla %0 +RAG\ minimum\ score\ must\ be\ a\ number=Minimalny wynik RAG musi być liczbą +RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Minimalny wynik RAG musi być większy niż 0 i mniejszy niż 1 +Temperature\ must\ be\ a\ number=Temperatura musi być liczbą Link=Odnośnik Source\ URL=Źródłowy adres URL @@ -1789,7 +1777,6 @@ Add\ file\ link=Dodaj odnośnik do pliku Assign=Przypisz -plain\ text=czysty tekst Keep\ existing\ entry=Zachowaj istniejący wpis diff --git a/src/main/resources/l10n/JabRef_pt.properties b/src/main/resources/l10n/JabRef_pt.properties index 4b832e05929..5f2bfd52712 100644 --- a/src/main/resources/l10n/JabRef_pt.properties +++ b/src/main/resources/l10n/JabRef_pt.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Não é possível monitorar as alterações de arquivos. Por favor feche os arquivos e processe e reinicie. Você pode encontrar erros se continuar com esta sessão. -%0\ contains\ the\ regular\ expression\ %1=%0 contém a Expressão Regular %1 - -%0\ contains\ the\ term\ %1=%0 contém o termo %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 não contém a Expressão Regular %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 não contém o termo %1 %0/%1\ entries=%0/%1 entradas @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Operação de exportação concluída Reveal\ in\ File\ Explorer=Mostrar no Explorador de Arquivos -%0\ matches\ the\ regular\ expression\ %1=%0 encontrada a expressão regular %1 - -%0\ matches\ the\ term\ %1=%0 encontrado o termo %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Abreviar nomes de periódicos das entradas selecionadas (DEFAULT abreviação) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Abreviar nomes de periódicos das referências selecionadas (abreviação DOTLESS) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Abreviar nomes de periódicos das entradas selecionadas ( abreviação SHORTEST UNIQUE) @@ -79,10 +68,6 @@ All\ entries=Todas as referências Also\ remove\ subgroups=Também remover subgrupos -and=e - -any\ field\ that\ matches\ the\ regular\ expression\ %0=qualquer campo que corresponde a expressão regular %0 - Appearance=Aparência Application=Aplicação @@ -125,10 +110,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Impossível criar o g Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Não é possível abrir a pasta, pois o arquivo é um link online. -case\ insensitive=Insensível ao caso - -case\ sensitive=sensível ao caso - Case\ sensitive=Sensível ao caso change\ assignment\ of\ entries=Alterar atribuição de referências @@ -423,9 +404,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Grupo independente\: Quando selecionado, mostra apenas as referências deste grupo I\ Agree=Concordo -Indexing\ for\ %0=Indexando para %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 de %1 vinculados arquivos adicionados ao índice - Invalid\ URL=URL inválida Online\ help=Ajuda online @@ -514,8 +492,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Nenhum nome de periódico pôde ser No\ journal\ names\ could\ be\ unabbreviated.=Nenhum nome de periódico pôde ser desabreviado. -not=não - not\ found=não encontrado Nothing\ to\ redo=Nada para refazer @@ -711,8 +687,6 @@ Fulltext\ search=Pesquisa de texto completo Help\ on\ regular\ expression\ search=Ajuda sobre busca por expressão regular Searching\ for\ duplicates...=Procurando por duplicatas... Searching\ for\ files=Procurando por arquivos... -The\ search\ is\ case-insensitive.=A busca não faz distinção entre maiúsculas e minúsculas. -The\ search\ is\ case-sensitive.=A busca diferencia maiúsculas de minúsculas. Use\ regular\ expression\ search=Utilizar pesquisa por expressão regular search\ expression=expressão de pesquisa Free\ search\ expression=Expressão de busca livre @@ -725,10 +699,6 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Por favor, abra ou i Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Por favor, digite um nome de campo para procurar uma palavra-chave. No\ results\ found.=Nenhum resultado encontrado. Found\ %0\ results.=Encontrados %0 resultados. -Invalid\ regular\ expression=Expressão regular inválida -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Esta pesquisa contém entradas com a expressão regular %0 em que qualquer campo -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Esta pesquisa contém entradas com o termo %0 em que qualquer campo -This\ search\ contains\ entries\ in\ which=Esta pesquisa contém entradas cujo Empty\ search\ ID=ID de pesquisa vazia The\ given\ search\ ID\ was\ empty.=O ID de pesquisa fornecido estava vazio. Clear\ search=Limpar pesquisa @@ -794,7 +764,6 @@ New\ BibTeX\ sublibrary=Nova sub-base de dados BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Alterna entre nomes de periódicos abreviados e completos se o nome do periódico é conhecido. -the\ field\ %0=o campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=O grupo "%0" já contém a seleção. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=A opção de output depende de uma opção de importação válida. @@ -1362,7 +1331,6 @@ Default\ pattern=Ppadrão predefinido Link=Linkar -plain\ text=texto sem formatação diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index c7707f6a7e9..69e456b44f8 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Não é possível monitorar as alterações de arquivos. Por favor feche os arquivos e os processors e reinicie. Você pode encontrar erros se continuar com esta sessão. -%0\ contains\ the\ regular\ expression\ %1=%0 contém a Expressão Regular %1 - -%0\ contains\ the\ term\ %1=%0 contém o termo %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 não contém a Expressão Regular %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 não contém o termo %1 %0/%1\ entries=%0/%1 entradas @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Operação de exportação concluída Reveal\ in\ File\ Explorer=Mostrar no explorador de arquivos -%0\ matches\ the\ regular\ expression\ %1=%0 encontrada a expressão regular %1 - -%0\ matches\ the\ term\ %1=%0 encontrado o termo %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Abreviar nomes de periódicos das referências selecionadas (abreviação padrão) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Abreviar nomes de periódicos das referências selecionadas (abreviação sem ponto) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Abreviar nomes de periódicos das referências selecionadas (MENOR abreviação ÚNICA) @@ -89,10 +78,6 @@ All\ entries=Todas as referências Also\ remove\ subgroups=Também remover subgrupos -and=e - -any\ field\ that\ matches\ the\ regular\ expression\ %0=qualquer campo que corresponde a expressão regular %0 - Appearance=Aparência Application=Aplicação @@ -136,10 +121,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Impossível criar o g Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Não foi possível abrir a pasta, pois o arquivo é um link online. -case\ insensitive=Insensível ao caso - -case\ sensitive=sensível ao caso - Case\ sensitive=Sensível ao caso change\ assignment\ of\ entries=Alterar atribuição de referências @@ -288,6 +269,10 @@ Dynamically\ group\ entries\ by\ searching\ a\ field\ for\ a\ keyword=Agrupar re Each\ line\ must\ be\ of\ the\ following\ form\:\ 'tab\:field1;field2;...;fieldN'.=Cada linha deve ter o seguinte formato\: 'tab\:field1;field2;...;fieldN'. +Search\ groups\ migration\ of\ %0=Buscar grupos de migração de %0 +The\ search\ groups\ syntax\ is\ outdated.\ Do\ you\ want\ to\ migrate\ to\ the\ new\ syntax?= A sintaxe dos grupos de pesquisa está desatualizada. Você deseja migrar para a nova sintaxe? +Migrate=Migrar +Keep\ as\ is=Manter como está Edit=Editar Edit\ file\ type=Editar tipo de arquivo @@ -501,10 +486,12 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Grupo independente\: Quando selecionado, mostra apenas as referências deste grupo I\ Agree=Concordo -Indexing\ PDF\ files=Indexando arquivos PDF -Indexing\ for\ %0=Indexando %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 de %1 arquivos vinculados adicionados ao índice - +Score=Pontuação +Indexing\ bib\ fields\ for\ %0=Indexando campos bib para %0 +Indexing\ PDF\ files\ for\ %0=Indexando arquivos PDF para %0 +%0\ of\ %1\ entries\ added\ to\ the\ index.=%0 de %1 entradas adicionadas ao índice. +%0\ of\ %1\ entries\ removed\ from\ the\ index.=%0 dos %1 registros removidos do índice. +Removing\ entries\ from\ index\ for\ %0=Removendo entradas do índice %0 Invalid\ URL=URL inválida Online\ help=Ajuda online @@ -619,8 +606,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Nenhum nome de periódico pôde ser No\ journal\ names\ could\ be\ unabbreviated.=Nenhum nome de periódico pôde ser desabreviado. -not=não - not\ found=não encontrado Nothing\ to\ redo=Nada para refazer @@ -831,8 +816,6 @@ Fulltext\ search=Pesquisa de texto completo Help\ on\ regular\ expression\ search=Ajuda sobre busca por expressão regular Searching\ for\ duplicates...=Procurando por duplicatas... Searching\ for\ files=Procurando por arquivos... -The\ search\ is\ case-insensitive.=A busca não faz distinção entre maiúsculas e minúsculas. -The\ search\ is\ case-sensitive.=A busca diferencia maiúsculas de minúsculas. Use\ regular\ expression\ search=Utilizar pesquisa por expressão regular search\ expression=expressão de pesquisa Free\ search\ expression=Expressão de busca livre @@ -845,17 +828,13 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Por favor, abra ou i Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Por favor, digite um nome de campo para buscar palavras-chave. No\ results\ found.=Nenhum resultado encontrado. Found\ %0\ results.=Encontrados %0 resultados. -Invalid\ regular\ expression=Expressão regular inválida -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Esta pesquisa contém entradas com a expressão regular %0 em que qualquer campo -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Esta pesquisa contém entradas com o termo %0 em que qualquer campo -This\ search\ contains\ entries\ in\ which=Esta pesquisa contém referências em que Empty\ search\ ID=ID de pesquisa vazio The\ given\ search\ ID\ was\ empty.=O ID de pesquisa fornecido estava vazio. Clear\ search=Limpar busca Search\ document\ identifier\ online=Pesquisar identificador de documento na web Search\ for\ unlinked\ local\ files=Procurar por arquivos locais desvinculados Search\ full\ text\ documents\ online=Pesquisar textos completos on-line -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Dica\:\n\nPara pesquisar todos os campos por Smith, digite\:\nsmith\n\nPara procurar por Smith no campo autor e eletrico no campo título, digite\:\nauthor\=Ferreiro e title\=eletrico +Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\:Smith\ AND\ title\:electrical=Dica\:\n\nPara pesquisar todos os campos por Smith, digite\:\nsmith\n\nPara pesquisar no campo author por Smith e no campo title por electrical, digite\:\nauthor\:Smith AND title\:electrical Search\ term\ is\ empty.=O termo de pesquisa está vazio. Invalid\ regular\ expression.=Expressão regular inválida. Searching\ for\ a\ keyword=Procurando palavras-chave @@ -942,7 +921,6 @@ New\ BibTeX\ sublibrary=Nova sub-base de dados BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Alterna entre nomes de periódicos abreviados e completos se o nome do periódico é conhecido. -the\ field\ %0=o campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=O grupo "%0" já contém a seleção. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=A opção de output depende de uma opção de importação válida. @@ -2473,10 +2451,9 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Indexar automati Rebuild\ fulltext\ search\ index=Recriar índice da pesquisa completa Rebuild\ fulltext\ search\ index\ for\ current\ library?=Recriar o índice de pesquisa completa para a biblioteca atual? Rebuilding\ fulltext\ search\ index...=Recriando índice de busca completa... -Failed\ to\ access\ fulltext\ search\ index=Falha ao acessar o índice da pesquisa completa Found\ match\ in\ %0=Correspondência encontrada em %0 On\ page\ %0=Na página %0 -Found\ matches\ in\ Annotations\:=Encontradas partidas em anotações (Annotations)\: +Found\ matches\ in\ annotations\:=Encontradas correspondências em anotações\: Fetcher\ cannot\ be\ tested\!=O buscador não pode ser testado\! Fetcher\ unknown\!=Buscador desconhecido\! @@ -2543,8 +2520,8 @@ AI=IA AI\ chat=Bate-papo IA I\ agree=Eu concordo Privacy\ notice=Aviso de privacidade -Show\ 'AI\ Chat'\ tab=Mostrar aba 'Bate-Papo IA' -Show\ 'AI\ Summary'\ tab=Mostrar aba 'Sumário IA' +Show\ tab\ 'AI\ Chat'=Mostrar aba 'Chat de IA' +Show\ tab\ 'AI\ Summary'=Mostrar aba 'Resumo IA' Submit=Submeter Unable\ to\ chat=Não foi possível conversar Clear\ chat\ history=Limpar histórico de bate-papo @@ -2561,7 +2538,6 @@ Please\ provide\ a\ non-empty\ and\ unique\ citation\ key\ for\ this\ entry.=Por RAG\ -\ maximum\ results\ count=RAG - contagem máxima de resultados RAG\ -\ minimum\ score=RAG - pontuação mínima RAG\ max\ results\ count\ must\ be\ greater\ than\ 0=A contagem máxima de resultados RAG deve ser maior que 0 -RAG\ min\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=RAG Pontuação mínima deve ser maior que 0 e menor que 1 Clear\ embeddings\ cache=Limpar cache de incorporação Clear\ embeddings\ cache\ for\ current\ library?=Limpar o cache de incorporação da biblioteca atual? Clearing\ embeddings\ cache...=Limpando o cache de incorporação... @@ -2574,6 +2550,7 @@ Instruction\ for\ AI\ (also\ known\ as\ prompt\ or\ system\ message)=Instrução The\ instruction\ has\ to\ be\ provided=A instrução tem de ser fornecida An\ I/O\ error\ occurred\ while\ opening\ the\ embedding\ model\ by\ URL\ %0=Um erro de I/O ocorreu ao abrir o modelo de incorporação pela URL %0 Got\ error\ while\ processing\ the\ file\:=Ocorreu um erro ao processar o arquivo\: +The\ model\ by\ URL\ %0\ is\ malformed=O modelo pela URL %0 está malformado Unable\ to\ find\ the\ embedding\ model\ by\ the\ URL\ %0=Não foi possível encontrar o modelo de incorporação pela URL %0 API\ base\ URL\ has\ to\ be\ provided=URL base da API tem de ser fornecida Chat\ model=Modelo de chat @@ -2634,11 +2611,12 @@ Only\ PDF\ files\ can\ be\ used\ for\ chatting=Apenas arquivos PDF podem ser usa The\ chat\ history\ will\ not\ be\ stored\ in\ next\ sessions=O histórico de bate-papo não será armazenado nas próximas sessões Unable\ to\ generate\ embeddings\ for\ file\ '%0',\ because\ JabRef\ was\ unable\ to\ extract\ text\ from\ the\ file=Não foi possível gerar incorporações para o arquivo '%0', porque JabRef não conseguiu extrair o texto do arquivo Chat\ with\ group=Bate-papo em grupo -No\ database\ is\ set.=Nenhum banco de dados está definido. +No\ library\ is\ selected.=Nenhuma biblioteca foi selecionada. Unable\ to\ chat\ with\ group=Não é possível conversar com o grupo Waiting\ for\ AI\ reply...=Aguardando resposta IA... An\ error\ occurred\ while\ opening\ chat\ history\ storage.\ Chat\ history\ of\ entries\ and\ groups\ will\ not\ be\ stored\ in\ the\ next\ session.=Ocorreu um erro ao abrir o armazenamento do histórico de bate-papo. O histórico de bate-papo de entradas e grupos não será armazenado na próxima sessão. An\ error\ occurred\ while\ opening\ summary\ storage.\ Summaries\ of\ entries\ will\ not\ be\ stored\ in\ the\ next\ session.=Ocorreu um erro ao abrir o armazenamento de resumo. Os resumos das entradas não serão armazenados na próxima sessão. +An\ error\ occurred\ while\ opening\ the\ embeddings\ cache\ file.\ Embeddings\ will\ not\ be\ stored\ in\ the\ next\ session.=Ocorreu um erro ao abrir o arquivo de cache de incorporações. As incorporações não serão armazenadas na próxima sessão. Invalid\ citation\ key\ for\ %0\ (%1)=Chave de citação inválida para %0 (%1) No\ citation\ key\ for\ %0=Nenhuma chave de citação para %0 Please\ attach\ at\ least\ one\ PDF\ file\ to\ enable\ summarization\ of\ PDF\ file(s).=Por favor, anexe pelo menos um arquivo PDF para habilitar a sumarização do(s) arquivo(s) PDF. @@ -2646,6 +2624,9 @@ Unable\ to\ generate\ summary=Não é possível gerar o resumo Group\ %0=Grupo %0 AI\ chat\ with\ %0=Chat IA com %0 Generating\ embeddings\ for\ %0=Gerando incorporações para %0 +RAG\ minimum\ score\ must\ be\ a\ number=A pontuação mínima de RAG deve ser um número +RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Pontuação mínima de RAG deve ser maior que 0 e menor que 1 +Temperature\ must\ be\ a\ number=A temperatura deve ser um número Link=Linkar Source\ URL=URL de origem @@ -2661,7 +2642,6 @@ Left\ Entry=Entrada esquerda Merge\ %0=Mesclar %0 Right\ Entry=Entrada direita Unmerge\ %0=Separar %0 -plain\ text=texto sem formatação The\ %0s\ are\ the\ same.\ However,\ the\ order\ of\ field\ content\ differs=O %0s é o mesmo. No entanto, a ordem do conteúdo do campo difere do conteúdo diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index c6a81488979..ad69bad8a89 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Не удается отслеживать изменения файла. Закройте файлы и перезапустите программу. Вы можете столкнуться с ошибками, если продолжите текущую сессию. -%0\ contains\ the\ regular\ expression\ %1=%0 содержит регулярное выражение %1 - -%0\ contains\ the\ term\ %1=%0 содержит условие %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 не содержит регулярного выражения %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 не содержит условия %1 %0/%1\ entries=%0/%1 записей @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Операция экспорта в Reveal\ in\ File\ Explorer=Открыть в Проводнике -%0\ matches\ the\ regular\ expression\ %1=%0 соответствует регулярному выражению %1 - -%0\ matches\ the\ term\ %1=%0 соответствует условию %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Сокращать названия журналов для выбранных записей (сокращения ПО УМОЛЧАНИЮ) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Сокращения названий журналов для выбранных записей (сокращение БЕЗ ТОЧЕК) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Сокращать называния журналов для выбранных записей (КРАТЧАЙШЕЕ УНИКАЛЬНОЕ сокращение) @@ -86,10 +75,6 @@ All\ entries=Все записи Also\ remove\ subgroups=Также удалить подгруппы -and=и - -any\ field\ that\ matches\ the\ regular\ expression\ %0=любое поле, соответствующее регулярному выражению %0 - Appearance=Представление Application=Приложение @@ -133,10 +118,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Не удалось Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Невозможно открыть папку, так как файл является онлайн-ссылкой. -case\ insensitive=без учета регистра - -case\ sensitive=с учетом регистра - Case\ sensitive=С учетом регистра change\ assignment\ of\ entries=изменить назначение для записей @@ -450,9 +431,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Независимая группа\: Просмотр записей только этой группы (если выбрано) I\ Agree=Я согласен -Indexing\ for\ %0=Индексация для %0 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 из %1 связанных файлов добавлено в индекс - Invalid\ URL=Недопустимый URL-адрес Online\ help=Онлайн-справка @@ -547,8 +525,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Названия журналов н No\ journal\ names\ could\ be\ unabbreviated.=Названия журналов не могут быть развернуты. -not=не - not\ found=не найдено Nothing\ to\ redo=Нет действий для повтора @@ -759,17 +735,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Для начала Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Пожалуйста, введите имя поля для поиска ключевых слов. No\ results\ found.=Результаты не найдены. Found\ %0\ results.=Найдено %0 результатов. -Invalid\ regular\ expression=Неправильное регулярное выражение -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Поиск содержит записи, в которых любое поле содержит регулярное выражение %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Поиск содержит записи, в которых любое поле содержит условие %0 -This\ search\ contains\ entries\ in\ which=Поиск содержит записи, в которых Empty\ search\ ID=Пустой поисковый запрос The\ given\ search\ ID\ was\ empty.=Указанный поисковый ID был пустым. Clear\ search=Очистить поиск Search\ document\ identifier\ online=Искать идентификатор документа в сети Search\ for\ unlinked\ local\ files=Искать не связанные локальные файлы Search\ full\ text\ documents\ online=Искать полный текст документа в сети -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Подсказка\:\nдля поиска всех полей со значением Smith, введите\:\n

smith

\nДля поиска в поле Автор значения Smith а в поле Заголовок значения electrical, введите\:\n

author\=smith and title\=electrical Search\ term\ is\ empty.=Поисковый запрос пуст. Invalid\ regular\ expression.=Неправильное регулярное выражение. Searching\ for\ a\ keyword=Поиск ключевого слова @@ -844,7 +815,6 @@ New\ BibTeX\ sublibrary=Создать подчиненную БД BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Переключение полного/сокращенного имени журнала для известных имен журналов. -the\ field\ %0=поле %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Группа "%0" уже содержит выбранное. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Параметры вывода зависят от допустимых параметров импорта. @@ -2273,10 +2243,8 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Автомати Rebuild\ fulltext\ search\ index=Перестроить полнотекствой индекс Rebuild\ fulltext\ search\ index\ for\ current\ library?=Перестроить полнотекстовой индекс для текущей библиотеки? Rebuilding\ fulltext\ search\ index...=Перестроить полнотекствой индекс... -Failed\ to\ access\ fulltext\ search\ index=Не удалось получить доступ к поисковому индексу Found\ match\ in\ %0=Найдены совпадения в %0 On\ page\ %0=На странице %0 -Found\ matches\ in\ Annotations\:=Найдены совпадения в аннотациях\: Fetcher\ cannot\ be\ tested\!=Невозможно проверить сборщик данных\! Fetcher\ unknown\!=Неизвестный сборщик данных\! @@ -2317,7 +2285,6 @@ Link=Ссылка Assign=Назначить Do\ not\ assign=Не назначать -plain\ text=обычный текст diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 443fa9c6ad2..b8b99413bbe 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Kan inte övervaka filändringar. Stäng filer och processer och starta om. Du kan stöta på fel om du fortsätter med denna session. -%0\ contains\ the\ regular\ expression\ %1=%0 innehåller det reguljära uttrycket %1 - -%0\ contains\ the\ term\ %1=%0 innehåller termen %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 innehåller inte det reguljära uttrycket %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 innehåller inte termen %1 %0/%1\ entries=%0/%1 poster @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Exportoperationen slutfördes framgå Reveal\ in\ File\ Explorer=Visa i Filutforskaren -%0\ matches\ the\ regular\ expression\ %1=%0 matchar det reguljära uttrycket %1 - -%0\ matches\ the\ term\ %1=%0 matchar termen %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Förkorta tidskriftsnamnen för valda poster (STANDARD förkortning) Abbreviate\ names=Förkorta namn @@ -74,10 +63,6 @@ A\ string\ with\ the\ label\ '%0'\ already\ exists.=En sträng med namnet '%0' f All\ entries=Alla poster -and=och - -any\ field\ that\ matches\ the\ regular\ expression\ %0=något fält som matchar det reguljära uttrycket %0 - Appearance=Utseende Application=Program @@ -118,10 +103,6 @@ Cannot\ create\ group=Kan inte skapa grupp Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Kan inte skapa grupp. Skapa ett bibliotek först. -case\ insensitive=ej skiftlägeskänsligt - -case\ sensitive=skiftlägeskänsligt - Case\ sensitive=Shiftlägeskänlig change\ assignment\ of\ entries=ändra tilldelning av poster @@ -401,8 +382,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Oberoende grupp\: Visar endast poster tillhörandes denna grupp när den markeras I\ Agree=Jag godkänner -Indexing\ for\ %0=Indexerar %0 - Invalid\ URL=Ogiltig URL Online\ help=Onlinehjälp @@ -486,8 +465,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Inga tidskriftsnamn kunde förkortas No\ journal\ names\ could\ be\ unabbreviated.=Inga tidskriftsnamn kunde expanderas. -not=inte - not\ found=hittades inte Nothing\ to\ redo=Inget att göra om. @@ -658,9 +635,6 @@ Please\ enter\ a\ search\ string=Ange en söksträng Please\ open\ or\ start\ a\ new\ library\ before\ searching=Öppna eller skapa ett nytt bibliotek innan du söker No\ results\ found.=Inga resultat hittades. Found\ %0\ results.=Hittade %0 resultat. -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Denna sökning innehåller poster där något fält innehåller det reguljära uttrycket %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Denna sökning innehåller poster där något fält innehåller termen %0 -This\ search\ contains\ entries\ in\ which=Denna sökning innehåller poster där Select\ all=Välj alla @@ -713,7 +687,6 @@ nested\ AUX\ files=nästlade AUX-filer Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Växlar mellan fullt och förkortat tidskiftsnamn om tidskriften är känd. -the\ field\ %0=fältet %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Gruppen "%0" innehåller redan de valda posterna. @@ -1503,7 +1476,6 @@ Previous\ preview\ style=Föregående förhandsgranskningsstil Link=Länk -plain\ text=klartext diff --git a/src/main/resources/l10n/JabRef_tl.properties b/src/main/resources/l10n/JabRef_tl.properties index e1f499fc3e0..d536a38d6f6 100644 --- a/src/main/resources/l10n/JabRef_tl.properties +++ b/src/main/resources/l10n/JabRef_tl.properties @@ -1,17 +1,6 @@ -%0\ contains\ the\ regular\ expression\ %1=%0 ay naglalaman ng regular na ekspresyon%1 -%0\ contains\ the\ term\ %1=%ay naglalaman ng mga term%1 -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 hindi ay nag lalaman ng regular na ekspresyon %1 -%0\ doesn't\ contain\ the\ term\ %1=%0 hindi naglalaman ng termeno %1 - - - - -%0\ matches\ the\ regular\ expression\ %1=%0 nag tugma sa regular na ekspresyon %1 - -%0\ matches\ the\ term\ %1=%0 tumugma sa termino %1 Abbreviate\ names=Pinaikli na mga pangalan @@ -60,10 +49,6 @@ String\ dialog,\ remove\ string=String dialog, tanggalin ang string All\ entries=Lahat ng entries -and=at - -any\ field\ that\ matches\ the\ regular\ expression\ %0=anumang patlang ang nagtugma sa regular na ekspresyon %0 - Appearance=Ang hitsura Application=Ang aplikasyon @@ -99,10 +84,6 @@ Cancel=Kansela -case\ insensitive=sensitibo ang kaso - -case\ sensitive=sensitibo ang kaso - Case\ sensitive=Sensitibo ang kaso change\ assignment\ of\ entries=palitan ang pagtatalaga ng mga entries @@ -346,7 +327,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Malayang grupo\: Kapag pumili, tingnan lamang ang grupo ng mga entries - Invalid\ URL=Hindi balido ang URL @@ -419,8 +399,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Walang talaarawan na pangalan ang pu No\ journal\ names\ could\ be\ unabbreviated.=Walang talaarawag ang puwedeng paikliin. -not=hindi - not\ found=hindi nakita Nothing\ to\ redo=Walang dapat e-redo @@ -591,9 +569,6 @@ Please\ enter\ a\ search\ string=Pakiusap sa pagpapasok ng string sa paghahanap Please\ open\ or\ start\ a\ new\ library\ before\ searching=Pakiusap buksan o magsimula ng bagong library bago maghanap No\ results\ found.=Walang resulta ang nakita. Found\ %0\ results.=Nakita ang %0 na mga resulta. -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Itong paghahanap ay naglalaman ng mga entries kung saan ay anumang patlang ang nilalaman ng regular na ekspresyon %0 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Itong paghahanap ay naglalaman ng mga entries kung saan ay anumang patlang na naglalaman ng termino %0 -This\ search\ contains\ entries\ in\ which=Itong paghahanap ay naglalaman ng entries kung saan Select\ all=Piliin ang lahat @@ -649,7 +624,6 @@ New\ BibTeX\ sublibrary=Bago ang BibTeX na mababang library Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Lilipat sa pagitan ng buong at dinaglat na pangalan ng journal kung kulala ang pangalan ng journal. -the\ field\ %0=ang patlang na %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Ang grupo na '%0' ay naglalaman na ng pagpili. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Ang opsyon ng output ay depende sa isang wastong pagpipilian sa pag-import. @@ -1234,7 +1208,6 @@ Default\ pattern=Default na pattern Link=Ang link -plain\ text=plain na teksto diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index b5c144f4b50..85414b55085 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Dosya değişiklikleri izlenemiyor. Lütfen dosyaları ve süreçleri kapatın ve yeniden başlatın. Bu seansa devam ederseniz hatalarla karşılaşabilirsiniz. -%0\ contains\ the\ regular\ expression\ %1=%0 şu düzenli ifadeyi içeriyor %1 - -%0\ contains\ the\ term\ %1=%0 şu terimi içeriyor %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 şu Düzenli İfadeyi içermiyor %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 şu terimi içermiyor %1 %0/%1\ entries=%0/%1 girdi @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Dışa aktarım işlemi başarıyla t Reveal\ in\ File\ Explorer=Dosya Gezgini'nde Göster -%0\ matches\ the\ regular\ expression\ %1=%0 şu Düzenli İfadeyle eşleşiyor %1 - -%0\ matches\ the\ term\ %1=%0 şu terimle eşleşiyor %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Seçili girdilerin dergi isimlerini kısalt (ÖN TANIMLI kısaltma) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Seçilen girdilerin dergi isimlerini kısalt (NOKTASIZ kısaltması) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Seçili girdilerin dergi isimlerini kısalt (EN KISA ÖZGÜN kısaltma) @@ -84,10 +73,6 @@ All\ entries=Tüm girdiler Also\ remove\ subgroups=Tüm alt grupları da sil -and=ve - -any\ field\ that\ matches\ the\ regular\ expression\ %0=%0 düzenli ifadesine uyan herhangi bir alan - Appearance=Görünüm Application=Uygulama @@ -130,10 +115,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Grup oluşturulamıyo Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Dosya çevrim içi bir link olduğundan klasör açılamadı. -case\ insensitive=büyük/kü.ük harfe duyarsız - -case\ sensitive=büyük/küçük harfe duyarlı - Case\ sensitive=Büyük/küçük harfe duyarlı change\ assignment\ of\ entries=girdilerin atanmasını değiştir @@ -452,9 +433,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Bağımsız grup\: Seçildiğinde, yalnızca bu grubun girdilerini göster I\ Agree=Kabul Ediyorum -Indexing\ for\ %0=%0 için dizinleniyor -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=%1 bağlantılı dosyanın %0'i dizine eklendi - Invalid\ URL=Geçersiz URL Online\ help=Çevrimiçi yardım @@ -566,8 +544,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Hiçbir dergi adı kısaltılamadı. No\ journal\ names\ could\ be\ unabbreviated.=Hiçbir dergi adı kısaltması açılamadı. -not=hariç - not\ found=bulunmadı Nothing\ to\ redo=Yinelenecek bir şey yok @@ -768,8 +744,6 @@ Fulltext\ search=Tam metin arama Help\ on\ regular\ expression\ search=Düzenli İfade Arama hakkında yardım Searching\ for\ duplicates...=Çift nüshalar aranıyor... Searching\ for\ files=Dosyalar aranıyor -The\ search\ is\ case-insensitive.=Arama büyük/küçük harfe duyarsız. -The\ search\ is\ case-sensitive.=Arama büyük/küçük harfe duyarlı. Use\ regular\ expression\ search=Düzenli İfade Aramayı kullan search\ expression=arama ifadesi Free\ search\ expression=Serbest arama ifadesi @@ -782,17 +756,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Lütfen aramadan ön Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=Anahtar sözcük aramak için lütfen bir alan adı giriniz. No\ results\ found.=Hiçbir sonuç bulunmadı. Found\ %0\ results.=%0 sonuç bulundu. -Invalid\ regular\ expression=Geçersiz düzenli ifade -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=Bu arama, %0 düzenli ifadesini içeren herhangi bir alan bulunan girdileri içerir -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=Bu arama, %0 terimini içeren herhangi bir alan bulunan girdileri içerir -This\ search\ contains\ entries\ in\ which=Bu arama içinde şu olan girdileri içerir Empty\ search\ ID=Boş arama IDsi The\ given\ search\ ID\ was\ empty.=Verilen arama IDsi boştu. Clear\ search=Aramayı temizle Search\ document\ identifier\ online=Belge tanımlayıcıyı çevrim içi ara Search\ for\ unlinked\ local\ files=Bağlantılı olmayan yerel dosyaları ara Search\ full\ text\ documents\ online=Çevrim içi tam metin belgeleri ara -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=İpucu\:\n\nTüm alanlarda Smith'i aramak için şunu girin\:\nsmith\n\nyazar alanında Smith'i ve başlık alanında elektriksel'i aramak için şunu girin\:\nauthor\=Smith and title\=elektriksel Search\ term\ is\ empty.=Arama terimi boş. Invalid\ regular\ expression.=Geçersiz düzenli ifade. Searching\ for\ a\ keyword=Bir anahtar sözcük aranıyor @@ -872,7 +841,6 @@ New\ BibTeX\ sublibrary=Yeni BibTeX alt veritabanı Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Dergi adı biliniyorsa tam ve kısaltılmış dergi adı arasında geçiş yapar. -the\ field\ %0=alan %0 The\ group\ "%0"\ already\ contains\ the\ selection.="%0" grubu seçimi zaten kapsıyor. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Çıktı seçeneği geçerli bir içe aktarım seçeneğine bağlıdır. @@ -2376,10 +2344,8 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Tüm bağlantıl Rebuild\ fulltext\ search\ index=Tam metin arama dizinini yeniden oluştur Rebuild\ fulltext\ search\ index\ for\ current\ library?=Tam metin arama dizini mevcut veri tabanı için yeniden oluşturulsun mu? Rebuilding\ fulltext\ search\ index...=Tam metin arama dizini yeniden oluşturuluyor... -Failed\ to\ access\ fulltext\ search\ index=Tam metin arama dizinine erişilemedi Found\ match\ in\ %0=%0'da eşleşme bulundu On\ page\ %0=Sayfa %0'de -Found\ matches\ in\ Annotations\:=Ek açıklamalarda eşleşmeler bulundu\: Fetcher\ cannot\ be\ tested\!=Getirici test edilemiyor\! Fetcher\ unknown\!=Getirici bilinmiyor\! @@ -2455,7 +2421,6 @@ Left\ Entry=Sol Girdi Merge\ %0=Birleştir %0 Right\ Entry=Sağ Girdi Unmerge\ %0=Ayrıştır %0 -plain\ text=salt metin The\ %0s\ are\ the\ same.\ However,\ the\ order\ of\ field\ content\ differs=%0ler aynı. Lakin, alan içerik sıralaması farklı diff --git a/src/main/resources/l10n/JabRef_uk.properties b/src/main/resources/l10n/JabRef_uk.properties index fe6a8e341a1..4b0335667d1 100644 --- a/src/main/resources/l10n/JabRef_uk.properties +++ b/src/main/resources/l10n/JabRef_uk.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=Неможливо контролювати зміни файлу. Будь ласка, закрийте файли та процеси і перезапустіть. Ви можете зіткнутися з помилками, якщо продовжите сесію. -%0\ contains\ the\ regular\ expression\ %1=%0 містить регулярний вираз %1 - -%0\ contains\ the\ term\ %1=%0 містить термін %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 не містить регулярний вираз %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 не містить термін %1 %0/%1\ entries=%1 Стаття @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=Експорт PAM операції Reveal\ in\ File\ Explorer=Розкрити у файловому провіднику -%0\ matches\ the\ regular\ expression\ %1=%0 відповідностей по регулярному виразу %1 - -%0\ matches\ the\ term\ %1=%0 співпадань по терміну %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Скорочувати назви журналу для вибраних записів (абревіатура за замовчуванням) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=Скорочувати назви журналу для вибраних записів (абревіатура без крапки) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Скорочувати назви журналу для вибраних записів (найкоротша унікальна абревіатура) @@ -66,10 +55,6 @@ All\ entries=Всі записи Also\ remove\ subgroups=Також видалити підгрупи -and=та - -any\ field\ that\ matches\ the\ regular\ expression\ %0=%0 будь-яке поле яке відповідає регулярному виразу %1 - Appearance=Оформлення Application=Застосунок @@ -96,10 +81,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Не вдається Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=Не вдається відкрити папку, оскільки файл є посиланням. -case\ insensitive=без урахування регістру - -case\ sensitive=з урахуванням регістру - Case\ sensitive=З урахуванням регістру change\ assignment\ of\ entries=змінити призначення записів @@ -530,8 +511,6 @@ Current\ value\:\ %0=Поточне значення\: %0 - - diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index b840a2caf0a..69c20026bfc 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1,17 +1,6 @@ -%0\ contains\ the\ regular\ expression\ %1=%0 chứa biểu thức chính tắc %1 -%0\ contains\ the\ term\ %1=%0 chứa thuật ngữ %1 -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 không chứa biểu thức chính tắc %1 -%0\ doesn't\ contain\ the\ term\ %1=%0 không chứa thuật ngữ %1 - - - - -%0\ matches\ the\ regular\ expression\ %1=%0 khớp biểu thức chính tắc %1 - -%0\ matches\ the\ term\ %1=%0 khớp thuật ngữ %1 Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=Viết tắt tên tạp chí của các mục được chọn (mặc định viết tắt) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=Viết tắt tên tạp chí của các mục được chọn (viết tắt ngắn và duy nhất) @@ -62,10 +51,6 @@ The\ label\ of\ the\ string\ cannot\ contain\ the\ '\#'\ character.=Nhãn của All\ entries=Tất cả các mục -and=và - -any\ field\ that\ matches\ the\ regular\ expression\ %0=bất kỳ dữ liệu nào khớp Biểu thức Chính tắc %0 - Appearance=Diện mạo Application=Ứng dụng @@ -103,10 +88,6 @@ Cannot\ create\ group=Không thể tạo nhóm Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Không thể tạo nhóm. Xin tạo thư viện trước. -case\ insensitive=không phân biệt chữ hoa/thường - -case\ sensitive=phân biệt chữ hoa/thường - Case\ sensitive=Phân biệt chữ hoa/thường change\ assignment\ of\ entries=đổi phép gán các mục @@ -354,7 +335,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Nhóm độc lập\: Khi được chọn, chỉ xem các mục của nhóm này - Invalid\ URL=URL không hợp lệ Online\ help=Trợ giúp trực tuyến @@ -427,8 +407,6 @@ No\ journal\ names\ could\ be\ abbreviated.=Không có tên tạp chí nào có No\ journal\ names\ could\ be\ unabbreviated.=Không có tên tạp chí nào có thể viết đầy đủ. -not=không - not\ found=không tìm thấy Nothing\ to\ redo=Không có lệnh nào để lặp lại @@ -643,7 +621,6 @@ New\ BibTeX\ sublibrary=CSDL con BibTeX mới Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Chuyển đổi giữa tên đầy đủ và tên viết tắt tạp chí nếu biết tên tạp chí đó. -the\ field\ %0=dữ liệu %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Nhóm "%0" đã chứa phép chọn. The\ output\ option\ depends\ on\ a\ valid\ import\ option.=Tùy chọn đầu ra phụ thuộc vào một tùy chọn nhập hợp lệ. diff --git a/src/main/resources/l10n/JabRef_zh_CN.properties b/src/main/resources/l10n/JabRef_zh_CN.properties index b706e7be88e..9b391a81922 100644 --- a/src/main/resources/l10n/JabRef_zh_CN.properties +++ b/src/main/resources/l10n/JabRef_zh_CN.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=无法监视文件更改。请关闭文件和处理并重新启动。如果您继续本次会话,您可能会遇到错误。 -%0\ contains\ the\ regular\ expression\ %1=%0 包含正则表达式 %1 - -%0\ contains\ the\ term\ %1=%0 包含词组 %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 不包含正则表达式 %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 不包含词组 %1 %0/%1\ entries=%0/%1 条目 @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=导出成功。 Reveal\ in\ File\ Explorer=在文件夹中显示 -%0\ matches\ the\ regular\ expression\ %1=%0 匹配正则表达式 %1 - -%0\ matches\ the\ term\ %1=%0 匹配词组 %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=缩写选中条目的journal字段(默认缩写) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DOTLESS\ abbreviation)=缩写选定条目的journal字段(无点缩写) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=缩写选中记录的journal字段(最简缩写) @@ -84,10 +73,6 @@ All\ entries=所有记录 Also\ remove\ subgroups=同时移除子组 -and=和 - -any\ field\ that\ matches\ the\ regular\ expression\ %0=能够匹配正则表达式 %0 的任何字段 - Appearance=外观 Application=应用程序 @@ -130,10 +115,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=无法创建分组。 Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=这是一个在线链接,因此无法打开文件夹。 -case\ insensitive=忽略大小写 - -case\ sensitive=区分大小写 - Case\ sensitive=区分大小写 change\ assignment\ of\ entries=修改记录的组分配 @@ -444,9 +425,6 @@ Include\ subgroups\:\ When\ selected,\ view\ entries\ contained\ in\ this\ group Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=独立分组:当分组被选中时,只显示属于此分组的记录 I\ Agree=我同意 -Indexing\ for\ %0=正在为%0建立索引 -%0\ of\ %1\ linked\ files\ added\ to\ the\ index=已添加%0/%1个文件到索引 - Invalid\ URL=非法的 URL Online\ help=帮助文档 @@ -549,8 +527,6 @@ No\ journal\ names\ could\ be\ abbreviated.=没有可供缩写的期刊全称。 No\ journal\ names\ could\ be\ unabbreviated.=没有可供展开的期刊名缩写。 -not=非 - not\ found=未找到 Nothing\ to\ redo=没有可恢复的操作 @@ -751,8 +727,6 @@ Fulltext\ search=全文搜索 Help\ on\ regular\ expression\ search=正则表达式搜索帮助 Searching\ for\ duplicates...=正在查找重复记录... Searching\ for\ files=正在查找文件 -The\ search\ is\ case-insensitive.=不区分大小写 -The\ search\ is\ case-sensitive.=区分大小写 Use\ regular\ expression\ search=使用正则表达式搜索 search\ expression=查询表达式\: Free\ search\ expression=检索语句 @@ -765,17 +739,12 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=请在搜索前打 Please\ enter\ a\ field\ name\ to\ search\ for\ a\ keyword.=请输入字段名称以搜索关键字。 No\ results\ found.=没有找到结果。 Found\ %0\ results.=找到 %0 条结果。 -Invalid\ regular\ expression=正则表达式无效 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ %0=搜索匹配正则表达式%0的所有条目 -This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ %0=搜索含有%0的条目字段 -This\ search\ contains\ entries\ in\ which=这次搜索的结果记录符合条件: Empty\ search\ ID=清空搜索ID The\ given\ search\ ID\ was\ empty.=给定的搜索 ID 为空。 Clear\ search=清除搜索 Search\ document\ identifier\ online=在线查找文档DOI Search\ for\ unlinked\ local\ files=查找未链接的本地文件 Search\ full\ text\ documents\ online=在线查找全文 -Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Hint\:\n\nTo search all fields for Smith, enter\:\nsmith\n\nTo search the field author for Smith and the field title for electrical, enter\:\nauthor\=Smith and title\=electrical Search\ term\ is\ empty.=Search term is empty. Invalid\ regular\ expression.=无效的正则表达式 Searching\ for\ a\ keyword=搜索关键词 @@ -849,7 +818,6 @@ New\ BibTeX\ sublibrary=新建 BibTeX 子文献库 Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=在已知的期刊名简写和全称之间切换。 -the\ field\ %0=字段 %0 The\ group\ "%0"\ already\ contains\ the\ selection.=分组 "%0" 中已经包含选中的项。 The\ output\ option\ depends\ on\ a\ valid\ import\ option.=输出选项依赖于一个合法的导入选项。 @@ -2333,10 +2301,8 @@ Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=全文搜索时 Rebuild\ fulltext\ search\ index=重建全文索引 Rebuild\ fulltext\ search\ index\ for\ current\ library?=是否为当前文献库重建全文索引? Rebuilding\ fulltext\ search\ index...=正在重建全文索引... -Failed\ to\ access\ fulltext\ search\ index=无法访问全文检索索引 Found\ match\ in\ %0=在 %0 找到匹配项 On\ page\ %0=在页面 %0 -Found\ matches\ in\ Annotations\:=在注释中找到匹配项: Fetcher\ cannot\ be\ tested\!=Fetcher cannot be tested\! Fetcher\ unknown\!=Fetcher unknown\! @@ -2412,7 +2378,6 @@ Left\ Entry=Left Entry Merge\ %0=Merge %0 Right\ Entry=Right Entry Unmerge\ %0=Unmerge %0 -plain\ text=纯文本 The\ %0s\ are\ the\ same.\ However,\ the\ order\ of\ field\ content\ differs=The %0s are the same. However, the order of field content differs diff --git a/src/main/resources/l10n/JabRef_zh_TW.properties b/src/main/resources/l10n/JabRef_zh_TW.properties index fd78123f1f1..a7df93ce477 100644 --- a/src/main/resources/l10n/JabRef_zh_TW.properties +++ b/src/main/resources/l10n/JabRef_zh_TW.properties @@ -1,11 +1,4 @@ Unable\ to\ monitor\ file\ changes.\ Please\ close\ files\ and\ processes\ and\ restart.\ You\ may\ encounter\ errors\ if\ you\ continue\ with\ this\ session.=無法監控檔案變更。請關閉文件和程式並重新啟動。如果繼續進行當前操作,可能會發生錯誤。 -%0\ contains\ the\ regular\ expression\ %1=%0 包含正規表達式 %1 - -%0\ contains\ the\ term\ %1=%0 包含字詞 %1 - -%0\ doesn't\ contain\ the\ regular\ expression\ %1=%0 不包含正規表達式 %1 - -%0\ doesn't\ contain\ the\ term\ %1=%0 不包含字詞 %1 %0/%1\ entries=%0/%1 條目 @@ -13,10 +6,6 @@ Export\ operation\ finished\ successfully.=匯出成功。 Reveal\ in\ File\ Explorer=在檔案總管中顯示 -%0\ matches\ the\ regular\ expression\ %1=%0 符合正規表達式 %1 - -%0\ matches\ the\ term\ %1=%0 符合字詞 %1 - Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (DEFAULT\ abbreviation)=縮寫選取條目的期刊名稱(以預設格式縮寫) Abbreviate\ journal\ names\ of\ the\ selected\ entries\ (SHORTEST\ UNIQUE\ abbreviation)=縮寫選取條目的期刊名稱(以 SHORTEST UNIQUE 格式縮寫) @@ -60,10 +49,6 @@ Remove\ string\ %0=移除字串 %0 All\ entries=所有條目 -and=和 - -any\ field\ that\ matches\ the\ regular\ expression\ %0=匹配正規表達式 %0 的任何欄位 - Appearance=外觀設定 Application=應用程式 @@ -105,10 +90,6 @@ Cannot\ create\ group.\ Please\ create\ a\ library\ first.=無法創建群組。 Cannot\ open\ folder\ as\ the\ file\ is\ an\ online\ link.=這個檔案是一個線上連結,因此無法開啟資料夾。 -case\ insensitive=不區分大小寫 - -case\ sensitive=區分大小寫 - Case\ sensitive=區分大小寫 change\ assignment\ of\ entries=修改條目的分發組別 @@ -350,7 +331,6 @@ Imported\ entries=已匯入條目 I\ Agree=我同意 - Invalid\ URL=無效的連結 Online\ help=說明文件 @@ -416,7 +396,6 @@ No\ journal\ names\ could\ be\ abbreviated.=期刊名稱可以縮寫 No\ journal\ names\ could\ be\ unabbreviated.=期刊名稱不可以縮寫 - not\ found=沒有找到 @@ -587,7 +566,6 @@ LaTeX\ AUX\ file\:=LaTeX AUX 檔案: found\ in\ AUX\ file=在 AUX 檔案内找到 -the\ field\ %0=欄位 %0 The\ group\ "%0"\ already\ contains\ the\ selection.=群組「%0」中已經包含選取的內容。 From e801f4117fd62e4f5f42857c7b8d9135a90696fb Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 7 Sep 2024 12:39:53 +0200 Subject: [PATCH 003/324] Enable Slf4jBestPractices (#11714) * Enable Slf4jBestPractices * Remove unused imports --- rewrite.yml | 3 +++ src/main/java/org/jabref/gui/ClipBoardManager.java | 2 +- .../java/org/jabref/gui/FallbackExceptionHandler.java | 2 +- .../java/org/jabref/gui/copyfiles/CopyFilesTask.java | 2 +- .../java/org/jabref/gui/desktop/os/NativeDesktop.java | 2 +- .../org/jabref/gui/entryeditor/RelatedArticlesTab.java | 2 +- .../fileannotationtab/FileAnnotationTabViewModel.java | 2 +- .../gui/exporter/WriteMetadataToLinkedPdfsAction.java | 2 +- src/main/java/org/jabref/gui/icon/IconTheme.java | 3 +-- .../gui/importer/fetcher/LookupIdentifierAction.java | 2 +- .../java/org/jabref/gui/journals/AbbreviateAction.java | 4 ++-- .../gui/linkedfile/DownloadLinkedFileAction.java | 3 +-- .../gui/linkedfile/RedownloadMissingFilesAction.java | 3 +-- .../jabref/gui/maintable/NewLibraryFromPdfAction.java | 2 +- .../ExternalFileTypesTabViewModel.java | 3 +-- .../org/jabref/gui/preview/CopyCitationAction.java | 2 +- .../gui/texparser/ParseLatexDialogViewModel.java | 2 +- src/main/java/org/jabref/gui/theme/StyleSheet.java | 4 ++-- .../ai/ingestion/GenerateEmbeddingsForSeveralTask.java | 2 +- src/main/java/org/jabref/logic/bst/BstVMVisitor.java | 4 ++-- .../java/org/jabref/logic/bst/util/BstCaseChanger.java | 10 +++++----- .../org/jabref/logic/bst/util/BstWidthCalculator.java | 4 ++-- .../org/jabref/logic/citationstyle/CitationStyle.java | 2 +- .../formatter/bibtexfields/HtmlToLatexFormatter.java | 2 +- .../bibtexfields/UnicodeToLatexFormatter.java | 2 +- .../jabref/logic/importer/fetcher/ArXivFetcher.java | 2 +- .../jabref/logic/importer/fetcher/GoogleScholar.java | 2 +- .../jabref/logic/importer/fetcher/MedlineFetcher.java | 3 +-- .../jabref/logic/importer/fetcher/OpenAccessDoi.java | 2 +- .../logic/importer/fileformat/MarcXmlParser.java | 4 ++-- .../logic/importer/fileformat/MrDLibImporter.java | 2 +- .../logic/importer/fileformat/PicaXmlParser.java | 2 +- .../jabref/logic/integrity/LatexIntegrityChecker.java | 2 +- src/main/java/org/jabref/logic/l10n/Localization.java | 2 +- src/main/java/org/jabref/logic/layout/LayoutEntry.java | 4 +--- .../java/org/jabref/logic/layout/format/RTFChars.java | 4 ++-- .../org/jabref/logic/openoffice/backend/Backend52.java | 3 +-- .../java/org/jabref/logic/pdf/FileAnnotationCache.java | 2 +- .../org/jabref/logic/pdf/PdfAnnotationImporter.java | 2 +- .../java/org/jabref/logic/shared/DBMSConnection.java | 2 +- src/main/java/org/jabref/logic/util/io/FileUtil.java | 2 +- src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java | 2 +- .../org/jabref/migrations/PreferencesMigrations.java | 8 ++------ .../java/org/jabref/model/entry/identifier/DOI.java | 2 +- .../org/jabref/model/entry/identifier/IacrEprint.java | 2 +- src/main/java/org/jabref/model/groups/SearchGroup.java | 3 +-- 46 files changed, 59 insertions(+), 69 deletions(-) diff --git a/rewrite.yml b/rewrite.yml index 77e3a3c8bac..3019abef3b9 100644 --- a/rewrite.yml +++ b/rewrite.yml @@ -206,3 +206,6 @@ recipeList: - org.openrewrite.java.testing.junit5.RemoveTryCatchFailBlocks - org.openrewrite.java.testing.junit5.LifecycleNonPrivate - org.openrewrite.java.testing.junit5.StaticImports + + # Logging + - org.openrewrite.java.logging.slf4j.Slf4jBestPractices diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java index 2f66c1e12f9..f135aeab52e 100644 --- a/src/main/java/org/jabref/gui/ClipBoardManager.java +++ b/src/main/java/org/jabref/gui/ClipBoardManager.java @@ -110,7 +110,7 @@ public static String getContentsPrimary() { try { return (String) contents.getTransferData(DataFlavor.stringFlavor); } catch (UnsupportedFlavorException | IOException e) { - LOGGER.warn(e.getMessage()); + LOGGER.warn("", e); } } } diff --git a/src/main/java/org/jabref/gui/FallbackExceptionHandler.java b/src/main/java/org/jabref/gui/FallbackExceptionHandler.java index 25b2f320baa..2f42d2a00a1 100644 --- a/src/main/java/org/jabref/gui/FallbackExceptionHandler.java +++ b/src/main/java/org/jabref/gui/FallbackExceptionHandler.java @@ -19,7 +19,7 @@ public static void installExceptionHandler() { @Override public void uncaughtException(Thread thread, Throwable exception) { - LOGGER.error("Uncaught exception occurred in " + thread, exception); + LOGGER.error("Uncaught exception occurred in {}", thread, exception); UiTaskExecutor.runInJavaFXThread(() -> { DialogService dialogService = Injector.instantiateModelOrService(DialogService.class); dialogService.showErrorDialogAndWait("Uncaught exception occurred in " + thread, exception); diff --git a/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java b/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java index 067b7e948b2..7c895c53bdf 100644 --- a/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java +++ b/src/main/java/org/jabref/gui/copyfiles/CopyFilesTask.java @@ -28,7 +28,7 @@ public class CopyFilesTask extends Task> { - private static final Logger LOGGER = LoggerFactory.getLogger(CopyFilesAction.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CopyFilesTask.class); private static final String LOGFILE_PREFIX = "copyFileslog_"; private static final String LOGFILE_EXT = ".log"; private final BibDatabaseContext databaseContext; diff --git a/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java b/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java index e8c15d35a54..fb8a2b9c521 100644 --- a/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java +++ b/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java @@ -130,7 +130,7 @@ public String getHostName() { try { hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { - LoggerFactory.getLogger(OS.class).info("Hostname not found. Using \"localhost\" as fallback.", e); + LoggerFactory.getLogger(NativeDesktop.class).info("Hostname not found. Using \"localhost\" as fallback.", e); hostName = "localhost"; } } diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index ddedc7fc75e..ac2851847eb 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -146,7 +146,7 @@ private ScrollPane getRelatedArticleInfo(List list, MrDLibFetcher fetc try { JabRefDesktop.openBrowser(entry.getField(StandardField.URL).get(), preferencesService.getFilePreferences()); } catch (IOException e) { - LOGGER.error("Error opening the browser to: " + entry.getField(StandardField.URL).get(), e); + LOGGER.error("Error opening the browser to: {}", entry.getField(StandardField.URL).get(), e); dialogService.showErrorDialogAndWait(e); } } diff --git a/src/main/java/org/jabref/gui/entryeditor/fileannotationtab/FileAnnotationTabViewModel.java b/src/main/java/org/jabref/gui/entryeditor/fileannotationtab/FileAnnotationTabViewModel.java index e5135c67cdc..28fe4f1a27f 100644 --- a/src/main/java/org/jabref/gui/entryeditor/fileannotationtab/FileAnnotationTabViewModel.java +++ b/src/main/java/org/jabref/gui/entryeditor/fileannotationtab/FileAnnotationTabViewModel.java @@ -97,7 +97,7 @@ public void notifyNewSelectedFile(Path newFile) { try { fileMonitor.addListenerForFile(currentFile, fileListener); } catch (IOException e) { - LOGGER.error("Problem while watching file for changes " + currentFile, e); + LOGGER.error("Problem while watching file for changes {}", currentFile, e); } } diff --git a/src/main/java/org/jabref/gui/exporter/WriteMetadataToLinkedPdfsAction.java b/src/main/java/org/jabref/gui/exporter/WriteMetadataToLinkedPdfsAction.java index 95f8eb2c7d0..7f864cf3597 100644 --- a/src/main/java/org/jabref/gui/exporter/WriteMetadataToLinkedPdfsAction.java +++ b/src/main/java/org/jabref/gui/exporter/WriteMetadataToLinkedPdfsAction.java @@ -198,7 +198,7 @@ protected Void call() throws Exception { String.valueOf(entriesChanged), String.valueOf(skipped), String.valueOf(errors))); if (!failedWrittenFiles.isEmpty()) { - LOGGER.error("Failed to write XMP data to PDFs:\n" + failedWrittenFiles); + LOGGER.error("Failed to write XMP data to PDFs:\n{}", failedWrittenFiles); } return null; diff --git a/src/main/java/org/jabref/gui/icon/IconTheme.java b/src/main/java/org/jabref/gui/icon/IconTheme.java index 099c2c7b2cc..0cd33366896 100644 --- a/src/main/java/org/jabref/gui/icon/IconTheme.java +++ b/src/main/java/org/jabref/gui/icon/IconTheme.java @@ -107,8 +107,7 @@ private static Image getImageFX(String name) { public static URL getIconUrl(String name) { String key = Objects.requireNonNull(name, "icon name"); if (!KEY_TO_ICON.containsKey(key)) { - LOGGER.warn("Could not find icon url by name " + name + ", so falling back on default icon " - + DEFAULT_ICON_PATH); + LOGGER.warn("Could not find icon url by name {}, so falling back on default icon {}", name, DEFAULT_ICON_PATH); } String path = KEY_TO_ICON.getOrDefault(key, DEFAULT_ICON_PATH); return Objects.requireNonNull(IconTheme.class.getResource(path), "Path must not be null for key " + key); diff --git a/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java b/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java index 94342c93219..366461f30fa 100644 --- a/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java +++ b/src/main/java/org/jabref/gui/importer/fetcher/LookupIdentifierAction.java @@ -82,7 +82,7 @@ private String lookupIdentifiers(List bibEntries) { try { identifier = fetcher.findIdentifier(bibEntry); } catch (FetcherException e) { - LOGGER.error("Could not fetch " + fetcher.getIdentifierName(), e); + LOGGER.error("Could not fetch {}", fetcher.getIdentifierName(), e); } if (identifier.isPresent() && !bibEntry.hasField(identifier.get().getDefaultField())) { Optional fieldChange = bibEntry.setField(identifier.get().getDefaultField(), identifier.get().getNormalized()); diff --git a/src/main/java/org/jabref/gui/journals/AbbreviateAction.java b/src/main/java/org/jabref/gui/journals/AbbreviateAction.java index d293fc1c9c2..5b2698a68e9 100644 --- a/src/main/java/org/jabref/gui/journals/AbbreviateAction.java +++ b/src/main/java/org/jabref/gui/journals/AbbreviateAction.java @@ -69,7 +69,7 @@ public AbbreviateAction(StandardActions action, case ABBREVIATE_DEFAULT -> abbreviationType = AbbreviationType.DEFAULT; case ABBREVIATE_DOTLESS -> abbreviationType = AbbreviationType.DOTLESS; case ABBREVIATE_SHORTEST_UNIQUE -> abbreviationType = AbbreviationType.SHORTEST_UNIQUE; - default -> LOGGER.debug("Unknown action: " + action.name()); + default -> LOGGER.debug("Unknown action: {}", action.name()); } this.executable.bind(ActionHelper.needsEntriesSelected(stateManager)); @@ -92,7 +92,7 @@ public void execute() { .onSuccess(dialogService::notify) .executeWith(taskExecutor)); } else { - LOGGER.debug("Unknown action: " + action.name()); + LOGGER.debug("Unknown action: {}", action.name()); } } diff --git a/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java b/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java index 54695f9577b..490da28bdca 100644 --- a/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java +++ b/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java @@ -20,7 +20,6 @@ import javafx.beans.property.SimpleDoubleProperty; import org.jabref.gui.DialogService; -import org.jabref.gui.LibraryTab; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; @@ -48,7 +47,7 @@ public class DownloadLinkedFileAction extends SimpleCommand { - private static final Logger LOGGER = LoggerFactory.getLogger(LibraryTab.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DownloadLinkedFileAction.class); private final DialogService dialogService; private final BibEntry entry; diff --git a/src/main/java/org/jabref/gui/linkedfile/RedownloadMissingFilesAction.java b/src/main/java/org/jabref/gui/linkedfile/RedownloadMissingFilesAction.java index 3a69061b10f..53b6f7ae29d 100644 --- a/src/main/java/org/jabref/gui/linkedfile/RedownloadMissingFilesAction.java +++ b/src/main/java/org/jabref/gui/linkedfile/RedownloadMissingFilesAction.java @@ -5,7 +5,6 @@ import java.util.Optional; import org.jabref.gui.DialogService; -import org.jabref.gui.LibraryTab; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.util.TaskExecutor; @@ -21,7 +20,7 @@ public class RedownloadMissingFilesAction extends SimpleCommand { - private static final Logger LOGGER = LoggerFactory.getLogger(LibraryTab.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RedownloadMissingFilesAction.class); private final StateManager stateManager; private final DialogService dialogService; diff --git a/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java index dc872022ffc..aa953498bd4 100644 --- a/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java +++ b/src/main/java/org/jabref/gui/maintable/NewLibraryFromPdfAction.java @@ -28,7 +28,7 @@ * */ public abstract class NewLibraryFromPdfAction extends SimpleCommand { - private static final Logger LOGGER = LoggerFactory.getLogger(NewLibraryFromPdfAction .class); + private static final Logger LOGGER = LoggerFactory.getLogger(NewLibraryFromPdfAction.class); protected final PreferencesService preferencesService; diff --git a/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java b/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java index faacc66b978..65d2b28a780 100644 --- a/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/externalfiletypes/ExternalFileTypesTabViewModel.java @@ -8,7 +8,6 @@ import javafx.collections.ObservableList; import org.jabref.gui.DialogService; -import org.jabref.gui.exporter.CreateModifyExporterDialogViewModel; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.preferences.PreferenceTabViewModel; @@ -20,7 +19,7 @@ public class ExternalFileTypesTabViewModel implements PreferenceTabViewModel { - private static final Logger LOGGER = LoggerFactory.getLogger(CreateModifyExporterDialogViewModel.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ExternalFileTypesTabViewModel.class); private final ObservableList fileTypes = FXCollections.observableArrayList(); private final FilePreferences filePreferences; diff --git a/src/main/java/org/jabref/gui/preview/CopyCitationAction.java b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java index dd67b61d861..175aa1f490c 100644 --- a/src/main/java/org/jabref/gui/preview/CopyCitationAction.java +++ b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java @@ -170,7 +170,7 @@ private void setClipBoardContent(List citations) { case HTML -> content = processHtml(citations); case TEXT -> content = processText(citations); default -> { - LOGGER.warn("unknown output format: '" + outputFormat + "', processing it via the default."); + LOGGER.warn("unknown output format: '{}', processing it via the default.", outputFormat); content = processText(citations); } } diff --git a/src/main/java/org/jabref/gui/texparser/ParseLatexDialogViewModel.java b/src/main/java/org/jabref/gui/texparser/ParseLatexDialogViewModel.java index 257c5e797d3..afa92a56a93 100644 --- a/src/main/java/org/jabref/gui/texparser/ParseLatexDialogViewModel.java +++ b/src/main/java/org/jabref/gui/texparser/ParseLatexDialogViewModel.java @@ -162,7 +162,7 @@ private FileNodeViewModel searchDirectory(Path directory) throws IOException { try (Stream filesStream = Files.list(directory)) { fileListPartition = filesStream.collect(Collectors.partitioningBy(path -> path.toFile().isDirectory())); } catch (IOException e) { - LOGGER.error("%s while searching files: %s".formatted(e.getClass().getName(), e.getMessage())); + LOGGER.error("%s while searching files: %s".formatted(e.getClass().getName(), e.getMessage()), e); return parent; } diff --git a/src/main/java/org/jabref/gui/theme/StyleSheet.java b/src/main/java/org/jabref/gui/theme/StyleSheet.java index 63db7bcacf1..19ff00a2333 100644 --- a/src/main/java/org/jabref/gui/theme/StyleSheet.java +++ b/src/main/java/org/jabref/gui/theme/StyleSheet.java @@ -40,9 +40,9 @@ static Optional create(String name) { try { styleSheetUrl = Optional.of(Path.of(name).toUri().toURL()); } catch (InvalidPathException e) { - LOGGER.warn("Cannot load additional css {} because it is an invalid path: {}", name, e.getLocalizedMessage()); + LOGGER.warn("Cannot load additional css {} because it is an invalid path: {}", name, e.getLocalizedMessage(), e); } catch (MalformedURLException e) { - LOGGER.warn("Cannot load additional css url {} because it is a malformed url: {}", name, e.getLocalizedMessage()); + LOGGER.warn("Cannot load additional css url {} because it is a malformed url: {}", name, e.getLocalizedMessage(), e); } } diff --git a/src/main/java/org/jabref/logic/ai/ingestion/GenerateEmbeddingsForSeveralTask.java b/src/main/java/org/jabref/logic/ai/ingestion/GenerateEmbeddingsForSeveralTask.java index 43a0c813e7d..e1846d897e8 100644 --- a/src/main/java/org/jabref/logic/ai/ingestion/GenerateEmbeddingsForSeveralTask.java +++ b/src/main/java/org/jabref/logic/ai/ingestion/GenerateEmbeddingsForSeveralTask.java @@ -27,7 +27,7 @@ * And it also will store the embeddings. */ public class GenerateEmbeddingsForSeveralTask extends BackgroundTask { - private static final Logger LOGGER = LoggerFactory.getLogger(GenerateEmbeddingsTask.class); + private static final Logger LOGGER = LoggerFactory.getLogger(GenerateEmbeddingsForSeveralTask.class); private final StringProperty name; private final List> linkedFiles; diff --git a/src/main/java/org/jabref/logic/bst/BstVMVisitor.java b/src/main/java/org/jabref/logic/bst/BstVMVisitor.java index a5ac46b6bf1..f2b64ae45f4 100644 --- a/src/main/java/org/jabref/logic/bst/BstVMVisitor.java +++ b/src/main/java/org/jabref/logic/bst/BstVMVisitor.java @@ -273,8 +273,8 @@ public Integer visitStackitem(BstParser.StackitemContext ctx) { } } catch (BstVMException e) { bstVMContext.path().ifPresentOrElse( - path -> LOGGER.error("{} ({})", e.getMessage(), path), - () -> LOGGER.error(e.getMessage())); + path -> LOGGER.error("{} ({})", e.getMessage(), path, e), + () -> LOGGER.error("", e)); throw e; } } diff --git a/src/main/java/org/jabref/logic/bst/util/BstCaseChanger.java b/src/main/java/org/jabref/logic/bst/util/BstCaseChanger.java index dd3e7c7b05c..1af4472c263 100644 --- a/src/main/java/org/jabref/logic/bst/util/BstCaseChanger.java +++ b/src/main/java/org/jabref/logic/bst/util/BstCaseChanger.java @@ -110,7 +110,7 @@ private String doChangeCase(String s, FormatMode format) { sb.append(c[i]); i++; if (braceLevel == 0) { - LOGGER.warn("Too many closing braces in string: " + s); + LOGGER.warn("Too many closing braces in string: {}", s); } else { braceLevel--; } @@ -125,7 +125,7 @@ private String doChangeCase(String s, FormatMode format) { i++; } if (braceLevel > 0) { - LOGGER.warn("No enough closing braces in string: " + s); + LOGGER.warn("No enough closing braces in string: {}", s); } return sb.toString(); } @@ -204,7 +204,7 @@ private int convertAccented(char[] c, int start, String s, StringBuilder sb, For } break; default: - LOGGER.info("convertAccented - Unknown format: " + format); + LOGGER.info("convertAccented - Unknown format: {}", format); break; } return pos; @@ -222,7 +222,7 @@ private int convertNonControl(char[] c, int start, StringBuilder sb, FormatMode pos++; } default -> - LOGGER.info("convertNonControl - Unknown format: " + format); + LOGGER.info("convertNonControl - Unknown format: {}", format); } return pos; } @@ -247,7 +247,7 @@ private int convertCharIfBraceLevelIsZero(char[] c, int start, StringBuilder sb, case ALL_UPPERS -> sb.append(Character.toUpperCase(c[i])); default -> - LOGGER.info("convertCharIfBraceLevelIsZero - Unknown format: " + format); + LOGGER.info("convertCharIfBraceLevelIsZero - Unknown format: {}", format); } i++; return i; diff --git a/src/main/java/org/jabref/logic/bst/util/BstWidthCalculator.java b/src/main/java/org/jabref/logic/bst/util/BstWidthCalculator.java index c286fe1497b..873b75cebb8 100644 --- a/src/main/java/org/jabref/logic/bst/util/BstWidthCalculator.java +++ b/src/main/java/org/jabref/logic/bst/util/BstWidthCalculator.java @@ -227,14 +227,14 @@ public static int width(String toMeasure) { if (braceLevel > 0) { braceLevel--; } else { - LOGGER.warn("Too many closing braces in string: " + toMeasure); + LOGGER.warn("Too many closing braces in string: {}", toMeasure); } } result += BstWidthCalculator.getCharWidth(c[i]); i++; } if (braceLevel > 0) { - LOGGER.warn("No enough closing braces in string: " + toMeasure); + LOGGER.warn("No enough closing braces in string: {}", toMeasure); } return result; } diff --git a/src/main/java/org/jabref/logic/citationstyle/CitationStyle.java b/src/main/java/org/jabref/logic/citationstyle/CitationStyle.java index 2da81dd1d54..649a925e63b 100644 --- a/src/main/java/org/jabref/logic/citationstyle/CitationStyle.java +++ b/src/main/java/org/jabref/logic/citationstyle/CitationStyle.java @@ -124,7 +124,7 @@ static Optional parseStyleInfo(String filename, String content) { return Optional.empty(); } } catch (XMLStreamException e) { - LOGGER.error("Error parsing XML for file {}: {}", filename, e.getMessage()); + LOGGER.error("Error parsing XML for file {}: {}", filename, e.getMessage(), e); return Optional.empty(); } } diff --git a/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java b/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java index fef72df2c78..735513f9cd6 100644 --- a/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java +++ b/src/main/java/org/jabref/logic/formatter/bibtexfields/HtmlToLatexFormatter.java @@ -106,7 +106,7 @@ public String format(String text) { // Find non-covered special characters with alphabetic codes m = ESCAPED_PATTERN4.matcher(result); while (m.find()) { - LOGGER.warn("HTML escaped char not converted: " + m.group(1)); + LOGGER.warn("HTML escaped char not converted: {}", m.group(1)); } return result.trim(); diff --git a/src/main/java/org/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java b/src/main/java/org/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java index e93825d2954..d1ffcbc66d9 100644 --- a/src/main/java/org/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java +++ b/src/main/java/org/jabref/logic/formatter/bibtexfields/UnicodeToLatexFormatter.java @@ -63,7 +63,7 @@ public String format(String text) { for (int i = 0; i <= (result.length() - 1); i++) { int cp = result.codePointAt(i); if (cp >= 129) { - LOGGER.warn("Unicode character not converted: " + cp); + LOGGER.warn("Unicode character not converted: {}", cp); } } return result; diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java index cf487d4ec6b..0c17ff5e283 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java @@ -392,7 +392,7 @@ public String getIdentifierName() { */ protected class ArXiv implements FulltextFetcher, PagedSearchBasedFetcher, IdBasedFetcher, IdFetcher { - private static final Logger LOGGER = LoggerFactory.getLogger(ArXivFetcher.ArXiv.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ArXiv.class); private static final String API_URL = "https://export.arxiv.org/api/query"; diff --git a/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java b/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java index f0461e8338e..c9a6d54cc7d 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/GoogleScholar.java @@ -106,7 +106,7 @@ private Optional search(String url) throws IOException { if (!target.isEmpty() && new URLDownload(target).isPdf()) { // TODO: check title inside pdf + length? // TODO: report error function needed?! query -> result - LOGGER.info("Fulltext PDF found @ Google: " + target); + LOGGER.info("Fulltext PDF found @ Google: {}", target); pdfLink = Optional.of(new URL(target)); break; } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MedlineFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MedlineFetcher.java index a3444ad3530..1ff01428aa6 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MedlineFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MedlineFetcher.java @@ -204,8 +204,7 @@ public List performSearch(QueryNode luceneQuery) throws FetcherExcepti return Collections.emptyList(); } if (numberOfResultsFound > NUMBER_TO_FETCH) { - LOGGER.info( - numberOfResultsFound + " results found. Only 50 relevant results will be fetched by default."); + LOGGER.info("{} results found. Only 50 relevant results will be fetched by default.", numberOfResultsFound); } // pass the list of ids to fetchMedline to download them. like a id fetcher for mutliple ids diff --git a/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java b/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java index 740bc3f0a86..4469361b3cb 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/OpenAccessDoi.java @@ -24,7 +24,7 @@ * API is documented at http://unpaywall.org/api/v2 */ public class OpenAccessDoi implements FulltextFetcher { - private static final Logger LOGGER = LoggerFactory.getLogger(FulltextFetcher.class); + private static final Logger LOGGER = LoggerFactory.getLogger(OpenAccessDoi.class); private static final String API_URL = "https://api.oadoi.org/v2/"; diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java b/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java index 3a219afe2c7..df46c0e15e9 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MarcXmlParser.java @@ -95,7 +95,7 @@ private BibEntry parseEntry(Element element) { List datafields = getChildren("datafield", element); for (Element datafield : datafields) { String tag = datafield.getAttribute("tag"); - LOGGER.debug("tag: " + tag); + LOGGER.debug("tag: {}", tag); if ("020".equals(tag)) { putIsbn(bibEntry, datafield); @@ -146,7 +146,7 @@ private void putIsbn(BibEntry bibEntry, Element datafield) { int length = isbn.length(); if (length != 10 && length != 13) { - LOGGER.debug("Malformed ISBN recieved, length: " + length); + LOGGER.debug("Malformed ISBN recieved, length: {}", length); return; } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index 8d21d2465e1..a97bae7d049 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -83,7 +83,7 @@ private String convertToString(BufferedReader input) { stringBuilder.append(line); } } catch (Exception e) { - LOGGER.error(e.getMessage()); + LOGGER.error("", e); } return stringBuilder.toString(); } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PicaXmlParser.java b/src/main/java/org/jabref/logic/importer/fileformat/PicaXmlParser.java index 481d2811b63..ed5e89dd8a9 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PicaXmlParser.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PicaXmlParser.java @@ -98,7 +98,7 @@ private BibEntry parseEntry(Element e) { List datafields = getChildren("datafield", e); for (Element datafield : datafields) { String tag = datafield.getAttribute("tag"); - LOGGER.debug("tag: " + tag); + LOGGER.debug("tag: {}", tag); // genre/type of the entry https://swbtools.bsz-bw.de/cgi-bin/k10plushelp.pl?cmd=kat&val=0500&katalog=Standard if ("002@".equals(tag)) { diff --git a/src/main/java/org/jabref/logic/integrity/LatexIntegrityChecker.java b/src/main/java/org/jabref/logic/integrity/LatexIntegrityChecker.java index b12dfadbf04..d2de418349c 100644 --- a/src/main/java/org/jabref/logic/integrity/LatexIntegrityChecker.java +++ b/src/main/java/org/jabref/logic/integrity/LatexIntegrityChecker.java @@ -37,7 +37,7 @@ */ public class LatexIntegrityChecker implements EntryChecker { - private static final Logger LOGGER = LoggerFactory.getLogger(SnuggleSession.class); + private static final Logger LOGGER = LoggerFactory.getLogger(LatexIntegrityChecker.class); private static final SnuggleEngine ENGINE = new SnuggleEngine(); private static final SnuggleSession SESSION; private static final ResourceBundle ERROR_MESSAGES = ENGINE.getPackages().getFirst().getErrorMessageBundle(); diff --git a/src/main/java/org/jabref/logic/l10n/Localization.java b/src/main/java/org/jabref/logic/l10n/Localization.java index 75a2c7e91e2..c5dcacc5cf5 100644 --- a/src/main/java/org/jabref/logic/l10n/Localization.java +++ b/src/main/java/org/jabref/logic/l10n/Localization.java @@ -84,7 +84,7 @@ public static void setLanguage(Language language) { createResourceBundles(locale); } catch (MissingResourceException ex) { // should not happen as we have scripts to enforce this - LoggerFactory.getLogger(Localization.class).warn("Could not find bundles for language " + locale + ", switching to full english language", ex); + LoggerFactory.getLogger(Localization.class).warn("Could not find bundles for language {}, switching to full english language", locale, ex); setLanguage(Language.ENGLISH); } } diff --git a/src/main/java/org/jabref/logic/layout/LayoutEntry.java b/src/main/java/org/jabref/logic/layout/LayoutEntry.java index 7d0cf3d3a4d..5ea2222e4c8 100644 --- a/src/main/java/org/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/org/jabref/logic/layout/LayoutEntry.java @@ -236,9 +236,7 @@ private String handleOptionField(BibEntry bibtex, BibDatabase database) { if (InternalField.TYPE_HEADER.getName().equals(text)) { fieldEntry = bibtex.getType().getDisplayName(); } else if (InternalField.OBSOLETE_TYPE_HEADER.getName().equals(text)) { - LOGGER.warn("'" + InternalField.OBSOLETE_TYPE_HEADER - + "' is an obsolete name for the entry type. Please update your layout to use '" - + InternalField.TYPE_HEADER + "' instead."); + LOGGER.warn("'{}' is an obsolete name for the entry type. Please update your layout to use '{}' instead.", InternalField.OBSOLETE_TYPE_HEADER, InternalField.TYPE_HEADER); fieldEntry = bibtex.getType().getDisplayName(); } else { // changed section begin - arudert diff --git a/src/main/java/org/jabref/logic/layout/format/RTFChars.java b/src/main/java/org/jabref/logic/layout/format/RTFChars.java index 48e30d5167e..649e85b7ba3 100644 --- a/src/main/java/org/jabref/logic/layout/format/RTFChars.java +++ b/src/main/java/org/jabref/logic/layout/format/RTFChars.java @@ -25,7 +25,7 @@ */ public class RTFChars implements LayoutFormatter { - private static final Logger LOGGER = LoggerFactory.getLogger(LayoutFormatter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RTFChars.class); private static final RtfCharMap RTF_CHARS = new RtfCharMap(); @@ -130,7 +130,7 @@ public String format(String field) { i += part.i; sb.append("{\\b ").append(part.s).append('}'); } else { - LOGGER.info("Unknown command " + command); + LOGGER.info("Unknown command {}", command); } if (c == ' ') { // command was separated with the content by ' ' diff --git a/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java b/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java index 47ed61a31ec..a07ceda0734 100644 --- a/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java +++ b/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java @@ -199,8 +199,7 @@ public CitationGroup createCitationGroup(XTextDocument doc, cit.setPageInfo(pageInfo); } else { if (pageInfo.isPresent()) { - LOGGER.warn("dataModel JabRef52" - + " only supports pageInfo for the last citation of a group"); + LOGGER.warn("dataModel JabRef52" + " only supports pageInfo for the last citation of a group"); } } break; diff --git a/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java b/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java index e29482abf1d..a9becd355ca 100644 --- a/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java +++ b/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java @@ -17,7 +17,7 @@ public class FileAnnotationCache { - private static final Logger LOGGER = LoggerFactory.getLogger(FileAnnotation.class); + private static final Logger LOGGER = LoggerFactory.getLogger(FileAnnotationCache.class); // cache size in entries private final static int CACHE_SIZE = 10; diff --git a/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java b/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java index 26c97e1469b..0dadd01e019 100644 --- a/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java +++ b/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java @@ -72,7 +72,7 @@ private boolean isSupportedAnnotationType(PDAnnotation annotation) { return false; } if ("Link".equals(annotation.getSubtype()) || "Widget".equals(annotation.getSubtype())) { - LOGGER.debug(annotation.getSubtype() + " is excluded from the supported file annotations"); + LOGGER.debug("{} is excluded from the supported file annotations", annotation.getSubtype()); return false; } try { diff --git a/src/main/java/org/jabref/logic/shared/DBMSConnection.java b/src/main/java/org/jabref/logic/shared/DBMSConnection.java index a01f83a8481..2d1438f6136 100644 --- a/src/main/java/org/jabref/logic/shared/DBMSConnection.java +++ b/src/main/java/org/jabref/logic/shared/DBMSConnection.java @@ -39,7 +39,7 @@ public DBMSConnection(DBMSConnectionProperties connectionProperties) throws SQLE } catch (SQLException e) { // Some systems like PostgreSQL retrieves 0 to every exception. // Therefore a stable error determination is not possible. - LOGGER.error("Could not connect to database: {} - Error code: {}", e.getMessage(), e.getErrorCode()); + LOGGER.error("Could not connect to database: {} - Error code: {}", e.getMessage(), e.getErrorCode(), e); throw e; } } diff --git a/src/main/java/org/jabref/logic/util/io/FileUtil.java b/src/main/java/org/jabref/logic/util/io/FileUtil.java index b2bd50dbfaa..e128beb06b8 100644 --- a/src/main/java/org/jabref/logic/util/io/FileUtil.java +++ b/src/main/java/org/jabref/logic/util/io/FileUtil.java @@ -366,7 +366,7 @@ public static Optional findSingleFileRecursively(String filename, Path roo .filter(f -> f.getFileName().toString().equals(filename)) .findFirst(); } catch (UncheckedIOException | IOException ex) { - LOGGER.error("Error trying to locate the file " + filename + " inside the directory " + rootDirectory); + LOGGER.error("Error trying to locate the file {} inside the directory {}", filename, rootDirectory); } return Optional.empty(); } diff --git a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java index 34f447edb0f..cf329b15fb7 100644 --- a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java +++ b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java @@ -181,7 +181,7 @@ private String generateXmpStringWithXmpDeclaration(List entries) { serializer.serialize(meta, os, true); return os.toString(StandardCharsets.UTF_8); } catch (TransformerException e) { - LOGGER.warn("Transformation into XMP not possible: " + e.getMessage(), e); + LOGGER.warn("Transformation into XMP not possible: {}", e.getMessage(), e); return ""; } catch (UnsupportedEncodingException e) { LOGGER.warn("Unsupported encoding to UTF-8 of bib entries in XMP metadata.", e); diff --git a/src/main/java/org/jabref/migrations/PreferencesMigrations.java b/src/main/java/org/jabref/migrations/PreferencesMigrations.java index b5b19344f51..62c1dbfb632 100644 --- a/src/main/java/org/jabref/migrations/PreferencesMigrations.java +++ b/src/main/java/org/jabref/migrations/PreferencesMigrations.java @@ -242,18 +242,14 @@ private static void migrateFileImportPattern(String oldStylePattern, String newS oldStylePattern.equals(preferenceFileNamePattern)) { // Upgrade the old-style File Name pattern to new one: mainPrefsNode.put(JabRefPreferences.IMPORT_FILENAMEPATTERN, newStylePattern); - LOGGER.info("migrated old style " + JabRefPreferences.IMPORT_FILENAMEPATTERN + - " value \"" + oldStylePattern + "\" to new value \"" + - newStylePattern + "\" in the preference file"); + LOGGER.info("migrated old style {} value \"{}\" to new value \"{}\" in the preference file", JabRefPreferences.IMPORT_FILENAMEPATTERN, oldStylePattern, newStylePattern); if (prefs.hasKey(JabRefPreferences.IMPORT_FILENAMEPATTERN)) { // Update also the key in the current application settings, if necessary: String fileNamePattern = prefs.get(JabRefPreferences.IMPORT_FILENAMEPATTERN); if (oldStylePattern.equals(fileNamePattern)) { prefs.put(JabRefPreferences.IMPORT_FILENAMEPATTERN, newStylePattern); - LOGGER.info("migrated old style " + JabRefPreferences.IMPORT_FILENAMEPATTERN + - " value \"" + oldStylePattern + "\" to new value \"" + - newStylePattern + "\" in the running application"); + LOGGER.info("migrated old style {} value \"{}\" to new value \"{}\" in the running application", JabRefPreferences.IMPORT_FILENAMEPATTERN, oldStylePattern, newStylePattern); } } } diff --git a/src/main/java/org/jabref/model/entry/identifier/DOI.java b/src/main/java/org/jabref/model/entry/identifier/DOI.java index 0cead0708a7..a8c0f7533c0 100644 --- a/src/main/java/org/jabref/model/entry/identifier/DOI.java +++ b/src/main/java/org/jabref/model/entry/identifier/DOI.java @@ -268,7 +268,7 @@ public Optional getExternalURIFromBase(URI base) { return Optional.of(uri); } catch (URISyntaxException e) { // should never happen - LOGGER.error(doi + " could not be encoded as URI.", e); + LOGGER.error("{} could not be encoded as URI.", doi, e); return Optional.empty(); } } diff --git a/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java b/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java index c385b9316ab..165596e2020 100644 --- a/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java +++ b/src/main/java/org/jabref/model/entry/identifier/IacrEprint.java @@ -66,7 +66,7 @@ public Optional getExternalURI() { return Optional.of(uri); } catch (URISyntaxException e) { // should never happen - LOGGER.error(iacrEprint + " could not be encoded as URI.", e); + LOGGER.error("{} could not be encoded as URI.", iacrEprint, e); return Optional.empty(); } } diff --git a/src/main/java/org/jabref/model/groups/SearchGroup.java b/src/main/java/org/jabref/model/groups/SearchGroup.java index 9823ae5a7e8..e366f8c6d83 100644 --- a/src/main/java/org/jabref/model/groups/SearchGroup.java +++ b/src/main/java/org/jabref/model/groups/SearchGroup.java @@ -91,8 +91,7 @@ public AbstractGroup deepCopy() { } catch (Throwable t) { // this should never happen, because the constructor obviously // succeeded in creating _this_ instance! - LOGGER.error("Internal error in SearchGroup.deepCopy(). " - + "Please report this on https://github.com/JabRef/jabref/issues", t); + LOGGER.error("Internal error in SearchGroup.deepCopy(). " + "Please report this on https://github.com/JabRef/jabref/issues", t); return null; } } From bcbe126f5df732fed3ad80bf6490434539522eca Mon Sep 17 00:00:00 2001 From: Subhramit Basu Bhowmick Date: Sat, 7 Sep 2024 18:01:41 +0530 Subject: [PATCH 004/324] [IMP] Add re-distribution of numeric CSL citations (#11712) * Initial commit * Semi-fix: 0-based index * add method for getting multiple citations * Use XTextRangeCompare * Fix update order * Remove dead code, undo ai refactor changes * Fix remaining order issues, Remove dead code, undo ai refactor changes * Restore exceptions: UpdateCSLBibliography * Refine * Fix checkstyle * Remove experiment * Fix OOBibBase.java exceptions * Fix OpenOfficePanel.java exceptions * Fix adapter exception indent * Fix adapter exception order * Restore javadoc * Restore javadoc, remove dead code * Remove dead code * Improve implementation (general changes) * Change printStackTrace->Logger * Fix readExistingMarks() * Remove logs * Finish CSLReferenceMarkManager * openRewrite * fix unit test (std streams -> logger) * Redundant log * Safety, refactoring * Add log * Better log * Change log level (non-breaking) * Add handling for multiple entries * Better log * Restore javadoc * Restore javadoc * Use list instead of singleton * Adapt test * Add comment * Add stricter conditions for update * Add stricter conditions for reading * Make xtextcompare final * Null handling * Update javadoc * Refactor * Remove redundant condition * Fix non-numeric side effect * Enhance implementation * Add newline * Bug fix: no sync in refresh bibliography * fix logger openrewrite --------- Co-authored-by: Siedlerchr --- .../org/jabref/gui/openoffice/OOBibBase.java | 28 +-- .../gui/preview/CopyCitationAction.java | 2 +- .../logic/citationstyle/CSLAdapter.java | 6 +- .../citationstyle/CitationStyleGenerator.java | 18 +- .../CitationStylePreviewLayout.java | 2 +- .../logic/openoffice/ReferenceMark.java | 80 ++++--- .../oocsltext/CSLCitationOOAdapter.java | 58 ++--- .../openoffice/oocsltext/CSLFormatUtils.java | 6 +- .../oocsltext/CSLReferenceMark.java | 66 +++-- .../oocsltext/CSLReferenceMarkManager.java | 226 ++++++++++++++---- .../oocsltext/CSLUpdateBibliography.java | 5 +- .../CitationStyleGeneratorTest.java | 26 +- .../citationstyle/CitationStyleTest.java | 2 +- .../logic/openoffice/ReferenceMarkTest.java | 29 ++- .../oocsltext/CSLFormatUtilsTest.java | 16 +- 15 files changed, 375 insertions(+), 195 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index 2a19cfe7149..40a37a69d9f 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -87,8 +87,8 @@ public OOBibBase(Path loPath, DialogService dialogService) } private void initializeCitationAdapter(XTextDocument doc) throws WrappedTargetException, NoSuchElementException { - this.cslCitationOOAdapter = new CSLCitationOOAdapter(doc); - this.cslCitationOOAdapter.readExistingMarks(); + this.cslCitationOOAdapter = new CSLCitationOOAdapter(doc); + this.cslCitationOOAdapter.readAndUpdateExistingMarks(); } public void guiActionSelectDocument(boolean autoSelectForSingle) throws WrappedTargetException, NoSuchElementException { @@ -161,9 +161,9 @@ void showDialog(String errorTitle, OOError err) { OOVoidResult collectResults(String errorTitle, List> results) { String msg = results.stream() - .filter(OOVoidResult::isError) - .map(e -> e.getError().getLocalizedMessage()) - .collect(Collectors.joining("\n\n")); + .filter(OOVoidResult::isError) + .map(e -> e.getError().getLocalizedMessage()) + .collect(Collectors.joining("\n\n")); if (msg.isEmpty()) { return OOVoidResult.ok(); } else { @@ -233,10 +233,10 @@ private static OOVoidResult checkRangeOverlaps(XTextDocument doc, OOFro int maxReportedOverlaps = 10; try { return frontend.checkRangeOverlaps(doc, - new ArrayList<>(), - requireSeparation, - maxReportedOverlaps) - .mapError(OOError::from); + new ArrayList<>(), + requireSeparation, + maxReportedOverlaps) + .mapError(OOError::from); } catch (NoDocumentException ex) { return OOVoidResult.error(OOError.from(ex).setTitle(errorTitle)); } catch (WrappedTargetException ex) { @@ -322,7 +322,7 @@ OOResult getFrontend(XTextDocument doc) { } catch (NoDocumentException ex) { return OOResult.error(OOError.from(ex).setTitle(errorTitle)); } catch (WrappedTargetException - | RuntimeException ex) { + | RuntimeException ex) { return OOResult.error(OOError.fromMisc(ex).setTitle(errorTitle)); } } @@ -601,7 +601,7 @@ public void guiActionInsertEntry(List entries, this.cslCitationOOAdapter.insertInTextCitation(cursor.get(), citationStyle, entries, bibDatabaseContext, bibEntryTypesManager); } else if (citationType == CitationType.INVISIBLE_CIT) { // "Insert empty citation" - this.cslCitationOOAdapter.insertEmpty(cursor.get(), entries); + this.cslCitationOOAdapter.insertEmpty(cursor.get(), citationStyle, entries); } // If "Automatically sync bibliography when inserting citations" is enabled @@ -813,7 +813,7 @@ public Optional exportCitedHelper(List databases, bool } catch (DisposedException ex) { OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); } catch (WrappedTargetException - | com.sun.star.lang.IllegalArgumentException ex) { + | com.sun.star.lang.IllegalArgumentException ex) { LOGGER.warn("Problem generating new database.", ex); OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); } @@ -881,8 +881,8 @@ public void guiActionUpdateDocument(List databases, OOStyle style) } catch (DisposedException ex) { OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); } catch (CreationException - | WrappedTargetException - | com.sun.star.lang.IllegalArgumentException ex) { + | WrappedTargetException + | com.sun.star.lang.IllegalArgumentException ex) { LOGGER.warn("Could not update JStyle bibliography", ex); OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); } diff --git a/src/main/java/org/jabref/gui/preview/CopyCitationAction.java b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java index 175aa1f490c..bbf9af78fa1 100644 --- a/src/main/java/org/jabref/gui/preview/CopyCitationAction.java +++ b/src/main/java/org/jabref/gui/preview/CopyCitationAction.java @@ -88,7 +88,7 @@ private List generateCitations() throws IOException { } if (styleSource != null) { - return CitationStyleGenerator.generateCitations( + return CitationStyleGenerator.generateBibliographies( selectedEntries, styleSource, outputFormat, diff --git a/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java b/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java index 422b83b7078..734690679bb 100644 --- a/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java +++ b/src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java @@ -17,12 +17,12 @@ /** * Provides an adapter class to CSL. It holds a CSL instance under the hood that is only recreated when * the style changes. - * + *

* Note on the API: The first call to {@link #makeBibliography} is expensive since the * CSL instance will be created. As long as the style stays the same, we can reuse this instance. On style-change, the * engine is re-instantiated. Therefore, the use-case of this class is many calls to {@link #makeBibliography} with the * same style. Changing the output format is cheap. - * + *

* Note on the implementation: * The main function {@link #makeBibliography} will enforce * synchronized calling. The main CSL engine under the hood is not thread-safe. Since this class is usually called from @@ -51,7 +51,7 @@ public synchronized List makeBibliography(List bibEntries, Str return Arrays.asList(bibliography.getEntries()); } - public synchronized Citation makeInText(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) throws IOException { + public synchronized Citation makeCitation(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) throws IOException { dataProvider.setData(bibEntries, databaseContext, entryTypesManager); initialize(style, outputFormat); cslInstance.registerCitationItems(dataProvider.getIds()); diff --git a/src/main/java/org/jabref/logic/citationstyle/CitationStyleGenerator.java b/src/main/java/org/jabref/logic/citationstyle/CitationStyleGenerator.java index 6e285e1d6d9..0a5a079c86e 100644 --- a/src/main/java/org/jabref/logic/citationstyle/CitationStyleGenerator.java +++ b/src/main/java/org/jabref/logic/citationstyle/CitationStyleGenerator.java @@ -31,8 +31,8 @@ private CitationStyleGenerator() { * * @implNote the citation is generated using JavaScript which may take some time, better call it from outside the main Thread */ - protected static String generateCitation(List bibEntries, CitationStyle style, BibEntryTypesManager entryTypesManager) { - return generateCitation(bibEntries, style.getSource(), entryTypesManager); + protected static String generateBibliography(List bibEntries, CitationStyle style, BibEntryTypesManager entryTypesManager) { + return generateBibliography(bibEntries, style.getSource(), entryTypesManager); } /** @@ -40,8 +40,8 @@ protected static String generateCitation(List bibEntries, CitationStyl * * @implNote the citation is generated using JavaScript which may take some time, better call it from outside the main Thread */ - protected static String generateCitation(List bibEntries, String style, BibEntryTypesManager entryTypesManager) { - return generateCitation(bibEntries, style, CitationStyleOutputFormat.HTML, new BibDatabaseContext(), entryTypesManager).getFirst(); + protected static String generateBibliography(List bibEntries, String style, BibEntryTypesManager entryTypesManager) { + return generateBibliography(bibEntries, style, CitationStyleOutputFormat.HTML, new BibDatabaseContext(), entryTypesManager).getFirst(); } /** @@ -49,12 +49,12 @@ protected static String generateCitation(List bibEntries, String style * * @implNote the citation is generated using JavaScript which may take some time, better call it from outside the main Thread */ - public static List generateCitation(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) { - return generateCitations(bibEntries, style, outputFormat, databaseContext, entryTypesManager); + public static List generateBibliography(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) { + return generateBibliographies(bibEntries, style, outputFormat, databaseContext, entryTypesManager); } - public static Citation generateInText(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) throws IOException { - return CSL_ADAPTER.makeInText(bibEntries, style, outputFormat, databaseContext, entryTypesManager); + public static Citation generateCitation(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) throws IOException { + return CSL_ADAPTER.makeCitation(bibEntries, style, outputFormat, databaseContext, entryTypesManager); } /** @@ -62,7 +62,7 @@ public static Citation generateInText(List bibEntries, String style, C * * @implNote The citations are generated using JavaScript which may take some time, better call it from outside the main thread. */ - public static List generateCitations(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) { + public static List generateBibliographies(List bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) { try { return CSL_ADAPTER.makeBibliography(bibEntries, style, outputFormat, databaseContext, entryTypesManager); } catch (IllegalArgumentException e) { diff --git a/src/main/java/org/jabref/logic/citationstyle/CitationStylePreviewLayout.java b/src/main/java/org/jabref/logic/citationstyle/CitationStylePreviewLayout.java index 9a584765aaf..12feae5483e 100644 --- a/src/main/java/org/jabref/logic/citationstyle/CitationStylePreviewLayout.java +++ b/src/main/java/org/jabref/logic/citationstyle/CitationStylePreviewLayout.java @@ -18,7 +18,7 @@ public CitationStylePreviewLayout(CitationStyle citationStyle, BibEntryTypesMana @Override public String generatePreview(BibEntry entry, BibDatabaseContext databaseContext) { - return CitationStyleGenerator.generateCitation(List.of(entry), citationStyle.getSource(), CitationStyleOutputFormat.HTML, databaseContext, bibEntryTypesManager).getFirst(); + return CitationStyleGenerator.generateBibliography(List.of(entry), citationStyle.getSource(), CitationStyleOutputFormat.HTML, databaseContext, bibEntryTypesManager).getFirst(); } @Override diff --git a/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java b/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java index e8b466d6965..a4f1bdae054 100644 --- a/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java +++ b/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java @@ -1,5 +1,7 @@ package org.jabref.logic.openoffice; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -9,13 +11,16 @@ import org.slf4j.LoggerFactory; public class ReferenceMark { + public static final String[] PREFIXES = {"JABREF_", "CID_"}; + private static final Logger LOGGER = LoggerFactory.getLogger(ReferenceMark.class); - private static final Pattern REFERENCE_MARK_FORMAT = Pattern.compile("^JABREF_(\\w+) CID_(\\w+) (\\w+)$"); - private final String name; + private static final Pattern REFERENCE_MARK_FORMAT = Pattern.compile("^((?:JABREF_\\w+ CID_\\w+(?:,\\s*)?)+)(\\s*\\w+)?$"); + private static final Pattern ENTRY_PATTERN = Pattern.compile("JABREF_(\\w+) CID_(\\w+)"); - private String citationKey; - private Integer citationNumber; + private final String name; + private List citationKeys; + private List citationNumbers; private String uniqueId; /** @@ -23,36 +28,45 @@ public class ReferenceMark { */ public ReferenceMark(String name) { this.name = name; + parse(name); + } - Matcher matcher = getMatcher(name); + public ReferenceMark(String name, List citationKeys, List citationNumbers, String uniqueId) { + this.name = name; + this.citationKeys = citationKeys; + this.citationNumbers = citationNumbers; + this.uniqueId = uniqueId; + } + + private void parse(String name) { + Matcher matcher = REFERENCE_MARK_FORMAT.matcher(name); if (!matcher.matches()) { LOGGER.warn("CSLReferenceMark: name={} does not match pattern. Assuming random values", name); - this.citationKey = CUID.randomCUID2(8).toString(); - this.citationNumber = 0; - this.uniqueId = this.citationKey; + this.citationKeys = List.of(CUID.randomCUID2(8).toString()); + this.citationNumbers = List.of(0); + this.uniqueId = this.citationKeys.getFirst(); return; } - this.citationKey = matcher.group(1); - this.citationNumber = Integer.parseInt(matcher.group(2)); - this.uniqueId = matcher.group(3); + String entriesString = matcher.group(1).trim(); + this.uniqueId = matcher.group(2) != null ? matcher.group(2).trim() : CUID.randomCUID2(8).toString(); - LOGGER.debug("CSLReferenceMark: citationKey={} citationNumber={} uniqueId={}", getCitationKey(), getCitationNumber(), getUniqueId()); - } + this.citationKeys = new ArrayList<>(); + this.citationNumbers = new ArrayList<>(); - public ReferenceMark(String name, String citationKey, Integer citationNumber, String uniqueId) { - this.name = name; - this.citationKey = citationKey; - this.citationNumber = citationNumber; - this.uniqueId = uniqueId; - } + Matcher entryMatcher = ENTRY_PATTERN.matcher(entriesString); + while (entryMatcher.find()) { + this.citationKeys.add(entryMatcher.group(1)); + this.citationNumbers.add(Integer.parseInt(entryMatcher.group(2))); + } - private ReferenceMark(String name, String citationKey, String citationNumber, String uniqueId) { - this(name, citationKey, Integer.parseInt(citationNumber), uniqueId); - } + if (this.citationKeys.isEmpty() || this.citationNumbers.isEmpty()) { + LOGGER.warn("CSLReferenceMark: Failed to parse any entries from name={}. Assuming random values", name); + this.citationKeys = List.of(CUID.randomCUID2(8).toString()); + this.citationNumbers = List.of(0); + } - private static Matcher getMatcher(String name) { - return REFERENCE_MARK_FORMAT.matcher(name); + LOGGER.debug("CSLReferenceMark: citationKeys={} citationNumbers={} uniqueId={}", getCitationKeys(), getCitationNumbers(), getUniqueId()); } public String getName() { @@ -60,14 +74,14 @@ public String getName() { } /** - * The BibTeX citation key + * The BibTeX citation keys */ - public String getCitationKey() { - return citationKey; + public List getCitationKeys() { + return citationKeys; } - public int getCitationNumber() { - return citationNumber; + public List getCitationNumbers() { + return citationNumbers; } public String getUniqueId() { @@ -75,11 +89,7 @@ public String getUniqueId() { } public static Optional of(String name) { - Matcher matcher = getMatcher(name); - if (!matcher.matches()) { - return Optional.empty(); - } - - return Optional.of(new ReferenceMark(name, matcher.group(1), matcher.group(2), matcher.group(3))); + ReferenceMark mark = new ReferenceMark(name); + return mark.citationKeys.isEmpty() ? Optional.empty() : Optional.of(mark); } } diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java index 9b529754431..865806947f3 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLCitationOOAdapter.java @@ -41,8 +41,8 @@ public CSLCitationOOAdapter(XTextDocument doc) { this.markManager = new CSLReferenceMarkManager(doc); } - public void readExistingMarks() throws WrappedTargetException, NoSuchElementException { - markManager.readExistingMarks(); + public void readAndUpdateExistingMarks() throws WrappedTargetException, NoSuchElementException { + markManager.readAndUpdateExistingMarks(); } /** @@ -58,7 +58,7 @@ public void insertCitation(XTextCursor cursor, CitationStyle selectedStyle, List if (isAlphanumeric) { inTextCitation = CSLFormatUtils.generateAlphanumericCitation(entries, bibDatabaseContext); } else { - inTextCitation = CitationStyleGenerator.generateInText(entries, style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager).getText(); + inTextCitation = CitationStyleGenerator.generateCitation(entries, style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager).getText(); } String formattedCitation = CSLFormatUtils.transformHTML(inTextCitation); @@ -68,7 +68,7 @@ public void insertCitation(XTextCursor cursor, CitationStyle selectedStyle, List } OOText ooText = OOFormat.setLocaleNone(OOText.fromString(formattedCitation)); - insertMultipleReferenceMarks(cursor, entries, ooText); + insertReferences(cursor, entries, ooText, selectedStyle.isNumericStyle()); cursor.collapseToEnd(); } @@ -98,7 +98,7 @@ public void insertInTextCitation(XTextCursor cursor, CitationStyle selectedStyle // Combine author name with the citation inTextCitation = authorName + " " + inTextCitation; } else { - inTextCitation = CitationStyleGenerator.generateInText(List.of(currentEntry), style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager).getText(); + inTextCitation = CitationStyleGenerator.generateCitation(List.of(currentEntry), style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager).getText(); } String formattedCitation = CSLFormatUtils.transformHTML(inTextCitation); String finalText; @@ -118,7 +118,7 @@ public void insertInTextCitation(XTextCursor cursor, CitationStyle selectedStyle finalText += ","; } OOText ooText = OOFormat.setLocaleNone(OOText.fromString(finalText)); - insertMultipleReferenceMarks(cursor, List.of(currentEntry), ooText); + insertReferences(cursor, List.of(currentEntry), ooText, selectedStyle.isNumericStyle()); cursor.collapseToEnd(); } } @@ -127,13 +127,10 @@ public void insertInTextCitation(XTextCursor cursor, CitationStyle selectedStyle * Inserts "empty" citations for a list of entries at the cursor to the document. * Adds the entries to the list for which bibliography is to be generated. */ - public void insertEmpty(XTextCursor cursor, List entries) + public void insertEmpty(XTextCursor cursor, CitationStyle selectedStyle, List entries) throws CreationException, Exception { - for (BibEntry entry : entries) { - CSLReferenceMark mark = markManager.createReferenceMark(entry); - OOText emptyOOText = OOFormat.setLocaleNone(OOText.fromString("")); - mark.insertReferenceIntoOO(document, cursor, emptyOOText, false, false, true); - } + OOText emptyOOText = OOFormat.setLocaleNone(OOText.fromString("")); + insertReferences(cursor, entries, emptyOOText, selectedStyle.isNumericStyle()); // Move the cursor to the end of the inserted text - although no need as we don't insert any text, but a good practice cursor.collapseToEnd(); @@ -144,7 +141,9 @@ public void insertEmpty(XTextCursor cursor, List entries) * The list is generated based on the existing citations, in-text citations and empty citations in the document. */ public void insertBibliography(XTextCursor cursor, CitationStyle selectedStyle, List entries, BibDatabaseContext bibDatabaseContext, BibEntryTypesManager bibEntryTypesManager) - throws WrappedTargetException, CreationException { + throws WrappedTargetException, CreationException, NoSuchElementException { + markManager.setUpdateRequired(selectedStyle.isNumericStyle()); + readAndUpdateExistingMarks(); OOText title = OOFormat.paragraph(OOText.fromString(CSLFormatUtils.DEFAULT_BIBLIOGRAPHY_TITLE), CSLFormatUtils.DEFAULT_BIBLIOGRAPHY_HEADER_PARAGRAPH_FORMAT); OOTextIntoOO.write(document, cursor, OOText.fromString(title.toString())); @@ -158,7 +157,7 @@ public void insertBibliography(XTextCursor cursor, CitationStyle selectedStyle, entries.sort(Comparator.comparingInt(entry -> markManager.getCitationNumber(entry.getCitationKey().orElse("")))); for (BibEntry entry : entries) { - String citation = CitationStyleGenerator.generateCitation(List.of(entry), style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager).getFirst(); + String citation = CitationStyleGenerator.generateBibliography(List.of(entry), style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager).getFirst(); String citationKey = entry.getCitationKey().orElse(""); int currentNumber = markManager.getCitationNumber(citationKey); @@ -174,7 +173,7 @@ public void insertBibliography(XTextCursor cursor, CitationStyle selectedStyle, } } else { // Ordering will be according to citeproc item data provider (default) - List citations = CitationStyleGenerator.generateCitation(entries, style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager); + List citations = CitationStyleGenerator.generateBibliography(entries, style, CSLFormatUtils.OUTPUT_FORMAT, bibDatabaseContext, bibEntryTypesManager); for (String citation : citations) { String formattedCitation = CSLFormatUtils.transformHTML(citation); @@ -186,14 +185,9 @@ public void insertBibliography(XTextCursor cursor, CitationStyle selectedStyle, } /** - * Inserts multiple references and also adds a space before the citation if not already present ("smart space"). - * - * @implNote It is difficult to "segment" a single citation generated for a group of entries into distinct parts based on the entries such that each entry can be draped with its corresponding reference mark. - * This is because of the sheer variety in the styles of citations and the separators between them (when grouped) in case of Citation Style Language. - * Furthermore, it is also difficult to generate a "single" reference mark for a group of entries. - * Thus, in case of citations for a group of entries, we first insert the citation (text), then insert the invisible reference marks for each entry separately after it. + * Inserts references and also adds a space before the citation if not already present ("smart space"). */ - private void insertMultipleReferenceMarks(XTextCursor cursor, List entries, OOText ooText) + private void insertReferences(XTextCursor cursor, List entries, OOText ooText, boolean isNumericStyle) throws CreationException, Exception { boolean preceedingSpaceExists; XTextCursor checkCursor = cursor.getText().createTextCursorByRange(cursor.getStart()); @@ -211,23 +205,15 @@ private void insertMultipleReferenceMarks(XTextCursor cursor, List ent } } - if (entries.size() == 1) { - CSLReferenceMark mark = markManager.createReferenceMark(entries.getFirst()); - mark.insertReferenceIntoOO(document, cursor, ooText, !preceedingSpaceExists, false, true); - } else { - if (!preceedingSpaceExists) { - cursor.getText().insertString(cursor, " ", false); - } - OOTextIntoOO.write(document, cursor, ooText); - for (BibEntry entry : entries) { - CSLReferenceMark mark = markManager.createReferenceMark(entry); - OOText emptyOOText = OOFormat.setLocaleNone(OOText.fromString("")); - mark.insertReferenceIntoOO(document, cursor, emptyOOText, false, false, true); - } - } + CSLReferenceMark mark = markManager.createReferenceMark(entries); + mark.insertReferenceIntoOO(document, cursor, ooText, !preceedingSpaceExists, false); // Move the cursor to the end of the inserted text cursor.collapseToEnd(); + + markManager.setUpdateRequired(isNumericStyle); + readAndUpdateExistingMarks(); + cursor.collapseToEnd(); } /** diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java index 0ae50cb4716..1ac64172287 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtils.java @@ -36,7 +36,7 @@ public class CSLFormatUtils { /** * Transforms provided HTML into a format that can be fully parsed and inserted into an OO document. - * Context: The HTML produced by {@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation} or {@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateInText(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateInText} is not directly (completely) parsable by by {@link OOTextIntoOO#write(XTextDocument, XTextCursor, OOText) write}. + * Context: The HTML produced by {@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateBibliography(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateBibliography} or {@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation} is not directly (completely) parsable by by {@link OOTextIntoOO#write(XTextDocument, XTextCursor, OOText) write}. * For more details, read the documentation for the {@link OOTextIntoOO} class. * Additional Information. * @@ -76,7 +76,7 @@ public static String transformHTML(String html) { } /** - * Alphanumeric citations are not natively supported by citeproc-java (see {@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateInText(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateInText}). + * Alphanumeric citations are not natively supported by citeproc-java (see {@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation}). * Thus, we manually format a citation to produce its alphanumeric form. * * @param entries the list of entries for which the alphanumeric citation is to be generated. @@ -113,7 +113,7 @@ public static String generateAlphanumericCitation(List entries, BibDat /** * Method to update citation number of a bibliographic entry (to be inserted in the list of references). - * By default, citeproc-java ({@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation} always start the numbering of a list of citations with "1". + * By default, citeproc-java ({@link org.jabref.logic.citationstyle.CitationStyleGenerator#generateBibliography(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateBibliography} always start the numbering of a list of citations with "1". * If a citation doesn't correspond to the first cited entry, the number should be changed to the relevant current citation number. * If an entries has been cited before, the colder number should be reused. * The number can be enclosed in different formats, such as "1", "1.", "1)", "(1)" or "[1]". diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMark.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMark.java index 49f11127c0c..85df85be987 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMark.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMark.java @@ -1,5 +1,7 @@ package org.jabref.logic.openoffice.oocsltext; +import java.util.List; + import org.jabref.logic.openoffice.ReferenceMark; import org.jabref.model.openoffice.DocumentAnnotation; import org.jabref.model.openoffice.ootext.OOText; @@ -17,8 +19,6 @@ import com.sun.star.uno.Exception; import com.sun.star.uno.UnoRuntime; import io.github.thibaultmeyer.cuid.CUID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import static org.jabref.logic.openoffice.backend.NamedRangeReferenceMark.safeInsertSpacesBetweenReferenceMarks; @@ -26,31 +26,57 @@ * Class to handle a reference mark. See {@link CSLReferenceMarkManager} for the management of all reference marks. */ public class CSLReferenceMark { - - private static final Logger LOGGER = LoggerFactory.getLogger(CSLReferenceMark.class); - - private final ReferenceMark referenceMark; - private final XTextContent textContent; + private ReferenceMark referenceMark; + private XTextContent textContent; + private final List citationKeys; + private List citationNumbers; public CSLReferenceMark(XNamed named, ReferenceMark referenceMark) { this.referenceMark = referenceMark; - textContent = UnoRuntime.queryInterface(XTextContent.class, named); - } - - public CSLReferenceMark(XNamed named, String name, String citationKey, Integer citationNumber, String uniqueId) { - referenceMark = new ReferenceMark(name, citationKey, citationNumber, uniqueId); this.textContent = UnoRuntime.queryInterface(XTextContent.class, named); + this.citationKeys = referenceMark.getCitationKeys(); + this.citationNumbers = referenceMark.getCitationNumbers(); } - public static CSLReferenceMark of(String citationKey, Integer citationNumber, XMultiServiceFactory factory) throws Exception { + public static CSLReferenceMark of(List citationKeys, List citationNumbers, XMultiServiceFactory factory) throws Exception { String uniqueId = CUID.randomCUID2(8).toString(); - String name = "JABREF_" + citationKey + " CID_" + citationNumber + " " + uniqueId; + String name = buildReferenceName(citationKeys, citationNumbers, uniqueId); XNamed named = UnoRuntime.queryInterface(XNamed.class, factory.createInstance("com.sun.star.text.ReferenceMark")); named.setName(name); - return new CSLReferenceMark(named, name, citationKey, citationNumber, uniqueId); + ReferenceMark referenceMark = new ReferenceMark(name, citationKeys, citationNumbers, uniqueId); + return new CSLReferenceMark(named, referenceMark); + } + + private static String buildReferenceName(List citationKeys, List citationNumbers, String uniqueId) { + StringBuilder nameBuilder = new StringBuilder(); + for (int i = 0; i < citationKeys.size(); i++) { + if (i > 0) { + nameBuilder.append(", "); + } + nameBuilder.append(ReferenceMark.PREFIXES[0]).append(citationKeys.get(i)) + .append(" ").append(ReferenceMark.PREFIXES[1]).append(citationNumbers.get(i)); + } + nameBuilder.append(" ").append(uniqueId); + return nameBuilder.toString(); + } + + public List getCitationKeys() { + return citationKeys; + } + + public void setCitationNumbers(List numbers) { + this.citationNumbers = numbers; } - public void insertReferenceIntoOO(XTextDocument doc, XTextCursor position, OOText ooText, boolean insertSpaceBefore, boolean insertSpaceAfter, boolean withoutBrackets) + public XTextContent getTextContent() { + return textContent; + } + + public String getName() { + return referenceMark.getName(); + } + + public void insertReferenceIntoOO(XTextDocument doc, XTextCursor position, OOText ooText, boolean insertSpaceBefore, boolean insertSpaceAfter) throws CreationException, WrappedTargetException { // Ensure the cursor is at the end of its range position.collapseToEnd(); @@ -100,11 +126,11 @@ public void insertReferenceIntoOO(XTextDocument doc, XTextCursor position, OOTex position.gotoRange(cursorAfter.getEnd(), false); } - public XTextContent getTextContent() { - return textContent; + public void updateTextContent(XTextContent newTextContent) { + this.textContent = newTextContent; } - public String getName() { - return referenceMark.getName(); + public void updateName(String newName) { + this.referenceMark = new ReferenceMark(newName, this.citationKeys, this.citationNumbers, this.referenceMark.getUniqueId()); } } diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java index 42440572166..66ceb6d36ba 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java @@ -2,9 +2,11 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.IdentityHashMap; +import java.util.List; import java.util.Map; -import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.jabref.logic.openoffice.ReferenceMark; import org.jabref.model.entry.BibEntry; @@ -12,10 +14,16 @@ import com.sun.star.container.NoSuchElementException; import com.sun.star.container.XNameAccess; import com.sun.star.container.XNamed; +import com.sun.star.lang.IllegalArgumentException; import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.text.XReferenceMarksSupplier; +import com.sun.star.text.XText; +import com.sun.star.text.XTextContent; +import com.sun.star.text.XTextCursor; import com.sun.star.text.XTextDocument; +import com.sun.star.text.XTextRange; +import com.sun.star.text.XTextRangeCompare; import com.sun.star.uno.Exception; import com.sun.star.uno.UnoRuntime; import io.github.thibaultmeyer.cuid.CUID; @@ -25,73 +33,205 @@ public class CSLReferenceMarkManager { private static final Logger LOGGER = LoggerFactory.getLogger(CSLReferenceMarkManager.class); - private final HashMap marksByName; - private final ArrayList marksByID; - private final IdentityHashMap idsByMark; private final XTextDocument document; private final XMultiServiceFactory factory; - private final HashMap citationKeyToNumber; + private final Map marksByName = new HashMap<>(); + private final List marksInOrder = new ArrayList<>(); + private Map citationKeyToNumber = new HashMap<>(); + private final XTextRangeCompare textRangeCompare; private int highestCitationNumber = 0; - private final Map citationOrder = new HashMap<>(); + private boolean isUpdateRequired; public CSLReferenceMarkManager(XTextDocument document) { this.document = document; this.factory = UnoRuntime.queryInterface(XMultiServiceFactory.class, document); - this.marksByName = new HashMap<>(); - this.marksByID = new ArrayList<>(); - this.idsByMark = new IdentityHashMap<>(); - this.citationKeyToNumber = new HashMap<>(); + this.textRangeCompare = UnoRuntime.queryInterface(XTextRangeCompare.class, document.getText()); + this.isUpdateRequired = false; } - public CSLReferenceMark createReferenceMark(BibEntry entry) throws Exception { - String citationKey = entry.getCitationKey().orElse(CUID.randomCUID2(8).toString()); - int citationNumber = getCitationNumber(citationKey); - CSLReferenceMark referenceMark = CSLReferenceMark.of(citationKey, citationNumber, factory); - addMark(referenceMark); + public CSLReferenceMark createReferenceMark(List entries) throws Exception { + List citationKeys = entries.stream() + .map(entry -> entry.getCitationKey().orElse(CUID.randomCUID2(8).toString())) + .collect(Collectors.toList()); + + List citationNumbers = citationKeys.stream() + .map(this::getCitationNumber) + .collect(Collectors.toList()); + + CSLReferenceMark referenceMark = CSLReferenceMark.of(citationKeys, citationNumbers, factory); + marksByName.put(referenceMark.getName(), referenceMark); + marksInOrder.add(referenceMark); return referenceMark; } - public void addMark(CSLReferenceMark mark) { - marksByName.put(mark.getName(), mark); - idsByMark.put(mark, marksByID.size()); - marksByID.add(mark); - updateCitationInfo(mark.getName()); + public void setUpdateRequired(boolean isNumeric) { + this.isUpdateRequired = isNumeric; } - public void readExistingMarks() throws WrappedTargetException, NoSuchElementException { - XReferenceMarksSupplier supplier = UnoRuntime.queryInterface(XReferenceMarksSupplier.class, document); - XNameAccess marks = supplier.getReferenceMarks(); + public void updateAllCitationNumbers() throws Exception { + sortMarksInOrder(); + Map newCitationKeyToNumber = new HashMap<>(); + int currentNumber = 1; - citationOrder.clear(); - int citationCounter = 0; + for (CSLReferenceMark mark : marksInOrder) { + List citationKeys = mark.getCitationKeys(); + List assignedNumbers = new ArrayList<>(); - for (String name : marks.getElementNames()) { - Optional referenceMark = ReferenceMark.of(name); - if (!referenceMark.isEmpty()) { - citationOrder.putIfAbsent(referenceMark.map(ReferenceMark::getCitationKey).get(), ++citationCounter); - XNamed named = UnoRuntime.queryInterface(XNamed.class, marks.getByName(name)); - CSLReferenceMark mark = new CSLReferenceMark(named, referenceMark.get()); - addMark(mark); + for (String citationKey : citationKeys) { + int assignedNumber; + if (newCitationKeyToNumber.containsKey(citationKey)) { + assignedNumber = newCitationKeyToNumber.get(citationKey); + } else { + assignedNumber = currentNumber; + newCitationKeyToNumber.put(citationKey, assignedNumber); + currentNumber++; + } + assignedNumbers.add(assignedNumber); } + + mark.setCitationNumbers(assignedNumbers); + updateMarkAndText(mark, assignedNumbers); } + + citationKeyToNumber = newCitationKeyToNumber; + } + + private void sortMarksInOrder() { + marksInOrder.sort((m1, m2) -> compareTextRanges(m2.getTextContent().getAnchor(), m1.getTextContent().getAnchor())); } - private void updateCitationInfo(String name) { - Optional referenceMark = ReferenceMark.of(name); - if (referenceMark.isPresent()) { - int citationNumber = referenceMark.get().getCitationNumber(); - citationKeyToNumber.put(referenceMark.get().getCitationKey(), citationNumber); - highestCitationNumber = Math.max(highestCitationNumber, citationNumber); - } else { - LOGGER.warn("Could not parse ReferenceMark name: {}", name); + private int compareTextRanges(XTextRange r1, XTextRange r2) { + try { + return r1 != null && r2 != null ? textRangeCompare.compareRegionStarts(r1, r2) : 0; + } catch (IllegalArgumentException e) { + LOGGER.warn("Error comparing text ranges: {}", e.getMessage(), e); + return 0; } } - public boolean hasCitationForKey(String citationKey) { - return citationKeyToNumber.containsKey(citationKey); + private void updateMarkAndText(CSLReferenceMark mark, List newNumbers) throws Exception { + XTextContent oldContent = mark.getTextContent(); + XTextRange range = oldContent.getAnchor(); + + if (range != null) { + XText text = range.getText(); + + // Store the position of the mark + XTextCursor cursor = text.createTextCursorByRange(range); + + // Get the current text content + String currentText = range.getString(); + + // Update the citation numbers in the text + String updatedText = updateCitationText(currentText, newNumbers); + + // Remove the old reference mark without removing the text (The only way to edit a reference mark is to remove it and add a new one) + text.removeTextContent(oldContent); + + // Update the text + cursor.setString(updatedText); + + // Create a new reference mark with updated name + String updatedName = updateReferenceName(mark.getName(), newNumbers); + XNamed newNamed = UnoRuntime.queryInterface(XNamed.class, + factory.createInstance("com.sun.star.text.ReferenceMark")); + newNamed.setName(updatedName); + XTextContent newContent = UnoRuntime.queryInterface(XTextContent.class, newNamed); + + // Attach the new reference mark to the cursor range + newContent.attach(cursor); + + // Update our internal reference to the new text content and name + mark.updateTextContent(newContent); + mark.updateName(updatedName); + mark.setCitationNumbers(newNumbers); + } + } + + private String updateReferenceName(String oldName, List newNumbers) { + String[] parts = oldName.split(" "); + if (oldName.startsWith("JABREF_") && oldName.contains("CID") && parts.length >= 3) { + StringBuilder newName = new StringBuilder(); + for (int i = 0; i < parts.length - 1; i += 2) { + // Each iteration of the loop (incrementing by 2) represents one full citation (key + number) + if (i > 0) { + newName.append(", "); + } + newName.append(parts[i]).append(" "); + newName.append(ReferenceMark.PREFIXES[1]).append(newNumbers.get(i / 2)); + } + newName.append(" ").append(parts[parts.length - 1]); + return newName.toString(); + } + return oldName; + } + + private String updateCitationText(String currentText, List newNumbers) { + Pattern pattern = Pattern.compile("(\\D*)(\\d+)(\\D*)"); + Matcher matcher = pattern.matcher(currentText); + StringBuilder result = new StringBuilder(); + int lastEnd = 0; + int numberIndex = 0; + + while (matcher.find()) { + result.append(currentText, lastEnd, matcher.start(2)); + result.append(newNumbers.get(numberIndex++)); + lastEnd = matcher.end(2); + } + result.append(currentText.substring(lastEnd)); + + return result.toString(); } public int getCitationNumber(String citationKey) { return citationKeyToNumber.computeIfAbsent(citationKey, k -> ++highestCitationNumber); } + + public void readAndUpdateExistingMarks() throws WrappedTargetException, NoSuchElementException { + marksByName.clear(); + marksInOrder.clear(); + citationKeyToNumber.clear(); + + XReferenceMarksSupplier supplier = UnoRuntime.queryInterface(XReferenceMarksSupplier.class, document); + XNameAccess marks = supplier.getReferenceMarks(); + + for (String name : marks.getElementNames()) { + if (name.startsWith(ReferenceMark.PREFIXES[0]) && name.contains(ReferenceMark.PREFIXES[1]) && name.split(" ").length >= 3) { + XNamed named = UnoRuntime.queryInterface(XNamed.class, marks.getByName(name)); + + ReferenceMark referenceMark = new ReferenceMark(name); + List citationKeys = referenceMark.getCitationKeys(); + List citationNumbers = referenceMark.getCitationNumbers(); + + if (!citationKeys.isEmpty() && !citationNumbers.isEmpty()) { + CSLReferenceMark mark = new CSLReferenceMark(named, referenceMark); + marksByName.put(name, mark); + marksInOrder.add(mark); + + for (int i = 0; i < citationKeys.size(); i++) { + String key = citationKeys.get(i); + int number = citationNumbers.get(i); + citationKeyToNumber.put(key, number); + highestCitationNumber = Math.max(highestCitationNumber, number); + } + } else { + LOGGER.warn("Cannot parse reference mark - invalid format: {}", name); + } + } + } + + LOGGER.debug("Read {} existing marks", marksByName.size()); + + if (isUpdateRequired) { + try { + updateAllCitationNumbers(); + } catch (Exception e) { + LOGGER.warn("Error updating citation numbers", e); + } + } + } + + public boolean hasCitationForKey(String citationKey) { + return citationKeyToNumber.containsKey(citationKey); + } } diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java index 21cb87b6cf6..107974934b4 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLUpdateBibliography.java @@ -12,6 +12,7 @@ import org.jabref.model.openoffice.uno.NoDocumentException; import org.jabref.model.openoffice.uno.UnoTextSection; +import com.sun.star.container.NoSuchElementException; import com.sun.star.lang.WrappedTargetException; import com.sun.star.text.XTextCursor; import com.sun.star.text.XTextDocument; @@ -41,7 +42,7 @@ public void rebuildCSLBibliography(XTextDocument doc, CitationStyle citationStyle, BibDatabaseContext bibDatabaseContext, BibEntryTypesManager bibEntryTypesManager) - throws WrappedTargetException, NoDocumentException, CreationException { + throws WrappedTargetException, NoDocumentException, CreationException, NoSuchElementException { LOGGER.debug("Starting to rebuild CSL bibliography"); // Ensure the bibliography section exists @@ -87,7 +88,7 @@ private void populateCSLBibTextSection(XTextDocument doc, CitationStyle citationStyle, BibDatabaseContext bibDatabaseContext, BibEntryTypesManager bibEntryTypesManager) - throws WrappedTargetException, NoDocumentException, CreationException { + throws WrappedTargetException, NoDocumentException, CreationException, NoSuchElementException { LOGGER.debug("Populating CSL bibliography section"); Optional sectionRange = getBibliographyRange(doc); diff --git a/src/test/java/org/jabref/logic/citationstyle/CitationStyleGeneratorTest.java b/src/test/java/org/jabref/logic/citationstyle/CitationStyleGeneratorTest.java index 3ee3a339fc0..d1a6891e874 100644 --- a/src/test/java/org/jabref/logic/citationstyle/CitationStyleGeneratorTest.java +++ b/src/test/java/org/jabref/logic/citationstyle/CitationStyleGeneratorTest.java @@ -34,7 +34,7 @@ class CitationStyleGeneratorTest { void aCMCitation() { context.setMode(BibDatabaseMode.BIBLATEX); CitationStyle style = styleList.stream().filter(e -> "ACM SIGGRAPH".equals(e.getTitle())).findAny().get(); - String citation = CitationStyleGenerator.generateCitation(List.of(testEntry), style.getSource(), CitationStyleOutputFormat.HTML, context, bibEntryTypesManager).getFirst(); + String citation = CitationStyleGenerator.generateBibliography(List.of(testEntry), style.getSource(), CitationStyleOutputFormat.HTML, context, bibEntryTypesManager).getFirst(); // if the acm-siggraph.csl citation style changes this has to be modified String expected = "

" @@ -49,7 +49,7 @@ void aCMCitation() { void aPACitation() { context.setMode(BibDatabaseMode.BIBLATEX); CitationStyle style = styleList.stream().filter(e -> "American Psychological Association 7th edition".equals(e.getTitle())).findAny().get(); - String citation = CitationStyleGenerator.generateCitation(List.of(testEntry), style.getSource(), CitationStyleOutputFormat.HTML, context, bibEntryTypesManager).getFirst(); + String citation = CitationStyleGenerator.generateBibliography(List.of(testEntry), style.getSource(), CitationStyleOutputFormat.HTML, context, bibEntryTypesManager).getFirst(); // if the apa-7th-citation.csl citation style changes this has to be modified String expected = "
" @@ -61,7 +61,7 @@ void aPACitation() { } /** - * Fails due to citeproc-java ({@link CitationStyleGenerator#generateInText(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateInText}) returning an empty citation. + * Fails due to citeproc-java ({@link CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation}) returning an empty citation. * Alphanumeric citations are thus, currently manually generated by formatting (see {@link org.jabref.logic.openoffice.oocsltext.CSLFormatUtils#generateAlphanumericCitation(List, BibDatabaseContext) generateAlphaNumericCitation}). */ @Test @@ -69,7 +69,7 @@ void aPACitation() { void din1502AlphanumericInTextCitation() throws IOException { context.setMode(BibDatabaseMode.BIBLATEX); CitationStyle style = styleList.stream().filter(e -> "DIN 1505-2 (alphanumeric, Deutsch) - standard superseded by ISO-690".equals(e.getTitle())).findAny().get(); - Citation citation = CitationStyleGenerator.generateInText(List.of(testEntry), style.getSource(), CitationStyleOutputFormat.HTML, context, bibEntryTypesManager); + Citation citation = CitationStyleGenerator.generateCitation(List.of(testEntry), style.getSource(), CitationStyleOutputFormat.HTML, context, bibEntryTypesManager); String inTextCitationText = citation.getText(); assertEquals("[Smit2016]", inTextCitationText); @@ -84,7 +84,7 @@ void ignoreNewLine() { String expected = "
\n" + "
[1]
F. Last and J. Doe,
\n" + "
\n"; - String citation = CitationStyleGenerator.generateCitation(List.of(entry), CitationStyle.getDefault(), bibEntryTypesManager); + String citation = CitationStyleGenerator.generateBibliography(List.of(entry), CitationStyle.getDefault(), bibEntryTypesManager); assertEquals(expected, citation); } @@ -97,14 +97,14 @@ void ignoreCarriageReturnNewLine() { String expected = "
\n" + "
[1]
F. Last and J. Doe,
\n" + "
\n"; - String citation = CitationStyleGenerator.generateCitation(List.of(entry), CitationStyle.getDefault(), bibEntryTypesManager); + String citation = CitationStyleGenerator.generateBibliography(List.of(entry), CitationStyle.getDefault(), bibEntryTypesManager); assertEquals(expected, citation); } @Test void missingCitationStyle() { String expected = Localization.lang("Cannot generate preview based on selected citation style."); - String citation = CitationStyleGenerator.generateCitation(List.of(new BibEntry()), "faulty citation style", bibEntryTypesManager); + String citation = CitationStyleGenerator.generateBibliography(List.of(new BibEntry()), "faulty citation style", bibEntryTypesManager); assertEquals(expected, citation); } @@ -117,7 +117,7 @@ void htmlFormat() { String style = CitationStyle.getDefault().getSource(); CitationStyleOutputFormat format = CitationStyleOutputFormat.HTML; - String actualCitation = CitationStyleGenerator.generateCitation(List.of(testEntry), style, format, context, bibEntryTypesManager).getFirst(); + String actualCitation = CitationStyleGenerator.generateBibliography(List.of(testEntry), style, format, context, bibEntryTypesManager).getFirst(); assertEquals(expectedCitation, actualCitation); } @@ -128,7 +128,7 @@ void textFormat() { String style = CitationStyle.getDefault().getSource(); CitationStyleOutputFormat format = CitationStyleOutputFormat.TEXT; - String actualCitation = CitationStyleGenerator.generateCitation(List.of(testEntry), style, format, context, bibEntryTypesManager).getFirst(); + String actualCitation = CitationStyleGenerator.generateBibliography(List.of(testEntry), style, format, context, bibEntryTypesManager).getFirst(); assertEquals(expectedCitation, actualCitation); } @@ -142,7 +142,7 @@ void handleDiacritics() { String expected = "
\n" + "
[1]
F. Läst and J. Doe,
\n" + "
\n"; - String citation = CitationStyleGenerator.generateCitation(List.of(entry), CitationStyle.getDefault(), bibEntryTypesManager); + String citation = CitationStyleGenerator.generateBibliography(List.of(entry), CitationStyle.getDefault(), bibEntryTypesManager); assertEquals(expected, citation); } @@ -153,7 +153,7 @@ void handleAmpersand() { String style = CitationStyle.getDefault().getSource(); CitationStyleOutputFormat format = CitationStyleOutputFormat.TEXT; - String actualCitation = CitationStyleGenerator.generateCitation(List.of(testEntry), style, format, context, bibEntryTypesManager).getFirst(); + String actualCitation = CitationStyleGenerator.generateBibliography(List.of(testEntry), style, format, context, bibEntryTypesManager).getFirst(); assertEquals(expectedCitation, actualCitation); } @@ -178,7 +178,7 @@ void handleCrossRefFields() { BibDatabaseContext bibDatabaseContext = new BibDatabaseContext(new BibDatabase(List.of(firstEntry, secondEntry))); String style = CitationStyle.getDefault().getSource(); - String actualCitation = CitationStyleGenerator.generateCitation(List.of(firstEntry), style, CitationStyleOutputFormat.TEXT, bibDatabaseContext, bibEntryTypesManager).getFirst(); + String actualCitation = CitationStyleGenerator.generateBibliography(List.of(firstEntry), style, CitationStyleOutputFormat.TEXT, bibDatabaseContext, bibEntryTypesManager).getFirst(); assertEquals(expectedCitation, actualCitation); } @@ -591,7 +591,7 @@ static Stream cslMapping() { void cslMapping(String expected, BibDatabaseMode mode, BibEntry entry, String cslFileName) { context.setMode(mode); - String citation = CitationStyleGenerator.generateCitation( + String citation = CitationStyleGenerator.generateBibliography( List.of(entry), CitationStyle.createCitationStyleFromFile(cslFileName).orElseThrow().getSource(), CitationStyleOutputFormat.TEXT, diff --git a/src/test/java/org/jabref/logic/citationstyle/CitationStyleTest.java b/src/test/java/org/jabref/logic/citationstyle/CitationStyleTest.java index 8423e534659..d6ac7203d9b 100644 --- a/src/test/java/org/jabref/logic/citationstyle/CitationStyleTest.java +++ b/src/test/java/org/jabref/logic/citationstyle/CitationStyleTest.java @@ -30,7 +30,7 @@ void getDefault() { void defaultCitation() { BibDatabaseContext context = new BibDatabaseContext(new BibDatabase(List.of(TestEntry.getTestEntry()))); context.setMode(BibDatabaseMode.BIBLATEX); - String citation = CitationStyleGenerator.generateCitation(List.of(TestEntry.getTestEntry()), CitationStyle.getDefault().getSource(), CitationStyleOutputFormat.HTML, context, new BibEntryTypesManager()).getFirst(); + String citation = CitationStyleGenerator.generateBibliography(List.of(TestEntry.getTestEntry()), CitationStyle.getDefault().getSource(), CitationStyleOutputFormat.HTML, context, new BibEntryTypesManager()).getFirst(); // if the default citation style changes this has to be modified String expected = """ diff --git a/src/test/java/org/jabref/logic/openoffice/ReferenceMarkTest.java b/src/test/java/org/jabref/logic/openoffice/ReferenceMarkTest.java index 7ac3f127dec..a23895b1f93 100644 --- a/src/test/java/org/jabref/logic/openoffice/ReferenceMarkTest.java +++ b/src/test/java/org/jabref/logic/openoffice/ReferenceMarkTest.java @@ -1,5 +1,6 @@ package org.jabref.logic.openoffice; +import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -14,19 +15,35 @@ class ReferenceMarkTest { @ParameterizedTest @MethodSource @DisplayName("Test parsing of valid reference marks") - void validParsing(String name, String expectedCitationKey, String expectedCitationNumber, String expectedUniqueId) { + void validParsing(String name, List expectedCitationKeys, List expectedCitationNumbers, String expectedUniqueId) { ReferenceMark referenceMark = new ReferenceMark(name); - assertEquals(expectedCitationKey, referenceMark.getCitationKey()); - assertEquals(expectedCitationNumber, String.valueOf(referenceMark.getCitationNumber())); + assertEquals(expectedCitationKeys, referenceMark.getCitationKeys()); + assertEquals(expectedCitationNumbers, referenceMark.getCitationNumbers()); assertEquals(expectedUniqueId, referenceMark.getUniqueId()); } private static Stream validParsing() { return Stream.of( - Arguments.of("JABREF_key1 CID_12345 uniqueId1", "key1", "12345", "uniqueId1"), - Arguments.of("JABREF_key2 CID_67890 uniqueId2", "key2", "67890", "uniqueId2"), - Arguments.of("JABREF_key3 CID_54321 uniqueId3", "key3", "54321", "uniqueId3") + // Single citation cases + Arguments.of( + "JABREF_key1 CID_12345 uniqueId1", + List.of("key1"), List.of(12345), "uniqueId1" + ), + Arguments.of( + "JABREF_key2 CID_67890 uniqueId2", + List.of("key2"), List.of(67890), "uniqueId2" + ), + + // Multiple citation cases + Arguments.of( + "JABREF_key3 CID_54321, JABREF_key4 CID_98765 uniqueId3", + List.of("key3", "key4"), List.of(54321, 98765), "uniqueId3" + ), + Arguments.of( + "JABREF_key5 CID_11111, JABREF_key6 CID_22222, JABREF_key7 CID_33333 uniqueId4", + List.of("key5", "key6", "key7"), List.of(11111, 22222, 33333), "uniqueId4" + ) ); } } diff --git a/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java b/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java index ada5ac67c42..57e054027fa 100644 --- a/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java +++ b/src/test/java/org/jabref/logic/openoffice/oocsltext/CSLFormatUtilsTest.java @@ -143,13 +143,13 @@ static Stream ooHTMLTransformFromRawHTML() { /** * Test to check correct transformation of raw CSL bibliography generated by citeproc-java methods into OO-ready text. *

- * Precondition: This test assumes that {@link CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation} works as expected. + * Precondition: This test assumes that {@link CitationStyleGenerator#generateBibliography(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateBibliography} works as expected. *

*/ @ParameterizedTest @MethodSource void ooHTMLTransformFromRawBibliography(String expected, CitationStyle style) { - String citation = CitationStyleGenerator.generateCitation(List.of(testEntry), style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager).getFirst(); + String citation = CitationStyleGenerator.generateBibliography(List.of(testEntry), style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager).getFirst(); String actual = CSLFormatUtils.transformHTML(citation); assertEquals(expected, actual); } @@ -275,13 +275,13 @@ static Stream ooHTMLTransformFromRawBibliography() { /** * Test to check correct transformation of raw CSL citation with a single entry generated by citeproc-java methods into OO-ready text. *

- * Precondition: This test assumes that {@link CitationStyleGenerator#generateInText(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateInText} works as expected. + * Precondition: This test assumes that {@link CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation} works as expected. *

*/ @ParameterizedTest @MethodSource void ooHTMLTransformFromCitationWithSingleEntry(String expected, CitationStyle style) throws IOException { - Citation citation = CitationStyleGenerator.generateInText(List.of(testEntry), style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager); + Citation citation = CitationStyleGenerator.generateCitation(List.of(testEntry), style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager); String inTextCitationText = citation.getText(); String actual = CSLFormatUtils.transformHTML(inTextCitationText); OOText ooText = OOText.fromString(actual); @@ -377,7 +377,7 @@ static Stream ooHTMLTransformFromCitationWithSingleEntry() { /** * Test to check correct transformation of raw CSL citations with multiple entries generated by citeproc-java methods into OO-ready text. *

- * Precondition: This test assumes that {@link CitationStyleGenerator#generateInText(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateInText} works as expected. + * Precondition: This test assumes that {@link CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation} works as expected. *

*/ @ParameterizedTest @@ -408,7 +408,7 @@ void ooHTMLTransformFromCitationWithMultipleEntries(String expected, CitationSty List entries = List.of(entry1, entry2); BibDatabaseContext context = new BibDatabaseContext(new BibDatabase(entries)); context.setMode(BibDatabaseMode.BIBLATEX); - Citation citation = CitationStyleGenerator.generateInText(entries, style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager); + Citation citation = CitationStyleGenerator.generateCitation(entries, style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager); String inTextCitationText = citation.getText(); String actual = CSLFormatUtils.transformHTML(inTextCitationText); assertEquals(expected, actual); @@ -503,14 +503,14 @@ static Stream ooHTMLTransformFromCitationWithMultipleEntries() { * The numeric index should change to the provided "current number". * The rest of the citation should stay as it is (other numbers in the body shouldn't be affected). *

- * Precondition 1: This test assumes that {@link CitationStyleGenerator#generateCitation(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateCitation} works as expected.
+ * Precondition 1: This test assumes that {@link CitationStyleGenerator#generateBibliography(List, String, CitationStyleOutputFormat, BibDatabaseContext, BibEntryTypesManager) generateBibliography} works as expected.
* Precondition 2: This test assumes that the method {@link CSLFormatUtils#transformHTML(String) transformHTML} works as expected.
* Precondition 3: Run this test ONLY on numeric Citation Styles.

*/ @ParameterizedTest @MethodSource void updateSingleNumericCitation(String expected, CitationStyle style) { - String citation = CitationStyleGenerator.generateCitation(List.of(testEntry), style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager).getFirst(); + String citation = CitationStyleGenerator.generateBibliography(List.of(testEntry), style.getSource(), CSLFormatUtils.OUTPUT_FORMAT, context, bibEntryTypesManager).getFirst(); String transformedCitation = CSLFormatUtils.transformHTML(citation); String actual = CSLFormatUtils.updateSingleBibliographyNumber(transformedCitation, 3); assertEquals(expected, actual); From adf30e9430b622021bc17d415ba67801986829fe Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:59:33 +0200 Subject: [PATCH 005/324] Custom export format: Browse opens selected template folder (#11717) * Fix * CHANGELOG.md --- CHANGELOG.md | 1 + .../exporter/CreateModifyExporterDialog.fxml | 75 ++++++++++--------- .../CreateModifyExporterDialogViewModel.java | 6 +- 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ff60969f28..23356917938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We enhanced the indexing speed. [#11502](https://github.com/JabRef/jabref/pull/11502) - ⚠️ Renamed command line parameters `embeddBibfileInPdf` to `embedBibFileInPdf`, `writeMetadatatoPdf` to `writeMetadataToPdf`, and `writeXMPtoPdf` to `writeXmpToPdf`. [#11575](https://github.com/JabRef/jabref/pull/11575) - The browse button for a Custom theme now opens in the directory of the current used CSS file. [#11597](https://github.com/JabRef/jabref/pull/11597) +- The browse button for a Custom exporter now opens in the directory of the current used exporter file. [#11717](https://github.com/JabRef/jabref/pull/11717) - We improved the display of long messages in the integrity check dialog. [#11619](https://github.com/JabRef/jabref/pull/11619) ### Fixed diff --git a/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialog.fxml b/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialog.fxml index b6021164738..e01fb6c255c 100644 --- a/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialog.fxml +++ b/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialog.fxml @@ -6,48 +6,49 @@ - + + - + - - - - - - - - - - - - - - - - - - + diff --git a/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialogViewModel.java b/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialogViewModel.java index d9e0c1bc69c..14c67b45538 100644 --- a/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialogViewModel.java +++ b/src/main/java/org/jabref/gui/exporter/CreateModifyExporterDialogViewModel.java @@ -73,10 +73,14 @@ public ExporterViewModel saveExporter() { } public void browse() { + String fileDir = layoutFile.getValue().isEmpty() + ? preferences.getExportPreferences().getExportWorkingDirectory().toString() + : layoutFile.getValue(); + FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .addExtensionFilter(Localization.lang("Custom layout file"), StandardFileType.LAYOUT) .withDefaultExtension(Localization.lang("Custom layout file"), StandardFileType.LAYOUT) - .withInitialDirectory(preferences.getExportPreferences().getExportWorkingDirectory()).build(); + .withInitialDirectory(fileDir).build(); dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(f -> layoutFile.set(f.toAbsolutePath().toString())); } From 1c232b87243381a5a18742dfd247ca048a18ad3e Mon Sep 17 00:00:00 2001 From: Christoph Date: Sat, 7 Sep 2024 16:07:45 +0200 Subject: [PATCH 006/324] use braces corrector for abstract in arxiv (#11716) * use braces corrector for abstract * changelog * fix checkstyle * checkstyle --- CHANGELOG.md | 1 + .../jabref/logic/importer/fetcher/ArXivFetcher.java | 12 +++++++----- .../logic/importer/fetcher/ArXivFetcherTest.java | 7 +++++++ .../jabref/logic/integrity/BracesCorrectorTest.java | 5 +++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23356917938..7c307ed39c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed an issue where the full-text search results were incomplete. [#8626](https://github.com/JabRef/jabref/issues/8626) - We fixed an issue where search result highlighting was incorrectly highlighting the boolean operators. [#11595](https://github.com/JabRef/jabref/issues/11595) - We fixed an issue where search result highlighting was broken at complex searches. [#8067](https://github.com/JabRef/jabref/issues/8067) +- We fixed an issue where unescaped braces in the arXiv fetcher were not treated [#11704](https://github.com/JabRef/jabref/issues/11704) ### Removed diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java index 0c17ff5e283..8b94ef5ba06 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ArXivFetcher.java @@ -32,6 +32,7 @@ import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.PagedSearchBasedFetcher; import org.jabref.logic.importer.fetcher.transformers.ArXivQueryTransformer; +import org.jabref.logic.integrity.BracesCorrector; import org.jabref.logic.util.io.XMLUtil; import org.jabref.logic.util.strings.StringSimilarity; import org.jabref.model.entry.BibEntry; @@ -92,9 +93,9 @@ public class ArXivFetcher implements FulltextFetcher, PagedSearchBasedFetcher, I */ private static final Set CHOSEN_MANUAL_DOI_FIELDS = Set.of(StandardField.DOI, StandardField.PUBLISHER, InternalField.KEY_FIELD); - private static final Map ARXIV_KEYWORDS_WITH_COMMA_REPLACEMENTS = Collections.unmodifiableMap(Map.of( + private static final Map ARXIV_KEYWORDS_WITH_COMMA_REPLACEMENTS = Map.of( "Computational Engineering, Finance, and Science", "Computational Engineering / Finance / Science", - "Distributed, Parallel, and Cluster Computing", "Distributed / Parallel / Cluster Computing")); + "Distributed, Parallel, and Cluster Computing", "Distributed / Parallel / Cluster Computing"); private final ArXiv arXiv; private final DoiFetcher doiFetcher; @@ -390,7 +391,7 @@ public String getIdentifierName() { * arxiv2bib which is live * dspace-portalmec */ - protected class ArXiv implements FulltextFetcher, PagedSearchBasedFetcher, IdBasedFetcher, IdFetcher { + protected static class ArXiv implements FulltextFetcher, PagedSearchBasedFetcher, IdBasedFetcher, IdFetcher { private static final Logger LOGGER = LoggerFactory.getLogger(ArXiv.class); @@ -545,7 +546,7 @@ private Document callApi(String searchQuery, List ids, int star } uriBuilder.addParameter("start", String.valueOf(start)); uriBuilder.addParameter("max_results", String.valueOf(maxResults)); - URL url = null; + URL url; try { url = uriBuilder.build().toURL(); } catch (MalformedURLException | URISyntaxException e) { @@ -614,6 +615,7 @@ public Page performSearchPaged(QueryNode luceneQuery, int pageNumber) .stream() .map(arXivEntry -> arXivEntry.toBibEntry(importFormatPreferences.bibEntryPreferences().getKeywordSeparator())) .collect(Collectors.toList()); + return new Page<>(transformedQuery, pageNumber, filterYears(searchResult, transformer)); } @@ -684,7 +686,7 @@ public ArXivEntry(Node item) { // Abstract of the article abstractText = XMLUtil.getNodeContent(item, "summary").map(ArXivEntry::correctLineBreaks) - .map(String::trim); + .map(String::trim).map(BracesCorrector::apply); // Authors of the article authorNames = new ArrayList<>(); diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java index 13884df4761..03d5c9f5573 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ArXivFetcherTest.java @@ -575,4 +575,11 @@ void retrievePartialResultWhenCannotGetInformationFromArXivAssignedDOI() throws ArXivFetcher modifiedArXivFetcher = Mockito.spy(new ArXivFetcher(importFormatPreferences, modifiedDoiFetcher)); assertEquals(Optional.of(expected), modifiedArXivFetcher.performSearchById("1701.00587")); } + + @Test + void abstractIsCleanedUp() throws Exception { + Optional entry = fetcher.performSearchById("2407.02238"); + String escaped = "{One of the primary areas of interest in High Performance Computing is the improvement of performance of parallel workloads. Nowadays, compilable source code-based optimization tasks that employ deep learning often exploit LLVM Intermediate Representations (IRs) for extracting features from source code. Most such works target specific tasks, or are designed with a pre-defined set of heuristics. So far, pre-trained models are rare in this domain, but the possibilities have been widely discussed. Especially approaches mimicking large-language models (LLMs) have been proposed. But these have prohibitively large training costs. In this paper, we propose MIREncoder, a M}ulti-modal IR-based Auto-Encoder that can be pre-trained to generate a learned embedding space to be used for downstream tasks by machine learning-based approaches. A multi-modal approach enables us to better extract features from compilable programs. It allows us to better model code syntax, semantics and structure. For code-based performance optimizations, these features are very important while making optimization decisions. A pre-trained model/embedding implicitly enables the usage of transfer learning, and helps move away from task-specific trained models. Additionally, a pre-trained model used for downstream performance optimization should itself have reduced overhead, and be easily usable. These considerations have led us to propose a modeling approach that i) understands code semantics and structure, ii) enables use of transfer learning, and iii) is small and simple enough to be easily re-purposed or reused even with low resource availability. Our evaluations will show that our proposed approach can outperform the state of the art while reducing overhead."; + assertEquals(Optional.of(escaped), entry.get().getField(StandardField.ABSTRACT)); + } } diff --git a/src/test/java/org/jabref/logic/integrity/BracesCorrectorTest.java b/src/test/java/org/jabref/logic/integrity/BracesCorrectorTest.java index 4d77ff3e5b3..092992b6353 100644 --- a/src/test/java/org/jabref/logic/integrity/BracesCorrectorTest.java +++ b/src/test/java/org/jabref/logic/integrity/BracesCorrectorTest.java @@ -46,4 +46,9 @@ void inputWithMaskedBraces() { void inputWithMixedBraces() { assertEquals("{b{anana\\\\\\}}}", BracesCorrector.apply("{b{anana\\\\\\}")); } + + @Test + void inputUnbalanced() { + assertEquals("{{ban}ana}", BracesCorrector.apply("ban}ana}")); + } } From 8299b4e847b10599c57c0914205120f1160e2ae7 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 7 Sep 2024 16:38:32 +0200 Subject: [PATCH 007/324] improve-fetchers (#11715) * Make getTrustLevel() mandatory * Remove obsolete `@Override` * Really remoe TrustLevel * Fix link * Fix checkstyle * Fix tests --- .../logic/importer/FulltextFetcher.java | 4 +-- .../logic/importer/FulltextFetchers.java | 3 +- .../logic/importer/fetcher/CiteSeer.java | 5 +++ .../logic/importer/fetcher/JstorFetcher.java | 5 --- .../logic/importer/fetcher/TrustLevel.java | 2 +- .../logic/importer/FulltextFetchersTest.java | 32 ++++++++++++------- .../logic/importer/WebFetchersTest.java | 7 ++-- 7 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/FulltextFetcher.java b/src/main/java/org/jabref/logic/importer/FulltextFetcher.java index dc578db661c..a6438be2ade 100644 --- a/src/main/java/org/jabref/logic/importer/FulltextFetcher.java +++ b/src/main/java/org/jabref/logic/importer/FulltextFetcher.java @@ -30,7 +30,5 @@ public interface FulltextFetcher { * * @return The trust level of the fetcher, the higher the better */ - default TrustLevel getTrustLevel() { - return TrustLevel.UNKNOWN; - } + TrustLevel getTrustLevel(); } diff --git a/src/main/java/org/jabref/logic/importer/FulltextFetchers.java b/src/main/java/org/jabref/logic/importer/FulltextFetchers.java index a8dee84dd33..2b8a86dd842 100644 --- a/src/main/java/org/jabref/logic/importer/FulltextFetchers.java +++ b/src/main/java/org/jabref/logic/importer/FulltextFetchers.java @@ -14,7 +14,6 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; -import java.util.stream.Collectors; import org.jabref.logic.net.URLDownload; import org.jabref.logic.util.HeadlessExecutorService; @@ -113,6 +112,6 @@ private Callable> getCallable(BibEntry entry, FulltextFe private List>> getCallables(BibEntry entry, Set fetchers) { return fetchers.stream() .map(f -> getCallable(entry, f)) - .collect(Collectors.toList()); + .toList(); } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java b/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java index 20e73b6bb1b..3f282609f77 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/CiteSeer.java @@ -113,4 +113,9 @@ public Optional findFullText(BibEntry entry) throws IOException, FetcherExc return Optional.empty(); } + + @Override + public TrustLevel getTrustLevel() { + return TrustLevel.META_SEARCH; + } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java index eb54b87dff0..83957549a56 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/JstorFetcher.java @@ -132,9 +132,4 @@ public Optional findFullText(BibEntry entry) throws FetcherException, IOExc public TrustLevel getTrustLevel() { return TrustLevel.META_SEARCH; } - - @Override - public void doPostCleanup(BibEntry entry) { - // do nothing - } } diff --git a/src/main/java/org/jabref/logic/importer/fetcher/TrustLevel.java b/src/main/java/org/jabref/logic/importer/fetcher/TrustLevel.java index 8e72398a78a..c26b5520dc0 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/TrustLevel.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/TrustLevel.java @@ -1,7 +1,7 @@ package org.jabref.logic.importer.fetcher; /** - * Discussion on the trust levels is available at our documentation on fetchers. + * Discussion on the trust levels is available at our documentation on fulltext fetchers. */ public enum TrustLevel { SOURCE(3), diff --git a/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java b/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java index c7e7a9bb7b9..948f8077a0f 100644 --- a/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java +++ b/src/test/java/org/jabref/logic/importer/FulltextFetchersTest.java @@ -20,36 +20,47 @@ @FetcherTest class FulltextFetchersTest { - private BibEntry entry = new BibEntry(); + /** + * Required for testing the FulltextFetchers class. + * That code is not put to the FulltextFetcher class itself, because subclasses of FulltextFetcher should implement the getTrustLevel method. + */ + private interface FulltextFetcherWithTrustLevel extends FulltextFetcher { + default TrustLevel getTrustLevel() { + return TrustLevel.UNKNOWN; + } + } @Test void acceptPdfUrls() throws MalformedURLException { URL pdfUrl = new URL("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); - FulltextFetcher finder = e -> Optional.of(pdfUrl); + FulltextFetcherWithTrustLevel finder = e -> Optional.of(pdfUrl); FulltextFetchers fetcher = new FulltextFetchers(Set.of(finder)); - assertEquals(Optional.of(pdfUrl), fetcher.findFullTextPDF(entry)); + assertEquals(Optional.of(pdfUrl), fetcher.findFullTextPDF(new BibEntry())); } @Test void rejectNonPdfUrls() throws MalformedURLException { URL pdfUrl = new URL("https://github.com/JabRef/jabref/blob/master/README.md"); - FulltextFetcher finder = e -> Optional.of(pdfUrl); + FulltextFetcherWithTrustLevel finder = e -> Optional.of(pdfUrl); FulltextFetchers fetcher = new FulltextFetchers(Set.of(finder)); - assertEquals(Optional.empty(), fetcher.findFullTextPDF(entry)); + assertEquals(Optional.empty(), fetcher.findFullTextPDF(new BibEntry())); } @Test void noTrustLevel() throws MalformedURLException { URL pdfUrl = new URL("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); - FulltextFetcher finder = e -> Optional.of(pdfUrl); + FulltextFetcherWithTrustLevel finder = e -> Optional.of(pdfUrl); FulltextFetchers fetcher = new FulltextFetchers(Set.of(finder)); - assertEquals(Optional.of(pdfUrl), fetcher.findFullTextPDF(entry)); + assertEquals(Optional.of(pdfUrl), fetcher.findFullTextPDF(new BibEntry())); } @Test void higherTrustLevelWins() throws IOException, FetcherException { + // set an (arbitrary) DOI to the test entry to skip side effects inside the "findFullTextPDF" method + BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.5220/0007903201120130"); + FulltextFetcher finderHigh = mock(FulltextFetcher.class); when(finderHigh.getTrustLevel()).thenReturn(TrustLevel.SOURCE); final URL highUrl = new URL("http://docs.oasis-open.org/wsbpel/2.0/OS/wsbpel-v2.0-OS.pdf"); @@ -60,11 +71,8 @@ void higherTrustLevelWins() throws IOException, FetcherException { final URL lowUrl = new URL("http://docs.oasis-open.org/opencsa/sca-bpel/sca-bpel-1.1-spec-cd-01.pdf"); when(finderLow.findFullText(entry)).thenReturn(Optional.of(lowUrl)); - FulltextFetchers fetcher = new FulltextFetchers(Set.of(finderLow, finderHigh)); - - // set an (arbitrary) DOI to the test entry to skip side effects inside the "findFullTextPDF" method - entry.setField(StandardField.DOI, "10.5220/0007903201120130"); + FulltextFetchers fetchers = new FulltextFetchers(Set.of(finderLow, finderHigh)); - assertEquals(Optional.of(highUrl), fetcher.findFullTextPDF(entry)); + assertEquals(Optional.of(highUrl), fetchers.findFullTextPDF(entry)); } } diff --git a/src/test/java/org/jabref/logic/importer/WebFetchersTest.java b/src/test/java/org/jabref/logic/importer/WebFetchersTest.java index b8abaf86b45..ba033cb070e 100644 --- a/src/test/java/org/jabref/logic/importer/WebFetchersTest.java +++ b/src/test/java/org/jabref/logic/importer/WebFetchersTest.java @@ -35,7 +35,10 @@ class WebFetchersTest { private static final Logger LOGGER = LoggerFactory.getLogger(WebFetchersTest.class); - private static final Set IGNORED_INACCESSIBLE_FETCHERS = Set.of("ArXivFetcher$ArXiv"); + + private static final Set IGNORED_INACCESSIBLE_FETCHERS = Set.of( + "org.jabref.logic.importer.fetcher.ArXivFetcher$ArXiv", + "org.jabref.logic.importer.FulltextFetchersTest$FulltextFetcherWithTrustLevel"); private ImportFormatPreferences importFormatPreferences; private ImporterPreferences importerPreferences; @@ -49,7 +52,7 @@ void setUp() { private Set> getIgnoredInaccessibleClasses() { return IGNORED_INACCESSIBLE_FETCHERS.stream() - .map(className -> "org.jabref.logic.importer.fetcher." + className) + .map(className -> "" + className) .map(classPath -> { try { return Class.forName(classPath); From 4b633aacaafb3b17201ab537ff4b0bb2aa5c88f5 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 7 Sep 2024 17:00:46 +0200 Subject: [PATCH 008/324] Remove unused method (#11718) * Remove unused method * Fix imports * Remove imports --- .../org/jabref/logic/net/URLDownload.java | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/src/main/java/org/jabref/logic/net/URLDownload.java b/src/main/java/org/jabref/logic/net/URLDownload.java index db9e3b4d9f7..636448716bd 100644 --- a/src/main/java/org/jabref/logic/net/URLDownload.java +++ b/src/main/java/org/jabref/logic/net/URLDownload.java @@ -23,8 +23,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; import java.time.Duration; import java.util.Collections; import java.util.HashMap; @@ -34,10 +32,7 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; import org.jabref.http.dto.SimpleHttpResponse; import org.jabref.logic.importer.FetcherClientException; @@ -91,54 +86,6 @@ public URLDownload(URL source) { this.addHeader("User-Agent", URLDownload.USER_AGENT); } - /** - * Older java VMs does not automatically trust the zbMATH certificate. In this case the following exception is - * thrown: sun.security.validator.ValidatorException: PKIX path building failed: - * sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested - * target JM > 8u101 may trust the certificate by default according to http://stackoverflow.com/a/34111150/873661 - *

- * We will fix this issue by accepting all (!) certificates. This is ugly; but as JabRef does not rely on - * security-relevant information this is kind of OK (no, actually it is not...). - *

- * Taken from http://stackoverflow.com/a/6055903/873661 and https://stackoverflow.com/a/19542614/873661 - * - * @deprecated - */ - @Deprecated - public static void bypassSSLVerification() { - LOGGER.warn("Fix SSL exceptions by accepting ALL certificates"); - - // Create a trust manager that does not validate certificate chains - TrustManager[] trustAllCerts = {new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - }}; - - try { - // Install all-trusting trust manager - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, trustAllCerts, new SecureRandom()); - HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); - - // Install all-trusting host verifier - HostnameVerifier allHostsValid = (hostname, session) -> true; - HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); - } catch ( - Exception e) { - LOGGER.error("A problem occurred when bypassing SSL verification", e); - } - } - /** * @param socketFactory trust manager * @param verifier host verifier From 2b55ddb5eae9d21b0ad7fc11d2344c5ee383275f Mon Sep 17 00:00:00 2001 From: Subhramit Basu Bhowmick Date: Sat, 7 Sep 2024 23:18:02 +0530 Subject: [PATCH 009/324] Use stricter regex (#11720) --- .../java/org/jabref/logic/openoffice/ReferenceMark.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java b/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java index a4f1bdae054..9d59e23c3b9 100644 --- a/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java +++ b/src/main/java/org/jabref/logic/openoffice/ReferenceMark.java @@ -15,7 +15,7 @@ public class ReferenceMark { private static final Logger LOGGER = LoggerFactory.getLogger(ReferenceMark.class); - private static final Pattern REFERENCE_MARK_FORMAT = Pattern.compile("^((?:JABREF_\\w+ CID_\\w+(?:,\\s*)?)+)(\\s*\\w+)?$"); + private static final Pattern REFERENCE_MARK_FORMAT = Pattern.compile("^(JABREF_\\w+ CID_\\d+(?:, JABREF_\\w+ CID_\\d+)*) (\\w+)$"); private static final Pattern ENTRY_PATTERN = Pattern.compile("JABREF_(\\w+) CID_(\\w+)"); private final String name; @@ -24,7 +24,11 @@ public class ReferenceMark { private String uniqueId; /** - * @param name Format: JABREF_{citationKey} CID_{citationNumber} {uniqueId} + * @param name Allowed formats: + * Single entry: JABREF_{citationKey} CID_{citationNumber} {uniqueId} + * Group of entries: JABREF_{citationKey1} CID_{citationNumber1}, JABREF_{citationKey2} CID_{citationNumber2}, ..., JABREF_{citationKeyN} CID_{citationNumberN} {uniqueId} + * Disallowed: JABREF_{citationKey} CID_{citationNumber} (no unique ID at the end) + * Disallowed: JABREF_{citationKey1} CID_{citationNumber1} JABREF_{citationKey2} CID_{citationNumber2} {uniqueId} (no comma between entries) */ public ReferenceMark(String name) { this.name = name; From 121eb9bf1389ceef628d7e360f1f2aa65b75a474 Mon Sep 17 00:00:00 2001 From: Loay Ghreeb <52158423+LoayGhreeb@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:01:52 +0300 Subject: [PATCH 010/324] Update lucene version (#11719) * Update lucene version * Change version --- src/main/java/module-info.java | 2 +- src/main/java/org/jabref/gui/LibraryTab.java | 4 +++- .../model/search/Analyzer/LatexAwareNGramAnalyzer.java | 2 +- .../org/jabref/model/search/SearchFieldConstants.java | 10 ++++++++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 040717bf907..c6ed2d0cad3 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -155,7 +155,7 @@ // region: Lucene /** - * In case the version is updated, please also adapt {@link org.jabref.model.search.SearchFieldConstants#VERSION} to the newly used version. + * In case the version is updated, please also increment {@link org.jabref.model.search.SearchFieldConstants#VERSION} to trigger reindexing. */ uses org.apache.lucene.codecs.lucene99.Lucene99Codec; requires org.apache.lucene.analysis.common; diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index ecfaa501e70..0542c7023fe 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -858,7 +858,9 @@ private void onClosed(Event event) { LOGGER.error("Problem when closing directory monitor", e); } try { - luceneManager.close(); + if (luceneManager != null) { + luceneManager.close(); + } } catch (RuntimeException e) { LOGGER.error("Problem when closing lucene indexer", e); } diff --git a/src/main/java/org/jabref/model/search/Analyzer/LatexAwareNGramAnalyzer.java b/src/main/java/org/jabref/model/search/Analyzer/LatexAwareNGramAnalyzer.java index f1f9ddabc3f..aafb993390d 100644 --- a/src/main/java/org/jabref/model/search/Analyzer/LatexAwareNGramAnalyzer.java +++ b/src/main/java/org/jabref/model/search/Analyzer/LatexAwareNGramAnalyzer.java @@ -26,7 +26,7 @@ protected TokenStreamComponents createComponents(String fieldName) { result = new StopFilter(result, EnglishAnalyzer.ENGLISH_STOP_WORDS_SET); result = new ASCIIFoldingFilter(result); result = new LowerCaseFilter(result); - result = new EdgeNGramTokenFilter(result, minGram, maxGram, true); + result = new EdgeNGramTokenFilter(result, minGram, maxGram, true); return new TokenStreamComponents(source, result); } } diff --git a/src/main/java/org/jabref/model/search/SearchFieldConstants.java b/src/main/java/org/jabref/model/search/SearchFieldConstants.java index 8becbeb1851..12aa58576da 100644 --- a/src/main/java/org/jabref/model/search/SearchFieldConstants.java +++ b/src/main/java/org/jabref/model/search/SearchFieldConstants.java @@ -9,8 +9,14 @@ import org.apache.lucene.analysis.en.EnglishAnalyzer; public enum SearchFieldConstants { - - VERSION("99"), + /** + * Version number for the search index. + * Increment when: + * 1. Index changes require reindexing (e.g., new/removed/renamed fields, analyzer changes) + * 2. Lucene codec changes (see module-info.java Lucene section) + * Incrementing triggers reindexing. + */ + VERSION("1"), DEFAULT_FIELD("any"), ENTRY_ID("id"), ENTRY_TYPE("entrytype"), From fbe1e15c4eebb9e11cf93e9c4e7b326212b4810f Mon Sep 17 00:00:00 2001 From: Subhramit Basu Bhowmick Date: Sat, 7 Sep 2024 23:44:04 +0530 Subject: [PATCH 011/324] Fix edge case bug: number before "1" (#11723) --- .../openoffice/oocsltext/CSLReferenceMarkManager.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java index 66ceb6d36ba..408851d322d 100644 --- a/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java +++ b/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java @@ -175,7 +175,13 @@ private String updateCitationText(String currentText, List newNumbers) while (matcher.find()) { result.append(currentText, lastEnd, matcher.start(2)); - result.append(newNumbers.get(numberIndex++)); + if (numberIndex < newNumbers.size()) { + result.append(newNumbers.get(numberIndex)); + } else { + // If we've run out of new numbers, increment the last used number + result.append(newNumbers.getLast() + (numberIndex - newNumbers.size() + 1)); + } + numberIndex++; lastEnd = matcher.end(2); } result.append(currentText.substring(lastEnd)); From 43c26ae690ecc3c65aad849ebb80886778ecf10a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 7 Sep 2024 20:17:30 +0200 Subject: [PATCH 012/324] Refine ACS test code (#11722) * Refine ACS test code * Minor improvements --- build.gradle | 2 ++ src/main/java/module-info.java | 6 ++-- .../jabref/logic/importer/fetcher/ACS.java | 2 +- .../logic/importer/fetcher/ACSTest.java | 35 +++++++------------ 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/build.gradle b/build.gradle index fd199a8b667..9bd82d66fb8 100644 --- a/build.gradle +++ b/build.gradle @@ -255,10 +255,12 @@ dependencies { implementation 'org.controlsfx:controlsfx:11.2.1' + // region HTTP clients implementation 'org.jsoup:jsoup:1.18.1' implementation 'com.konghq:unirest-java-core:4.4.4' implementation 'com.konghq:unirest-modules-gson:4.4.4' implementation 'org.apache.httpcomponents.client5:httpclient5:5.3.1' + // endregion implementation 'org.slf4j:slf4j-api:2.0.16' implementation 'org.tinylog:tinylog-api:2.7.0' diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index c6ed2d0cad3..65e89455413 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -89,11 +89,11 @@ // dependency injection using HK2 requires org.glassfish.hk2.api; - // region: http clients - requires unirest.java.core; - requires unirest.modules.gson; + // region HTTP clients requires org.apache.httpcomponents.core5.httpcore5; requires org.jsoup; + requires unirest.java.core; + requires unirest.modules.gson; // endregion // region: SQL databases diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ACS.java b/src/main/java/org/jabref/logic/importer/fetcher/ACS.java index 3c81d89db2a..e185b6fece2 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ACS.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ACS.java @@ -17,7 +17,7 @@ import org.slf4j.LoggerFactory; /** - * FulltextFetcher implementation that attempts to find a PDF URL at ACS. + * FulltextFetcher implementation that attempts to find a PDF URL at ACS. */ public class ACS implements FulltextFetcher { private static final Logger LOGGER = LoggerFactory.getLogger(ACS.class); diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java index 2552b5cc735..dca2cb16424 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ACSTest.java @@ -1,56 +1,47 @@ package org.jabref.logic.importer.fetcher; -import java.io.IOException; import java.net.URL; import java.util.Optional; +import org.jabref.logic.importer.FulltextFetcher; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.support.DisabledOnCIServer; import org.jabref.testutils.category.FetcherTest; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @FetcherTest class ACSTest { - private ACS finder; - private BibEntry entry; - - @BeforeEach - void setUp() { - finder = new ACS(); - entry = new BibEntry(); - } + private FulltextFetcher fetcher = new ACS(); @Test @DisabledOnCIServer("CI server is unreliable") - void findByDOI() throws IOException { - entry.setField(StandardField.DOI, "10.1021/bk-2006-STYG.ch014"); - + void findByDOI() throws Exception { + // DOI randomly chosen from https://pubs.acs.org/toc/acscii/0/0 + BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1021/acscentsci.4c00971"); assertEquals( - Optional.of(new URL("https://pubs.acs.org/doi/pdf/10.1021/bk-2006-STYG.ch014")), - finder.findFullText(entry) + Optional.of(new URL("https://pubs.acs.org/doi/pdf/10.1021/acscentsci.4c00971")), + fetcher.findFullText(entry) ); } @Test @DisabledOnCIServer("CI server is unreliable") - void notFoundByDOI() throws IOException { - entry.setField(StandardField.DOI, "10.1021/bk-2006-WWW.ch014"); - - assertEquals(Optional.empty(), finder.findFullText(entry)); + void notFoundByDOI() throws Exception { + BibEntry entry = new BibEntry().withField(StandardField.DOI, "10.1021/bk-2006-WWW.ch014"); + assertEquals(Optional.empty(), fetcher.findFullText(entry)); } @Test - void entityWithoutDoi() throws IOException { - assertEquals(Optional.empty(), finder.findFullText(entry)); + void entityWithoutDoi() throws Exception { + assertEquals(Optional.empty(), fetcher.findFullText(new BibEntry())); } @Test void trustLevel() { - assertEquals(TrustLevel.PUBLISHER, finder.getTrustLevel()); + assertEquals(TrustLevel.PUBLISHER, fetcher.getTrustLevel()); } } From d446b82994be48b14d0d8795e1d8fc57f2863a93 Mon Sep 17 00:00:00 2001 From: Christoph Date: Sat, 7 Sep 2024 21:44:44 +0200 Subject: [PATCH 013/324] Reduce log noise, even in debug mode (#11721) * Reduce log noise, even in debug mode * remove line --------- Co-authored-by: Subhramit Basu Bhowmick --- src/main/java/org/jabref/gui/maintable/MainTable.java | 4 ++-- src/main/java/org/jabref/gui/theme/StyleSheetFile.java | 4 ++-- src/main/java/org/jabref/logic/xmp/XmpUtilReader.java | 2 +- .../model/search/Analyzer/LatexToUnicodeFoldingFilter.java | 2 +- src/main/resources/tinylog.properties | 7 +++++++ 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index 91daebd7088..ecce71476de 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -186,7 +186,7 @@ public MainTable(MainTableDataModel model, .filter(column -> column.getModel().equals(columnModel)) .findFirst() .ifPresent(column -> { - LOGGER.debug("Adding sort order for col {} ", column); + LOGGER.trace("Adding sort order for col {} ", column); this.getSortOrder().add(column); })); @@ -201,7 +201,7 @@ public MainTable(MainTableDataModel model, // Enable sorting model.getEntriesFilteredAndSorted().comparatorProperty().bind(this.comparatorProperty()); - this.getStylesheets().add(MainTable.class.getResource("MainTable.css").toExternalForm()); + this.getStylesheets().add(Objects.requireNonNull(MainTable.class.getResource("MainTable.css")).toExternalForm()); // Store visual state new PersistenceVisualStateTable(this, mainTablePreferences.getColumnPreferences()).addListeners(); diff --git a/src/main/java/org/jabref/gui/theme/StyleSheetFile.java b/src/main/java/org/jabref/gui/theme/StyleSheetFile.java index 0fb16e363c4..9401e51b18b 100644 --- a/src/main/java/org/jabref/gui/theme/StyleSheetFile.java +++ b/src/main/java/org/jabref/gui/theme/StyleSheetFile.java @@ -113,10 +113,10 @@ static Optional getDataUrl(URL url) { byte[] data = inputStream.readNBytes(MAX_IN_MEMORY_CSS_LENGTH); if (data.length < MAX_IN_MEMORY_CSS_LENGTH) { String embeddedDataUrl = DATA_URL_PREFIX + Base64.getEncoder().encodeToString(data); - LOGGER.debug("Embedded css in data URL of length {}", embeddedDataUrl.length()); + LOGGER.trace("Embedded css in data URL of length {}", embeddedDataUrl.length()); return Optional.of(embeddedDataUrl); } else { - LOGGER.debug("Not embedding css in data URL as the length is >= {}", MAX_IN_MEMORY_CSS_LENGTH); + LOGGER.trace("Not embedding css in data URL as the length is >= {}", MAX_IN_MEMORY_CSS_LENGTH); } } } catch (IOException e) { diff --git a/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java b/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java index a5e4d009d32..a3c6e37a934 100644 --- a/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java +++ b/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java @@ -129,7 +129,7 @@ private List getXmpMetadata(PDDocument document) { try { metaList.add(XmpUtilShared.parseXmpMetadata(new ByteArrayInputStream(xmpMetaString.getBytes()))); } catch (IOException ex) { - LOGGER.warn("Problem parsing XMP schema. Continuing with other schemas.", ex); + LOGGER.debug("Problem parsing XMP schema. Continuing with other schemas.", ex); } } return metaList; diff --git a/src/main/java/org/jabref/model/search/Analyzer/LatexToUnicodeFoldingFilter.java b/src/main/java/org/jabref/model/search/Analyzer/LatexToUnicodeFoldingFilter.java index 786378ed344..5cd7fd64042 100644 --- a/src/main/java/org/jabref/model/search/Analyzer/LatexToUnicodeFoldingFilter.java +++ b/src/main/java/org/jabref/model/search/Analyzer/LatexToUnicodeFoldingFilter.java @@ -83,7 +83,7 @@ public static FoldingResult foldToUnicode(char[] input, int inputPos, int length char[] subArray = Arrays.copyOfRange(input, inputPos, inputPos + length); String s = new String(subArray); String result = FORMATTER.format(s); - LOGGER.debug("Folding {} to {}", s, result); + LOGGER.trace("Folding {} to {}", s, result); return new FoldingResult(result.toCharArray(), result.length()); } } diff --git a/src/main/resources/tinylog.properties b/src/main/resources/tinylog.properties index a1168dd1506..0d5ea5c4a90 100644 --- a/src/main/resources/tinylog.properties +++ b/src/main/resources/tinylog.properties @@ -7,6 +7,12 @@ writerConsole.format = {date} [{thread}] {class}.{method}()\n{level}: {message}\ # More shrunk exception logs. See https://tinylog.org/v2/configuration/#strip-stack-trace-elements for details exception = strip: jdk.internal +level@org.apache.pdfbox.pdmodel.font = error +level@org.apache.pdfbox.pdmodel.PDSimpleFont = error +level@org.apache.fontbox.util.autodetect.FontFileFinder = warn +level@org.apache.fontbox.ttf = warn +level@ai.djl = info + #level@org.jabref.model.entry.BibEntry = debug #level@org.jabref.gui.maintable.PersistenceVisualStateTable = debug @@ -15,6 +21,7 @@ level@org.jabref.http.server.Server = debug #level@org.jabref.gui.JabRefGUI = debug # AI debugging +#level@ai.djl = debug #level@org.jabref.gui.entryeditor.aichattab.AiChat = trace #level@org.jabref.gui.JabRefGUI = trace #level@org.jabref.logic.ai.AiService = trace From 9fc4ae5753ae14e3143cfa052cd9a1899e7083e4 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sun, 8 Sep 2024 00:44:11 +0200 Subject: [PATCH 014/324] Add parser test (#11726) --- .../logic/importer/fileformat/BibtexParserTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java index f0ff769ee1c..e38ab786aaa 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java @@ -662,6 +662,18 @@ void parseRecognizesFieldsWithEscapedQuotationMarks() throws IOException { assertEquals(List.of(expected), result.getDatabase().getEntries()); } + @Test + void parseRecognizesFieldsWithQuotationMarksInBrackets() throws IOException { + ParserResult result = parser + .parse(new StringReader("@article{test,title=\"Comments on {\"}Filenames and Fonts{\"}\"}")); + + BibEntry expected = new BibEntry(StandardEntryType.Article) + .withCitationKey("test") + .withField(StandardField.TITLE, "Comments on {\"}Filenames and Fonts{\"}"); + + assertEquals(List.of(expected), result.getDatabase().getEntries()); + } + @Test void parseIgnoresAndWarnsAboutEntryWithFieldsThatAreNotSeperatedByComma() throws IOException { ParserResult result = parser From 7965eaa4f2e874772cf00f72cfcf6d5320eee550 Mon Sep 17 00:00:00 2001 From: leaf-soba Date: Sun, 8 Sep 2024 16:47:11 +0800 Subject: [PATCH 015/324] Add abstract param layout formatter test (#11713) * Rename "Show 'Ai Chat' tab" to "Show tab 'AI Chat'" solve #11708 * add unit test and refactor parseArgument add unit test and refactor AbstractParamLayoutFormatter.parseArgument * rewrite the test method name rewrite the test method name --- .../layout/AbstractParamLayoutFormatter.java | 52 ++++++----- .../AbstractParamLayoutFormatterTest.java | 88 +++++++++++++++++++ 2 files changed, 116 insertions(+), 24 deletions(-) create mode 100644 src/test/java/org/jabref/logic/layout/format/AbstractParamLayoutFormatterTest.java diff --git a/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java b/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java index bbd1344ddf9..44209654bb6 100644 --- a/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java +++ b/src/main/java/org/jabref/logic/layout/AbstractParamLayoutFormatter.java @@ -26,34 +26,38 @@ protected static List parseArgument(String arg) { StringBuilder current = new StringBuilder(); boolean escaped = false; for (int i = 0; i < arg.length(); i++) { - if ((arg.charAt(i) == AbstractParamLayoutFormatter.SEPARATOR) && !escaped) { - parts.add(current.toString()); - current = new StringBuilder(); - } else if (arg.charAt(i) == '\\') { - if (escaped) { - escaped = false; - current.append(arg.charAt(i)); - } else { - escaped = true; - } - } else if (escaped) { - // Handle newline and tab: - if (arg.charAt(i) == 'n') { - current.append('\n'); - } else if (arg.charAt(i) == 't') { - current.append('\t'); - } else { - if ((arg.charAt(i) != ',') && (arg.charAt(i) != '"')) { - current.append('\\'); - } - current.append(arg.charAt(i)); - } + char currentChar = arg.charAt(i); + if (escaped) { + handleEscapedCharacter(current, currentChar); escaped = false; + } else if (currentChar == '\\') { + escaped = true; + } else if (currentChar == AbstractParamLayoutFormatter.SEPARATOR) { + addPart(parts, current); } else { - current.append(arg.charAt(i)); + current.append(currentChar); } } - parts.add(current.toString()); + addPart(parts, current); return parts; } + + private static void handleEscapedCharacter(StringBuilder current, char currentChar) { + switch (currentChar) { + case 'n' -> current.append('\n'); + case 't' -> current.append('\t'); + case ',' -> current.append(','); + case '"' -> current.append('"'); + case '\\' -> current.append('\\'); + default -> { + current.append('\\'); + current.append(currentChar); + } + } + } + + private static void addPart(List parts, StringBuilder current) { + parts.add(current.toString()); + current.setLength(0); + } } diff --git a/src/test/java/org/jabref/logic/layout/format/AbstractParamLayoutFormatterTest.java b/src/test/java/org/jabref/logic/layout/format/AbstractParamLayoutFormatterTest.java new file mode 100644 index 00000000000..6cc2ede6ed0 --- /dev/null +++ b/src/test/java/org/jabref/logic/layout/format/AbstractParamLayoutFormatterTest.java @@ -0,0 +1,88 @@ +package org.jabref.logic.layout.format; + +import java.util.List; + +import org.jabref.logic.layout.AbstractParamLayoutFormatter; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AbstractParamLayoutFormatterTest { + static class ParseArgumentTester extends AbstractParamLayoutFormatter { + public static List callParseArgument(String arg) { + return parseArgument(arg); + } + + @Override + public String format(String fieldText) { + return null; + } + + @Override + public void setArgument(String arg) { + } + } + + @Test + void simpleArguments() { + String input = "arg1,arg2,arg3"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1", "arg2", "arg3"), result, + "Simple arguments should be split correctly by commas"); + } + + @Test + void escapedCommas() { + String input = "arg1\\,arg2,arg3"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1,arg2", "arg3"), result, + "Escaped commas should be treated as literal commas"); + } + + @Test + void escapedBackslash() { + String input = "arg1\\\\,arg2"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1\\", "arg2"), result, "Escaped backslashes should be treated correctly"); + } + + @Test + void emptyArgument() { + String input = ""; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of(""), result, "Empty string should return a list with an empty string"); + } + + @Test + void singleArgument() { + String input = "singleArg"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("singleArg"), result, + "Single argument should return a list with the argument itself"); + } + + @Test + void newlineAndTabEscapeSequences() { + String input = "arg1\\narg2\\targ3"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1\narg2\targ3"), result, + "Escape sequences like newline and tab should be handled correctly"); + } + + @Test + void multipleEscapedCharacters() { + String input = "arg1\\n,arg2\\t,arg3\\,arg4"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1\n", "arg2\t", "arg3,arg4"), result, + "Multiple escaped characters should be handled correctly"); + } + + @Test + void mixedCases() { + String input = "arg1,arg2\\,withComma,arg3\\nnewline,arg4\\\\backslash"; + List result = ParseArgumentTester.callParseArgument(input); + assertEquals(List.of("arg1", "arg2,withComma", "arg3\nnewline", "arg4\\backslash"), result, + "Mixed cases should be parsed correctly"); + } +} From d8b935e76d9cc5e24572e3e663fbc0b9fca25f59 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 8 Sep 2024 11:13:26 +0200 Subject: [PATCH 016/324] Adds OpenFastTrace for requirements tracking (#11710) * Initial requirement * Initial requirement * Add OpenFastTrace * Fix linting * Remove wrong disable rule --- .github/workflows/tests.yml | 16 ++++++ build.gradle | 6 +++ docs/contributing.md | 2 + docs/requirements/ai.md | 16 ++++++ docs/requirements/index.md | 49 +++++++++++++++++++ .../chatprompt/ChatPromptComponent.java | 1 + 6 files changed, 90 insertions(+) create mode 100644 docs/requirements/ai.md create mode 100644 docs/requirements/index.md diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3edf09d599c..b4fd2c565f2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -332,6 +332,22 @@ jobs: env: CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} + requirements_coverage: + name: "Validate requiremenet coverage" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + show-progress: 'false' + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: 21.0.2 + distribution: 'temurin' + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - run: ./gradlew traceRequirements + # This is https://github.com/marketplace/actions/gradle-wrapper-validation # It ensures that the jar file is from gradle and not by a strange third party. gradlevalidation: diff --git a/build.gradle b/build.gradle index 9bd82d66fb8..064c2cbf97a 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,8 @@ plugins { id 'idea' id 'org.openrewrite.rewrite' version '6.20.0' + + id "org.itsallcode.openfasttrace" version "3.0.0" } // Enable following for debugging @@ -898,3 +900,7 @@ jmh { iterations = 10 fork = 2 } + +requirementTracing { + inputDirectories = files('docs', 'src/main/java', 'src/test/java') +} diff --git a/docs/contributing.md b/docs/contributing.md index 0e64dfe09b0..d827129b175 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -112,3 +112,5 @@ If you want to indicate that a pull request is not yet complete **before** creat For improving developer's documentation, go on at the [docs/ subdirectory of JabRef's code](https://github.com/JabRef/jabref/tree/main/docs) and edit the file. GitHub offers a good guide at [Editing files in another user's repository](https://help.github.com/en/github/managing-files-in-a-repository/editing-files-in-another-users-repository). + +One can also add [callouts](https://just-the-docs.github.io/just-the-docs-tests/components/callouts/). diff --git a/docs/requirements/ai.md b/docs/requirements/ai.md new file mode 100644 index 00000000000..dfe6be9f004 --- /dev/null +++ b/docs/requirements/ai.md @@ -0,0 +1,16 @@ +--- +parent: Requirements +--- +# AI + +## User Interface + +### Chatting with AI +`req~ai.chat.new-message-based-on-previous~1` + +To enable simple editing and resending of previous messages, Cursor Up should show last message. +This should only happen if the current text field is empty. + +Needs: impl + + diff --git a/docs/requirements/index.md b/docs/requirements/index.md new file mode 100644 index 00000000000..bee1af1c590 --- /dev/null +++ b/docs/requirements/index.md @@ -0,0 +1,49 @@ +--- +nav_order: 7 +has_children: true +--- +# Requirements + +This part of the documentation collects requirements using [OpenFastTrace](https://github.com/itsallcode/openfasttrace). + +## Specifying requirements + +One writes directly below a Markdown heading a requirement identifier. + +Example: + +```markdown +### Example +`req~ai.example~1` +``` + +It is important that there is no empty line directly after the heading. + +{: note} +One needs to add `` to the end of the file, because the id of the requirement needs to follow the heading directly. + +## Linking implementations + +Then, one writes down at the requirement. +Directly at the end, one writes that it requires an implementation: + +```markdown +Needs: impl +``` + +One can also state that there should be detailed design document (`dsn`). +However, typically in JabRef, we go from the requirement directly to the implementation. + +Then, at the implementation, a comment is added this implementation is covered: + +```java +// [impl->req~ai.example~1] +``` + +When executing the gradle task `traceRequirements`, `build/tracing.txt` is generated. +In case of a tracing error, one can inspect this file to see which requirements were not covered. + +## More Information + +- [User manual of OpenFastTrace](https://github.com/itsallcode/openfasttrace/blob/main/doc/user_guide.md) +- We cannot copy and paste real examples here, because of [openfasttrace#280](https://github.com/itsallcode/openfasttrace/issues/280). diff --git a/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.java b/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.java index d89fbb6be05..8bb590103ac 100644 --- a/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.java @@ -88,6 +88,7 @@ private void initialize() { // will be true (this is important). } } else if (keyEvent.getCode() == KeyCode.UP) { + // [impl->req~ai.chat.new-message-based-on-previous~1] if ((currentUserMessageScroll.get() < history.get().size() - 1) && (userPromptTextArea.getText().isEmpty() || showingHistoryMessage.get())) { // 1. We should not go up the maximum number of user messages. // 2. We can scroll history only on two conditions: From 17b7697f7eb75a13b29147a801c9fe9918c94523 Mon Sep 17 00:00:00 2001 From: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Date: Sun, 8 Sep 2024 13:32:39 +0200 Subject: [PATCH 017/324] Show only one notification when cutting an entry (#11724) * Move cut and copy out of MainTable into LibraryTab * Move ImportHandler to LibraryTab and Reword methods * Seperated notifications * l10n * CHANGELOG.md * Wording consistency --- CHANGELOG.md | 3 +- src/main/java/org/jabref/gui/LibraryTab.java | 254 +++++++++++------- .../java/org/jabref/gui/edit/EditAction.java | 8 +- .../jabref/gui/entryeditor/EntryEditor.java | 2 +- .../org/jabref/gui/frame/JabRefFrame.java | 1 - .../jabref/gui/importer/NewEntryAction.java | 2 +- .../importer/actions/OpenDatabaseAction.java | 1 - .../org/jabref/gui/maintable/MainTable.java | 88 +----- .../gui/openoffice/OpenOfficePanel.java | 1 - .../gui/shared/SharedDatabaseUIManager.java | 1 - src/main/resources/l10n/JabRef_en.properties | 3 + 11 files changed, 169 insertions(+), 195 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c307ed39c5..e2a090ea191 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed an issue where the full-text search results were incomplete. [#8626](https://github.com/JabRef/jabref/issues/8626) - We fixed an issue where search result highlighting was incorrectly highlighting the boolean operators. [#11595](https://github.com/JabRef/jabref/issues/11595) - We fixed an issue where search result highlighting was broken at complex searches. [#8067](https://github.com/JabRef/jabref/issues/8067) -- We fixed an issue where unescaped braces in the arXiv fetcher were not treated [#11704](https://github.com/JabRef/jabref/issues/11704) +- We fixed an issue where two contradicting notifications were shown when cutting an entry in the main table. [#11724](https://github.com/JabRef/jabref/pull/11724) +- We fixed an issue where unescaped braces in the arXiv fetcher were not treated. [#11704](https://github.com/JabRef/jabref/issues/11704) ### Removed diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index 0542c7023fe..d17a0a1871e 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -1,5 +1,6 @@ package org.jabref.gui; +import java.io.IOException; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -46,6 +47,7 @@ import org.jabref.gui.dialogs.AutosaveUiManager; import org.jabref.gui.entryeditor.EntryEditor; import org.jabref.gui.exporter.SaveDatabaseAction; +import org.jabref.gui.externalfiles.ImportHandler; import org.jabref.gui.fieldeditors.LinkedFileViewModel; import org.jabref.gui.importer.actions.OpenDatabaseAction; import org.jabref.gui.linkedfile.DeleteFileAction; @@ -63,15 +65,16 @@ import org.jabref.gui.util.OptionalObjectProperty; import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.UiTaskExecutor; -import org.jabref.logic.ai.AiService; import org.jabref.logic.citationstyle.CitationStyleCache; +import org.jabref.logic.importer.FetcherClientException; +import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.importer.FetcherServerException; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; import org.jabref.logic.pdf.FileAnnotationCache; import org.jabref.logic.search.LuceneManager; import org.jabref.logic.shared.DatabaseLocation; -import org.jabref.logic.util.UpdateField; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; @@ -82,6 +85,7 @@ import org.jabref.model.entry.Author; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.model.entry.BibtexString; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.FieldChangedEvent; @@ -118,7 +122,6 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private final CountingUndoManager undoManager; private final DialogService dialogService; private final PreferencesService preferencesService; - private final AiService aiService; private final FileUpdateMonitor fileUpdateMonitor; private final StateManager stateManager; private final BibEntryTypesManager entryTypesManager; @@ -162,6 +165,8 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private final ClipBoardManager clipBoardManager; private final TaskExecutor taskExecutor; private final DirectoryMonitorManager directoryMonitorManager; + + private ImportHandler importHandler; private LuceneManager luceneManager; /** @@ -174,7 +179,6 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext, LibraryTabContainer tabContainer, DialogService dialogService, PreferencesService preferencesService, - AiService aiService, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, @@ -187,7 +191,6 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext, this.undoManager = undoManager; this.dialogService = dialogService; this.preferencesService = Objects.requireNonNull(preferencesService); - this.aiService = Objects.requireNonNull(aiService); this.stateManager = Objects.requireNonNull(stateManager); this.fileUpdateMonitor = fileUpdateMonitor; this.entryTypesManager = entryTypesManager; @@ -222,6 +225,14 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { new CitationStyleCache(bibDatabaseContext); annotationCache = new FileAnnotationCache(bibDatabaseContext, preferencesService.getFilePreferences()); + importHandler = new ImportHandler( + bibDatabaseContext, + preferencesService, + fileUpdateMonitor, + undoManager, + stateManager, + dialogService, + taskExecutor); setupMainPanel(); setupAutoCompletion(); @@ -449,63 +460,6 @@ public SuggestionProviders getSuggestionProviders() { return suggestionProviders; } - /** - * Removes the selected entries and files linked to selected entries from the database - * - * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" - */ - public void delete(StandardActions mode) { - delete(mode, mainTable.getSelectedEntries()); - } - - /** - * Removes the selected entries and files linked to selected entries from the database - * - * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" - */ - private void delete(StandardActions mode, List entries) { - if (entries.isEmpty()) { - return; - } - if (mode == StandardActions.DELETE_ENTRY && !showDeleteConfirmationDialog(entries.size())) { - return; - } - - // Delete selected entries - getUndoManager().addEdit(new UndoableRemoveEntries(bibDatabaseContext.getDatabase(), entries, mode == StandardActions.CUT)); - bibDatabaseContext.getDatabase().removeEntries(entries); - - if (mode != StandardActions.CUT) { - List linkedFileList = entries.stream() - .flatMap(entry -> entry.getFiles().stream()) - .distinct() - .toList(); - - if (!linkedFileList.isEmpty()) { - List viewModels = linkedFileList.stream() - .map(linkedFile -> linkedFile.toModel(null, bibDatabaseContext, null, null, preferencesService)) - .collect(Collectors.toList()); - - new DeleteFileAction(dialogService, preferencesService.getFilePreferences(), bibDatabaseContext, viewModels).execute(); - } - } - - ensureNotShowingBottomPanel(entries); - - this.changedProperty.setValue(true); - switch (mode) { - case StandardActions.CUT -> dialogService.notify(Localization.lang("Cut %0 entry(ies)", entries.size())); - case StandardActions.DELETE_ENTRY -> dialogService.notify(Localization.lang("Deleted %0 entry(ies)", entries.size())); - } - - // prevent the main table from loosing focus - mainTable.requestFocus(); - } - - public void delete(BibEntry entry) { - delete(StandardActions.DELETE_ENTRY, Collections.singletonList(entry)); - } - public void registerUndoableChanges(List changes) { NamedCompound ce = new NamedCompound(Localization.lang("Save actions")); for (FieldChange change : changes) { @@ -517,31 +471,6 @@ public void registerUndoableChanges(List changes) { } } - public void insertEntry(final BibEntry bibEntry) { - if (bibEntry != null) { - insertEntries(Collections.singletonList(bibEntry)); - } - } - - public void insertEntries(final List entries) { - if (!entries.isEmpty()) { - bibDatabaseContext.getDatabase().insertEntries(entries); - - // Set owner and timestamp - UpdateField.setAutomaticFields(entries, - preferencesService.getOwnerPreferences(), - preferencesService.getTimestampPreferences()); - // Create an UndoableInsertEntries object. - getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries)); - - this.changedProperty.setValue(true); // The database just changed. - if (preferencesService.getEntryEditorPreferences().shouldOpenOnNewEntry()) { - showAndEdit(entries.getFirst()); - } - clearAndSelect(entries.getFirst()); - } - } - public void editEntryAndFocusField(BibEntry entry, Field field) { showAndEdit(entry); Platform.runLater(() -> { @@ -563,7 +492,7 @@ private void createMainTable() { clipBoardManager, entryTypesManager, taskExecutor, - fileUpdateMonitor); + importHandler); // Add the listener that binds selection to state manager (TODO: should be replaced by proper JavaFX binding as soon as table is implemented in JavaFX) // content binding between StateManager#getselectedEntries and mainTable#getSelectedEntries does not work here as it does not trigger the ActionHelper#needsEntriesSelected checker for the menubar mainTable.addSelectionListener(event -> { @@ -949,20 +878,151 @@ public void resetChangeMonitor() { stateManager)); } - public void copy() { - mainTable.copy(); + public void insertEntry(final BibEntry bibEntry) { + insertEntries(List.of(bibEntry)); + } + + public void insertEntries(final List entries) { + if (!entries.isEmpty()) { + importHandler.importCleanedEntries(entries); + + // Create an UndoableInsertEntries object. + getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries)); + + markBaseChanged(); + if (preferencesService.getEntryEditorPreferences().shouldOpenOnNewEntry()) { + showAndEdit(entries.getFirst()); + } + clearAndSelect(entries.getFirst()); + } + } + + public void copyEntry() { + int entriesCopied = doCopyEntry(getSelectedEntries()); + if (entriesCopied >= 0) { + dialogService.notify(Localization.lang("Copied %0 entry(ies)", entriesCopied)); + } else { + dialogService.notify(Localization.lang("Copy failed", entriesCopied)); + } } - public void paste() { - mainTable.paste(); + private int doCopyEntry(List selectedEntries) { + if (!selectedEntries.isEmpty()) { + List stringConstants = bibDatabaseContext.getDatabase().getUsedStrings(selectedEntries); + try { + if (stringConstants.isEmpty()) { + clipBoardManager.setContent(selectedEntries, entryTypesManager); + } else { + clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants); + } + return selectedEntries.size(); + } catch (IOException e) { + LOGGER.error("Error while copying selected entries to clipboard.", e); + return -1; + } + } + + return 0; + } + + public void pasteEntry() { + List entriesToAdd; + String content = ClipBoardManager.getContents(); + entriesToAdd = importHandler.handleBibTeXData(content); + if (entriesToAdd.isEmpty()) { + entriesToAdd = handleNonBibTeXStringData(content); + } + if (entriesToAdd.isEmpty()) { + return; + } + + importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); + } + + private List handleNonBibTeXStringData(String data) { + try { + return this.importHandler.handleStringData(data); + } catch ( + FetcherException exception) { + if (exception instanceof FetcherClientException) { + dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("No data was found for the identifier")); + } else if (exception instanceof FetcherServerException) { + dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("Server not available")); + } else { + dialogService.showErrorDialogAndWait(exception); + } + return List.of(); + } } public void dropEntry(List entriesToAdd) { - mainTable.dropEntry(entriesToAdd); + importHandler.importEntriesWithDuplicateCheck(bibDatabaseContext, entriesToAdd); } - public void cut() { - mainTable.cut(); + public void cutEntry() { + int entriesCopied = doCopyEntry(getSelectedEntries()); + int entriesDeleted = doDeleteEntry(StandardActions.CUT, mainTable.getSelectedEntries()); + + if (entriesCopied == entriesDeleted) { + dialogService.notify(Localization.lang("Cut %0 entry(ies)", entriesCopied)); + } else { + dialogService.notify(Localization.lang("Cut failed", entriesCopied)); + undoManager.undo(); + clipBoardManager.setContent(""); + } + } + + /** + * Removes the selected entries and files linked to selected entries from the database + */ + public void deleteEntry() { + int entriesDeleted = doDeleteEntry(StandardActions.DELETE_ENTRY, mainTable.getSelectedEntries()); + dialogService.notify(Localization.lang("Deleted %0 entry(ies)", entriesDeleted)); + } + + public void deleteEntry(BibEntry entry) { + doDeleteEntry(StandardActions.DELETE_ENTRY, Collections.singletonList(entry)); + } + + /** + * Removes the selected entries and files linked to selected entries from the database + * + * @param mode If DELETE_ENTRY the user will get asked if he really wants to delete the entries, and it will be localized as "deleted". If true the action will be localized as "cut" + */ + private int doDeleteEntry(StandardActions mode, List entries) { + if (entries.isEmpty()) { + return 0; + } + if (mode == StandardActions.DELETE_ENTRY && !showDeleteConfirmationDialog(entries.size())) { + return -1; + } + + // Delete selected entries + getUndoManager().addEdit(new UndoableRemoveEntries(bibDatabaseContext.getDatabase(), entries, mode == StandardActions.CUT)); + bibDatabaseContext.getDatabase().removeEntries(entries); + + if (mode != StandardActions.CUT) { + List linkedFileList = entries.stream() + .flatMap(entry -> entry.getFiles().stream()) + .distinct() + .toList(); + + if (!linkedFileList.isEmpty()) { + List viewModels = linkedFileList.stream() + .map(linkedFile -> linkedFile.toModel(null, bibDatabaseContext, null, null, preferencesService)) + .collect(Collectors.toList()); + + new DeleteFileAction(dialogService, preferencesService.getFilePreferences(), bibDatabaseContext, viewModels).execute(); + } + } + + ensureNotShowingBottomPanel(entries); + markBaseChanged(); + + // prevent the main table from loosing focus + mainTable.requestFocus(); + + return entries.size(); } public boolean isModified() { @@ -993,7 +1053,6 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi Path file, DialogService dialogService, PreferencesService preferencesService, - AiService aiService, StateManager stateManager, LibraryTabContainer tabContainer, FileUpdateMonitor fileUpdateMonitor, @@ -1009,7 +1068,6 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, @@ -1031,7 +1089,6 @@ public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, LibraryTabContainer tabContainer, DialogService dialogService, PreferencesService preferencesService, - AiService aiService, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, @@ -1045,7 +1102,6 @@ public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, diff --git a/src/main/java/org/jabref/gui/edit/EditAction.java b/src/main/java/org/jabref/gui/edit/EditAction.java index 2c870a821cb..c6be070e0e8 100644 --- a/src/main/java/org/jabref/gui/edit/EditAction.java +++ b/src/main/java/org/jabref/gui/edit/EditAction.java @@ -78,10 +78,10 @@ public void execute() { // Not sure what is selected -> copy/paste/cut selected entries except for Preview and CodeArea switch (action) { - case COPY -> tabSupplier.get().copy(); - case CUT -> tabSupplier.get().cut(); - case PASTE -> tabSupplier.get().paste(); - case DELETE_ENTRY -> tabSupplier.get().delete(StandardActions.DELETE_ENTRY); + case COPY -> tabSupplier.get().copyEntry(); + case CUT -> tabSupplier.get().cutEntry(); + case PASTE -> tabSupplier.get().pasteEntry(); + case DELETE_ENTRY -> tabSupplier.get().deleteEntry(); case UNDO -> { if (undoManager.canUndo()) { undoManager.undo(); diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 67be8a5f908..e13eb0ecb6c 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -249,7 +249,7 @@ public void close() { @FXML private void deleteEntry() { - libraryTab.delete(currentlyEditedEntry); + libraryTab.deleteEntry(currentlyEditedEntry); } @FXML diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index 499b47162bc..15e98498ef8 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -434,7 +434,6 @@ public void addTab(@NonNull BibDatabaseContext databaseContext, boolean raisePan this, dialogService, prefs, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, diff --git a/src/main/java/org/jabref/gui/importer/NewEntryAction.java b/src/main/java/org/jabref/gui/importer/NewEntryAction.java index a47e1a9f6c6..6a3e70cc249 100644 --- a/src/main/java/org/jabref/gui/importer/NewEntryAction.java +++ b/src/main/java/org/jabref/gui/importer/NewEntryAction.java @@ -43,7 +43,7 @@ public NewEntryAction(Supplier tabSupplier, DialogService dialogServ public NewEntryAction(Supplier tabSupplier, EntryType type, DialogService dialogService, PreferencesService preferences, StateManager stateManager) { this(tabSupplier, dialogService, preferences, stateManager); - this.type = Optional.of(type); + this.type = Optional.ofNullable(type); } @Override diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index 97ccf23758d..2074b7f4081 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -200,7 +200,6 @@ private void openTheFile(Path file) { file, dialogService, preferencesService, - aiService, stateManager, tabContainer, fileUpdateMonitor, diff --git a/src/main/java/org/jabref/gui/maintable/MainTable.java b/src/main/java/org/jabref/gui/maintable/MainTable.java index ecce71476de..6b8fcd4d53b 100644 --- a/src/main/java/org/jabref/gui/maintable/MainTable.java +++ b/src/main/java/org/jabref/gui/maintable/MainTable.java @@ -1,7 +1,6 @@ package org.jabref.gui.maintable; import java.io.File; -import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -45,17 +44,11 @@ import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.UiTaskExecutor; import org.jabref.gui.util.ViewModelTableRowFactory; -import org.jabref.logic.importer.FetcherClientException; -import org.jabref.logic.importer.FetcherException; -import org.jabref.logic.importer.FetcherServerException; import org.jabref.logic.journals.JournalAbbreviationRepository; -import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.event.EntriesAddedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; -import org.jabref.model.entry.BibtexString; -import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.FilePreferences; import org.jabref.preferences.PreferencesService; @@ -74,18 +67,14 @@ public class MainTable extends TableView { private static final PseudoClass NOT_MATCHING_SEARCH_AND_GROUPS = PseudoClass.getPseudoClass("not-matching-search-and-groups"); private final LibraryTab libraryTab; - private final DialogService dialogService; private final StateManager stateManager; private final BibDatabaseContext database; private final MainTableDataModel model; - - private final ImportHandler importHandler; private final CustomLocalDragboard localDragboard; - private final ClipBoardManager clipBoardManager; - private final BibEntryTypesManager entryTypesManager; private final TaskExecutor taskExecutor; private final UndoManager undoManager; private final FilePreferences filePreferences; + private final ImportHandler importHandler; private long lastKeyPressTime; private String columnSearchTerm; @@ -100,31 +89,20 @@ public MainTable(MainTableDataModel model, ClipBoardManager clipBoardManager, BibEntryTypesManager entryTypesManager, TaskExecutor taskExecutor, - FileUpdateMonitor fileUpdateMonitor) { + ImportHandler importHandler) { super(); this.libraryTab = libraryTab; - this.dialogService = dialogService; this.stateManager = stateManager; this.database = Objects.requireNonNull(database); this.model = model; - this.clipBoardManager = clipBoardManager; - this.entryTypesManager = entryTypesManager; this.taskExecutor = taskExecutor; this.undoManager = libraryTab.getUndoManager(); this.filePreferences = preferencesService.getFilePreferences(); + this.importHandler = importHandler; MainTablePreferences mainTablePreferences = preferencesService.getMainTablePreferences(); - importHandler = new ImportHandler( - database, - preferencesService, - fileUpdateMonitor, - undoManager, - stateManager, - dialogService, - taskExecutor); - localDragboard = stateManager.getLocalDragboard(); this.setOnDragOver(this::handleOnDragOverTableView); @@ -272,29 +250,6 @@ public void clearAndSelect(BibEntry bibEntry) { }); } - public void copy() { - List selectedEntries = getSelectedEntries(); - - if (!selectedEntries.isEmpty()) { - List stringConstants = getUsedStringValues(selectedEntries); - try { - if (stringConstants.isEmpty()) { - clipBoardManager.setContent(selectedEntries, entryTypesManager); - } else { - clipBoardManager.setContent(selectedEntries, entryTypesManager, stringConstants); - } - dialogService.notify(Localization.lang("Copied %0 entry(ies)", selectedEntries.size())); - } catch (IOException e) { - LOGGER.error("Error while copying selected entries to clipboard.", e); - } - } - } - - public void cut() { - copy(); - libraryTab.delete(StandardActions.CUT); - } - private void scrollToNextMatchCategory() { BibEntryTableViewModel selectedEntry = getSelectionModel().getSelectedItem(); if (selectedEntry == null) { @@ -403,39 +358,6 @@ private void clearAndSelectLast() { scrollTo(getItems().size() - 1); } - public void paste() { - List entriesToAdd; - String content = ClipBoardManager.getContents(); - entriesToAdd = importHandler.handleBibTeXData(content); - if (entriesToAdd.isEmpty()) { - entriesToAdd = handleNonBibTeXStringData(content); - } - if (entriesToAdd.isEmpty()) { - return; - } - - importHandler.importEntriesWithDuplicateCheck(database, entriesToAdd); - } - - private List handleNonBibTeXStringData(String data) { - try { - return this.importHandler.handleStringData(data); - } catch (FetcherException exception) { - if (exception instanceof FetcherClientException) { - dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("No data was found for the identifier")); - } else if (exception instanceof FetcherServerException) { - dialogService.showInformationDialogAndWait(Localization.lang("Look up identifier"), Localization.lang("Server not available")); - } else { - dialogService.showErrorDialogAndWait(exception); - } - return List.of(); - } - } - - public void dropEntry(List entriesToAdd) { - importHandler.importEntriesWithDuplicateCheck(database, entriesToAdd); - } - private void handleOnDragOver(TableRow row, BibEntryTableViewModel item, DragEvent event) { if (event.getDragboard().hasFiles()) { event.acceptTransferModes(TransferMode.ANY); @@ -558,8 +480,4 @@ private Optional findEntry(BibEntry entry) { .filter(viewModel -> viewModel.getEntry().equals(entry)) .findFirst(); } - - private List getUsedStringValues(List entries) { - return database.getDatabase().getUsedStrings(entries); - } } diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index c4416876ed8..4eb29ff872f 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -310,7 +310,6 @@ private void exportEntries() { tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, diff --git a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java index d6ef1dce709..480ecab64ff 100644 --- a/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java +++ b/src/main/java/org/jabref/gui/shared/SharedDatabaseUIManager.java @@ -176,7 +176,6 @@ public LibraryTab openNewSharedDatabaseTab(DBMSConnectionProperties dbmsConnecti tabContainer, dialogService, preferencesService, - aiService, stateManager, fileUpdateMonitor, entryTypesManager, diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 5ff0d0364d7..990890c3fc4 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2765,6 +2765,9 @@ Ask\ every\ time=Ask every time Value\ is\ not\ in\ Unicode's\ Normalization\ Form\ "Canonical\ Composition"\ (NFC)\ format=Value is not in Unicode's Normalization Form "Canonical Composition" (NFC) format +Copy\ failed=Copy failed +Cut\ failed=Cut failed + Group\ icons=Group icons Redownload\ file=Redownload file Redownload\ missing\ files=Redownload missing files From 0b305abaa99f589e7d32b4b6c20d43fb4d03f57e Mon Sep 17 00:00:00 2001 From: Ruslan Date: Sun, 8 Sep 2024 14:48:04 +0300 Subject: [PATCH 018/324] Remove unnecessary AI dependencies (#11727) * Remove unnecessary AI dependencies * Remove AiApiKeyProvider.java * Fix checkers --- src/main/java/org/jabref/Launcher.java | 2 - src/main/java/org/jabref/gui/JabRefGUI.java | 2 - .../jabref/gui/entryeditor/EntryEditor.java | 2 - .../org/jabref/gui/preferences/ai/AiTab.java | 6 +- .../gui/preferences/ai/AiTabViewModel.java | 21 ++--- .../java/org/jabref/logic/ai/AiService.java | 4 +- .../model/JabRefChatLanguageModel.java | 14 ++-- .../model/JvmOpenAiChatLanguageModel.java | 5 +- .../jabref/preferences/JabRefPreferences.java | 35 +------- .../preferences/PreferencesService.java | 9 --- .../preferences/ai/AiApiKeyProvider.java | 7 -- .../jabref/preferences/ai/AiPreferences.java | 80 +++++++++++-------- 12 files changed, 66 insertions(+), 121 deletions(-) delete mode 100644 src/main/java/org/jabref/preferences/ai/AiApiKeyProvider.java diff --git a/src/main/java/org/jabref/Launcher.java b/src/main/java/org/jabref/Launcher.java index 117c9fd5c1c..fa891388f98 100644 --- a/src/main/java/org/jabref/Launcher.java +++ b/src/main/java/org/jabref/Launcher.java @@ -36,7 +36,6 @@ import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.JabRefPreferences; import org.jabref.preferences.PreferencesService; -import org.jabref.preferences.ai.AiApiKeyProvider; import com.airhacks.afterburner.injection.Injector; import org.apache.commons.cli.ParseException; @@ -64,7 +63,6 @@ public static void main(String[] args) { // Initialize preferences final JabRefPreferences preferences = JabRefPreferences.getInstance(); Injector.setModelOrService(PreferencesService.class, preferences); - Injector.setModelOrService(AiApiKeyProvider.class, preferences); // Early exit in case another instance is already running if (!handleMultipleAppInstances(args, preferences.getRemotePreferences())) { diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java index 3e09d3f5c39..159d8bf5bea 100644 --- a/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/src/main/java/org/jabref/gui/JabRefGUI.java @@ -40,7 +40,6 @@ import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.GuiPreferences; import org.jabref.preferences.JabRefPreferences; -import org.jabref.preferences.ai.AiApiKeyProvider; import com.airhacks.afterburner.injection.Injector; import com.tobiasdiez.easybind.EasyBind; @@ -161,7 +160,6 @@ public void initialize() { preferencesService.getAiPreferences(), preferencesService.getFilePreferences(), preferencesService.getCitationKeyPatternPreferences(), - Injector.instantiateModelOrService(AiApiKeyProvider.class), dialogService, taskExecutor); Injector.setModelOrService(AiService.class, aiService); diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index e13eb0ecb6c..4caed630210 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -63,7 +63,6 @@ import org.jabref.model.util.DirectoryMonitorManager; import org.jabref.model.util.FileUpdateMonitor; import org.jabref.preferences.PreferencesService; -import org.jabref.preferences.ai.AiApiKeyProvider; import com.airhacks.afterburner.views.ViewLoader; import com.tobiasdiez.easybind.EasyBind; @@ -111,7 +110,6 @@ public class EntryEditor extends BorderPane { @Inject private DialogService dialogService; @Inject private TaskExecutor taskExecutor; @Inject private PreferencesService preferencesService; - @Inject private AiApiKeyProvider aiApiKeyProvider; @Inject private StateManager stateManager; @Inject private ThemeManager themeManager; @Inject private FileUpdateMonitor fileMonitor; diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java index daff2c9999e..d557ef919c3 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.java @@ -15,7 +15,6 @@ import org.jabref.gui.util.ViewModelListCellFactory; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; -import org.jabref.preferences.ai.AiApiKeyProvider; import org.jabref.preferences.ai.AiProvider; import org.jabref.preferences.ai.EmbeddingModel; @@ -23,15 +22,12 @@ import com.dlsc.gemsfx.ResizableTextArea; import com.dlsc.unitfx.IntegerInputField; import de.saxsys.mvvmfx.utils.validation.visualization.ControlsFxVisualizer; -import jakarta.inject.Inject; import org.controlsfx.control.SearchableComboBox; import org.controlsfx.control.textfield.CustomPasswordField; public class AiTab extends AbstractPreferenceTabView implements PreferencesTab { private static final String HUGGING_FACE_CHAT_MODEL_PROMPT = "TinyLlama/TinyLlama_v1.1 (or any other model name)"; - @Inject private AiApiKeyProvider aiApiKeyProvider; - @FXML private CheckBox enableAi; @FXML private ComboBox aiProviderComboBox; @@ -73,7 +69,7 @@ public AiTab() { } public void initialize() { - this.viewModel = new AiTabViewModel(preferencesService, aiApiKeyProvider); + this.viewModel = new AiTabViewModel(preferencesService); enableAi.selectedProperty().bindBidirectional(viewModel.enableAi()); diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java index b8bc2d4bc3f..031803d9f73 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java @@ -24,7 +24,6 @@ import org.jabref.logic.util.LocalizedNumbers; import org.jabref.model.strings.StringUtil; import org.jabref.preferences.PreferencesService; -import org.jabref.preferences.ai.AiApiKeyProvider; import org.jabref.preferences.ai.AiPreferences; import org.jabref.preferences.ai.AiProvider; import org.jabref.preferences.ai.EmbeddingModel; @@ -83,7 +82,6 @@ public class AiTabViewModel implements PreferenceTabViewModel { private final BooleanProperty disableExpertSettings = new SimpleBooleanProperty(true); private final AiPreferences aiPreferences; - private final AiApiKeyProvider aiApiKeyProvider; private final Validator apiKeyValidator; private final Validator chatModelValidator; @@ -99,11 +97,10 @@ public class AiTabViewModel implements PreferenceTabViewModel { private final Validator ragMinScoreTypeValidator; private final Validator ragMinScoreRangeValidator; - public AiTabViewModel(PreferencesService preferencesService, AiApiKeyProvider aiApiKeyProvider) { + public AiTabViewModel(PreferencesService preferencesService) { this.oldLocale = Locale.getDefault(); this.aiPreferences = preferencesService.getAiPreferences(); - this.aiApiKeyProvider = aiApiKeyProvider; this.enableAi.addListener((observable, oldValue, newValue) -> { disableBasicSettings.set(!newValue); @@ -266,9 +263,9 @@ public AiTabViewModel(PreferencesService preferencesService, AiApiKeyProvider ai @Override public void setValues() { - openAiApiKey.setValue(aiApiKeyProvider.getApiKeyForAiProvider(AiProvider.OPEN_AI)); - mistralAiApiKey.setValue(aiApiKeyProvider.getApiKeyForAiProvider(AiProvider.MISTRAL_AI)); - huggingFaceApiKey.setValue(aiApiKeyProvider.getApiKeyForAiProvider(AiProvider.HUGGING_FACE)); + openAiApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.OPEN_AI)); + mistralAiApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.MISTRAL_AI)); + huggingFaceApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.HUGGING_FACE)); openAiApiBaseUrl.setValue(aiPreferences.getOpenAiApiBaseUrl()); mistralAiApiBaseUrl.setValue(aiPreferences.getMistralAiApiBaseUrl()); @@ -305,9 +302,9 @@ public void storeSettings() { aiPreferences.setMistralAiChatModel(mistralAiChatModel.get() == null ? "" : mistralAiChatModel.get()); aiPreferences.setHuggingFaceChatModel(huggingFaceChatModel.get() == null ? "" : huggingFaceChatModel.get()); - aiApiKeyProvider.storeAiApiKeyInKeyring(AiProvider.OPEN_AI, openAiApiKey.get() == null ? "" : openAiApiKey.get()); - aiApiKeyProvider.storeAiApiKeyInKeyring(AiProvider.MISTRAL_AI, mistralAiApiKey.get() == null ? "" : mistralAiApiKey.get()); - aiApiKeyProvider.storeAiApiKeyInKeyring(AiProvider.HUGGING_FACE, huggingFaceApiKey.get() == null ? "" : huggingFaceApiKey.get()); + aiPreferences.storeAiApiKeyInKeyring(AiProvider.OPEN_AI, openAiApiKey.get() == null ? "" : openAiApiKey.get()); + aiPreferences.storeAiApiKeyInKeyring(AiProvider.MISTRAL_AI, mistralAiApiKey.get() == null ? "" : mistralAiApiKey.get()); + aiPreferences.storeAiApiKeyInKeyring(AiProvider.HUGGING_FACE, huggingFaceApiKey.get() == null ? "" : huggingFaceApiKey.get()); // We notify in all cases without a real check if something was changed aiPreferences.apiKeyUpdated(); @@ -389,10 +386,6 @@ public BooleanProperty enableAi() { return enableAi; } - public boolean getEnableAi() { - return enableAi.get(); - } - public ReadOnlyListProperty aiProvidersProperty() { return aiProvidersList; } diff --git a/src/main/java/org/jabref/logic/ai/AiService.java b/src/main/java/org/jabref/logic/ai/AiService.java index 0503307df27..a33e254c722 100644 --- a/src/main/java/org/jabref/logic/ai/AiService.java +++ b/src/main/java/org/jabref/logic/ai/AiService.java @@ -28,7 +28,6 @@ import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.preferences.FilePreferences; -import org.jabref.preferences.ai.AiApiKeyProvider; import org.jabref.preferences.ai.AiPreferences; import com.airhacks.afterburner.injection.Injector; @@ -79,7 +78,6 @@ public class AiService implements AutoCloseable { public AiService(AiPreferences aiPreferences, FilePreferences filePreferences, CitationKeyPatternPreferences citationKeyPatternPreferences, - AiApiKeyProvider aiApiKeyProvider, DialogService dialogService, TaskExecutor taskExecutor ) { @@ -88,7 +86,7 @@ public AiService(AiPreferences aiPreferences, this.dialogService = dialogService; this.taskExecutor = taskExecutor; - this.jabRefChatLanguageModel = new JabRefChatLanguageModel(aiPreferences, aiApiKeyProvider); + this.jabRefChatLanguageModel = new JabRefChatLanguageModel(aiPreferences); this.mvStoreEmbeddingStore = new MVStoreEmbeddingStore(JabRefDesktop.getAiFilesDirectory().resolve(EMBEDDINGS_FILE_NAME), dialogService); this.mvStoreFullyIngestedDocumentsTracker = new MVStoreFullyIngestedDocumentsTracker(JabRefDesktop.getAiFilesDirectory().resolve(FULLY_INGESTED_FILE_NAME), dialogService); diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 8bd71112cb8..5e9c424e3ab 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -9,7 +9,6 @@ import org.jabref.logic.ai.chatting.AiChatLogic; import org.jabref.logic.l10n.Localization; -import org.jabref.preferences.ai.AiApiKeyProvider; import org.jabref.preferences.ai.AiPreferences; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -24,13 +23,13 @@ /** * Wrapper around langchain4j chat language model. *

- * This class listens to preferences changes. + * Notice, that the real chat model is created lazily, when it's needed. This is done, so API key is fetched only, + * when user wants to chat with AI. */ public class JabRefChatLanguageModel implements ChatLanguageModel, AutoCloseable { private static final Duration CONNECTION_TIMEOUT = Duration.ofSeconds(5); private final AiPreferences aiPreferences; - private final AiApiKeyProvider apiKeyProvider; private final HttpClient httpClient; private final ExecutorService executorService = Executors.newSingleThreadExecutor( @@ -39,9 +38,8 @@ public class JabRefChatLanguageModel implements ChatLanguageModel, AutoCloseable private Optional langchainChatModel = Optional.empty(); - public JabRefChatLanguageModel(AiPreferences aiPreferences, AiApiKeyProvider apiKeyProvider) { + public JabRefChatLanguageModel(AiPreferences aiPreferences) { this.aiPreferences = aiPreferences; - this.apiKeyProvider = apiKeyProvider; this.httpClient = HttpClient.newBuilder().connectTimeout(CONNECTION_TIMEOUT).executor(executorService).build(); setupListeningToPreferencesChanges(); @@ -54,7 +52,7 @@ public JabRefChatLanguageModel(AiPreferences aiPreferences, AiApiKeyProvider api * and see {@link org.jabref.logic.ai.chatting.chathistory.ChatHistoryStorage}. */ private void rebuild() { - String apiKey = apiKeyProvider.getApiKeyForAiProvider(aiPreferences.getAiProvider()); + String apiKey = aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider()); if (!aiPreferences.getEnableAi() || apiKey.isEmpty()) { langchainChatModel = Optional.empty(); return; @@ -62,7 +60,7 @@ private void rebuild() { switch (aiPreferences.getAiProvider()) { case OPEN_AI -> { - langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, apiKeyProvider, httpClient)); + langchainChatModel = Optional.of(new JvmOpenAiChatLanguageModel(aiPreferences, httpClient)); } case MISTRAL_AI -> { @@ -118,7 +116,7 @@ public Response generate(List list) { if (langchainChatModel.isEmpty()) { if (!aiPreferences.getEnableAi()) { throw new RuntimeException(Localization.lang("In order to use AI chat, you need to enable chatting with attached PDF files in JabRef preferences (AI tab).")); - } else if (apiKeyProvider.getApiKeyForAiProvider(aiPreferences.getAiProvider()).isEmpty()) { + } else if (aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider()).isEmpty()) { throw new RuntimeException(Localization.lang("In order to use AI chat, set an API key inside JabRef preferences (AI tab).")); } else { rebuild(); diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java index f38435aaf8b..06b029b6551 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JvmOpenAiChatLanguageModel.java @@ -3,7 +3,6 @@ import java.net.http.HttpClient; import java.util.List; -import org.jabref.preferences.ai.AiApiKeyProvider; import org.jabref.preferences.ai.AiPreferences; import dev.langchain4j.data.message.AiMessage; @@ -30,11 +29,11 @@ public class JvmOpenAiChatLanguageModel implements ChatLanguageModel { private final ChatClient chatClient; - public JvmOpenAiChatLanguageModel(AiPreferences aiPreferences, AiApiKeyProvider aiApiKeyProvider, HttpClient httpClient) { + public JvmOpenAiChatLanguageModel(AiPreferences aiPreferences, HttpClient httpClient) { this.aiPreferences = aiPreferences; OpenAI openAI = OpenAI - .newBuilder(aiApiKeyProvider.getApiKeyForAiProvider(aiPreferences.getAiProvider())) + .newBuilder(aiPreferences.getApiKeyForAiProvider(aiPreferences.getAiProvider())) .httpClient(httpClient) .baseUrl(aiPreferences.getSelectedApiBaseUrl()) .build(); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 7a370e2dd49..9e069357f5c 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -127,7 +127,6 @@ import org.jabref.model.metadata.SelfContainedSaveOrder; import org.jabref.model.search.SearchFlags; import org.jabref.model.strings.StringUtil; -import org.jabref.preferences.ai.AiApiKeyProvider; import org.jabref.preferences.ai.AiPreferences; import org.jabref.preferences.ai.AiProvider; import org.jabref.preferences.ai.EmbeddingModel; @@ -155,7 +154,7 @@ */ @Singleton @Service -public class JabRefPreferences implements PreferencesService, AiApiKeyProvider { +public class JabRefPreferences implements PreferencesService { // Push to application preferences public static final String PUSH_EMACS_PATH = "emacsPath"; @@ -485,9 +484,6 @@ public class JabRefPreferences implements PreferencesService, AiApiKeyProvider { private static final String AI_RAG_MAX_RESULTS_COUNT = "aiRagMaxResultsCount"; private static final String AI_RAG_MIN_SCORE = "aiRagMinScore"; - private static final String KEYRING_AI_SERVICE = "org.jabref.ai"; - private static final String KEYRING_AI_SERVICE_ACCOUNT = "apiKey"; - private static final Logger LOGGER = LoggerFactory.getLogger(JabRefPreferences.class); private static final Preferences PREFS_NODE = Preferences.userRoot().node("/org/jabref"); @@ -2793,7 +2789,6 @@ public AiPreferences getAiPreferences() { boolean aiEnabled = getBoolean(AI_ENABLED); aiPreferences = new AiPreferences( - this, aiEnabled, AiProvider.valueOf(get(AI_PROVIDER)), get(AI_OPEN_AI_CHAT_MODEL), @@ -2838,34 +2833,6 @@ public AiPreferences getAiPreferences() { return aiPreferences; } - public String getApiKeyForAiProvider(AiProvider aiProvider) { - try (final Keyring keyring = Keyring.create()) { - return keyring.getPassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name()); - } catch (PasswordAccessException e) { - LOGGER.debug("No API key stored for provider {}. Returning an empty string", aiProvider.getLabel()); - return ""; - } catch (Exception e) { - LOGGER.warn("JabRef could not open keyring for retrieving {} API token", aiProvider.getLabel(), e); - return ""; - } - } - - public void storeAiApiKeyInKeyring(AiProvider aiProvider, String newKey) { - try (final Keyring keyring = Keyring.create()) { - if (StringUtil.isNullOrEmpty(newKey)) { - try { - keyring.deletePassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name()); - } catch (PasswordAccessException ex) { - LOGGER.debug("API key for provider {} not stored in keyring. JabRef does not store an empty key.", aiProvider.getLabel()); - } - } else { - keyring.setPassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name(), newKey); - } - } catch (Exception e) { - LOGGER.warn("JabRef could not open keyring for storing {} API token", aiProvider.getLabel(), e); - } - } - //************************************************************************************************************* // Misc preferences //************************************************************************************************************* diff --git a/src/main/java/org/jabref/preferences/PreferencesService.java b/src/main/java/org/jabref/preferences/PreferencesService.java index f7aff7fc0b1..ea7e99c99fd 100644 --- a/src/main/java/org/jabref/preferences/PreferencesService.java +++ b/src/main/java/org/jabref/preferences/PreferencesService.java @@ -34,7 +34,6 @@ import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.preferences.ai.AiPreferences; -import org.jabref.preferences.ai.AiProvider; import org.jvnet.hk2.annotations.Contract; @@ -152,12 +151,4 @@ public interface PreferencesService { UnlinkedFilesDialogPreferences getUnlinkedFilesDialogPreferences(); AiPreferences getAiPreferences(); - - /** - * Retrieves the API key for the specified AI provider. - * - * @param provider the AI provider for which the API key is requested - * @return the API key for the specified AI provider, or empty string if no key is found - */ - String getApiKeyForAiProvider(AiProvider provider); } diff --git a/src/main/java/org/jabref/preferences/ai/AiApiKeyProvider.java b/src/main/java/org/jabref/preferences/ai/AiApiKeyProvider.java deleted file mode 100644 index cedec6b8606..00000000000 --- a/src/main/java/org/jabref/preferences/ai/AiApiKeyProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.jabref.preferences.ai; - -public interface AiApiKeyProvider { - String getApiKeyForAiProvider(AiProvider provider); - - void storeAiApiKeyInKeyring(AiProvider aiProvider, String newKey); -} diff --git a/src/main/java/org/jabref/preferences/ai/AiPreferences.java b/src/main/java/org/jabref/preferences/ai/AiPreferences.java index a3ae3b2fefb..53f13f210a1 100644 --- a/src/main/java/org/jabref/preferences/ai/AiPreferences.java +++ b/src/main/java/org/jabref/preferences/ai/AiPreferences.java @@ -1,11 +1,13 @@ package org.jabref.preferences.ai; +import java.util.List; import java.util.Objects; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; +import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleIntegerProperty; @@ -14,10 +16,18 @@ import javafx.beans.property.StringProperty; import org.jabref.logic.ai.AiDefaultPreferences; -import org.jabref.preferences.PreferencesService; +import org.jabref.model.strings.StringUtil; + +import com.github.javakeyring.Keyring; +import com.github.javakeyring.PasswordAccessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class AiPreferences { - private final PreferencesService preferencesService; + private static final Logger LOGGER = LoggerFactory.getLogger(AiPreferences.class); + + private static final String KEYRING_AI_SERVICE = "org.jabref.ai"; + private static final String KEYRING_AI_SERVICE_ACCOUNT = "apiKey"; private final BooleanProperty enableAi; @@ -44,8 +54,7 @@ public class AiPreferences { private Runnable apiKeyChangeListener; - public AiPreferences(PreferencesService preferencesService, - boolean enableAi, + public AiPreferences(boolean enableAi, AiProvider aiProvider, String openAiChatModel, String mistralAiChatModel, @@ -63,8 +72,6 @@ public AiPreferences(PreferencesService preferencesService, int ragMaxResultsCount, double ragMinScore ) { - this.preferencesService = preferencesService; - this.enableAi = new SimpleBooleanProperty(enableAi); this.aiProvider = new SimpleObjectProperty<>(aiProvider); @@ -89,6 +96,35 @@ public AiPreferences(PreferencesService preferencesService, this.ragMinScore = new SimpleDoubleProperty(ragMinScore); } + public String getApiKeyForAiProvider(AiProvider aiProvider) { + try (final Keyring keyring = Keyring.create()) { + return keyring.getPassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name()); + } catch ( + PasswordAccessException e) { + LOGGER.debug("No API key stored for provider {}. Returning an empty string", aiProvider.getLabel()); + return ""; + } catch (Exception e) { + LOGGER.warn("JabRef could not open keyring for retrieving {} API token", aiProvider.getLabel(), e); + return ""; + } + } + + public void storeAiApiKeyInKeyring(AiProvider aiProvider, String newKey) { + try (final Keyring keyring = Keyring.create()) { + if (StringUtil.isNullOrEmpty(newKey)) { + try { + keyring.deletePassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name()); + } catch (PasswordAccessException ex) { + LOGGER.debug("API key for provider {} not stored in keyring. JabRef does not store an empty key.", aiProvider.getLabel()); + } + } else { + keyring.setPassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name(), newKey); + } + } catch (Exception e) { + LOGGER.warn("JabRef could not open keyring for storing {} API token", aiProvider.getLabel(), e); + } + } + public BooleanProperty enableAiProperty() { return enableAi; } @@ -355,43 +391,23 @@ public void addListenerToEmbeddingsParametersChange(Runnable runnable) { } public void addListenerToChatModels(Runnable runnable) { - openAiChatModel.addListener((observableValue, oldValue, newValue) -> { - if (!newValue.equals(oldValue)) { - runnable.run(); - } - }); - - mistralAiChatModel.addListener((observableValue, oldValue, newValue) -> { - if (!newValue.equals(oldValue)) { - runnable.run(); - } - }); + List> observables = List.of(openAiChatModel, mistralAiChatModel, huggingFaceChatModel); - huggingFaceChatModel.addListener((observableValue, oldValue, newValue) -> { + observables.forEach(obs -> obs.addListener((observableValue, oldValue, newValue) -> { if (!newValue.equals(oldValue)) { runnable.run(); } - }); + })); } public void addListenerToApiBaseUrls(Runnable runnable) { - openAiApiBaseUrl.addListener((observableValue, oldValue, newValue) -> { - if (!newValue.equals(oldValue)) { - runnable.run(); - } - }); + List> observables = List.of(openAiApiBaseUrl, mistralAiApiBaseUrl, huggingFaceApiBaseUrl); - mistralAiApiBaseUrl.addListener((observableValue, oldValue, newValue) -> { + observables.forEach(obs -> obs.addListener((observableValue, oldValue, newValue) -> { if (!newValue.equals(oldValue)) { runnable.run(); } - }); - - huggingFaceApiBaseUrl.addListener((observableValue, oldValue, newValue) -> { - if (!newValue.equals(oldValue)) { - runnable.run(); - } - }); + })); } public String getSelectedChatModel() { From f49dfac901843b82f8d32b743bd4001dafdd21ff Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 8 Sep 2024 18:26:20 +0200 Subject: [PATCH 019/324] Fix ArgumentProcessor (#11728) * Refine JavaDoc * Add TODOs Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> * Fix typos * Reoder settings * Fix arch flaw Co-authored-by: Christoph Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> * Fix checkstyle and formatting --------- Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Co-authored-by: Christoph --- .../org/jabref/cli/ArgumentProcessor.java | 40 +++++++++++-------- .../externalfiles/AutoLinkFilesAction.java | 19 ++++++++- .../externalfiles/AutoSetFileLinksUtil.java | 32 ++++----------- .../gui/frame/JabRefFrameViewModel.java | 17 +++++++- .../gui/maintable/BibEntryTableViewModel.java | 2 +- src/main/java/org/jabref/logic/UiCommand.java | 2 + .../jabref/logic/search/DatabaseSearcher.java | 1 + 7 files changed, 66 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index 1ac2d50da67..6d4649c7739 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -14,7 +14,6 @@ import java.util.prefs.BackingStoreException; import org.jabref.gui.externalfiles.AutoSetFileLinksUtil; -import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.util.CurrentThreadTaskExecutor; import org.jabref.logic.JabRefException; import org.jabref.logic.UiCommand; @@ -99,16 +98,13 @@ public ArgumentProcessor(String[] args, } /** - * Will open a file (like importFile), but will also request JabRef to focus on this database + * Will open a file (like {@link #importFile(String)}, but will also request JabRef to focus on this database. * - * @param argument See importFile. * @return ParserResult with setToOpenTab(true) */ - private Optional importToOpenBase(String argument) { - Optional result = importFile(argument); - + private Optional importToOpenBase(String importArguments) { + Optional result = importFile(importArguments); result.ifPresent(ParserResult::setToOpenTab); - return result; } @@ -125,9 +121,13 @@ private Optional importBibtexToOpenBase(String argument, ImportFor } } - private Optional importFile(String argument) { - LOGGER.debug("Importing file {}", argument); - String[] data = argument.split(","); + /** + * + * @param importArguments Format: fileName[,format] + */ + private Optional importFile(String importArguments) { + LOGGER.debug("Importing file {}", importArguments); + String[] data = importArguments.split(","); String address = data[0]; Path file; @@ -295,7 +295,7 @@ public void processArguments() { } private void writeMetadataToPdf(List loaded, - String filesAndCitekeys, + String filesAndCiteKeys, XmpPreferences xmpPreferences, FilePreferences filePreferences, BibDatabaseMode databaseMode, @@ -314,7 +314,7 @@ private void writeMetadataToPdf(List loaded, XmpPdfExporter xmpPdfExporter = new XmpPdfExporter(xmpPreferences); EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter = new EmbeddedBibFilePdfExporter(databaseMode, entryTypesManager, fieldPreferences); - if ("all".equals(filesAndCitekeys)) { + if ("all".equals(filesAndCiteKeys)) { for (BibEntry entry : databaseContext.getEntries()) { writeMetadataToPDFsOfEntry( databaseContext, @@ -332,7 +332,7 @@ private void writeMetadataToPdf(List loaded, List citeKeys = new ArrayList<>(); List pdfs = new ArrayList<>(); - for (String fileOrCiteKey : filesAndCitekeys.split(",")) { + for (String fileOrCiteKey : filesAndCiteKeys.split(",")) { if (fileOrCiteKey.toLowerCase(Locale.ROOT).endsWith(".pdf")) { pdfs.add(fileOrCiteKey); } else { @@ -368,7 +368,7 @@ private void writeMetadataToPDFsOfEntry(BibDatabaseContext databaseContext, EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter, JournalAbbreviationRepository abbreviationRepository, boolean writeXMP, - boolean embeddBibfile) { + boolean embedBibfile) { try { if (writeXMP) { if (xmpPdfExporter.exportToAllFilesOfEntry(databaseContext, filePreferences, entry, List.of(entry), abbreviationRepository)) { @@ -377,7 +377,7 @@ private void writeMetadataToPDFsOfEntry(BibDatabaseContext databaseContext, System.err.printf("Cannot write XMP metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.%n", citeKey); } } - if (embeddBibfile) { + if (embedBibfile) { if (embeddedBibFilePdfExporter.exportToAllFilesOfEntry(databaseContext, filePreferences, entry, List.of(entry), abbreviationRepository)) { System.out.printf("Successfully embedded metadata on at least one linked file of %s%n", citeKey); } else { @@ -461,6 +461,7 @@ private boolean exportMatches(List loaded) { List matches; try { + // extract current thread task executor from luceneManager matches = new DatabaseSearcher(query, databaseContext, new CurrentThreadTaskExecutor(), preferencesService.getFilePreferences()).getMatches(); } catch (IOException e) { LOGGER.error("Error occurred when searching", e); @@ -729,12 +730,17 @@ private void resetPreferences(String value) { private void automaticallySetFileLinks(List loaded) { for (ParserResult parserResult : loaded) { BibDatabase database = parserResult.getDatabase(); - LOGGER.info(Localization.lang("Automatically setting file links")); + LOGGER.info("Automatically setting file links for {}", + parserResult.getDatabaseContext().getDatabasePath() + .map(Path::getFileName) + .map(Path::toString).orElse("UNKNOWN")); + AutoSetFileLinksUtil util = new AutoSetFileLinksUtil( parserResult.getDatabaseContext(), preferencesService.getFilePreferences(), preferencesService.getAutoLinkPreferences()); - util.linkAssociatedFiles(database.getEntries(), new NamedCompound("")); + + util.linkAssociatedFiles(database.getEntries(), (linkedFile, bibEntry) -> bibEntry.addFile(linkedFile)); } } diff --git a/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java b/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java index 689d79dca69..41f7257732a 100644 --- a/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java +++ b/src/main/java/org/jabref/gui/externalfiles/AutoLinkFilesAction.java @@ -1,6 +1,7 @@ package org.jabref.gui.externalfiles; import java.util.List; +import java.util.function.BiConsumer; import javax.swing.undo.UndoManager; @@ -10,11 +11,15 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.undo.NamedCompound; +import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.util.BindingsHelper; import org.jabref.gui.util.TaskExecutor; +import org.jabref.logic.bibtex.FileFieldWriter; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.LinkedFile; +import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.PreferencesService; import static org.jabref.gui.actions.ActionHelper.needsDatabase; @@ -47,16 +52,26 @@ public AutoLinkFilesAction(DialogService dialogService, PreferencesService prefe public void execute() { final BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); final List entries = stateManager.getSelectedEntries(); - final AutoSetFileLinksUtil util = new AutoSetFileLinksUtil( + + AutoSetFileLinksUtil util = new AutoSetFileLinksUtil( database, preferences.getFilePreferences(), preferences.getAutoLinkPreferences()); final NamedCompound nc = new NamedCompound(Localization.lang("Automatically set file links")); Task linkFilesTask = new Task<>() { + final BiConsumer onLinkedFile = (linkedFile, entry) -> { + // lambda for gui actions that are relevant when setting the linked file entry when ui is opened + String newVal = FileFieldWriter.getStringRepresentation(linkedFile); + String oldVal = entry.getField(StandardField.FILE).orElse(null); + UndoableFieldChange fieldChange = new UndoableFieldChange(entry, StandardField.FILE, oldVal, newVal); + nc.addEdit(fieldChange); // push to undo manager is in succeeded + entry.addFile(linkedFile); + }; + @Override protected AutoSetFileLinksUtil.LinkFilesResult call() { - return util.linkAssociatedFiles(entries, nc); + return util.linkAssociatedFiles(entries, onLinkedFile); } @Override diff --git a/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java b/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java index 7733bedfb07..da256e45125 100644 --- a/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java +++ b/src/main/java/org/jabref/gui/externalfiles/AutoSetFileLinksUtil.java @@ -6,14 +6,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.function.BiConsumer; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.externalfiletype.UnknownExternalFileType; -import org.jabref.gui.undo.NamedCompound; -import org.jabref.gui.undo.UndoableFieldChange; -import org.jabref.gui.util.UiTaskExecutor; -import org.jabref.logic.bibtex.FileFieldWriter; import org.jabref.logic.util.io.AutoLinkPreferences; import org.jabref.logic.util.io.FileFinder; import org.jabref.logic.util.io.FileFinders; @@ -21,7 +18,6 @@ import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; -import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.FilePreferences; import org.slf4j.Logger; @@ -66,7 +62,7 @@ private AutoSetFileLinksUtil(List directories, FilePreferences filePrefere this.filePreferences = filePreferences; } - public LinkFilesResult linkAssociatedFiles(List entries, NamedCompound ce) { + public LinkFilesResult linkAssociatedFiles(List entries, BiConsumer onAddLinkedFile) { LinkFilesResult result = new LinkFilesResult(); for (BibEntry entry : entries) { @@ -79,26 +75,12 @@ public LinkFilesResult linkAssociatedFiles(List entries, NamedCompound LOGGER.error("Problem finding files", e); } - if (ce != null) { - boolean changed = false; - - for (LinkedFile linkedFile : linkedFiles) { - // store undo information - String newVal = FileFieldWriter.getStringRepresentation(linkedFile); - String oldVal = entry.getField(StandardField.FILE).orElse(null); - UndoableFieldChange fieldChange = new UndoableFieldChange(entry, StandardField.FILE, oldVal, newVal); - ce.addEdit(fieldChange); - changed = true; - - UiTaskExecutor.runInJavaFXThread(() -> { - entry.addFile(linkedFile); - }); - } - - if (changed) { - result.addBibEntry(entry); - } + for (LinkedFile linkedFile : linkedFiles) { + // store undo information + onAddLinkedFile.accept(linkedFile, entry); } + + result.addBibEntry(entry); } return result; } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java index 924a8baa675..42f7f0957fc 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java @@ -21,6 +21,7 @@ import org.jabref.gui.LibraryTab; import org.jabref.gui.LibraryTabContainer; import org.jabref.gui.StateManager; +import org.jabref.gui.externalfiles.AutoLinkFilesAction; import org.jabref.gui.importer.ImportEntriesDialog; import org.jabref.gui.importer.ParserResultWarningDialog; import org.jabref.gui.importer.actions.OpenDatabaseAction; @@ -158,7 +159,14 @@ public void handleUiCommands(List uiCommands) { .forEach(command -> openDatabases(command.parserResults())); } + // Handle automatically setting file links + uiCommands.stream() + .filter(UiCommand.AutoSetFileLinks.class::isInstance).findAny() + .map(UiCommand.AutoSetFileLinks.class::cast) + .ifPresent(autoSetFileLinks -> autoSetFileLinks(autoSetFileLinks.parserResults())); + // Handle jumpToEntry + // Needs to go last, because it requires all libraries opened uiCommands.stream() .filter(UiCommand.JumpToEntryKey.class::isInstance) .map(UiCommand.JumpToEntryKey.class::cast) @@ -172,14 +180,13 @@ public void handleUiCommands(List uiCommands) { } private void openDatabases(List parserResults) { - final List failed = new ArrayList<>(); final List toOpenTab = new ArrayList<>(); // Remove invalid databases List invalidDatabases = parserResults.stream() .filter(ParserResult::isInvalid) .toList(); - failed.addAll(invalidDatabases); + final List failed = new ArrayList<>(invalidDatabases); parserResults.removeAll(invalidDatabases); // passed file (we take the first one) should be focused @@ -397,4 +404,10 @@ void addImportedEntries(final LibraryTab tab, final ParserResult parserResult) { dialog.setTitle(Localization.lang("Import")); dialogService.showCustomDialogAndWait(dialog); } + + void autoSetFileLinks(List loaded) { + for (ParserResult parserResult : loaded) { + new AutoLinkFilesAction(dialogService, preferences, stateManager, undoManager, taskExecutor).execute(); + } + } } diff --git a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java index eded204b933..aa8fdc38ec3 100644 --- a/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java +++ b/src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java @@ -60,12 +60,12 @@ public class BibEntryTableViewModel { public BibEntryTableViewModel(BibEntry entry, BibDatabaseContext bibDatabaseContext, ObservableValue fieldValueFormatter) { this.entry = entry; + this.bibDatabaseContext = bibDatabaseContext; this.fieldValueFormatter = fieldValueFormatter; this.linkedFiles = getField(StandardField.FILE).mapOpt(FileFieldParser::parse).orElseOpt(Collections.emptyList()); this.linkedIdentifiers = createLinkedIdentifiersBinding(entry); this.matchedGroups = createMatchedGroupsBinding(bibDatabaseContext, entry); - this.bibDatabaseContext = bibDatabaseContext; } private static EasyBinding> createLinkedIdentifiersBinding(BibEntry entry) { diff --git a/src/main/java/org/jabref/logic/UiCommand.java b/src/main/java/org/jabref/logic/UiCommand.java index e409d65b0be..1fc8a699ce5 100644 --- a/src/main/java/org/jabref/logic/UiCommand.java +++ b/src/main/java/org/jabref/logic/UiCommand.java @@ -10,4 +10,6 @@ record BlankWorkspace() implements UiCommand { } record JumpToEntryKey(String citationKey) implements UiCommand { } record OpenDatabases(List parserResults) implements UiCommand { } + + record AutoSetFileLinks(List parserResults) implements UiCommand { } } diff --git a/src/main/java/org/jabref/logic/search/DatabaseSearcher.java b/src/main/java/org/jabref/logic/search/DatabaseSearcher.java index bf5e74e070b..1a8bc4e8945 100644 --- a/src/main/java/org/jabref/logic/search/DatabaseSearcher.java +++ b/src/main/java/org/jabref/logic/search/DatabaseSearcher.java @@ -22,6 +22,7 @@ public class DatabaseSearcher { private final SearchQuery query; private final LuceneManager luceneManager; + // get rid of task executor here or add a constuctor overload? public DatabaseSearcher(SearchQuery query, BibDatabaseContext databaseContext, TaskExecutor taskExecutor, FilePreferences filePreferences) throws IOException { this.databaseContext = databaseContext; this.query = Objects.requireNonNull(query); From 28164eba12394bf09ef686447764082f0b5f5ae3 Mon Sep 17 00:00:00 2001 From: Christoph Date: Sun, 8 Sep 2024 20:19:37 +0200 Subject: [PATCH 020/324] New Crowdin updates (#11730) * New translations jabref_en.properties (French) * New translations jabref_en.properties (Polish) * New translations jabref_en.properties (Portuguese, Brazilian) * New translations jabref_en.properties (Spanish) * New translations jabref_en.properties (Arabic) * New translations jabref_en.properties (Danish) * New translations jabref_en.properties (German) * New translations jabref_en.properties (Greek) * New translations jabref_en.properties (Finnish) * New translations jabref_en.properties (Italian) * New translations jabref_en.properties (Japanese) * New translations jabref_en.properties (Korean) * New translations jabref_en.properties (Dutch) * New translations jabref_en.properties (Norwegian) * New translations jabref_en.properties (Portuguese) * New translations jabref_en.properties (Russian) * New translations jabref_en.properties (Swedish) * New translations jabref_en.properties (Turkish) * New translations jabref_en.properties (Ukrainian) * New translations jabref_en.properties (Chinese Simplified) * New translations jabref_en.properties (Chinese Traditional) * New translations jabref_en.properties (Vietnamese) * New translations jabref_en.properties (Indonesian) * New translations jabref_en.properties (Persian) * New translations jabref_en.properties (Tagalog) --- src/main/resources/l10n/JabRef_ar.properties | 1 + src/main/resources/l10n/JabRef_da.properties | 1 + src/main/resources/l10n/JabRef_de.properties | 1 + src/main/resources/l10n/JabRef_el.properties | 1 + src/main/resources/l10n/JabRef_es.properties | 1 + src/main/resources/l10n/JabRef_fa.properties | 1 + src/main/resources/l10n/JabRef_fi.properties | 1 + src/main/resources/l10n/JabRef_fr.properties | 3 +++ src/main/resources/l10n/JabRef_id.properties | 1 + src/main/resources/l10n/JabRef_it.properties | 3 +++ src/main/resources/l10n/JabRef_ja.properties | 1 + src/main/resources/l10n/JabRef_ko.properties | 1 + src/main/resources/l10n/JabRef_nl.properties | 1 + src/main/resources/l10n/JabRef_no.properties | 1 + src/main/resources/l10n/JabRef_pl.properties | 3 +++ src/main/resources/l10n/JabRef_pt.properties | 1 + src/main/resources/l10n/JabRef_pt_BR.properties | 3 +++ src/main/resources/l10n/JabRef_ru.properties | 1 + src/main/resources/l10n/JabRef_sv.properties | 1 + src/main/resources/l10n/JabRef_tl.properties | 1 + src/main/resources/l10n/JabRef_tr.properties | 1 + src/main/resources/l10n/JabRef_uk.properties | 1 + src/main/resources/l10n/JabRef_vi.properties | 1 + src/main/resources/l10n/JabRef_zh_CN.properties | 1 + src/main/resources/l10n/JabRef_zh_TW.properties | 1 + 25 files changed, 33 insertions(+) diff --git a/src/main/resources/l10n/JabRef_ar.properties b/src/main/resources/l10n/JabRef_ar.properties index 996ce6bf593..44275e54d6b 100644 --- a/src/main/resources/l10n/JabRef_ar.properties +++ b/src/main/resources/l10n/JabRef_ar.properties @@ -716,5 +716,6 @@ File\ not\ found=لم يتم العثور على الملف + diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 296ce587c92..234153c4fae 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -1011,3 +1011,4 @@ Path\ to\ %0=Sti til %0 + diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index b3ae803b34e..6689fcc5d94 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2745,6 +2745,7 @@ Ask\ every\ time=Immer nachfragen Value\ is\ not\ in\ Unicode's\ Normalization\ Form\ "Canonical\ Composition"\ (NFC)\ format=Wert liegt nicht in der Unicode-Normalform "Kanonische Komposition" (NFC) Format vor + Group\ icons=Gruppensymbole Redownload\ file=Datei erneut herunterladen Redownload\ missing\ files=Fehlende Dateien erneut herunterladen diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index 9fdc68de6f4..2e7ec4c0f82 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -1794,3 +1794,4 @@ Related\ articles=Σχετικά άρθρα + diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index fa623b1d75d..510461198e9 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -2475,6 +2475,7 @@ Ask\ every\ time=Preguntar siempre Value\ is\ not\ in\ Unicode's\ Normalization\ Form\ "Canonical\ Composition"\ (NFC)\ format=El valor no está en el formato «composición canónica» (NFC) de la forma de normalización de Unicode + Redownload\ file=Volver a descargar archivo Redownload\ missing\ files=Volver a descargar archivos faltantes Redownload\ missing\ files\ for\ current\ library?=¿Quiere volver a descargar los archivos faltantes en la biblioteca actual? diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index 2901bb40930..a579532fa30 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -652,5 +652,6 @@ Auto\ complete\ enabled.=تکمیل خودکار غیرفعال شد. + diff --git a/src/main/resources/l10n/JabRef_fi.properties b/src/main/resources/l10n/JabRef_fi.properties index 5850a7ae7c7..66442149920 100644 --- a/src/main/resources/l10n/JabRef_fi.properties +++ b/src/main/resources/l10n/JabRef_fi.properties @@ -596,5 +596,6 @@ Proxy\ requires\ password=Välityspalvelin vaatii salasanan + diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 379b261e014..0e53c04e124 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -2765,6 +2765,9 @@ Ask\ every\ time=Toujours demander Value\ is\ not\ in\ Unicode's\ Normalization\ Form\ "Canonical\ Composition"\ (NFC)\ format=Une valeur n'est pas au format de Normalisation de l'Unicode "Composition Canonique" (NFC) +Copy\ failed=Échec de la copie +Cut\ failed=Échec de la coupe + Group\ icons=Icônes de groupe Redownload\ file=Télécharger à nouveau le fichier Redownload\ missing\ files=Télécharger à nouveau les fichiers manquants diff --git a/src/main/resources/l10n/JabRef_id.properties b/src/main/resources/l10n/JabRef_id.properties index 6692e127384..6ee10e99a5f 100644 --- a/src/main/resources/l10n/JabRef_id.properties +++ b/src/main/resources/l10n/JabRef_id.properties @@ -1558,3 +1558,4 @@ Related\ articles=Artikel terkait + diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 5c45d339556..2d88ccb5727 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -2731,6 +2731,9 @@ Ask\ every\ time=Chiedi ogni volta Value\ is\ not\ in\ Unicode's\ Normalization\ Form\ "Canonical\ Composition"\ (NFC)\ format=Il valore non è nel formato di Normalizzazione della "Composizione Canonica" (NFC) di Unicode +Copy\ failed=Copia non riuscita +Cut\ failed=Taglio fallito + Group\ icons=Icone di gruppo Redownload\ file=Scarica nuovamente il file Redownload\ missing\ files=Scarica nuovamente i file mancanti diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index 8c2787d36d0..42e975a2cd9 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -2364,3 +2364,4 @@ Related\ articles=関連文献 + diff --git a/src/main/resources/l10n/JabRef_ko.properties b/src/main/resources/l10n/JabRef_ko.properties index 9599e486a08..331a92dd02e 100644 --- a/src/main/resources/l10n/JabRef_ko.properties +++ b/src/main/resources/l10n/JabRef_ko.properties @@ -2198,3 +2198,4 @@ Related\ articles=관련 글 + diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 906ab442817..8b67bace406 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -2464,3 +2464,4 @@ Related\ articles=Gerelateerde artikelen + diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index f1a5bf336f6..3b5c8239b23 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -1122,3 +1122,4 @@ Path\ to\ %0=Sti til %0 + diff --git a/src/main/resources/l10n/JabRef_pl.properties b/src/main/resources/l10n/JabRef_pl.properties index cf265d2535d..a9e12512966 100644 --- a/src/main/resources/l10n/JabRef_pl.properties +++ b/src/main/resources/l10n/JabRef_pl.properties @@ -1848,6 +1848,9 @@ Copied\ %0\ entry(ies)=Skopiowano %0 wpis(ów) Ask\ every\ time=Pytaj za każdym razem +Copy\ failed=Nie udało się skopiować +Cut\ failed=Nie udało się wyciąć + Redownload\ file=Pobierz ponownie plik Redownload\ missing\ files=Pobierz ponownie brakujące pliki Redownload\ missing\ files\ for\ current\ library?=Pobrać ponownie brakujące pliki dla bieżącej biblioteki? diff --git a/src/main/resources/l10n/JabRef_pt.properties b/src/main/resources/l10n/JabRef_pt.properties index 5f2bfd52712..f7a4a838b7b 100644 --- a/src/main/resources/l10n/JabRef_pt.properties +++ b/src/main/resources/l10n/JabRef_pt.properties @@ -1373,3 +1373,4 @@ Related\ articles=Artigos relacionados + diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 69e456b44f8..5896c114742 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -2760,6 +2760,9 @@ Ask\ every\ time=Sempre perguntar Value\ is\ not\ in\ Unicode's\ Normalization\ Form\ "Canonical\ Composition"\ (NFC)\ format=O valor não está no formato de Composição Canônica de Normalização do Unicode (NFC) +Copy\ failed=Falha ao copiar +Cut\ failed=Cortar falhou + Group\ icons=Ícones de grupo Redownload\ file=Baixar novamente o arquivo Redownload\ missing\ files=Baixar novamente arquivos ausentes diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index ad69bad8a89..bbb5fe20c57 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -2332,3 +2332,4 @@ Related\ articles=Связанные статьи + diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index b8b99413bbe..25ee8df12dd 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -1519,6 +1519,7 @@ Related\ articles=Relaterade artiklar + Warning\:\ The\ selected\ directory\ is\ not\ empty.=Varning\: Den valda mappen är inte tom. Warning\:\ Failed\ to\ check\ if\ the\ directory\ is\ empty.=Varning\: Det gick inte att kontrollera om katalogen är tom. Warning\:\ The\ selected\ directory\ is\ not\ a\ valid\ directory.=Varning\: Den valda mappen är inte en giltig mapp. diff --git a/src/main/resources/l10n/JabRef_tl.properties b/src/main/resources/l10n/JabRef_tl.properties index d536a38d6f6..8fbeea796c8 100644 --- a/src/main/resources/l10n/JabRef_tl.properties +++ b/src/main/resources/l10n/JabRef_tl.properties @@ -1251,3 +1251,4 @@ Related\ articles=Kaugnay na mga artikulo + diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index 85414b55085..a751e569474 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -2519,3 +2519,4 @@ More\ options...=Daha fazla seçenekler... + diff --git a/src/main/resources/l10n/JabRef_uk.properties b/src/main/resources/l10n/JabRef_uk.properties index 4b0335667d1..2d6106c3c6a 100644 --- a/src/main/resources/l10n/JabRef_uk.properties +++ b/src/main/resources/l10n/JabRef_uk.properties @@ -663,5 +663,6 @@ Proxy\ requires\ password=Потрібен пароль проксі-серве + diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index 69c20026bfc..3caae272168 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -1055,3 +1055,4 @@ Path\ to\ %0=Đường dẫn đến %0 + diff --git a/src/main/resources/l10n/JabRef_zh_CN.properties b/src/main/resources/l10n/JabRef_zh_CN.properties index 9b391a81922..5c1970d7b26 100644 --- a/src/main/resources/l10n/JabRef_zh_CN.properties +++ b/src/main/resources/l10n/JabRef_zh_CN.properties @@ -2451,3 +2451,4 @@ Related\ articles=相关文章 + diff --git a/src/main/resources/l10n/JabRef_zh_TW.properties b/src/main/resources/l10n/JabRef_zh_TW.properties index a7df93ce477..48b91b8829d 100644 --- a/src/main/resources/l10n/JabRef_zh_TW.properties +++ b/src/main/resources/l10n/JabRef_zh_TW.properties @@ -1044,3 +1044,4 @@ Related\ articles=相關文章 + From 3df3b4fd427b27e9ac8ef603c10996d7118f1f9a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 8 Sep 2024 22:43:30 +0200 Subject: [PATCH 021/324] Fixed an exception when searching for unlinked files. (#11731) * Fixed an exception when searching for unlinked files. Co-authored-by: Christoph * Update CHANGELOG.md --------- Co-authored-by: Christoph --- CHANGELOG.md | 1 + src/main/java/org/jabref/gui/util/FileNodeViewModel.java | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2a090ea191..a61a78fddcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed an issue where the full-text search results were incomplete. [#8626](https://github.com/JabRef/jabref/issues/8626) - We fixed an issue where search result highlighting was incorrectly highlighting the boolean operators. [#11595](https://github.com/JabRef/jabref/issues/11595) - We fixed an issue where search result highlighting was broken at complex searches. [#8067](https://github.com/JabRef/jabref/issues/8067) +- We fixed an exception when searching for unlinked files. [#11731](https://github.com/JabRef/jabref/issues/11731) - We fixed an issue where two contradicting notifications were shown when cutting an entry in the main table. [#11724](https://github.com/JabRef/jabref/pull/11724) - We fixed an issue where unescaped braces in the arXiv fetcher were not treated. [#11704](https://github.com/JabRef/jabref/issues/11704) diff --git a/src/main/java/org/jabref/gui/util/FileNodeViewModel.java b/src/main/java/org/jabref/gui/util/FileNodeViewModel.java index b4d23c1a140..253ea20a69f 100644 --- a/src/main/java/org/jabref/gui/util/FileNodeViewModel.java +++ b/src/main/java/org/jabref/gui/util/FileNodeViewModel.java @@ -64,7 +64,7 @@ public static String formatDateTime(FileTime fileTime) { */ public String getDisplayText() { if (path.toFile().isDirectory()) { - return "%s (%s %s)".formatted(path.getFileName(), Localization.lang("%0 file(s)", fileCount)); + return "%s (%s)".formatted(path.getFileName(), Localization.lang("%0 file(s)", fileCount)); } return path.getFileName().toString(); } @@ -75,7 +75,7 @@ public String getDisplayText() { */ public String getDisplayTextWithEditDate() { if (path.toFile().isDirectory()) { - return "%s (%s %s)".formatted(path.getFileName(), Localization.lang("%0 file(s)", fileCount)); + return "%s (%s)".formatted(path.getFileName(), Localization.lang("%0 file(s)", fileCount)); } FileTime lastEditedTime = null; try { @@ -83,7 +83,7 @@ public String getDisplayTextWithEditDate() { } catch (IOException e) { LOGGER.error("Could not get last modified time", e); } - return "%s (%s: %s)".formatted(path.getFileName().toString(), Localization.lang("last edited"), formatDateTime(lastEditedTime)); + return "%s (%s: %s)".formatted(path.getFileName(), Localization.lang("last edited"), formatDateTime(lastEditedTime)); } @Override @@ -104,10 +104,9 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - if (!(obj instanceof FileNodeViewModel)) { + if (!(obj instanceof FileNodeViewModel other)) { return false; } - FileNodeViewModel other = (FileNodeViewModel) obj; return Objects.equals(children, other.children) && (fileCount == other.fileCount) && Objects.equals(path, other.path); } } From 85d8d8ac2ed1bb25729a7e2b14e94680788d179b Mon Sep 17 00:00:00 2001 From: Christoph Date: Mon, 9 Sep 2024 12:30:16 +0200 Subject: [PATCH 022/324] Add pref switch to not store url (#11735) * Add option to disable keeping download url Refs https://discourse.jabref.org/t/import-adds-pdf-link-and-url-to-file-entry/4484/ * Fix checkstyle * Compilefix * add default * Update CHANGELOG.md * add addtional check * fix ui * fix test * fix fcking test --------- Co-authored-by: Oliver Kopp --- CHANGELOG.md | 1 + .../linkedfile/DownloadLinkedFileAction.java | 4 ++-- .../gui/preferences/websearch/WebSearchTab.fxml | 1 + .../gui/preferences/websearch/WebSearchTab.java | 2 ++ .../websearch/WebSearchTabViewModel.java | 9 +++++++-- .../org/jabref/preferences/FilePreferences.java | 17 ++++++++++++++++- .../jabref/preferences/JabRefPreferences.java | 6 +++++- src/main/resources/l10n/JabRef_en.properties | 1 + .../DownloadLinkedFileActionTest.java | 2 ++ 9 files changed, 37 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a61a78fddcb..b20c6bf2e94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We enabled creating a new file link manually. [#11017](https://github.com/JabRef/jabref/issues/11017) - We added a toggle button to invert the selected groups. [#9073](https://github.com/JabRef/jabref/issues/9073) - We reintroduced the floating search in the main table. [#4237](https://github.com/JabRef/jabref/issues/4237) +- We added a switch not to store the linked file URL, because it caused troubles at other apps. [#11735](https://github.com/JabRef/jabref/pull/11735) - When starting a new SLR, the selected catalogs now persist within and across JabRef sessions. [koppor#614](https://github.com/koppor/jabref/issues/614) - We added a different background color to the search bar to indicate when the search syntax is wrong. [#11658](https://github.com/JabRef/jabref/pull/11658) diff --git a/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java b/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java index 490da28bdca..ea434197f9c 100644 --- a/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java +++ b/src/main/java/org/jabref/gui/linkedfile/DownloadLinkedFileAction.java @@ -169,9 +169,9 @@ private void onSuccess(Path targetDirectory, Path downloadedFile) { if (newLinkedFile.getDescription().isEmpty() && !linkedFile.getDescription().isEmpty()) { newLinkedFile.setDescription((linkedFile.getDescription())); } - if (linkedFile.getSourceUrl().isEmpty() && LinkedFile.isOnlineLink(linkedFile.getLink())) { + if (linkedFile.getSourceUrl().isEmpty() && LinkedFile.isOnlineLink(linkedFile.getLink()) && filePreferences.shouldKeepDownloadUrl()) { newLinkedFile.setSourceURL(linkedFile.getLink()); - } else { + } else if (filePreferences.shouldKeepDownloadUrl()) { newLinkedFile.setSourceURL(linkedFile.getSourceUrl()); } diff --git a/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.fxml b/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.fxml index 57cd5a4a449..463debd9327 100644 --- a/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/websearch/WebSearchTab.fxml @@ -20,6 +20,7 @@ + - + @@ -37,16 +37,25 @@ - + + + + + + + + + + - + diff --git a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java index cb257d4cf80..724ea24ded7 100644 --- a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java @@ -10,8 +10,10 @@ import org.jabref.gui.DialogService; import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.logic.ai.AiDefaultPreferences; import org.jabref.preferences.FilePreferences; import org.jabref.preferences.ai.AiPreferences; +import org.jabref.preferences.ai.AiProvider; import com.airhacks.afterburner.views.ViewLoader; import org.slf4j.Logger; @@ -22,6 +24,7 @@ public class PrivacyNoticeComponent extends ScrollPane { @FXML private TextFlow openAiPrivacyTextFlow; @FXML private TextFlow mistralAiPrivacyTextFlow; + @FXML private TextFlow geminiPrivacyTextFlow; @FXML private TextFlow huggingFacePrivacyTextFlow; @FXML private Text embeddingModelText; @@ -43,9 +46,10 @@ public PrivacyNoticeComponent(AiPreferences aiPreferences, Runnable onIAgreeButt @FXML private void initialize() { - initPrivacyHyperlink(openAiPrivacyTextFlow, "https://openai.com/policies/privacy-policy/"); - initPrivacyHyperlink(mistralAiPrivacyTextFlow, "https://mistral.ai/terms/#privacy-policy"); - initPrivacyHyperlink(huggingFacePrivacyTextFlow, "https://huggingface.co/privacy"); + initPrivacyHyperlink(openAiPrivacyTextFlow, AiProvider.OPEN_AI); + initPrivacyHyperlink(mistralAiPrivacyTextFlow, AiProvider.MISTRAL_AI); + initPrivacyHyperlink(geminiPrivacyTextFlow, AiProvider.GEMINI); + initPrivacyHyperlink(huggingFacePrivacyTextFlow, AiProvider.HUGGING_FACE); String newEmbeddingModelText = embeddingModelText.getText().replaceAll("%0", aiPreferences.getEmbeddingModel().sizeInfo()); embeddingModelText.setText(newEmbeddingModelText); @@ -56,20 +60,19 @@ private void initialize() { embeddingModelText.wrappingWidthProperty().bind(this.widthProperty()); } - private void initPrivacyHyperlink(TextFlow textFlow, String link) { + private void initPrivacyHyperlink(TextFlow textFlow, AiProvider aiProvider) { if (textFlow.getChildren().isEmpty() || !(textFlow.getChildren().getFirst() instanceof Text text)) { return; } - String[] stringArray = text.getText().split("%0"); + String replacedText = text.getText().replaceAll("%0", aiProvider.getLabel()).replace("%1", ""); - if (stringArray.length != 2) { - return; - } + replacedText = replacedText.endsWith(".") ? replacedText.substring(0, replacedText.length() - 1) : replacedText; + text.setText(replacedText); text.wrappingWidthProperty().bind(this.widthProperty()); - text.setText(stringArray[0]); + String link = AiDefaultPreferences.PROVIDERS_PRIVACY_POLICIES.get(aiProvider); Hyperlink hyperlink = new Hyperlink(link); hyperlink.setWrapText(true); hyperlink.setFont(text.getFont()); @@ -79,11 +82,11 @@ private void initPrivacyHyperlink(TextFlow textFlow, String link) { textFlow.getChildren().add(hyperlink); - Text postText = new Text(stringArray[1]); - postText.setFont(text.getFont()); - postText.wrappingWidthProperty().bind(this.widthProperty()); + Text dot = new Text("."); + dot.setFont(text.getFont()); + dot.wrappingWidthProperty().bind(this.widthProperty()); - textFlow.getChildren().add(postText); + textFlow.getChildren().add(dot); } @FXML diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java index 031803d9f73..995fb277a21 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java @@ -49,12 +49,14 @@ public class AiTabViewModel implements PreferenceTabViewModel { private final StringProperty openAiChatModel = new SimpleStringProperty(); private final StringProperty mistralAiChatModel = new SimpleStringProperty(); + private final StringProperty geminiChatModel = new SimpleStringProperty(); private final StringProperty huggingFaceChatModel = new SimpleStringProperty(); private final StringProperty currentApiKey = new SimpleStringProperty(); private final StringProperty openAiApiKey = new SimpleStringProperty(); private final StringProperty mistralAiApiKey = new SimpleStringProperty(); + private final StringProperty geminiAiApiKey = new SimpleStringProperty(); private final StringProperty huggingFaceApiKey = new SimpleStringProperty(); private final BooleanProperty customizeExpertSettings = new SimpleBooleanProperty(); @@ -64,10 +66,11 @@ public class AiTabViewModel implements PreferenceTabViewModel { private final ObjectProperty selectedEmbeddingModel = new SimpleObjectProperty<>(); private final StringProperty currentApiBaseUrl = new SimpleStringProperty(); - private final BooleanProperty disableApiBaseUrl = new SimpleBooleanProperty(true); // {@link HuggingFaceChatModel} doesn't support setting API base URL + private final BooleanProperty disableApiBaseUrl = new SimpleBooleanProperty(true); // {@link HuggingFaceChatModel} and {@link GoogleAiGeminiChatModel} doesn't support setting API base URL private final StringProperty openAiApiBaseUrl = new SimpleStringProperty(); private final StringProperty mistralAiApiBaseUrl = new SimpleStringProperty(); + private final StringProperty geminiApiBaseUrl = new SimpleStringProperty(); private final StringProperty huggingFaceApiBaseUrl = new SimpleStringProperty(); private final StringProperty instruction = new SimpleStringProperty(); @@ -120,7 +123,7 @@ public AiTabViewModel(PreferencesService preferencesService) { String oldChatModel = currentChatModel.get(); chatModelsList.setAll(models); - disableApiBaseUrl.set(newValue == AiProvider.HUGGING_FACE); + disableApiBaseUrl.set(newValue == AiProvider.HUGGING_FACE || newValue == AiProvider.GEMINI); if (oldValue != null) { switch (oldValue) { @@ -134,6 +137,11 @@ public AiTabViewModel(PreferencesService preferencesService) { mistralAiApiKey.set(currentApiKey.get()); mistralAiApiBaseUrl.set(currentApiBaseUrl.get()); } + case GEMINI -> { + geminiChatModel.set(oldChatModel); + geminiAiApiKey.set(currentApiKey.get()); + geminiApiBaseUrl.set(currentApiBaseUrl.get()); + } case HUGGING_FACE -> { huggingFaceChatModel.set(oldChatModel); huggingFaceApiKey.set(currentApiKey.get()); @@ -153,6 +161,11 @@ public AiTabViewModel(PreferencesService preferencesService) { currentApiKey.set(mistralAiApiKey.get()); currentApiBaseUrl.set(mistralAiApiBaseUrl.get()); } + case GEMINI -> { + currentChatModel.set(geminiChatModel.get()); + currentApiKey.set(geminiAiApiKey.get()); + currentApiBaseUrl.set(geminiApiBaseUrl.get()); + } case HUGGING_FACE -> { currentChatModel.set(huggingFaceChatModel.get()); currentApiKey.set(huggingFaceApiKey.get()); @@ -165,6 +178,7 @@ public AiTabViewModel(PreferencesService preferencesService) { switch (selectedAiProvider.get()) { case OPEN_AI -> openAiChatModel.set(newValue); case MISTRAL_AI -> mistralAiChatModel.set(newValue); + case GEMINI -> geminiChatModel.set(newValue); case HUGGING_FACE -> huggingFaceChatModel.set(newValue); } @@ -182,6 +196,7 @@ public AiTabViewModel(PreferencesService preferencesService) { switch (selectedAiProvider.get()) { case OPEN_AI -> openAiApiKey.set(newValue); case MISTRAL_AI -> mistralAiApiKey.set(newValue); + case GEMINI -> geminiAiApiKey.set(newValue); case HUGGING_FACE -> huggingFaceApiKey.set(newValue); } }); @@ -190,6 +205,7 @@ public AiTabViewModel(PreferencesService preferencesService) { switch (selectedAiProvider.get()) { case OPEN_AI -> openAiApiBaseUrl.set(newValue); case MISTRAL_AI -> mistralAiApiBaseUrl.set(newValue); + case GEMINI -> geminiApiBaseUrl.set(newValue); case HUGGING_FACE -> huggingFaceApiBaseUrl.set(newValue); } }); @@ -265,14 +281,17 @@ public AiTabViewModel(PreferencesService preferencesService) { public void setValues() { openAiApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.OPEN_AI)); mistralAiApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.MISTRAL_AI)); + geminiAiApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.GEMINI)); huggingFaceApiKey.setValue(aiPreferences.getApiKeyForAiProvider(AiProvider.HUGGING_FACE)); openAiApiBaseUrl.setValue(aiPreferences.getOpenAiApiBaseUrl()); mistralAiApiBaseUrl.setValue(aiPreferences.getMistralAiApiBaseUrl()); + geminiApiBaseUrl.setValue(aiPreferences.getGeminiApiBaseUrl()); huggingFaceApiBaseUrl.setValue(aiPreferences.getHuggingFaceApiBaseUrl()); openAiChatModel.setValue(aiPreferences.getOpenAiChatModel()); mistralAiChatModel.setValue(aiPreferences.getMistralAiChatModel()); + geminiChatModel.setValue(aiPreferences.getGeminiChatModel()); huggingFaceChatModel.setValue(aiPreferences.getHuggingFaceChatModel()); enableAi.setValue(aiPreferences.getEnableAi()); @@ -282,7 +301,6 @@ public void setValues() { customizeExpertSettings.setValue(aiPreferences.getCustomizeExpertSettings()); selectedEmbeddingModel.setValue(aiPreferences.getEmbeddingModel()); - instruction.setValue(aiPreferences.getInstruction()); temperature.setValue(LocalizedNumbers.doubleToString(aiPreferences.getTemperature())); contextWindowSize.setValue(aiPreferences.getContextWindowSize()); @@ -300,10 +318,12 @@ public void storeSettings() { aiPreferences.setOpenAiChatModel(openAiChatModel.get() == null ? "" : openAiChatModel.get()); aiPreferences.setMistralAiChatModel(mistralAiChatModel.get() == null ? "" : mistralAiChatModel.get()); + aiPreferences.setGeminiChatModel(geminiChatModel.get() == null ? "" : geminiChatModel.get()); aiPreferences.setHuggingFaceChatModel(huggingFaceChatModel.get() == null ? "" : huggingFaceChatModel.get()); aiPreferences.storeAiApiKeyInKeyring(AiProvider.OPEN_AI, openAiApiKey.get() == null ? "" : openAiApiKey.get()); aiPreferences.storeAiApiKeyInKeyring(AiProvider.MISTRAL_AI, mistralAiApiKey.get() == null ? "" : mistralAiApiKey.get()); + aiPreferences.storeAiApiKeyInKeyring(AiProvider.GEMINI, geminiAiApiKey.get() == null ? "" : geminiAiApiKey.get()); aiPreferences.storeAiApiKeyInKeyring(AiProvider.HUGGING_FACE, huggingFaceApiKey.get() == null ? "" : huggingFaceApiKey.get()); // We notify in all cases without a real check if something was changed aiPreferences.apiKeyUpdated(); @@ -314,6 +334,7 @@ public void storeSettings() { aiPreferences.setOpenAiApiBaseUrl(openAiApiBaseUrl.get() == null ? "" : openAiApiBaseUrl.get()); aiPreferences.setMistralAiApiBaseUrl(mistralAiApiBaseUrl.get() == null ? "" : mistralAiApiBaseUrl.get()); + aiPreferences.setGeminiApiBaseUrl(geminiApiBaseUrl.get() == null ? "" : geminiApiBaseUrl.get()); aiPreferences.setHuggingFaceApiBaseUrl(huggingFaceApiBaseUrl.get() == null ? "" : huggingFaceApiBaseUrl.get()); aiPreferences.setInstruction(instruction.get()); diff --git a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java index 206fa0ae57d..e3fd6238667 100644 --- a/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java +++ b/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java @@ -11,12 +11,21 @@ public class AiDefaultPreferences { AiProvider.OPEN_AI, List.of("gpt-4o-mini", "gpt-4o", "gpt-4", "gpt-4-turbo", "gpt-3.5-turbo"), // "mistral" and "mixtral" are not language mistakes. AiProvider.MISTRAL_AI, List.of("open-mistral-nemo", "open-mistral-7b", "open-mixtral-8x7b", "open-mixtral-8x22b", "mistral-large-latest"), + AiProvider.GEMINI, List.of("gemini-1.5-flash", "gemini-1.5-pro", "gemini-1.0-pro"), AiProvider.HUGGING_FACE, List.of() ); + public static final Map PROVIDERS_PRIVACY_POLICIES = Map.of( + AiProvider.OPEN_AI, "https://openai.com/policies/privacy-policy/", + AiProvider.MISTRAL_AI, "https://mistral.ai/terms/#privacy-policy", + AiProvider.GEMINI, "https://ai.google.dev/gemini-api/terms", + AiProvider.HUGGING_FACE, "https://huggingface.co/privacy" + ); + public static final Map PROVIDERS_API_URLS = Map.of( AiProvider.OPEN_AI, "https://api.openai.com/v1", AiProvider.MISTRAL_AI, "https://api.mistral.ai/v1", + AiProvider.GEMINI, "https://generativelanguage.googleapis.com/v1beta/", AiProvider.HUGGING_FACE, "https://huggingface.co/api" ); @@ -34,6 +43,11 @@ public class AiDefaultPreferences { "open-mistral-7b", 32000, "open-mixtral-8x7b", 32000, "open-mixtral-8x22b", 64000 + ), + AiProvider.GEMINI, Map.of( + "gemini-1.5-flash", 1048576, + "gemini-1.5-pro", 2097152, + "gemini-1.0-pro", 32000 ) ); @@ -44,6 +58,7 @@ public class AiDefaultPreferences { public static final Map CHAT_MODELS = Map.of( AiProvider.OPEN_AI, "gpt-4o-mini", AiProvider.MISTRAL_AI, "open-mixtral-8x22b", + AiProvider.GEMINI, "gemini-1.5-flash", AiProvider.HUGGING_FACE, "" ); diff --git a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java index 5e9c424e3ab..fa4cccf0135 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java +++ b/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java @@ -16,6 +16,7 @@ import dev.langchain4j.data.message.ChatMessage; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel; import dev.langchain4j.model.huggingface.HuggingFaceChatModel; import dev.langchain4j.model.mistralai.MistralAiChatModel; import dev.langchain4j.model.output.Response; @@ -76,8 +77,20 @@ private void rebuild() { ); } + case GEMINI -> { + // NOTE: {@link GoogleAiGeminiChatModel} doesn't support API base url. + langchainChatModel = Optional.of(GoogleAiGeminiChatModel + .builder() + .apiKey(apiKey) + .modelName(aiPreferences.getSelectedChatModel()) + .temperature(aiPreferences.getTemperature()) + .logRequestsAndResponses(true) + .build() + ); + } + case HUGGING_FACE -> { - // NOTE: {@link HuggingFaceChatModel} doesn't support API base url :( + // NOTE: {@link HuggingFaceChatModel} doesn't support API base url. langchainChatModel = Optional.of(HuggingFaceChatModel .builder() .accessToken(apiKey) diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index f5beb092a4b..71010a99881 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -471,11 +471,13 @@ public class JabRefPreferences implements PreferencesService { private static final String AI_PROVIDER = "aiProvider"; private static final String AI_OPEN_AI_CHAT_MODEL = "aiOpenAiChatModel"; private static final String AI_MISTRAL_AI_CHAT_MODEL = "aiMistralAiChatModel"; + private static final String AI_GEMINI_CHAT_MODEL = "aiGeminiChatModel"; private static final String AI_HUGGING_FACE_CHAT_MODEL = "aiHuggingFaceChatModel"; private static final String AI_CUSTOMIZE_SETTINGS = "aiCustomizeSettings"; private static final String AI_EMBEDDING_MODEL = "aiEmbeddingModel"; private static final String AI_OPEN_AI_API_BASE_URL = "aiOpenAiApiBaseUrl"; private static final String AI_MISTRAL_AI_API_BASE_URL = "aiMistralAiApiBaseUrl"; + private static final String AI_GEMINI_API_BASE_URL = "aiGeminiApiBaseUrl"; private static final String AI_HUGGING_FACE_API_BASE_URL = "aiHuggingFaceApiBaseUrl"; private static final String AI_SYSTEM_MESSAGE = "aiSystemMessage"; private static final String AI_TEMPERATURE = "aiTemperature"; @@ -894,11 +896,13 @@ private JabRefPreferences() { defaults.put(AI_PROVIDER, AiDefaultPreferences.PROVIDER.name()); defaults.put(AI_OPEN_AI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.OPEN_AI)); defaults.put(AI_MISTRAL_AI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.MISTRAL_AI)); + defaults.put(AI_GEMINI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.GEMINI)); defaults.put(AI_HUGGING_FACE_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.HUGGING_FACE)); defaults.put(AI_CUSTOMIZE_SETTINGS, AiDefaultPreferences.CUSTOMIZE_SETTINGS); defaults.put(AI_EMBEDDING_MODEL, AiDefaultPreferences.EMBEDDING_MODEL.name()); defaults.put(AI_OPEN_AI_API_BASE_URL, AiDefaultPreferences.PROVIDERS_API_URLS.get(AiProvider.OPEN_AI)); defaults.put(AI_MISTRAL_AI_API_BASE_URL, AiDefaultPreferences.PROVIDERS_API_URLS.get(AiProvider.MISTRAL_AI)); + defaults.put(AI_GEMINI_API_BASE_URL, AiDefaultPreferences.PROVIDERS_API_URLS.get(AiProvider.GEMINI)); defaults.put(AI_HUGGING_FACE_API_BASE_URL, AiDefaultPreferences.PROVIDERS_API_URLS.get(AiProvider.HUGGING_FACE)); defaults.put(AI_SYSTEM_MESSAGE, AiDefaultPreferences.SYSTEM_MESSAGE); defaults.put(AI_TEMPERATURE, AiDefaultPreferences.TEMPERATURE); @@ -2797,10 +2801,12 @@ public AiPreferences getAiPreferences() { AiProvider.valueOf(get(AI_PROVIDER)), get(AI_OPEN_AI_CHAT_MODEL), get(AI_MISTRAL_AI_CHAT_MODEL), + get(AI_GEMINI_CHAT_MODEL), get(AI_HUGGING_FACE_CHAT_MODEL), getBoolean(AI_CUSTOMIZE_SETTINGS), get(AI_OPEN_AI_API_BASE_URL), get(AI_MISTRAL_AI_API_BASE_URL), + get(AI_GEMINI_API_BASE_URL), get(AI_HUGGING_FACE_API_BASE_URL), EmbeddingModel.valueOf(get(AI_EMBEDDING_MODEL)), get(AI_SYSTEM_MESSAGE), @@ -2817,12 +2823,14 @@ public AiPreferences getAiPreferences() { EasyBind.listen(aiPreferences.openAiChatModelProperty(), (obs, oldValue, newValue) -> put(AI_OPEN_AI_CHAT_MODEL, newValue)); EasyBind.listen(aiPreferences.mistralAiChatModelProperty(), (obs, oldValue, newValue) -> put(AI_MISTRAL_AI_CHAT_MODEL, newValue)); + EasyBind.listen(aiPreferences.geminiChatModelProperty(), (obs, oldValue, newValue) -> put(AI_GEMINI_CHAT_MODEL, newValue)); EasyBind.listen(aiPreferences.huggingFaceChatModelProperty(), (obs, oldValue, newValue) -> put(AI_HUGGING_FACE_CHAT_MODEL, newValue)); EasyBind.listen(aiPreferences.customizeExpertSettingsProperty(), (obs, oldValue, newValue) -> putBoolean(AI_CUSTOMIZE_SETTINGS, newValue)); EasyBind.listen(aiPreferences.openAiApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_OPEN_AI_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.mistralAiApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_MISTRAL_AI_API_BASE_URL, newValue)); + EasyBind.listen(aiPreferences.geminiApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_GEMINI_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.huggingFaceApiBaseUrlProperty(), (obs, oldValue, newValue) -> put(AI_HUGGING_FACE_API_BASE_URL, newValue)); EasyBind.listen(aiPreferences.embeddingModelProperty(), (obs, oldValue, newValue) -> put(AI_EMBEDDING_MODEL, newValue.name())); diff --git a/src/main/java/org/jabref/preferences/ai/AiPreferences.java b/src/main/java/org/jabref/preferences/ai/AiPreferences.java index 53f13f210a1..aaab39cb72b 100644 --- a/src/main/java/org/jabref/preferences/ai/AiPreferences.java +++ b/src/main/java/org/jabref/preferences/ai/AiPreferences.java @@ -35,12 +35,14 @@ public class AiPreferences { private final StringProperty openAiChatModel; private final StringProperty mistralAiChatModel; + private final StringProperty geminiChatModel; private final StringProperty huggingFaceChatModel; private final BooleanProperty customizeExpertSettings; private final StringProperty openAiApiBaseUrl; private final StringProperty mistralAiApiBaseUrl; + private final StringProperty geminiApiBaseUrl; private final StringProperty huggingFaceApiBaseUrl; private final ObjectProperty embeddingModel; @@ -58,10 +60,12 @@ public AiPreferences(boolean enableAi, AiProvider aiProvider, String openAiChatModel, String mistralAiChatModel, + String geminiChatModel, String huggingFaceChatModel, boolean customizeExpertSettings, String openAiApiBaseUrl, String mistralAiApiBaseUrl, + String geminiApiBaseUrl, String huggingFaceApiBaseUrl, EmbeddingModel embeddingModel, String instruction, @@ -78,12 +82,14 @@ public AiPreferences(boolean enableAi, this.openAiChatModel = new SimpleStringProperty(openAiChatModel); this.mistralAiChatModel = new SimpleStringProperty(mistralAiChatModel); + this.geminiChatModel = new SimpleStringProperty(geminiChatModel); this.huggingFaceChatModel = new SimpleStringProperty(huggingFaceChatModel); this.customizeExpertSettings = new SimpleBooleanProperty(customizeExpertSettings); this.openAiApiBaseUrl = new SimpleStringProperty(openAiApiBaseUrl); this.mistralAiApiBaseUrl = new SimpleStringProperty(mistralAiApiBaseUrl); + this.geminiApiBaseUrl = new SimpleStringProperty(geminiApiBaseUrl); this.huggingFaceApiBaseUrl = new SimpleStringProperty(huggingFaceApiBaseUrl); this.embeddingModel = new SimpleObjectProperty<>(embeddingModel); @@ -99,8 +105,7 @@ public AiPreferences(boolean enableAi, public String getApiKeyForAiProvider(AiProvider aiProvider) { try (final Keyring keyring = Keyring.create()) { return keyring.getPassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name()); - } catch ( - PasswordAccessException e) { + } catch (PasswordAccessException e) { LOGGER.debug("No API key stored for provider {}. Returning an empty string", aiProvider.getLabel()); return ""; } catch (Exception e) { @@ -173,6 +178,18 @@ public void setMistralAiChatModel(String mistralAiChatModel) { this.mistralAiChatModel.set(mistralAiChatModel); } + public StringProperty geminiChatModelProperty() { + return geminiChatModel; + } + + public String getGeminiChatModel() { + return geminiChatModel.get(); + } + + public void setGeminiChatModel(String geminiChatModel) { + this.geminiChatModel.set(geminiChatModel); + } + public StringProperty huggingFaceChatModelProperty() { return huggingFaceChatModel; } @@ -237,6 +254,18 @@ public void setMistralAiApiBaseUrl(String mistralAiApiBaseUrl) { this.mistralAiApiBaseUrl.set(mistralAiApiBaseUrl); } + public StringProperty geminiApiBaseUrlProperty() { + return geminiApiBaseUrl; + } + + public String getGeminiApiBaseUrl() { + return geminiApiBaseUrl.get(); + } + + public void setGeminiApiBaseUrl(String geminiApiBaseUrl) { + this.geminiApiBaseUrl.set(geminiApiBaseUrl); + } + public StringProperty huggingFaceApiBaseUrlProperty() { return huggingFaceApiBaseUrl; } @@ -293,6 +322,7 @@ public int getContextWindowSize() { case OPEN_AI -> AiDefaultPreferences.getContextWindowSize(AiProvider.OPEN_AI, openAiChatModel.get()); case MISTRAL_AI -> AiDefaultPreferences.getContextWindowSize(AiProvider.MISTRAL_AI, mistralAiChatModel.get()); case HUGGING_FACE -> AiDefaultPreferences.getContextWindowSize(AiProvider.HUGGING_FACE, huggingFaceChatModel.get()); + case GEMINI -> AiDefaultPreferences.getContextWindowSize(AiProvider.GEMINI, geminiChatModel.get()); }; } } @@ -418,6 +448,8 @@ public String getSelectedChatModel() { mistralAiChatModel.get(); case HUGGING_FACE -> huggingFaceChatModel.get(); + case GEMINI -> + geminiChatModel.get(); }; } @@ -430,6 +462,8 @@ public String getSelectedApiBaseUrl() { mistralAiApiBaseUrl.get(); case HUGGING_FACE -> huggingFaceApiBaseUrl.get(); + case GEMINI -> + geminiApiBaseUrl.get(); }; } else { return AiDefaultPreferences.PROVIDERS_API_URLS.get(aiProvider.get()); diff --git a/src/main/java/org/jabref/preferences/ai/AiProvider.java b/src/main/java/org/jabref/preferences/ai/AiProvider.java index 69c3405249d..b682035dc07 100644 --- a/src/main/java/org/jabref/preferences/ai/AiProvider.java +++ b/src/main/java/org/jabref/preferences/ai/AiProvider.java @@ -5,6 +5,7 @@ public enum AiProvider implements Serializable { OPEN_AI("OpenAI"), MISTRAL_AI("Mistral AI"), + GEMINI("Gemini"), HUGGING_FACE("Hugging Face"); private final String label; diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index a60384b6812..80d0c559891 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2570,9 +2570,6 @@ Enable\ AI\ functionality\ (summary\ generation\ and\ chatting)\ in\ JabRef=Enab Customize\ expert\ settings=Customize expert settings These\ parameters\ affect\ how\ the\ AI\ will\ answer\ your\ questions.=These parameters affect how the AI will answer your questions. Chat\ with\ AI\ about\ content\ of\ attached\ file(s)=Chat with AI about content of attached file(s) -If\ you\ have\ chosen\ the\ Hugging\ Face\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Hugging\ Face\ applies.\ You\ find\ it\ at\ %0.=If you have chosen the Hugging Face as AI provider, the privacy policy of Hugging Face applies. You find it at %0. -If\ you\ have\ chosen\ the\ Mistral\ AI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Mistral\ AI\ applies.\ You\ find\ it\ at\ %0.=If you have chosen the Mistral AI as AI provider, the privacy policy of Mistral AI applies. You find it at %0. -If\ you\ have\ chosen\ the\ OpenAI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ OpenAI\ applies.\ You\ find\ it\ at\ %0.=If you have chosen the OpenAI as AI provider, the privacy policy of OpenAI applies. You find it at %0. In\ order\ to\ use\ AI\ chat,\ you\ need\ to\ enable\ chatting\ with\ attached\ PDF\ files\ in\ JabRef\ preferences\ (AI\ tab).=In order to use AI chat, you need to enable chatting with attached PDF files in JabRef preferences (AI tab). In\ order\ to\ use\ AI\ chat,\ set\ an\ API\ key\ inside\ JabRef\ preferences\ (AI\ tab).=In order to use AI chat, set an API key inside JabRef preferences (AI tab). Unable\ to\ chat\ with\ AI.=Unable to chat with AI. @@ -2632,6 +2629,7 @@ Generating\ embeddings\ for\ %0=Generating embeddings for %0 RAG\ minimum\ score\ must\ be\ a\ number=RAG minimum score must be a number RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=RAG minimum score must be greater than 0 and less than 1 Temperature\ must\ be\ a\ number=Temperature must be a number +If\ you\ have\ chosen\ %0\ as\ an\ AI\ provider,\ the\ privacy\ policy\ of\ %0\ applies.\ You\ find\ it\ at\ %1.=If you have chosen %0 as an AI provider, the privacy policy of %0 applies. You find it at %1. Link=Link Source\ URL=Source URL From f7fde15943ab52c153649046c6de967672128916 Mon Sep 17 00:00:00 2001 From: Nihar Thakkar <63655579+18bce133@users.noreply.github.com> Date: Fri, 13 Sep 2024 05:52:56 -0700 Subject: [PATCH 039/324] Refactor EprintCleanup to handle institution, version, and EID fields (#11627) * Refactor EprintCleanup to handle institution, version, and EID fields * Add test for cleanup with VERSION, INSTITUTION, and EID * Add version to EPRINT if not present * Modify test to retain INSTITUTION as "tbd"; include documentation link * clear institution field if it is "arXiv" else keep it as it is. * Complied to OpenRewrite to ensure "modern" Java coding practices. * Update CHANGELOG.md * Add "real" hyperlink --------- Co-authored-by: Subhramit Basu Bhowmick Co-authored-by: Oliver Kopp --- CHANGELOG.md | 1 + .../jabref/logic/cleanup/EprintCleanup.java | 21 ++++++++++- .../logic/cleanup/EprintCleanupTest.java | 37 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b20c6bf2e94..49785c7fc89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We enabled creating a new file link manually. [#11017](https://github.com/JabRef/jabref/issues/11017) - We added a toggle button to invert the selected groups. [#9073](https://github.com/JabRef/jabref/issues/9073) - We reintroduced the floating search in the main table. [#4237](https://github.com/JabRef/jabref/issues/4237) +- We improved [cleanup](https://docs.jabref.org/finding-sorting-and-cleaning-entries/cleanupentries) of `arXiv` IDs in distributed in the fields `note`, `version`, `institution`, and `eid` fields. [#11306](https://github.com/JabRef/jabref/issues/11306) - We added a switch not to store the linked file URL, because it caused troubles at other apps. [#11735](https://github.com/JabRef/jabref/pull/11735) - When starting a new SLR, the selected catalogs now persist within and across JabRef sessions. [koppor#614](https://github.com/koppor/jabref/issues/614) - We added a different background color to the search bar to indicate when the search syntax is wrong. [#11658](https://github.com/JabRef/jabref/pull/11658) diff --git a/src/main/java/org/jabref/logic/cleanup/EprintCleanup.java b/src/main/java/org/jabref/logic/cleanup/EprintCleanup.java index 27ab856c499..abc56b9db6a 100644 --- a/src/main/java/org/jabref/logic/cleanup/EprintCleanup.java +++ b/src/main/java/org/jabref/logic/cleanup/EprintCleanup.java @@ -13,6 +13,8 @@ /** * Formats the DOI (e.g. removes http part) and also moves DOIs from note, url or ee field to the doi field. + * + * Background information on tex.stackexchange. */ public class EprintCleanup implements CleanupJob { @@ -20,11 +22,25 @@ public class EprintCleanup implements CleanupJob { public List cleanup(BibEntry entry) { List changes = new ArrayList<>(); - for (Field field : Arrays.asList(StandardField.URL, StandardField.JOURNAL, StandardField.JOURNALTITLE, StandardField.NOTE)) { + Optional version = entry.getField(StandardField.VERSION); + Optional institution = entry.getField(StandardField.INSTITUTION); + + for (Field field : Arrays.asList(StandardField.URL, StandardField.JOURNAL, StandardField.JOURNALTITLE, StandardField.NOTE, StandardField.EID)) { Optional arXivIdentifier = entry.getField(field).flatMap(ArXivIdentifier::parse); if (arXivIdentifier.isPresent()) { - entry.setField(StandardField.EPRINT, arXivIdentifier.get().getNormalized()) + String normalizedEprint = arXivIdentifier.get().getNormalized(); + + if (version.isPresent() && !normalizedEprint.contains("v" + version.get())) { + normalizedEprint += "v" + version.get(); + } + + if (institution.isPresent() && "arxiv".equalsIgnoreCase(institution.get())) { + entry.clearField(StandardField.INSTITUTION) + .ifPresent(changes::add); + } + + entry.setField(StandardField.EPRINT, normalizedEprint) .ifPresent(changes::add); entry.setField(StandardField.EPRINTTYPE, "arxiv") @@ -45,6 +61,7 @@ public List cleanup(BibEntry entry) { } } } + entry.clearField(StandardField.VERSION).ifPresent(changes::add); return changes; } diff --git a/src/test/java/org/jabref/logic/cleanup/EprintCleanupTest.java b/src/test/java/org/jabref/logic/cleanup/EprintCleanupTest.java index d27a98e59fa..f391a4bd44f 100644 --- a/src/test/java/org/jabref/logic/cleanup/EprintCleanupTest.java +++ b/src/test/java/org/jabref/logic/cleanup/EprintCleanupTest.java @@ -27,4 +27,41 @@ void cleanupCompleteEntry() { assertEquals(expected, input); } + + @Test + void cleanupEntryWithVersionAndInstitutionAndEid() { + BibEntry input = new BibEntry() + .withField(StandardField.NOTE, "arXiv: 1503.05173") + .withField(StandardField.VERSION, "1") + .withField(StandardField.INSTITUTION, "arXiv") + .withField(StandardField.EID, "arXiv:1503.05173"); + + BibEntry expected = new BibEntry() + .withField(StandardField.EPRINT, "1503.05173v1") + .withField(StandardField.EPRINTTYPE, "arxiv"); + + EprintCleanup cleanup = new EprintCleanup(); + cleanup.cleanup(input); + + assertEquals(expected, input); + } + + @Test + void cleanupEntryWithOtherInstitution() { + BibEntry input = new BibEntry() + .withField(StandardField.NOTE, "arXiv: 1503.05173") + .withField(StandardField.VERSION, "1") + .withField(StandardField.INSTITUTION, "OtherInstitution") + .withField(StandardField.EID, "arXiv:1503.05173"); + + BibEntry expected = new BibEntry() + .withField(StandardField.EPRINT, "1503.05173v1") + .withField(StandardField.EPRINTTYPE, "arxiv") + .withField(StandardField.INSTITUTION, "OtherInstitution"); + + EprintCleanup cleanup = new EprintCleanup(); + cleanup.cleanup(input); + + assertEquals(expected, input); + } } From 939f6961a9eafbac17c95bc0b97311b85d3262d2 Mon Sep 17 00:00:00 2001 From: leaf-soba Date: Fri, 13 Sep 2024 20:54:03 +0800 Subject: [PATCH 040/324] add unit test to generateInstitutionKey (#11756) * add unit test to generateInstitutionKey prepare to refactor this method * Update BracketedPatternTest.java --- .../citationkeypattern/BracketedPattern.java | 8 +++--- .../BracketedPatternTest.java | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java b/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java index 2407cf0fe7f..0447f748cef 100644 --- a/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java +++ b/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java @@ -36,6 +36,7 @@ import org.jabref.model.strings.LatexToUnicodeAdapter; import org.jabref.model.strings.StringUtil; +import com.google.common.annotations.VisibleForTesting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -1218,14 +1219,14 @@ protected static List parseFieldAndModifiers(String arg) { *

  • null if content is null
  • * */ - private static String generateInstitutionKey(String content) { + @VisibleForTesting + static String generateInstitutionKey(String content) { if (content == null) { return null; } if (content.isBlank()) { return ""; } - Matcher matcher = INLINE_ABBREVIATION.matcher(content); if (matcher.find()) { return LatexToUnicodeAdapter.format(matcher.group()); @@ -1309,8 +1310,7 @@ private static String generateInstitutionKey(String content) { // Putting parts together. return (university == null ? Objects.toString(rest, "") : university) + (school == null ? "" : school) - + ((department == null) - || ((school != null) && department.equals(school)) ? "" : department); + + ((department == null) || (department.equals(school)) ? "" : department); } /** diff --git a/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java b/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java index cc466d6b90e..4d1b3649778 100644 --- a/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java +++ b/src/test/java/org/jabref/logic/citationkeypattern/BracketedPatternTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; /** @@ -734,4 +735,31 @@ void editorFieldMarkers(String expectedCitationKey, String pattern, String edito BracketedPattern bracketedPattern = new BracketedPattern(pattern); assertEquals(expectedCitationKey, bracketedPattern.expand(bibEntry)); } + + @ParameterizedTest + @CsvSource({ + "'', ''", + "The Attributed Graph Grammar System ({AGG}),AGG", + "'The University of Science',UniScience", + "'School of Business, Department of Management',BM", + "'Graph Systems Research Group',GSRG", + "'The Great Institute, 123 Main Street, Springfield',GreatInstitute", + "'Invalid {\\Unicode}',Invalid", + "'School of Electrical Engineering ({SEE}), Department of Computer Science',SEE", + "'{The Attributed Graph Grammar System ({AGG})}',AGG", + "'{The Attributed Graph Grammar System}',AGGS", + "'{University of Example, Department of Computer Science, Some Address}',UniExampleCS", + "'{Example School of Engineering, Department of Computer Science, Some Address}',SomeAddressEECS", + "'{Example Institute, Computer Science Department, Some Address}',ExampleInstituteCS", + "'{Short Part, Some Address}',ShortPart", + "'{Example with Several Tokens, Some Address}',EST"}) + + void generateInstitutionKeyTest(String input, String expected) { + assertEquals(expected, BracketedPattern.generateInstitutionKey(input)); + } + + @Test + void generateInstitutionKeyNullTest() { + assertNull(BracketedPattern.generateInstitutionKey(null)); + } } From 35b0516cd1b044a720b7e1658a416692cff5cc19 Mon Sep 17 00:00:00 2001 From: Austin Schaefer Date: Sat, 14 Sep 2024 00:02:56 +0200 Subject: [PATCH 041/324] Add setting: always add "Cited on pages" text to JStyles. (#11732) * Add setting to always add "Cited on pages" text in JStyle Citations. * Add setting: always add "Cited on pages" text to JStyles. * Add changelog. * Add change to Changelog. * Fix translation key. Ensure checkstyle conformity. * Correct option text, position, & hiding behavior. The new option's presence now based on selected style, with presence being ensured only if the style is a JStyle. The option now appears always first from the top, using index based insertion to achieve this. The text has been updated to reference bibliographic entries as opposed to citations, which was factually incorrect. * Cited on pages... text now appears. Reference existing preference in OOBibBase to properly propagate setting, so that "Cited on pages" text literal will appear when user has it configured. Remove accomplished TODOs. * Shift changelog entry, fix setting string, misc. formatting * Attempt to update submodules to origin/master state. * Attempt to fix submodule hashes. * Re-ignore submodules. * Fix spacing. --------- Co-authored-by: Subhramit Basu Bhowmick --- CHANGELOG.md | 1 + .../org/jabref/gui/openoffice/OOBibBase.java | 10 ++--- .../gui/openoffice/OpenOfficePanel.java | 38 +++++++++++++++++-- .../openoffice/OpenOfficePreferences.java | 17 ++++++++- .../jabref/preferences/JabRefPreferences.java | 6 ++- src/main/resources/l10n/JabRef_en.properties | 1 + 6 files changed, 62 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49785c7fc89..967c615792e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We added a switch not to store the linked file URL, because it caused troubles at other apps. [#11735](https://github.com/JabRef/jabref/pull/11735) - When starting a new SLR, the selected catalogs now persist within and across JabRef sessions. [koppor#614](https://github.com/koppor/jabref/issues/614) - We added a different background color to the search bar to indicate when the search syntax is wrong. [#11658](https://github.com/JabRef/jabref/pull/11658) +- We added a setting which always adds the literal "Cited on pages" text before each JStyle citation. [#11691](https://github.com/JabRef/jabref/pull/11732) ### Changed diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index 40a37a69d9f..637c729a720 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -15,6 +15,7 @@ import org.jabref.logic.citationstyle.CitationStyle; import org.jabref.logic.l10n.Localization; import org.jabref.logic.openoffice.NoDocumentFoundException; +import org.jabref.logic.openoffice.OpenOfficePreferences; import org.jabref.logic.openoffice.action.EditInsert; import org.jabref.logic.openoffice.action.EditMerge; import org.jabref.logic.openoffice.action.EditSeparate; @@ -68,14 +69,13 @@ public class OOBibBase { private final DialogService dialogService; - // Shall we add "Cited on pages: ..." to resolved bibliography entries? - private final boolean alwaysAddCitedOnPages; // TODO (see comment above) + private final boolean alwaysAddCitedOnPages; private final OOBibBaseConnect connection; private CSLCitationOOAdapter cslCitationOOAdapter; - public OOBibBase(Path loPath, DialogService dialogService) + public OOBibBase(Path loPath, DialogService dialogService, OpenOfficePreferences openOfficePreferences) throws BootstrapException, CreationException { @@ -83,7 +83,7 @@ public OOBibBase(Path loPath, DialogService dialogService) this.dialogService = dialogService; this.connection = new OOBibBaseConnect(loPath, dialogService); - this.alwaysAddCitedOnPages = false; + this.alwaysAddCitedOnPages = openOfficePreferences.getAlwaysAddCitedOnPages(); } private void initializeCitationAdapter(XTextDocument doc) throws WrappedTargetException, NoSuchElementException { @@ -583,7 +583,7 @@ public void guiActionInsertEntry(List entries, } } - syncOptions.map(e -> e.setAlwaysAddCitedOnPages(this.alwaysAddCitedOnPages)); // TODO: Provide option to user: this is always false + syncOptions.map(e -> e.setAlwaysAddCitedOnPages(this.alwaysAddCitedOnPages)); try { diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index cff14afe648..fa38b9a385b 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -8,6 +8,7 @@ import javax.swing.undo.UndoManager; +import javafx.beans.property.SimpleObjectProperty; import javafx.concurrent.Task; import javafx.geometry.Insets; import javafx.geometry.Side; @@ -65,6 +66,7 @@ import com.sun.star.comp.helper.BootstrapException; import com.sun.star.container.NoSuchElementException; import com.sun.star.lang.WrappedTargetException; +import com.tobiasdiez.easybind.EasyBind; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -102,9 +104,12 @@ public class OpenOfficePanel { private final LibraryTabContainer tabContainer; private final FileUpdateMonitor fileUpdateMonitor; private final BibEntryTypesManager entryTypesManager; + private final OpenOfficePreferences openOfficePreferences; private OOBibBase ooBase; private OOStyle currentStyle; + private final SimpleObjectProperty currentStyleProperty; + public OpenOfficePanel(LibraryTabContainer tabContainer, PreferencesService preferencesService, KeyBindingRepository keyBindingRepository, @@ -126,6 +131,7 @@ public OpenOfficePanel(LibraryTabContainer tabContainer, this.clipBoardManager = clipBoardManager; this.undoManager = undoManager; this.currentStyle = preferencesService.getOpenOfficePreferences().getCurrentStyle(); + this.openOfficePreferences = preferencesService.getOpenOfficePreferences(); ActionFactory factory = new ActionFactory(); @@ -157,6 +163,8 @@ public OpenOfficePanel(LibraryTabContainer tabContainer, preferencesService.getLayoutFormatterPreferences(), abbreviationRepository); + currentStyleProperty = new SimpleObjectProperty<>(currentStyle); + initPanel(); } @@ -170,6 +178,7 @@ public Node getContent() { */ private boolean getOrUpdateTheStyle(String title) { currentStyle = loader.getUsedStyleUnified(); + currentStyleProperty.set(currentStyle); final boolean FAIL = true; final boolean PASS = false; @@ -215,6 +224,8 @@ private void initPanel() { dialogService.showCustomDialogAndWait(styleDialog) .ifPresent(selectedStyle -> { currentStyle = selectedStyle; + currentStyleProperty.set(currentStyle); + if (currentStyle instanceof JStyle jStyle) { try { jStyle.ensureUpToDate(); @@ -472,7 +483,7 @@ protected OOBibBase call() throws BootstrapException, CreationException { } private OOBibBase createBibBase(Path loPath) throws BootstrapException, CreationException { - return new OOBibBase(loPath, dialogService); + return new OOBibBase(loPath, dialogService, openOfficePreferences); } /** @@ -614,12 +625,27 @@ private boolean checkThatEntriesHaveKeys(List entries) { } private ContextMenu createSettingsPopup() { - OpenOfficePreferences openOfficePreferences = preferencesService.getOpenOfficePreferences(); - ContextMenu contextMenu = new ContextMenu(); CheckMenuItem autoSync = new CheckMenuItem(Localization.lang("Automatically sync bibliography when inserting citations")); - autoSync.selectedProperty().set(preferencesService.getOpenOfficePreferences().getSyncWhenCiting()); + autoSync.selectedProperty().set(openOfficePreferences.getSyncWhenCiting()); + + CheckMenuItem alwaysAddCitedOnPagesText = new CheckMenuItem(Localization.lang("Automatically add \"Cited on pages...\" at the end of bibliographic entries")); + alwaysAddCitedOnPagesText.selectedProperty().set(openOfficePreferences.getAlwaysAddCitedOnPages()); + alwaysAddCitedOnPagesText.setOnAction(e -> openOfficePreferences.setAlwaysAddCitedOnPages(alwaysAddCitedOnPagesText.isSelected())); + + EasyBind.listen(currentStyleProperty, (obs, oldValue, newValue) -> { + switch (newValue) { + case JStyle ignored -> { + if (!contextMenu.getItems().contains(alwaysAddCitedOnPagesText)) { + contextMenu.getItems().add(1, alwaysAddCitedOnPagesText); + } + } + case CitationStyle ignored -> + contextMenu.getItems().remove(alwaysAddCitedOnPagesText); + default -> { } + } + }); ToggleGroup toggleGroup = new ToggleGroup(); RadioMenuItem useActiveBase = new RadioMenuItem(Localization.lang("Look up BibTeX entries in the active tab only")); @@ -651,6 +677,10 @@ private ContextMenu createSettingsPopup() { new SeparatorMenuItem(), clearConnectionSettings); + if (currentStyle instanceof JStyle) { + contextMenu.getItems().add(1, alwaysAddCitedOnPagesText); + } + return contextMenu; } } diff --git a/src/main/java/org/jabref/logic/openoffice/OpenOfficePreferences.java b/src/main/java/org/jabref/logic/openoffice/OpenOfficePreferences.java index 7b0f4a2c287..b536fd48e0f 100644 --- a/src/main/java/org/jabref/logic/openoffice/OpenOfficePreferences.java +++ b/src/main/java/org/jabref/logic/openoffice/OpenOfficePreferences.java @@ -31,19 +31,22 @@ public class OpenOfficePreferences { private final ObservableList externalStyles; private final StringProperty currentJStyle; private final ObjectProperty currentStyle; + private final BooleanProperty alwaysAddCitedOnPages; public OpenOfficePreferences(String executablePath, boolean useAllDatabases, boolean syncWhenCiting, List externalStyles, String currentJStyle, - OOStyle currentStyle) { + OOStyle currentStyle, + boolean alwaysAddCitedOnPages) { this.executablePath = new SimpleStringProperty(executablePath); this.useAllDatabases = new SimpleBooleanProperty(useAllDatabases); this.syncWhenCiting = new SimpleBooleanProperty(syncWhenCiting); this.externalStyles = FXCollections.observableArrayList(externalStyles); this.currentJStyle = new SimpleStringProperty(currentJStyle); this.currentStyle = new SimpleObjectProperty<>(currentStyle); + this.alwaysAddCitedOnPages = new SimpleBooleanProperty(alwaysAddCitedOnPages); } public void clearConnectionSettings() { @@ -137,4 +140,16 @@ public ObjectProperty currentStyleProperty() { public void setCurrentStyle(OOStyle style) { this.currentStyle.set(style); } + + public boolean getAlwaysAddCitedOnPages() { + return this.alwaysAddCitedOnPages.get(); + } + + public BooleanProperty alwaysAddCitedOnPagesProperty() { + return this.alwaysAddCitedOnPages; + } + + public void setAlwaysAddCitedOnPages(boolean alwaysAddCitedOnPages) { + this.alwaysAddCitedOnPages.set(alwaysAddCitedOnPages); + } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 71010a99881..1c4506e45a2 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -371,6 +371,7 @@ public class JabRefPreferences implements PreferencesService { public static final String OO_BIBLIOGRAPHY_STYLE_FILE = "ooBibliographyStyleFile"; public static final String OO_EXTERNAL_STYLE_FILES = "ooExternalStyleFiles"; public static final String OO_CURRENT_STYLE = "ooCurrentStyle"; + public static final String OO_ALWAYS_ADD_CITED_ON_PAGES = "ooAlwaysAddCitedOnPages"; // Special field preferences public static final String SPECIALFIELDSENABLED = "specialFieldsEnabled"; @@ -759,6 +760,7 @@ private JabRefPreferences() { } defaults.put(OO_SYNC_WHEN_CITING, Boolean.TRUE); + defaults.put(OO_ALWAYS_ADD_CITED_ON_PAGES, Boolean.FALSE); defaults.put(OO_SHOW_PANEL, Boolean.FALSE); defaults.put(OO_USE_ALL_OPEN_BASES, Boolean.TRUE); defaults.put(OO_BIBLIOGRAPHY_STYLE_FILE, StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH); @@ -1383,10 +1385,12 @@ public OpenOfficePreferences getOpenOfficePreferences() { getBoolean(OO_SYNC_WHEN_CITING), getStringList(OO_EXTERNAL_STYLE_FILES), get(OO_BIBLIOGRAPHY_STYLE_FILE), - currentStyle); + currentStyle, + getBoolean(OO_ALWAYS_ADD_CITED_ON_PAGES)); EasyBind.listen(openOfficePreferences.executablePathProperty(), (obs, oldValue, newValue) -> put(OO_EXECUTABLE_PATH, newValue)); EasyBind.listen(openOfficePreferences.useAllDatabasesProperty(), (obs, oldValue, newValue) -> putBoolean(OO_USE_ALL_OPEN_BASES, newValue)); + EasyBind.listen(openOfficePreferences.alwaysAddCitedOnPagesProperty(), (obs, oldValue, newValue) -> putBoolean(OO_ALWAYS_ADD_CITED_ON_PAGES, newValue)); EasyBind.listen(openOfficePreferences.syncWhenCitingProperty(), (obs, oldValue, newValue) -> putBoolean(OO_SYNC_WHEN_CITING, newValue)); openOfficePreferences.getExternalStyles().addListener((InvalidationListener) change -> diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 80d0c559891..ed0d5a7f9a1 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1132,6 +1132,7 @@ Unable\ to\ reload\ style\ file=Unable to reload style file Problem\ during\ separating\ cite\ markers=Problem during separating cite markers +Automatically\ add\ "Cited\ on\ pages..."\ at\ the\ end\ of\ bibliographic\ entries=Automatically add "Cited on pages..." at the end of bibliographic entries Automatically\ sync\ bibliography\ when\ inserting\ citations=Automatically sync bibliography when inserting citations Look\ up\ BibTeX\ entries\ in\ the\ active\ tab\ only=Look up BibTeX entries in the active tab only Look\ up\ BibTeX\ entries\ in\ all\ open\ libraries=Look up BibTeX entries in all open libraries From 9634a13bbc91954b7e53c88312fca8e71069f8d5 Mon Sep 17 00:00:00 2001 From: Houssem Nasri Date: Fri, 13 Sep 2024 23:29:03 +0100 Subject: [PATCH 042/324] Enable/Disable the undo and redo toolbar/menu buttons correctly (#11758) * Enable/Disable the undo and redo toolbar/menu buttons correctly * Add changelog entry --- CHANGELOG.md | 1 + .../jabref/gui/undo/CountingUndoManager.java | 62 ++++++++++++++++--- .../java/org/jabref/gui/undo/RedoAction.java | 8 +-- .../java/org/jabref/gui/undo/UndoAction.java | 8 +-- 4 files changed, 63 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 967c615792e..57f964c3101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - The browse button for a Custom theme now opens in the directory of the current used CSS file. [#11597](https://github.com/JabRef/jabref/pull/11597) - The browse button for a Custom exporter now opens in the directory of the current used exporter file. [#11717](https://github.com/JabRef/jabref/pull/11717) - We improved the display of long messages in the integrity check dialog. [#11619](https://github.com/JabRef/jabref/pull/11619) +- We improved the undo/redo buttons in the main toolbar and main menu to be disabled when there is nothing to undo/redo. [#8807](https://github.com/JabRef/jabref/issues/8807) ### Fixed diff --git a/src/main/java/org/jabref/gui/undo/CountingUndoManager.java b/src/main/java/org/jabref/gui/undo/CountingUndoManager.java index dfe059dc467..1e4eaa8981d 100644 --- a/src/main/java/org/jabref/gui/undo/CountingUndoManager.java +++ b/src/main/java/org/jabref/gui/undo/CountingUndoManager.java @@ -4,35 +4,81 @@ import javax.swing.undo.UndoManager; import javax.swing.undo.UndoableEdit; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; + public class CountingUndoManager extends UndoManager { private int unchangedPoint; - private int current; + + /** + * Indicates the number of edits aka balance of edits on the stack +1 when an edit is added/redone and -1 when an edit is undoed. + * */ + private final IntegerProperty balanceProperty = new SimpleIntegerProperty(0); + private final BooleanProperty undoableProperty = new SimpleBooleanProperty(false); + private final BooleanProperty redoableProperty = new SimpleBooleanProperty(false); @Override public synchronized boolean addEdit(UndoableEdit edit) { - current++; - boolean result = super.addEdit(edit); - return result; + boolean editAdded = super.addEdit(edit); + if (editAdded) { + incrementBalance(); + updateUndoableStatus(); + updateRedoableStatus(); + return true; + } else { + return false; + } } @Override public synchronized void undo() throws CannotUndoException { super.undo(); - current--; + decrementBalance(); + updateUndoableStatus(); + updateRedoableStatus(); } @Override public synchronized void redo() throws CannotUndoException { super.redo(); - current++; + incrementBalance(); + updateUndoableStatus(); + updateRedoableStatus(); } public synchronized void markUnchanged() { - unchangedPoint = current; + unchangedPoint = balanceProperty.get(); } public synchronized boolean hasChanged() { - return current != unchangedPoint; + return balanceProperty.get() != unchangedPoint; + } + + private void incrementBalance() { + balanceProperty.setValue(balanceProperty.getValue() + 1); + } + + private void decrementBalance() { + balanceProperty.setValue(balanceProperty.getValue() - 1); + } + + private void updateUndoableStatus() { + undoableProperty.setValue(canUndo()); + } + + private void updateRedoableStatus() { + redoableProperty.setValue(canRedo()); + } + + public ReadOnlyBooleanProperty getUndoableProperty() { + return undoableProperty; + } + + public ReadOnlyBooleanProperty getRedoableProperty() { + return redoableProperty; } } diff --git a/src/main/java/org/jabref/gui/undo/RedoAction.java b/src/main/java/org/jabref/gui/undo/RedoAction.java index 9227017aced..27e8b23f436 100644 --- a/src/main/java/org/jabref/gui/undo/RedoAction.java +++ b/src/main/java/org/jabref/gui/undo/RedoAction.java @@ -7,7 +7,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.LibraryTab; import org.jabref.gui.StateManager; -import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.logic.l10n.Localization; @@ -22,9 +21,10 @@ public RedoAction(Supplier tabSupplier, DialogService dialogService, this.tabSupplier = tabSupplier; this.dialogService = dialogService; - // TODO: Rework the UndoManager to something like the following, if it had a property. - // this.executable.bind(frame.getCurrentBasePanel().getUndoManager().canUndo()) - this.executable.bind(ActionHelper.needsDatabase(stateManager)); + stateManager.activeTabProperty().addListener((observable, oldValue, activeLibraryTab) -> { + activeLibraryTab.ifPresent(libraryTab -> + this.executable.bind(libraryTab.getUndoManager().getRedoableProperty())); + }); } @Override diff --git a/src/main/java/org/jabref/gui/undo/UndoAction.java b/src/main/java/org/jabref/gui/undo/UndoAction.java index 9e219d637df..a61551bcf6b 100644 --- a/src/main/java/org/jabref/gui/undo/UndoAction.java +++ b/src/main/java/org/jabref/gui/undo/UndoAction.java @@ -7,7 +7,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.LibraryTab; import org.jabref.gui.StateManager; -import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.logic.l10n.Localization; @@ -22,9 +21,10 @@ public UndoAction(Supplier tabSupplier, DialogService dialogService, this.tabSupplier = tabSupplier; this.dialogService = dialogService; - // TODO: Rework the UndoManager to something like the following, if it had a property. - // this.executable.bind(frame.getCurrentBasePanel().getUndoManager().canUndo()) - this.executable.bind(ActionHelper.needsDatabase(stateManager)); + stateManager.activeTabProperty().addListener((observable, oldValue, activeLibraryTab) -> { + activeLibraryTab.ifPresent(libraryTab -> + this.executable.bind(libraryTab.getUndoManager().getUndoableProperty())); + }); } @Override From 67ca1743e79a66db250e9e0c74676dcd348aeb91 Mon Sep 17 00:00:00 2001 From: Christoph Date: Sat, 14 Sep 2024 11:49:16 +0200 Subject: [PATCH 043/324] New Crowdin updates (#11760) * New translations jabref_en.properties (French) * New translations jabref_en.properties (Polish) * New translations jabref_en.properties (Portuguese, Brazilian) * New translations jabref_en.properties (German) * New translations jabref_en.properties (Italian) --- src/main/resources/l10n/JabRef_de.properties | 3 --- src/main/resources/l10n/JabRef_fr.properties | 5 ++--- src/main/resources/l10n/JabRef_it.properties | 2 ++ src/main/resources/l10n/JabRef_pl.properties | 2 ++ src/main/resources/l10n/JabRef_pt_BR.properties | 5 ++--- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 6689fcc5d94..bd963be2dd0 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -2554,9 +2554,6 @@ Enable\ AI\ functionality\ (summary\ generation\ and\ chatting)\ in\ JabRef=Akti Customize\ expert\ settings=Experteneinstellungen anpassen These\ parameters\ affect\ how\ the\ AI\ will\ answer\ your\ questions.=Diese Parameter beeinflussen, wie die KI Ihre Fragen beantworten wird. Chat\ with\ AI\ about\ content\ of\ attached\ file(s)=Mit der KI über den Inhalt angehängter Datei(en) chatten -If\ you\ have\ chosen\ the\ Hugging\ Face\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Hugging\ Face\ applies.\ You\ find\ it\ at\ %0.=Wenn Sie das Hugging Face als AI Anbieter gewählt haben, gilt die Datenschutzrichtlinie von Hugging Face. Sie finden sie auf %0. -If\ you\ have\ chosen\ the\ Mistral\ AI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Mistral\ AI\ applies.\ You\ find\ it\ at\ %0.=Wenn Sie Mistral AI als KI-Anbieter ausgewählt haben, gilt die Datenschutzrichtlinie von Mistral AI. Sie finden sie unter %0. -If\ you\ have\ chosen\ the\ OpenAI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ OpenAI\ applies.\ You\ find\ it\ at\ %0.=Wenn Sie OpenAI als KI-Anbieter ausgewählt haben, gilt die Datenschutzrichtlinie von OpenAI. Sie finden sie unter %0. In\ order\ to\ use\ AI\ chat,\ you\ need\ to\ enable\ chatting\ with\ attached\ PDF\ files\ in\ JabRef\ preferences\ (AI\ tab).=Um AI-Chat zu nutzen, müssen Sie in den JabRef Einstellungen (Registerkarte KI) das Chatten mit angehängten PDF-Dateien aktivieren. In\ order\ to\ use\ AI\ chat,\ set\ an\ API\ key\ inside\ JabRef\ preferences\ (AI\ tab).=Um den AI-Chat zu nutzen, setzen Sie einen API-Schlüssel in den JabRef-Einstellungen (Registerkarte KI). Unable\ to\ chat\ with\ AI.=Mit der KI kann nicht gechattet werden. diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 205b7482e02..f1ce1d7ec1f 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -1132,6 +1132,7 @@ Unable\ to\ reload\ style\ file=Impossible de recharger le fichier de style Problem\ during\ separating\ cite\ markers=Problème lors de l'individualisation des appels à référence +Automatically\ add\ "Cited\ on\ pages..."\ at\ the\ end\ of\ bibliographic\ entries=Ajouter automatiquement "Cité en pages..." à la fin des entrées bibliographiques Automatically\ sync\ bibliography\ when\ inserting\ citations=Synchroniser automatiquement la bibliographie lors de l'insertion de citations Look\ up\ BibTeX\ entries\ in\ the\ active\ tab\ only=Rechercher les entrées BibTeX uniquement dans l'onglet actif Look\ up\ BibTeX\ entries\ in\ all\ open\ libraries=Rechercher les entrées BibTeX dans tous les fichiers ouverts @@ -2570,9 +2571,6 @@ Enable\ AI\ functionality\ (summary\ generation\ and\ chatting)\ in\ JabRef=Acti Customize\ expert\ settings=Personnaliser les paramètres experts These\ parameters\ affect\ how\ the\ AI\ will\ answer\ your\ questions.=Ces paramètres affectent la façon dont l'IA répondra à vos questions. Chat\ with\ AI\ about\ content\ of\ attached\ file(s)=Tchatter avec l'IA à propos du contenu de(s) fichier(s) joint(s) -If\ you\ have\ chosen\ the\ Hugging\ Face\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Hugging\ Face\ applies.\ You\ find\ it\ at\ %0.=Si vous avez choisi Hugging Face en tant que fournisseur d'IA, la politique de confidentialité de Hugging Face s'applique. Vous le trouverez à %0. -If\ you\ have\ chosen\ the\ Mistral\ AI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Mistral\ AI\ applies.\ You\ find\ it\ at\ %0.=Si vous avez choisi Mistral AI en tant que fournisseur d'IA, la politique de confidentialité de Mistral AI s'applique. Vous la trouverez à %0. -If\ you\ have\ chosen\ the\ OpenAI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ OpenAI\ applies.\ You\ find\ it\ at\ %0.=Si vous avez choisi OpenAI comme fournisseur d'IA, la politique de confidentialité d'OpenAI s'applique. Vous le trouverez à %0. In\ order\ to\ use\ AI\ chat,\ you\ need\ to\ enable\ chatting\ with\ attached\ PDF\ files\ in\ JabRef\ preferences\ (AI\ tab).=Pour utiliser le tchat IA, vous devez activer la discussion avec les fichiers PDF joints dans les préférences de JabRef (onglet IA). In\ order\ to\ use\ AI\ chat,\ set\ an\ API\ key\ inside\ JabRef\ preferences\ (AI\ tab).=Afin d'utiliser le tchat d'IA, définissez une clé API dans les préférences de JabRef (onglet IA). Unable\ to\ chat\ with\ AI.=Impossible de tchatter avec l'IA. @@ -2632,6 +2630,7 @@ Generating\ embeddings\ for\ %0=Générer des intégrations pour %0 RAG\ minimum\ score\ must\ be\ a\ number=Le score minimum de RAG doit être un nombre RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Le score minimum de RAG doit être compris entre 0 et 1 Temperature\ must\ be\ a\ number=La température doit être un nombre +If\ you\ have\ chosen\ %0\ as\ an\ AI\ provider,\ the\ privacy\ policy\ of\ %0\ applies.\ You\ find\ it\ at\ %1.=Si vous avez choisi %0 comme fournisseur d'IA, la politique de confidentialité de %0 s'applique. Vous la trouverez sur %1. Link=Lien Source\ URL=URL de la source diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index ad2e52e1d25..f0e2705bde9 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -1132,6 +1132,7 @@ Unable\ to\ reload\ style\ file=Impossibile ricaricare il file di stile Problem\ during\ separating\ cite\ markers=Problema durante la separazione dei marcatori di citazione +Automatically\ add\ "Cited\ on\ pages..."\ at\ the\ end\ of\ bibliographic\ entries=Aggiungere automaticamente "Citato nelle pagine..." alla fine delle voci bibliografiche Automatically\ sync\ bibliography\ when\ inserting\ citations=Sincronizza automaticamente la bibliografia all'inserimento delle citazioni Look\ up\ BibTeX\ entries\ in\ the\ active\ tab\ only=Ricerca le voci BibTeX solo nella scheda attiva Look\ up\ BibTeX\ entries\ in\ all\ open\ libraries=Ricerca le voci BibTeX in tutte le librerie aperte @@ -2598,6 +2599,7 @@ Generating\ embeddings\ for\ %0=Generazione di incorporamenti per %0 RAG\ minimum\ score\ must\ be\ a\ number=Il punteggio minimo di RAG deve essere un numero RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Il punteggio minimo di RAG deve essere maggiore di 0 e minore di 1 Temperature\ must\ be\ a\ number=La temperatura deve essere un numero +If\ you\ have\ chosen\ %0\ as\ an\ AI\ provider,\ the\ privacy\ policy\ of\ %0\ applies.\ You\ find\ it\ at\ %1.=Se hai scelto %0 come fornitore di Intelligenza Artificiale, si applica la politica sulla privacy di %0. Puoi trovarla su %1. Link=Collegamento Source\ URL=URL di origine diff --git a/src/main/resources/l10n/JabRef_pl.properties b/src/main/resources/l10n/JabRef_pl.properties index dcfd08de8ff..6a8172ac4ec 100644 --- a/src/main/resources/l10n/JabRef_pl.properties +++ b/src/main/resources/l10n/JabRef_pl.properties @@ -1039,6 +1039,7 @@ Unable\ to\ reload\ style\ file=Nie można przeładować pliku stylu Problem\ during\ separating\ cite\ markers=Problem podczas oddzielania znaczników cytowania +Automatically\ add\ "Cited\ on\ pages..."\ at\ the\ end\ of\ bibliographic\ entries=Automatycznie dodaj "Cytowane na stronach..." na końcu wpisów bibliograficznych Autodetecting\ paths...=Automatyczne wykrywanie ścieżek ... Found\ more\ than\ one\ OpenOffice/LibreOffice\ executable.=Znaleziono więcej niż jeden plik wykonywalny OpenOffice/LibreOffice. Please\ choose\ which\ one\ to\ connect\ to\:=Proszę wybrać, z którym połączyć\: @@ -1772,6 +1773,7 @@ Generating\ embeddings\ for\ %0=Generowanie osadzeń dla %0 RAG\ minimum\ score\ must\ be\ a\ number=Minimalny wynik RAG musi być liczbą RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Minimalny wynik RAG musi być większy niż 0 i mniejszy niż 1 Temperature\ must\ be\ a\ number=Temperatura musi być liczbą +If\ you\ have\ chosen\ %0\ as\ an\ AI\ provider,\ the\ privacy\ policy\ of\ %0\ applies.\ You\ find\ it\ at\ %1.=Jeśli wybrałeś %0 jako dostawcę AI, zastosowanie ma polityka prywatności %0. Znajdziesz ją pod adresem %1. Link=Odnośnik Source\ URL=Źródłowy adres URL diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 32881703f65..a1b71b3c180 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -1128,6 +1128,7 @@ Unable\ to\ reload\ style\ file=Não foi possível recarregar o arquivo de estil Problem\ during\ separating\ cite\ markers=Problema ao separar marcadores de citação +Automatically\ add\ "Cited\ on\ pages..."\ at\ the\ end\ of\ bibliographic\ entries=Adicionar automaticamente "Citado nas páginas..." no final das entradas bibliográficas Automatically\ sync\ bibliography\ when\ inserting\ citations=Sincronizar bibliografia automaticamente ao inserir citações Look\ up\ BibTeX\ entries\ in\ the\ active\ tab\ only=Pesquisar por referências BibTeX apenas na aba ativa Look\ up\ BibTeX\ entries\ in\ all\ open\ libraries=Pesquisar referências BibTeX em todas as bases de dados abertas @@ -2566,9 +2567,6 @@ Enable\ AI\ functionality\ (summary\ generation\ and\ chatting)\ in\ JabRef=Ativ Customize\ expert\ settings=Personalizar configurações avançadas These\ parameters\ affect\ how\ the\ AI\ will\ answer\ your\ questions.=Estes parâmetros afetam como a IA irá responder às suas perguntas. Chat\ with\ AI\ about\ content\ of\ attached\ file(s)=Converse com IA sobre o conteúdo do(s) arquivo(s) anexado(s) -If\ you\ have\ chosen\ the\ Hugging\ Face\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Hugging\ Face\ applies.\ You\ find\ it\ at\ %0.=Se você escolheu o Hugging Face como fornecedor de IA, a política de privacidade do Hugging Face se aplica. Você encontra-o na %0. -If\ you\ have\ chosen\ the\ Mistral\ AI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ Mistral\ AI\ applies.\ You\ find\ it\ at\ %0.=Se você escolheu o Mistral AI como fornecedor de IA, a política de privacidade do Mistral AI se aplica. Você encontra-o na %0. -If\ you\ have\ chosen\ the\ OpenAI\ as\ AI\ provider,\ the\ privacy\ policy\ of\ OpenAI\ applies.\ You\ find\ it\ at\ %0.=Se você escolheu o OpenAI como fornecedor de IA, a política de privacidade do OpenAI se aplica. Você encontra-o na %0. In\ order\ to\ use\ AI\ chat,\ you\ need\ to\ enable\ chatting\ with\ attached\ PDF\ files\ in\ JabRef\ preferences\ (AI\ tab).=Para usar o chat IA, você precisa habilitar o chat com arquivos PDF anexados nas preferências do JabRef (IA). In\ order\ to\ use\ AI\ chat,\ set\ an\ API\ key\ inside\ JabRef\ preferences\ (AI\ tab).=Para usar o bate-papo com IA, defina uma chave de API dentro da aba Preferências do JabRef (aba IA). Unable\ to\ chat\ with\ AI.=Incapaz de conversar com IA. @@ -2627,6 +2625,7 @@ Generating\ embeddings\ for\ %0=Gerando incorporações para %0 RAG\ minimum\ score\ must\ be\ a\ number=A pontuação mínima de RAG deve ser um número RAG\ minimum\ score\ must\ be\ greater\ than\ 0\ and\ less\ than\ 1=Pontuação mínima de RAG deve ser maior que 0 e menor que 1 Temperature\ must\ be\ a\ number=A temperatura deve ser um número +If\ you\ have\ chosen\ %0\ as\ an\ AI\ provider,\ the\ privacy\ policy\ of\ %0\ applies.\ You\ find\ it\ at\ %1.=Se você escolheu %0 como fornecedor de IA, a política de privacidade de %0 se aplica. Você encontra-o na %1. Link=Linkar Source\ URL=URL de origem From 7c958e7dd067adbfd7244224aa551c6b3f1e9721 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 15 Sep 2024 10:55:56 +0200 Subject: [PATCH 044/324] Fix architecture gui/logic (#11729) * Refine JavaDoc * Add TODOs Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> * Fix typos * Reoder settings * Fix arch flaw Co-authored-by: Christoph Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> * Fix checkstyle and formatting * Make BackgroundTask independent from UI * Move BackgroundTask from gui to logic Co-authored-by: Christoph * protected -> public Co-authored-by: Christoph * Move CurrentThreadTaskExecutor from gui to logic Co-authored-by: Christoph * protected/package private -> public Co-authored-by: Christoph * Fix formatting * Make ArchitectureTest "real" * Fix typo in "cancelled" Co-authored-by: Christoph * Fix JavaDoc * Move execute(JavaFX Task) down to UiTaskExecutor Co-authored-by: Christoph * Fixed an exception when searching for unlinked files. Co-authored-by: Christoph * Fix CHANGELOG * Move TaskExecutor from gui to logic Co-authored-by: Christoph * Fix more checkstyle * Introduce NotifcationService Also: - Move openAiChat from AiService (logic) to GroupTree (gui) * move unlinked files filter to logic * Inline JabRefDesktop.get*Directory() (to avoid dependency to gui from logic) * move search display mode enum * Introduce "Directories" * Remove unused variables * Move ChatHistoryService to UI * move fallback exception handler to logic and add consumer for thread execution * remove dialog service from logic class * Route ChatHistoryService correctly * Do not do architecture tests for test classes * remove dialog service in test * Fix checkstyle * Sort and shelve preferences objects * Fix CHANGELOG * Checkstyle imports * Refactor NativeDesktop - Integrate OS into NativeDesktop - Integrate JabRefDesktop into NativeDesktop * Compile fix * Introduce OS (and move things from NativeDesktop) * Move FilePreferences to logic Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> * Fix imports * More optimize imports... * One more... * Move externalFileTypes from FilePreferences to ExternalApplicationPreferences * Adapt classes to new structure of ExternalApplicatoinPreferences Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> * Move MrDlibPreferences * Move AutoCompleteFirstNameMode to logic.preferences * Move detectProgramPath to OS * Rename "PreferenceService" to "Preferences" * Adapt name of factory * Move class - we do it differently in main JabRef * Move Preferences to logic (to prepare split up in gui / non-gui) * Infrastructore for gui / non-gui * Rename Preferences to CliPreferences * Fix names - begin to move getEntryEditorPreferences() * Rename GuiPreferences to CoreGuiPreferences * Fix CliPreferences - GuiPreferences * Move constants * Move "getMergeDialogPreferences()" to GuiPreferences * Make LinkedFile independent from Gui * Push down AutoCompletePreferences * Pull down CoreGuiPreferences and Workspace preferences * Fix empty line * Push getUnlinkedFilesDialogPreferences() down * Push down ExternalApplicationsPreferences * Adapt code * fix imports * fix more imports * checkstyle * fix more imports * rewrite * Fix imports * Push down SidePanePreferences * Adapt code * Fix variable location * Push down GroupsPreferences * Adapt classes * Push down getSpecialFieldsPreferences() * Adapt code * Push down PreviewPreferences * Adapt code * Push down PushToApplicationPreferences * Push down NameDisplayPreferences * ADapt code * Push down main table preference, main table column preferences, and search dialog column preferences * Push down KeyBindingsRepository * Add warning if file could not be deleted * Remove some calls to NativeDesktop * Remove NativeDesktop from JabRefCliPreferences * Introduce constants (and migrations may be accessed by GUI) * Fix wrong logger * Relax migrations * Move PreferencesFilter to gui * Move LuceneIndexer to logic * Remove preferences package from tests * Fix imports * Fix checkstyle * Fix compile error * Fix logger * Add workaround * Discard changes to src/test/resources/org/jabref/logic/exporter/ModsExportFormatTestOnlyRequiredFields.xml * Discard changes to src/test/resources/org/jabref/logic/exporter/ModsExportFormatTestAllFields.xml * Reset *.xml to main * Creaate LastFilesOpenedPreferences * Re-activate code for Server * NativeDesktop use is not restricted * Fix architecture test --------- Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com> Co-authored-by: Christoph --- docs/code-howtos/index.md | 4 +- .../org/jabref/benchmarks/Benchmarks.java | 12 +- src/main/java/org/jabref/Launcher.java | 17 +- .../org/jabref/cli/ArgumentProcessor.java | 81 +- src/main/java/org/jabref/cli/JabRefCLI.java | 14 +- .../java/org/jabref/gui/ClipBoardManager.java | 6 +- .../CoreGuiPreferences.java} | 65 +- .../java/org/jabref/gui/DialogService.java | 10 +- .../jabref/gui/FallbackExceptionHandler.java | 28 - .../org/jabref/gui/JabRefDialogService.java | 4 +- src/main/java/org/jabref/gui/JabRefGUI.java | 100 +- src/main/java/org/jabref/gui/LibraryTab.java | 74 +- .../java/org/jabref/gui/StateManager.java | 2 +- .../jabref/gui/UpdateTimestampListener.java | 12 +- .../WorkspacePreferences.java | 2 +- .../org/jabref/gui/actions/ActionHelper.java | 6 +- .../jabref/gui/ai/ClearEmbeddingsAction.java | 4 +- .../chathistory/ChatHistoryService.java | 17 +- .../ai/components/aichat/AiChatComponent.fxml | 17 +- .../ai/components/aichat/AiChatComponent.java | 6 +- .../aichat/AiChatGuardedComponent.java | 10 +- .../ai/components/aichat/AiChatWindow.java | 14 +- .../chathistory/ChatHistoryComponent.fxml | 5 +- .../chatmessage/ChatMessageComponent.fxml | 15 +- .../chatprompt/ChatPromptComponent.fxml | 8 +- .../AiPrivacyNoticeGuardedComponent.java | 12 +- .../privacynotice/PrivacyNoticeComponent.fxml | 14 +- .../privacynotice/PrivacyNoticeComponent.java | 16 +- .../components/summary/SummaryComponent.java | 8 +- .../summary/SummaryShowingComponent.fxml | 11 +- .../util/EmbeddingModelGuardedComponent.java | 8 +- .../util/errorstate/ErrorStateComponent.fxml | 8 +- .../AutoCompletePreferences.java | 1 + .../PersonNameStringConverter.java | 1 + .../gui/autosaveandbackup/BackupManager.java | 8 +- .../jabref/gui/auximport/FromAuxDialog.java | 4 +- .../gui/auximport/FromAuxDialogViewModel.java | 10 +- .../gui/backup/BackupResolverDialog.java | 6 +- .../BibtexExtractorViewModel.java | 29 +- .../ExtractBibtexActionOnline.java | 12 +- .../bibtexextractor/ExtractBibtexDialog.java | 8 +- .../GenerateCitationKeyAction.java | 26 +- .../GenerateCitationKeySingleAction.java | 14 +- .../org/jabref/gui/cleanup/CleanupAction.java | 12 +- .../org/jabref/gui/cleanup/CleanupDialog.java | 4 +- .../gui/cleanup/CleanupPresetPanel.fxml | 4 +- .../gui/cleanup/CleanupPresetPanel.java | 4 +- .../gui/cleanup/CleanupSingleAction.java | 8 +- .../org/jabref/gui/collab/ChangeScanner.java | 12 +- .../DatabaseChangeDetailsViewFactory.java | 18 +- .../gui/collab/DatabaseChangeMonitor.java | 14 +- .../collab/DatabaseChangeResolverFactory.java | 10 +- .../collab/DatabaseChangesResolverDialog.java | 10 +- .../entrychange/EntryChangeDetailsView.java | 12 +- .../entrychange/EntryChangeResolver.java | 10 +- .../EntryWithPreviewAndSourceDetailsView.java | 6 +- .../entrychange/PreviewWithSourceTab.java | 14 +- .../CitationKeyPatternsPanel.java | 4 +- .../SaveOrderConfigPanel.java | 6 +- .../jabref/gui/copyfiles/CopyFilesAction.java | 24 +- .../jabref/gui/copyfiles/CopyFilesTask.java | 12 +- .../gui/copyfiles/CopySingleFileAction.java | 2 +- .../org/jabref/gui/desktop/JabRefDesktop.java | 344 ----- .../jabref/gui/desktop/os/DefaultDesktop.java | 12 +- .../java/org/jabref/gui/desktop/os/Linux.java | 18 +- .../jabref/gui/desktop/os/NativeDesktop.java | 402 ++++-- .../java/org/jabref/gui/desktop/os/OSX.java | 11 +- .../org/jabref/gui/desktop/os/Windows.java | 64 +- .../jabref/gui/dialogs/AutosaveUiManager.java | 6 +- .../jabref/gui/dialogs/BackupUIManager.java | 24 +- .../documentviewer/DocumentViewerControl.java | 4 +- .../documentviewer/DocumentViewerView.java | 8 +- .../DocumentViewerViewModel.java | 10 +- .../ShowDocumentViewerAction.java | 4 +- .../DuplicateResolverDialog.java | 20 +- .../duplicationFinder/DuplicateSearch.java | 14 +- .../org/jabref/gui/edit/CopyMoreAction.java | 16 +- .../jabref/gui/edit/ManageKeywordsDialog.java | 4 +- .../gui/edit/ManageKeywordsViewModel.java | 2 +- .../jabref/gui/edit/OpenBrowserAction.java | 12 +- .../CopyOrMoveFieldContentTab.fxml | 1 - .../editfieldcontent/EditFieldContentTab.fxml | 3 +- .../renamefield/RenameFieldTab.fxml | 1 - .../org/jabref/gui/entryeditor/AiChatTab.java | 34 +- .../jabref/gui/entryeditor/AiSummaryTab.java | 20 +- .../jabref/gui/entryeditor/CommentsTab.java | 6 +- .../gui/entryeditor/DeprecatedFieldsTab.java | 6 +- .../entryeditor/DetailOptionalFieldsTab.java | 6 +- .../jabref/gui/entryeditor/EntryEditor.java | 68 +- .../gui/entryeditor/FieldsEditorTab.java | 8 +- .../ImportantOptionalFieldsTab.java | 6 +- .../gui/entryeditor/LatexCitationsTab.java | 6 +- .../LatexCitationsTabViewModel.java | 20 +- .../entryeditor/OptionalFieldsTabBase.java | 6 +- .../gui/entryeditor/OtherFieldsTab.java | 6 +- .../jabref/gui/entryeditor/PreviewTab.java | 8 +- .../gui/entryeditor/RelatedArticlesTab.java | 32 +- .../gui/entryeditor/RequiredFieldsTab.java | 6 +- .../org/jabref/gui/entryeditor/SciteTab.java | 17 +- .../gui/entryeditor/SciteTabViewModel.java | 14 +- .../org/jabref/gui/entryeditor/SourceTab.java | 2 +- .../gui/entryeditor/UserDefinedFieldsTab.java | 6 +- .../CitationRelationsTab.java | 24 +- .../CitationsRelationsTabViewModel.java | 20 +- .../FileAnnotationTabViewModel.java | 2 +- .../FulltextSearchResultsTab.java | 20 +- .../jabref/gui/entrytype/EntryTypeView.java | 15 +- .../gui/entrytype/EntryTypeViewModel.java | 26 +- .../gui/errorconsole/ErrorConsoleView.java | 6 +- .../errorconsole/ErrorConsoleViewModel.java | 14 +- .../gui/errorconsole/LogEventViewModel.java | 2 +- .../CreateModifyExporterDialogView.java | 4 +- .../CreateModifyExporterDialogViewModel.java | 6 +- .../jabref/gui/exporter/ExportCommand.java | 14 +- .../gui/exporter/ExportToClipboardAction.java | 12 +- .../org/jabref/gui/exporter/SaveAction.java | 10 +- .../jabref/gui/exporter/SaveAllAction.java | 10 +- .../gui/exporter/SaveDatabaseAction.java | 12 +- .../WriteMetadataToLinkedPdfsAction.java | 8 +- .../externalfiles/AutoLinkFilesAction.java | 11 +- .../externalfiles/AutoSetFileLinksUtil.java | 18 +- .../externalfiles/DownloadFullTextAction.java | 12 +- .../ExternalFilesEntryLinker.java | 9 +- .../externalfiles/FileExtensionViewModel.java | 10 +- .../gui/externalfiles/FileFilterUtils.java | 3 + .../gui/externalfiles/ImportHandler.java | 24 +- .../externalfiles/UnlinkedFilesCrawler.java | 8 +- .../UnlinkedFilesDialogPreferences.java | 6 +- .../UnlinkedFilesDialogView.java | 23 +- .../UnlinkedFilesDialogViewModel.java | 21 +- .../externalfiles/UnlinkedPDFFileFilter.java | 2 +- .../CustomExternalFileType.java | 3 +- .../externalfiletype/ExternalFileTypes.java | 34 +- .../gui/fieldeditors/CitationKeyEditor.java | 8 +- .../CitationKeyEditorViewModel.java | 10 +- .../jabref/gui/fieldeditors/DateEditor.java | 6 +- .../gui/fieldeditors/EditorValidator.java | 6 +- .../jabref/gui/fieldeditors/FieldEditors.java | 6 +- .../jabref/gui/fieldeditors/GroupEditor.java | 4 +- .../jabref/gui/fieldeditors/ISSNEditor.java | 12 +- .../gui/fieldeditors/ISSNEditorViewModel.java | 12 +- .../gui/fieldeditors/JournalEditor.fxml | 2 +- .../gui/fieldeditors/JournalEditor.java | 10 +- .../fieldeditors/JournalEditorViewModel.java | 2 +- .../gui/fieldeditors/KeywordsEditor.java | 6 +- .../fieldeditors/KeywordsEditorViewModel.java | 6 +- .../gui/fieldeditors/LinkedFileViewModel.java | 76 +- .../gui/fieldeditors/LinkedFilesEditor.java | 51 +- .../LinkedFilesEditorViewModel.java | 23 +- .../gui/fieldeditors/MarkdownEditor.java | 4 +- .../jabref/gui/fieldeditors/OwnerEditor.java | 8 +- .../fieldeditors/OwnerEditorViewModel.java | 6 +- .../gui/fieldeditors/PersonsEditor.java | 10 +- .../jabref/gui/fieldeditors/PopOverUtil.java | 4 +- .../jabref/gui/fieldeditors/SimpleEditor.java | 4 +- .../org/jabref/gui/fieldeditors/URLUtil.java | 6 +- .../jabref/gui/fieldeditors/UrlEditor.java | 10 +- .../gui/fieldeditors/UrlEditorViewModel.java | 12 +- .../WriteMetadataToSinglePdfAction.java | 6 +- .../contextmenu/EditorContextAction.java | 2 +- .../BaseIdentifierEditorViewModel.java | 12 +- .../DoiIdentifierEditorViewModel.java | 12 +- .../EprintIdentifierEditorViewModel.java | 6 +- .../ISBNIdentifierEditorViewModel.java | 6 +- .../identifier/IdentifierEditor.java | 18 +- .../fieldeditors/journalinfo/JournalInfo.fxml | 3 +- .../ExternalApplicationsPreferences.java | 16 +- .../org/jabref/gui/frame/JabRefFrame.java | 70 +- .../gui/frame/JabRefFrameViewModel.java | 23 +- .../java/org/jabref/gui/frame/MainMenu.java | 137 +- .../org/jabref/gui/frame/MainToolBar.java | 34 +- .../jabref/gui/frame/OpenConsoleAction.java | 18 +- .../jabref/gui/frame/SendAsEMailAction.java | 20 +- .../gui/frame/SendAsKindleEmailAction.java | 14 +- .../gui/frame/SendAsStandardEmailAction.java | 18 +- .../frame}/SidePanePreferences.java | 2 +- .../jabref/gui/groups/GroupDialogView.java | 8 +- .../gui/groups/GroupDialogViewModel.java | 28 +- .../jabref/gui/groups/GroupNodeViewModel.java | 26 +- .../org/jabref/gui/groups/GroupTreeView.java | 30 +- .../jabref/gui/groups/GroupTreeViewModel.java | 46 +- .../org/jabref/gui/help/AboutDialogView.java | 6 +- .../jabref/gui/help/AboutDialogViewModel.java | 12 +- .../java/org/jabref/gui/help/HelpAction.java | 13 +- .../org/jabref/gui/help/NewVersionDialog.java | 13 +- .../gui/help/SearchForUpdateAction.java | 12 +- .../org/jabref/gui/help/VersionWorker.java | 21 +- .../importer/GenerateEntryFromIdAction.java | 22 +- .../importer/GenerateEntryFromIdDialog.fxml | 1 - .../importer/GenerateEntryFromIdDialog.java | 12 +- .../jabref/gui/importer/ImportCommand.java | 36 +- .../ImportCustomEntryTypesDialog.java | 6 +- ...ImportCustomEntryTypesDialogViewModel.java | 12 +- .../gui/importer/ImportEntriesDialog.fxml | 2 +- .../gui/importer/ImportEntriesDialog.java | 8 +- .../gui/importer/ImportEntriesViewModel.java | 12 +- .../gui/importer/NewDatabaseAction.java | 12 +- .../jabref/gui/importer/NewEntryAction.java | 8 +- .../actions/CheckForNewEntryTypesAction.java | 10 +- .../importer/actions/GUIPostOpenAction.java | 6 +- .../actions/MergeReviewIntoCommentAction.java | 6 +- .../importer/actions/OpenDatabaseAction.java | 41 +- .../actions/SearchGroupsMigrationAction.java | 6 +- .../fetcher/LookupIdentifierAction.java | 4 +- .../importer/fetcher/WebSearchPaneView.java | 8 +- .../fetcher/WebSearchPaneViewModel.java | 24 +- .../gui/integrity/IntegrityCheckAction.java | 20 +- .../jabref/gui/journals/AbbreviateAction.java | 4 +- .../gui/journals/UndoableAbbreviator.java | 21 +- .../gui/keyboard/KeyBindingRepository.java | 2 +- .../constants/ConstantsPropertiesView.java | 8 +- .../ConstantsPropertiesViewModel.java | 10 +- .../general/GeneralPropertiesView.java | 6 +- .../general/GeneralPropertiesViewModel.java | 22 +- .../keypattern/KeyPatternPropertiesView.java | 14 +- .../KeyPatternPropertiesViewModel.java | 10 +- .../saving/SavingPropertiesView.java | 6 +- .../saving/SavingPropertiesViewModel.java | 12 +- .../gui/linkedfile/AttachFileAction.java | 10 +- .../linkedfile/AttachFileFromURLAction.java | 12 +- .../gui/linkedfile/DeleteFileAction.java | 6 +- .../linkedfile/DownloadLinkedFileAction.java | 34 +- .../gui/linkedfile/LinkedFileEditDialog.java | 6 +- .../LinkedFileEditDialogViewModel.java | 14 +- .../RedownloadMissingFilesAction.java | 21 +- .../org/jabref/gui/maintable/CellFactory.java | 18 +- .../maintable/ExtractReferencesAction.java | 26 +- .../org/jabref/gui/maintable/MainTable.java | 18 +- .../gui/maintable/MainTableColumnFactory.java | 22 +- .../gui/maintable/MainTableColumnModel.java | 8 +- .../gui/maintable/MainTableDataModel.java | 20 +- .../gui/maintable/MainTableTooltip.java | 8 +- .../maintable/NewLibraryFromPdfAction.java | 12 +- .../NewLibraryFromPdfActionOffline.java | 8 +- .../NewLibraryFromPdfActionOnline.java | 10 +- .../gui/maintable/OpenExternalFileAction.java | 18 +- .../gui/maintable/OpenFolderAction.java | 20 +- .../jabref/gui/maintable/OpenUrlAction.java | 12 +- .../PersistenceVisualStateTable.java | 3 +- .../jabref/gui/maintable/RightClickMenu.java | 76 +- .../maintable/SearchShortScienceAction.java | 12 +- .../gui/maintable/columns/FileColumn.java | 22 +- .../columns/LinkedIdentifierColumn.java | 10 +- .../maintable/columns/SpecialFieldColumn.java | 12 +- .../gui/mergeentries/FetchAndMergeEntry.java | 10 +- .../mergeentries}/MergeDialogPreferences.java | 17 +- .../gui/mergeentries/MergeEntriesAction.java | 10 +- .../gui/mergeentries/MergeEntriesDialog.java | 6 +- .../MergeWithFetchedEntryAction.java | 12 +- .../gui/mergeentries/MultiMergeEntries.fxml | 13 +- .../mergeentries/MultiMergeEntriesView.java | 8 +- .../MultiMergeEntriesViewModel.java | 4 +- .../newmergedialog/FieldRowView.java | 8 +- .../PersonsNameFieldRowView.java | 6 +- .../newmergedialog/ThreeWayMergeView.java | 20 +- .../newmergedialog/cell/FieldValueCell.java | 10 +- .../cell/OpenExternalLinkAction.java | 18 +- .../fieldsmerger/CommentMerger.java | 2 +- .../fieldsmerger/FieldMergerFactory.java | 2 +- .../fieldsmerger/KeywordMerger.java | 2 +- .../toolbar/ThreeWayMergeToolbar.java | 18 +- .../DetectOpenOfficeInstallation.java | 6 +- .../gui/openoffice/OpenOfficePanel.java | 46 +- .../gui/openoffice/StyleSelectDialog.fxml | 1 - .../gui/openoffice/StyleSelectDialogView.java | 14 +- .../StyleSelectDialogViewModel.java | 29 +- .../AbstractPreferenceTabView.java | 5 +- .../gui/preferences/GuiPreferences.java | 55 + .../gui/preferences/JabRefGuiPreferences.java | 1210 ++++++++++++++++ .../preferences/PreferencesDialogView.java | 7 +- .../PreferencesDialogViewModel.java | 6 +- .../preferences/PreferencesFilter.java | 8 +- .../preferences/PreferencesFilterDialog.java | 1 - .../org/jabref/gui/preferences/ai/AiTab.fxml | 23 +- .../org/jabref/gui/preferences/ai/AiTab.java | 32 +- .../gui/preferences/ai/AiTabViewModel.java | 12 +- .../autocompletion/AutoCompletionTab.java | 2 +- .../AutoCompletionTabViewModel.java | 2 +- .../CitationKeyPatternTab.java | 8 +- .../customentrytypes/CustomEntryTypesTab.java | 6 +- .../CustomEntryTypesTabViewModel.java | 16 +- .../customexporter/CustomExporterTab.java | 2 +- .../CustomExporterTabViewModel.java | 6 +- .../customimporter/CustomImporterTab.java | 2 +- .../CustomImporterTabViewModel.java | 6 +- .../gui/preferences/entry/EntryTab.java | 4 +- .../preferences/entry/EntryTabViewModel.java | 14 +- .../entryeditor/EntryEditorTab.java | 4 +- .../entryeditor/EntryEditorTabViewModel.java | 16 +- .../gui/preferences/export/ExportTab.java | 2 +- .../export/ExportTabViewModel.java | 2 +- .../gui/preferences/external/ExternalTab.java | 4 +- .../external/ExternalTabViewModel.java | 16 +- .../EditExternalFileTypeEntryDialog.java | 4 +- .../ExternalFileTypesTab.java | 2 +- .../ExternalFileTypesTabViewModel.java | 18 +- .../gui/preferences/general/GeneralTab.java | 6 +- .../general/GeneralTabViewModel.java | 16 +- .../gui/preferences/groups/GroupsTab.java | 2 +- .../journals/JournalAbbreviationsTab.fxml | 4 +- .../journals/JournalAbbreviationsTab.java | 4 +- .../JournalAbbreviationsTabViewModel.java | 4 +- .../keybindings/KeyBindingsTab.java | 2 +- .../keybindings/KeyBindingsTabViewModel.java | 6 +- .../linkedfiles/LinkedFilesTab.java | 8 +- .../linkedfiles/LinkedFilesTabViewModel.java | 6 +- .../nameformatter/NameFormatterTab.java | 4 +- .../gui/preferences/network/NetworkTab.java | 2 +- .../network/NetworkTabViewModel.java | 10 +- .../gui/preferences/preview/PreviewTab.java | 6 +- .../preview/PreviewTabViewModel.java | 6 +- .../NewProtectedTermsFileDialog.java | 2 +- .../protectedterms/ProtectedTermsTab.java | 2 +- .../ProtectedTermsTabViewModel.java | 23 +- .../gui/preferences/table/TableTab.java | 4 +- .../preferences/table/TableTabViewModel.java | 8 +- .../preferences/websearch/WebSearchTab.java | 2 +- .../websearch/WebSearchTabViewModel.java | 34 +- .../gui/preferences/xmp/XmpPrivacyTab.java | 10 +- .../gui/preview/CopyCitationAction.java | 22 +- .../org/jabref/gui/preview/PreviewPanel.java | 15 +- .../preview}/PreviewPreferences.java | 2 +- .../org/jabref/gui/preview/PreviewViewer.java | 19 +- .../gui/push/AbstractPushToApplication.java | 21 +- .../jabref/gui/push/PushToApplication.java | 1 - .../gui/push/PushToApplicationCommand.java | 24 +- .../push}/PushToApplicationPreferences.java | 2 +- .../gui/push/PushToApplicationSettings.java | 3 +- .../jabref/gui/push/PushToApplications.java | 30 +- .../java/org/jabref/gui/push/PushToEmacs.java | 15 +- .../jabref/gui/push/PushToEmacsSettings.java | 3 +- .../java/org/jabref/gui/push/PushToLyx.java | 11 +- .../jabref/gui/push/PushToLyxSettings.java | 3 +- .../jabref/gui/push/PushToSublimeText.java | 10 +- .../org/jabref/gui/push/PushToTeXstudio.java | 6 +- .../org/jabref/gui/push/PushToTeXworks.java | 8 +- .../org/jabref/gui/push/PushToTexShop.java | 10 +- .../org/jabref/gui/push/PushToTexmaker.java | 6 +- .../java/org/jabref/gui/push/PushToVim.java | 13 +- .../jabref/gui/push/PushToVimSettings.java | 3 +- .../org/jabref/gui/push/PushToWinEdt.java | 6 +- .../jabref/gui/remote/CLIMessageHandler.java | 11 +- .../jabref/gui/search/GlobalSearchBar.java | 21 +- .../gui/search/GlobalSearchResultDialog.fxml | 2 +- .../gui/search/GlobalSearchResultDialog.java | 30 +- .../GlobalSearchResultDialogViewModel.java | 2 +- .../RebuildFulltextSearchIndexAction.java | 4 +- .../jabref/gui/search/SearchResultsTable.java | 16 +- .../search/SearchResultsTableDataModel.java | 10 +- .../shared/SharedDatabaseLoginDialogView.java | 8 +- .../SharedDatabaseLoginDialogViewModel.java | 20 +- .../gui/shared/SharedDatabaseUIManager.java | 22 +- .../org/jabref/gui/sidepane/SidePane.java | 20 +- .../gui/sidepane/SidePaneContentFactory.java | 22 +- .../gui/sidepane/SidePaneViewModel.java | 36 +- .../jabref/gui/sidepane/TogglePaneAction.java | 2 +- .../gui/slr/ExistingStudySearchAction.java | 18 +- .../gui/slr/ManageStudyDefinitionView.java | 16 +- .../slr/ManageStudyDefinitionViewModel.java | 2 +- .../jabref/gui/slr/StartNewStudyAction.java | 10 +- .../gui/specialfields/SpecialFieldAction.java | 10 +- .../SpecialFieldMenuItemFactory.java | 20 +- .../specialfields/SpecialFieldViewModel.java | 10 +- .../gui/texparser/ParseLatexDialogView.java | 8 +- .../texparser/ParseLatexDialogViewModel.java | 20 +- .../texparser/ParseLatexResultViewModel.java | 2 +- .../java/org/jabref/gui/theme/StyleSheet.java | 1 + src/main/java/org/jabref/gui/theme/Theme.java | 2 +- .../org/jabref/gui/theme/ThemeManager.java | 10 +- .../java/org/jabref/gui/util/FieldsUtil.java | 6 +- .../org/jabref/gui/util/UiTaskExecutor.java | 34 +- .../org/jabref/http/server/Application.java | 3 +- .../jabref/http/server/LibrariesResource.java | 6 +- .../jabref/http/server/LibraryResource.java | 6 +- .../http/server/PreferencesFactory.java | 17 + .../java/org/jabref/http/server/Server.java | 7 +- .../FilePreferences.java | 15 +- .../InternalPreferences.java | 2 +- .../LibraryPreferences.java | 2 +- .../jabref/logic/ai/AiDefaultPreferences.java | 4 +- .../ai/AiPreferences.java | 5 +- .../java/org/jabref/logic/ai/AiService.java | 80 +- .../jabref/logic/ai/chatting/AiChatLogic.java | 2 +- .../logic/ai/chatting/AiChatService.java | 2 +- .../storages/MVStoreChatHistoryStorage.java | 4 +- .../model/JabRefChatLanguageModel.java | 2 +- .../model/JvmOpenAiChatLanguageModel.java | 2 +- .../ai/ingestion/FileEmbeddingsManager.java | 2 +- .../GenerateEmbeddingsForSeveralTask.java | 8 +- .../ai/ingestion/GenerateEmbeddingsTask.java | 6 +- .../logic/ai/ingestion/IngestionService.java | 6 +- .../logic/ai/ingestion/LowLevelIngestor.java | 2 +- .../ai/ingestion/MVStoreEmbeddingStore.java | 4 +- .../ingestion/model/JabRefEmbeddingModel.java | 14 +- .../model/UpdateEmbeddingModelTask.java | 4 +- .../MVStoreFullyIngestedDocumentsTracker.java | 4 +- .../ai/summarization/GenerateSummaryTask.java | 8 +- .../ai/summarization/SummariesService.java | 6 +- .../logic/ai/summarization/Summary.java | 2 +- .../storages/MVStoreSummariesStorage.java | 4 +- .../org/jabref/logic/ai/util/MVStoreBase.java | 4 +- .../jabref/logic/bibtex/BibEntryWriter.java | 2 +- .../CitationStyleOutputFormat.java | 2 +- .../cleanup}/CleanupPreferences.java | 8 +- .../jabref/logic/cleanup/CleanupWorker.java | 3 +- .../logic/cleanup/MoveFilesCleanup.java | 2 +- .../logic/cleanup/RelativePathsCleanup.java | 2 +- .../RemoveLinksToNotExistentFiles.java | 2 +- .../logic/cleanup/RenamePdfCleanup.java | 2 +- .../org/jabref/logic/crawler/Crawler.java | 10 +- .../jabref/logic/crawler/StudyRepository.java | 30 +- .../jabref/logic/database/DuplicateCheck.java | 2 +- .../exporter/EmbeddedBibFilePdfExporter.java | 2 +- .../logic/exporter/EndnoteXmlExporter.java | 2 +- .../exporter}/ExportPreferences.java | 3 +- .../org/jabref/logic/exporter/Exporter.java | 2 +- .../logic/exporter/ExporterFactory.java | 18 +- .../logic/exporter/MetaDataSerializer.java | 2 +- .../logic/exporter/TemplateExporter.java | 2 +- .../externalfiles/DateRange.java | 2 +- .../externalfiles/ExternalFileSorter.java | 2 +- .../externalfiles/LinkedFileHandler.java | 2 +- .../importer/ImportFormatPreferences.java | 2 +- .../jabref/logic/importer/WebFetchers.java | 2 +- .../logic/importer/fetcher/DOAJFetcher.java | 2 +- .../jabref/logic/importer/fetcher/IEEE.java | 2 +- .../logic/importer/fetcher/LOBIDFetcher.java | 2 +- .../logic/importer/fetcher/MathSciNet.java | 2 +- .../logic/importer/fetcher/MrDLibFetcher.java | 1 - .../importer/fetcher}/MrDlibPreferences.java | 2 +- .../logic/importer/fetcher/ResearchGate.java | 2 +- .../importer/fetcher/SpringerFetcher.java | 2 +- .../importer/fileformat/BibtexParser.java | 2 +- .../importer/fileformat/CoinsParser.java | 2 +- .../fileformat/PdfContentImporter.java | 2 +- .../fileformat/PdfMergeMetadataImporter.java | 2 +- .../jabref/logic/integrity/FieldCheckers.java | 2 +- .../jabref/logic/integrity/FileChecker.java | 2 +- .../logic/integrity/IntegrityCheck.java | 2 +- .../logic/layout/format/RisAuthors.java | 2 +- .../logic/layout/format/RisKeywords.java | 2 +- .../openoffice/OpenOfficeFileSearch.java | 2 +- src/main/java/org/jabref/logic/os/OS.java | 133 ++ .../logic/pdf/EntryAnnotationImporter.java | 2 +- .../jabref/logic/pdf/FileAnnotationCache.java | 2 +- .../AutoCompleteFirstNameMode.java | 2 +- .../preferences/CliPreferences.java} | 61 +- .../preferences/JabRefCliPreferences.java} | 1250 ++--------------- .../LastFilesOpenedPreferences.java | 52 + .../protectedterms/ProtectedTermsList.java | 2 +- .../jabref/logic/search/DatabaseSearcher.java | 4 +- .../search/LuceneIndexer.java | 4 +- .../jabref/logic/search/LuceneManager.java | 33 +- .../search/SearchDisplayMode.java | 2 +- .../search}/SearchPreferences.java | 3 +- .../search/indexing/BibFieldsIndexer.java | 10 +- .../indexing/DefaultLinkedFilesIndexer.java | 8 +- .../indexing/ReadOnlyLinkedFilesIndexer.java | 4 +- .../search/retrieval/LuceneSearcher.java | 4 +- .../{gui => logic}/util/BackgroundTask.java | 67 +- .../util/CurrentThreadTaskExecutor.java | 11 +- .../org/jabref/logic/util/Directories.java | 65 + .../logic/util/FallbackExceptionHandler.java | 36 + .../logic/util/HeadlessExecutorService.java | 5 +- .../logic/util/NotificationService.java | 11 + src/main/java/org/jabref/logic/util/OS.java | 70 - .../{gui => logic}/util/TaskExecutor.java | 17 +- .../logic/util/io/DatabaseFileLookup.java | 2 +- .../logic/util/io/FileNameUniqueness.java | 11 +- .../org/jabref/logic/util/io/FileUtil.java | 2 +- .../CustomEntryTypePreferenceMigration.java | 6 +- .../migrations/PreferencesMigrations.java | 127 +- .../{preferences => model}/ai/AiProvider.java | 2 +- .../ai/EmbeddingModel.java | 2 +- .../model/database/BibDatabaseContext.java | 6 +- .../entry}/BibEntryPreferences.java | 2 +- .../org/jabref/model/entry/LinkedFile.java | 20 +- .../model/entry/field/FieldFactory.java | 3 +- .../preferences/PreferenceServiceFactory.java | 14 - .../resources/xslt/mathml_latex/entities.xsl | 6 +- .../jabref/architecture/ArchitectureTest.java | 10 +- .../architecture/MainArchitectureTest.java | 77 +- .../org/jabref/cli/ArgumentProcessorTest.java | 29 +- .../java/org/jabref/cli/JabRefCLITest.java | 2 +- .../org/jabref/gui/ClipBoardManagerTest.java | 8 +- .../gui/UpdateTimestampListenerTest.java | 6 +- .../PersonNameStringConverterTest.java | 1 + .../SuggestionProvidersTest.java | 1 + .../BackupManagerDiscardedTest.java | 12 +- .../autosaveandbackup/BackupManagerTest.java | 12 +- .../jabref/gui/edit/CopyMoreActionTest.java | 28 +- .../gui/edit/ManageKeywordsViewModelTest.java | 2 +- .../gui/entryeditor/CommentsTabTest.java | 9 +- .../jabref/gui/entryeditor/SciteTabTest.java | 14 +- .../entryeditor/SciteTabViewModelTest.java | 10 +- .../CitationsRelationsTabViewModelTest.java | 24 +- .../exporter/ExportToClipboardActionTest.java | 12 +- .../gui/exporter/SaveDatabaseActionTest.java | 20 +- .../AutoSetFileLinksUtilTest.java | 10 +- .../gui/externalfiles/ImportHandlerTest.java | 36 +- .../UnlinkedFilesCrawlerTest.java | 8 +- .../ExternalFileTypesTest.java | 22 +- .../fieldeditors/LinkedFileViewModelTest.java | 17 +- .../LinkedFilesEditorViewModelTest.java | 16 +- .../gui/groups/GroupDialogViewModelTest.java | 26 +- .../gui/groups/GroupNodeViewModelTest.java | 18 +- .../gui/groups/GroupTreeViewModelTest.java | 30 +- .../gui/importer/NewEntryActionTest.java | 8 +- .../fetcher/WebSearchPaneViewModelTest.java | 8 +- .../gui/keyboard/KeyBindingsTabModelTest.java | 10 +- .../ConstantsPropertiesViewModelTest.java | 10 +- .../DownloadLinkedFileActionTest.java | 18 +- .../maintable/MainTableColumnModelTest.java | 4 +- .../mergeentries/FieldRowViewModelTest.java | 2 +- .../CustomEntryTypesTabViewModelTest.java | 14 +- .../ExternalFileTypesTabViewModelTest.java | 6 +- .../JournalAbbreviationsViewModelTabTest.java | 4 +- .../keybindings/KeyBindingViewModelTest.java | 11 +- .../gui/preview/CopyCitationActionTest.java | 2 +- .../org/jabref/gui/push/PushToEmacsTest.java | 15 +- .../jabref/gui/push/PushToTeXworksTest.java | 13 +- .../gui/search/GlobalSearchBarTest.java | 12 +- .../gui/sidepane/SidePaneViewModelTest.java | 18 +- .../ManageStudyDefinitionViewModelTest.java | 2 +- .../jabref/gui/theme/ThemeManagerTest.java | 2 +- .../gui/util/OpenConsoleActionTest.java | 4 +- .../org/jabref/http/server/ServerTest.java | 28 +- .../MVStoreChatHistoryStorageTest.java | 4 +- ...toreFullyIngestedDocumentsTrackerTest.java | 4 +- .../MVStoreSummariesStorageTest.java | 4 +- .../summarization/SummariesStorageTest.java | 2 +- .../logic/bibtex/BibEntryWriterTest.java | 2 +- .../jabref/logic/bibtex/FieldWriterTest.java | 2 +- .../logic/cleanup/CleanupWorkerTest.java | 3 +- .../jabref/logic/cleanup/ISSNCleanupTest.java | 3 +- .../logic/cleanup/MoveFilesCleanupTest.java | 2 +- .../RemoveLinksToNotExistentFilesTest.java | 2 +- .../logic/cleanup/RenamePdfCleanupTest.java | 2 +- .../org/jabref/logic/crawler/CrawlerTest.java | 8 +- .../StudyCatalogToFetcherConverterTest.java | 12 +- .../logic/crawler/StudyRepositoryTest.java | 20 +- .../exporter/BibtexDatabaseWriterTest.java | 2 +- .../EmbeddedBibFilePdfExporterTest.java | 2 +- .../exporter/EndnoteXmlExporterFilesTest.java | 2 +- .../exporter/EndnoteXmlExporterTest.java | 2 +- .../jabref/logic/exporter/ExporterTest.java | 10 +- .../exporter/MetaDataSerializerTest.java | 2 +- .../exporter/ModsExportFormatFilesTest.java | 2 +- .../logic/exporter/XmpPdfExporterTest.java | 2 +- .../logic/importer/OpenDatabaseTest.java | 2 +- .../logic/importer/WebFetchersTest.java | 2 +- .../importer/fetcher/IssnFetcherTest.java | 2 +- .../fetcher/LibraryOfCongressTest.java | 2 +- .../importer/fetcher/MrDLibFetcherTest.java | 1 - .../importer/fileformat/BibtexParserTest.java | 2 +- .../logic/integrity/IntegrityCheckTest.java | 2 +- .../logic/layout/format/RisKeywordsTest.java | 2 +- .../pdf/EntryAnnotationImporterTest.java | 2 +- .../JabRefGuiPreferencesTest.java} | 8 +- ...est.java => RemoteGuiPreferencesTest.java} | 2 +- .../jabref/logic/remote/RemoteSetupTest.java | 2 +- .../logic/search/DatabaseSearcherTest.java | 6 +- .../DatabaseSearcherWithBibFilesTest.java | 6 +- .../indexing/LinkedFilesIndexerTest.java | 12 +- .../logic/util/io/BackupFileUtilTest.java | 10 +- .../logic/util/io/FileNameUniquenessTest.java | 19 +- .../jabref/logic/util/io/FileUtilTest.java | 4 +- .../GuiPreferencesMigrationsTest.java | 223 +++ .../migrations/PreferencesMigrationsTest.java | 222 --- .../database/BibDatabaseContextTest.java | 11 +- .../styletester/StyleTesterMain.java | 4 +- ...er_science_bibliographies_empty_result.xml | 10 +- 572 files changed, 5406 insertions(+), 5192 deletions(-) rename src/main/java/org/jabref/{preferences/GuiPreferences.java => gui/CoreGuiPreferences.java} (61%) delete mode 100644 src/main/java/org/jabref/gui/FallbackExceptionHandler.java rename src/main/java/org/jabref/{preferences => gui}/WorkspacePreferences.java (99%) rename src/main/java/org/jabref/{logic => gui}/ai/chatting/chathistory/ChatHistoryService.java (93%) delete mode 100644 src/main/java/org/jabref/gui/desktop/JabRefDesktop.java rename src/main/java/org/jabref/{preferences => gui/externalfiles}/UnlinkedFilesDialogPreferences.java (94%) rename src/main/java/org/jabref/{preferences => gui/frame}/ExternalApplicationsPreferences.java (88%) rename src/main/java/org/jabref/{preferences => gui/frame}/SidePanePreferences.java (98%) rename src/main/java/org/jabref/{preferences => gui/mergeentries}/MergeDialogPreferences.java (88%) create mode 100644 src/main/java/org/jabref/gui/preferences/GuiPreferences.java create mode 100644 src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java rename src/main/java/org/jabref/{ => gui}/preferences/PreferencesFilter.java (93%) rename src/main/java/org/jabref/{preferences => gui/preview}/PreviewPreferences.java (99%) rename src/main/java/org/jabref/{preferences => gui/push}/PushToApplicationPreferences.java (98%) create mode 100644 src/main/java/org/jabref/http/server/PreferencesFactory.java rename src/main/java/org/jabref/{preferences => logic}/FilePreferences.java (92%) rename src/main/java/org/jabref/{preferences => logic}/InternalPreferences.java (98%) rename src/main/java/org/jabref/{preferences => logic}/LibraryPreferences.java (98%) rename src/main/java/org/jabref/{preferences => logic}/ai/AiPreferences.java (99%) rename src/main/java/org/jabref/{preferences => logic/cleanup}/CleanupPreferences.java (92%) rename src/main/java/org/jabref/{preferences => logic/exporter}/ExportPreferences.java (96%) rename src/main/java/org/jabref/{gui => logic}/externalfiles/DateRange.java (94%) rename src/main/java/org/jabref/{gui => logic}/externalfiles/ExternalFileSorter.java (93%) rename src/main/java/org/jabref/{preferences => logic/importer/fetcher}/MrDlibPreferences.java (97%) create mode 100644 src/main/java/org/jabref/logic/os/OS.java rename src/main/java/org/jabref/{gui/autocompleter => logic/preferences}/AutoCompleteFirstNameMode.java (95%) rename src/main/java/org/jabref/{preferences/PreferencesService.java => logic/preferences/CliPreferences.java} (66%) rename src/main/java/org/jabref/{preferences/JabRefPreferences.java => logic/preferences/JabRefCliPreferences.java} (60%) create mode 100644 src/main/java/org/jabref/logic/preferences/LastFilesOpenedPreferences.java rename src/main/java/org/jabref/{model => logic}/search/LuceneIndexer.java (88%) rename src/main/java/org/jabref/{gui => logic}/search/SearchDisplayMode.java (63%) rename src/main/java/org/jabref/{preferences => logic/search}/SearchPreferences.java (98%) rename src/main/java/org/jabref/{gui => logic}/util/BackgroundTask.java (83%) rename src/main/java/org/jabref/{gui => logic}/util/CurrentThreadTaskExecutor.java (93%) create mode 100644 src/main/java/org/jabref/logic/util/Directories.java create mode 100644 src/main/java/org/jabref/logic/util/FallbackExceptionHandler.java create mode 100644 src/main/java/org/jabref/logic/util/NotificationService.java delete mode 100644 src/main/java/org/jabref/logic/util/OS.java rename src/main/java/org/jabref/{gui => logic}/util/TaskExecutor.java (73%) rename src/main/java/org/jabref/{preferences => model}/ai/AiProvider.java (92%) rename src/main/java/org/jabref/{preferences => model}/ai/EmbeddingModel.java (99%) rename src/main/java/org/jabref/{preferences => model/entry}/BibEntryPreferences.java (95%) delete mode 100644 src/main/java/org/jabref/preferences/PreferenceServiceFactory.java rename src/test/java/org/jabref/{preferences/JabRefPreferencesTest.java => logic/preferences/JabRefGuiPreferencesTest.java} (76%) rename src/test/java/org/jabref/logic/remote/{RemotePreferencesTest.java => RemoteGuiPreferencesTest.java} (97%) create mode 100644 src/test/java/org/jabref/migrations/GuiPreferencesMigrationsTest.java delete mode 100644 src/test/java/org/jabref/migrations/PreferencesMigrationsTest.java diff --git a/docs/code-howtos/index.md b/docs/code-howtos/index.md index e8b49cc188f..932dcb04539 100644 --- a/docs/code-howtos/index.md +++ b/docs/code-howtos/index.md @@ -47,7 +47,7 @@ JabRef stores files relative to one of [multiple possible directories](https://d The convert the relative path to an absolute one, there is the `find` method in `FileUtil`: ```java -org.jabref.logic.util.io.FileUtil.find(org.jabref.model.database.BibDatabaseContext, java.lang.String, org.jabref.preferences.FilePreferences) +org.jabref.logic.util.io.FileUtil.find(org.jabref.model.database.BibDatabaseContext, java.lang.String, org.jabref.logic.FilePreferences) ``` `String path` Can be the files name or a relative path to it. The Preferences should only be directly accessed in the GUI. For the usage in logic pass them as parameter @@ -59,7 +59,7 @@ When adding a file to a library, the path should be stored relative to "the best This is implemented in `FileUtil`: ```java -org.jabref.logic.util.io.FileUtil.relativize(java.nio.file.Path, org.jabref.model.database.BibDatabaseContext, org.jabref.preferences.FilePreferences) +org.jabref.logic.util.io.FileUtil.relativize(java.nio.file.Path, org.jabref.model.database.BibDatabaseContext, org.jabref.logic.FilePreferences) ``` ## Setting a Directory for a .bib File diff --git a/src/jmh/java/org/jabref/benchmarks/Benchmarks.java b/src/jmh/java/org/jabref/benchmarks/Benchmarks.java index d2e79b24c63..e553c87ceec 100644 --- a/src/jmh/java/org/jabref/benchmarks/Benchmarks.java +++ b/src/jmh/java/org/jabref/benchmarks/Benchmarks.java @@ -16,7 +16,9 @@ import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.logic.layout.format.HTMLChars; import org.jabref.logic.layout.format.LatexToUnicodeFormatter; -import org.jabref.logic.util.OS; +import org.jabref.logic.os.OS; +import org.jabref.logic.preferences.CliPreferences; +import org.jabref.logic.preferences.JabRefCliPreferences; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.BibDatabaseMode; @@ -29,8 +31,6 @@ import org.jabref.model.groups.KeywordGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; -import org.jabref.preferences.JabRefPreferences; -import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.injection.Injector; import org.openjdk.jmh.Main; @@ -52,7 +52,7 @@ public class Benchmarks { @Setup public void init() throws Exception { - Injector.setModelOrService(PreferencesService.class, JabRefPreferences.getInstance()); + Injector.setModelOrService(CliPreferences.class, JabRefCliPreferences.getInstance()); Random randomizer = new Random(); for (int i = 0; i < 1000; i++) { @@ -89,8 +89,8 @@ private StringWriter getOutputWriter() throws IOException { @Benchmark public ParserResult parse() throws IOException { - PreferencesService preferencesService = Injector.instantiateModelOrService(PreferencesService.class); - BibtexParser parser = new BibtexParser(preferencesService.getImportFormatPreferences()); + CliPreferences preferences = Injector.instantiateModelOrService(CliPreferences.class); + BibtexParser parser = new BibtexParser(preferences.getImportFormatPreferences()); return parser.parse(new StringReader(bibtexString)); } diff --git a/src/main/java/org/jabref/Launcher.java b/src/main/java/org/jabref/Launcher.java index fa891388f98..1d3cb9cb3e1 100644 --- a/src/main/java/org/jabref/Launcher.java +++ b/src/main/java/org/jabref/Launcher.java @@ -14,6 +14,8 @@ import org.jabref.cli.ArgumentProcessor; import org.jabref.cli.JabRefCLI; import org.jabref.gui.JabRefGUI; +import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.gui.preferences.JabRefGuiPreferences; import org.jabref.gui.util.DefaultDirectoryMonitor; import org.jabref.gui.util.DefaultFileUpdateMonitor; import org.jabref.logic.UiCommand; @@ -24,18 +26,17 @@ import org.jabref.logic.net.ProxyRegisterer; import org.jabref.logic.net.ssl.SSLPreferences; import org.jabref.logic.net.ssl.TrustStoreManager; +import org.jabref.logic.preferences.CliPreferences; import org.jabref.logic.protectedterms.ProtectedTermsLoader; import org.jabref.logic.remote.RemotePreferences; import org.jabref.logic.remote.client.RemoteClient; import org.jabref.logic.util.BuildInfo; +import org.jabref.logic.util.Directories; import org.jabref.logic.util.HeadlessExecutorService; -import org.jabref.logic.util.OS; import org.jabref.migrations.PreferencesMigrations; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.util.DirectoryMonitor; import org.jabref.model.util.FileUpdateMonitor; -import org.jabref.preferences.JabRefPreferences; -import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.injection.Injector; import org.apache.commons.cli.ParseException; @@ -61,8 +62,9 @@ public static void main(String[] args) { Injector.setModelOrService(BuildInfo.class, new BuildInfo()); // Initialize preferences - final JabRefPreferences preferences = JabRefPreferences.getInstance(); - Injector.setModelOrService(PreferencesService.class, preferences); + final JabRefGuiPreferences preferences = JabRefGuiPreferences.getInstance(); + Injector.setModelOrService(CliPreferences.class, preferences); + Injector.setModelOrService(GuiPreferences.class, preferences); // Early exit in case another instance is already running if (!handleMultipleAppInstances(args, preferences.getRemotePreferences())) { @@ -95,6 +97,7 @@ public static void main(String[] args) { args, ArgumentProcessor.Mode.INITIAL_START, preferences, + preferences, fileUpdateMonitor, entryTypesManager); argumentProcessor.processArguments(); @@ -137,7 +140,7 @@ private static void initLogging(String[] args) { } // addLogToDisk - Path directory = OS.getNativeDesktop().getLogDirectory(); + Path directory = Directories.getLogDirectory(); try { Files.createDirectories(directory); } catch (IOException e) { @@ -204,7 +207,7 @@ private static void configureSSL(SSLPreferences sslPreferences) { } private static void clearOldSearchIndices() { - Path currentIndexPath = OS.getNativeDesktop().getFulltextIndexBaseDirectory(); + Path currentIndexPath = Directories.getFulltextIndexBaseDirectory(); Path appData = currentIndexPath.getParent(); try { diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index 6d4649c7739..64edddac7a4 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -14,7 +14,8 @@ import java.util.prefs.BackingStoreException; import org.jabref.gui.externalfiles.AutoSetFileLinksUtil; -import org.jabref.gui.util.CurrentThreadTaskExecutor; +import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.FilePreferences; import org.jabref.logic.JabRefException; import org.jabref.logic.UiCommand; import org.jabref.logic.bibtex.FieldPreferences; @@ -41,9 +42,12 @@ import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.os.OS; +import org.jabref.logic.preferences.CliPreferences; import org.jabref.logic.search.DatabaseSearcher; +import org.jabref.logic.search.SearchPreferences; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; -import org.jabref.logic.util.OS; +import org.jabref.logic.util.CurrentThreadTaskExecutor; import org.jabref.logic.util.io.FileUtil; import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabase; @@ -55,9 +59,6 @@ import org.jabref.model.strings.StringUtil; import org.jabref.model.util.DummyFileUpdateMonitor; import org.jabref.model.util.FileUpdateMonitor; -import org.jabref.preferences.FilePreferences; -import org.jabref.preferences.PreferencesService; -import org.jabref.preferences.SearchPreferences; import com.airhacks.afterburner.injection.Injector; import com.google.common.base.Throwables; @@ -73,7 +74,8 @@ public enum Mode { INITIAL_START, REMOTE_START } private final Mode startupMode; - private final PreferencesService preferencesService; + private final CliPreferences cliPreferences; + private final GuiPreferences guiPreferences; private final FileUpdateMonitor fileUpdateMonitor; private final BibEntryTypesManager entryTypesManager; @@ -83,16 +85,20 @@ public enum Mode { INITIAL_START, REMOTE_START } /** * First call the constructor, then call {@link #processArguments()}. * Afterward, you can access the {@link #getUiCommands()}. + * + * @implNote both cli and gui preferences are passed to make the dependency to GUI parts explicit */ public ArgumentProcessor(String[] args, Mode startupMode, - PreferencesService preferencesService, + CliPreferences cliPreferences, + GuiPreferences guiPreferences, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager) throws org.apache.commons.cli.ParseException { this.cli = new JabRefCLI(args); this.startupMode = startupMode; - this.preferencesService = preferencesService; + this.cliPreferences = cliPreferences; + this.guiPreferences = guiPreferences; this.fileUpdateMonitor = fileUpdateMonitor; this.entryTypesManager = entryTypesManager; } @@ -166,9 +172,9 @@ private Optional importFile(String importArguments) { private Optional importFile(Path file, String importFormat) { try { ImportFormatReader importFormatReader = new ImportFormatReader( - preferencesService.getImporterPreferences(), - preferencesService.getImportFormatPreferences(), - preferencesService.getCitationKeyPatternPreferences(), + cliPreferences.getImporterPreferences(), + cliPreferences.getImportFormatPreferences(), + cliPreferences.getCitationKeyPatternPreferences(), fileUpdateMonitor ); @@ -200,7 +206,7 @@ public void processArguments() { } if ((startupMode == Mode.INITIAL_START) && cli.isHelp()) { - JabRefCLI.printUsage(preferencesService); + JabRefCLI.printUsage(cliPreferences); guiNeeded = false; return; } @@ -249,11 +255,11 @@ public void processArguments() { if (!loaded.isEmpty()) { writeMetadataToPdf(loaded, cli.getWriteMetadataToPdf(), - preferencesService.getXmpPreferences(), - preferencesService.getFilePreferences(), - preferencesService.getLibraryPreferences().getDefaultBibDatabaseMode(), + cliPreferences.getXmpPreferences(), + cliPreferences.getFilePreferences(), + cliPreferences.getLibraryPreferences().getDefaultBibDatabaseMode(), Injector.instantiateModelOrService(BibEntryTypesManager.class), - preferencesService.getFieldPreferences(), + cliPreferences.getFieldPreferences(), Injector.instantiateModelOrService(JournalAbbreviationRepository.class), cli.isWriteXmpToPdf() || cli.isWriteMetadataToPdf(), cli.isEmbedBibFileInPdf() || cli.isWriteMetadataToPdf()); @@ -271,7 +277,7 @@ public void processArguments() { if (cli.isPreferencesExport()) { try { - preferencesService.exportPreferences(Path.of(cli.getPreferencesExport())); + cliPreferences.exportPreferences(Path.of(cli.getPreferencesExport())); } catch (JabRefException ex) { LOGGER.error("Cannot export preferences", ex); } @@ -456,13 +462,13 @@ private boolean exportMatches(List loaded) { ParserResult pr = loaded.getLast(); BibDatabaseContext databaseContext = pr.getDatabaseContext(); - SearchPreferences searchPreferences = preferencesService.getSearchPreferences(); + SearchPreferences searchPreferences = cliPreferences.getSearchPreferences(); SearchQuery query = new SearchQuery(searchTerm, searchPreferences.getSearchFlags()); List matches; try { // extract current thread task executor from luceneManager - matches = new DatabaseSearcher(query, databaseContext, new CurrentThreadTaskExecutor(), preferencesService.getFilePreferences()).getMatches(); + matches = new DatabaseSearcher(query, databaseContext, new CurrentThreadTaskExecutor(), cliPreferences.getFilePreferences()).getMatches(); } catch (IOException e) { LOGGER.error("Error occurred when searching", e); return false; @@ -494,7 +500,7 @@ private boolean exportMatches(List loaded) { } else { // export new database ExporterFactory exporterFactory = ExporterFactory.create( - preferencesService, + cliPreferences, Injector.instantiateModelOrService(BibEntryTypesManager.class)); Optional exporter = exporterFactory.getExporterByName(formatName); if (exporter.isEmpty()) { @@ -554,7 +560,7 @@ private List importAndOpenFiles() { try { pr = OpenDatabase.loadDatabase( Path.of(aLeftOver), - preferencesService.getImportFormatPreferences(), + cliPreferences.getImportFormatPreferences(), fileUpdateMonitor); // In contrast to org.jabref.gui.LibraryTab.onDatabaseLoadingSucceed, we do not execute OpenDatabaseAction.performPostOpenActions(result, dialogService); } catch (IOException ex) { @@ -594,7 +600,7 @@ private List importAndOpenFiles() { } if (!cli.isBlank() && cli.isBibtexImport()) { - importBibtexToOpenBase(cli.getBibtexImport(), preferencesService.getImportFormatPreferences()).ifPresent(loaded::add); + importBibtexToOpenBase(cli.getBibtexImport(), cliPreferences.getImportFormatPreferences()).ifPresent(loaded::add); } return loaded; @@ -630,12 +636,12 @@ private void saveDatabase(BibDatabase newBase, String subName) { try (AtomicFileWriter fileWriter = new AtomicFileWriter(Path.of(subName), StandardCharsets.UTF_8)) { BibWriter bibWriter = new BibWriter(fileWriter, OS.NEWLINE); SelfContainedSaveConfiguration saveConfiguration = (SelfContainedSaveConfiguration) new SelfContainedSaveConfiguration() - .withReformatOnSave(preferencesService.getLibraryPreferences().shouldAlwaysReformatOnSave()); + .withReformatOnSave(cliPreferences.getLibraryPreferences().shouldAlwaysReformatOnSave()); BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter( bibWriter, saveConfiguration, - preferencesService.getFieldPreferences(), - preferencesService.getCitationKeyPatternPreferences(), + cliPreferences.getFieldPreferences(), + cliPreferences.getCitationKeyPatternPreferences(), entryTypesManager); databaseWriter.saveDatabase(new BibDatabaseContext(newBase)); @@ -671,10 +677,10 @@ private void exportFile(List loaded, String[] data) { BibDatabaseContext databaseContext = parserResult.getDatabaseContext(); databaseContext.setDatabasePath(path); List fileDirForDatabase = databaseContext - .getFileDirectories(preferencesService.getFilePreferences()); + .getFileDirectories(cliPreferences.getFilePreferences()); System.out.println(Localization.lang("Exporting %0", data[0])); ExporterFactory exporterFactory = ExporterFactory.create( - preferencesService, + cliPreferences, Injector.instantiateModelOrService(BibEntryTypesManager.class)); Optional exporter = exporterFactory.getExporterByName(data[1]); if (exporter.isEmpty()) { @@ -697,8 +703,8 @@ private void exportFile(List loaded, String[] data) { private void importPreferences() { try { - preferencesService.importPreferences(Path.of(cli.getPreferencesImport())); - Injector.setModelOrService(BibEntryTypesManager.class, preferencesService.getCustomEntryTypesRepository()); + cliPreferences.importPreferences(Path.of(cli.getPreferencesImport())); + Injector.setModelOrService(BibEntryTypesManager.class, cliPreferences.getCustomEntryTypesRepository()); } catch (JabRefException ex) { LOGGER.error("Cannot import preferences", ex); } @@ -708,7 +714,7 @@ private void resetPreferences(String value) { if ("all".equals(value.trim())) { try { System.out.println(Localization.lang("Setting all preferences to default values.")); - preferencesService.clear(); + cliPreferences.clear(); new SharedDatabasePreferences().clear(); } catch (BackingStoreException e) { System.err.println(Localization.lang("Unable to clear preferences.")); @@ -718,7 +724,7 @@ private void resetPreferences(String value) { String[] keys = value.split(","); for (String key : keys) { try { - preferencesService.deleteKey(key.trim()); + cliPreferences.deleteKey(key.trim()); System.out.println(Localization.lang("Resetting preference key '%0'", key.trim())); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); @@ -734,11 +740,12 @@ private void automaticallySetFileLinks(List loaded) { parserResult.getDatabaseContext().getDatabasePath() .map(Path::getFileName) .map(Path::toString).orElse("UNKNOWN")); - + AutoSetFileLinksUtil util = new AutoSetFileLinksUtil( parserResult.getDatabaseContext(), - preferencesService.getFilePreferences(), - preferencesService.getAutoLinkPreferences()); + guiPreferences.getExternalApplicationsPreferences(), + cliPreferences.getFilePreferences(), + cliPreferences.getAutoLinkPreferences()); util.linkAssociatedFiles(database.getEntries(), (linkedFile, bibEntry) -> bibEntry.addFile(linkedFile)); } @@ -752,7 +759,7 @@ private void regenerateCitationKeys(List loaded) { CitationKeyGenerator keyGenerator = new CitationKeyGenerator( parserResult.getDatabaseContext(), - preferencesService.getCitationKeyPatternPreferences()); + cliPreferences.getCitationKeyPatternPreferences()); for (BibEntry entry : database.getEntries()) { keyGenerator.generateAndSetKey(entry); } @@ -777,8 +784,8 @@ private Optional fetch(String fetchCommand) { String query = split[1]; Set fetchers = WebFetchers.getSearchBasedFetchers( - preferencesService.getImportFormatPreferences(), - preferencesService.getImporterPreferences()); + cliPreferences.getImportFormatPreferences(), + cliPreferences.getImporterPreferences()); Optional selectedFetcher = fetchers.stream() .filter(fetcher -> fetcher.getName().equalsIgnoreCase(engine)) .findFirst(); diff --git a/src/main/java/org/jabref/cli/JabRefCLI.java b/src/main/java/org/jabref/cli/JabRefCLI.java index 4d36f61158b..0cd74a0bba4 100644 --- a/src/main/java/org/jabref/cli/JabRefCLI.java +++ b/src/main/java/org/jabref/cli/JabRefCLI.java @@ -8,12 +8,12 @@ import org.jabref.logic.exporter.ExporterFactory; import org.jabref.logic.importer.ImportFormatReader; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.os.OS; +import org.jabref.logic.preferences.CliPreferences; import org.jabref.logic.util.BuildInfo; -import org.jabref.logic.util.OS; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.strings.StringUtil; import org.jabref.model.util.DummyFileUpdateMonitor; -import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.injection.Injector; import org.apache.commons.cli.CommandLine; @@ -309,13 +309,13 @@ public void displayVersion() { System.out.println(getVersionInfo()); } - public static void printUsage(PreferencesService preferencesService) { + public static void printUsage(CliPreferences preferences) { String header = ""; ImportFormatReader importFormatReader = new ImportFormatReader( - preferencesService.getImporterPreferences(), - preferencesService.getImportFormatPreferences(), - preferencesService.getCitationKeyPatternPreferences(), + preferences.getImporterPreferences(), + preferences.getImportFormatPreferences(), + preferences.getCitationKeyPatternPreferences(), new DummyFileUpdateMonitor() ); List> importFormats = importFormatReader @@ -326,7 +326,7 @@ public static void printUsage(PreferencesService preferencesService) { String importFormatsList = "%s:%n%s%n".formatted(importFormatsIntro, alignStringTable(importFormats)); ExporterFactory exporterFactory = ExporterFactory.create( - preferencesService, + preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class)); List> exportFormats = exporterFactory .getExporters().stream() diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java index f135aeab52e..3e1455908e0 100644 --- a/src/main/java/org/jabref/gui/ClipBoardManager.java +++ b/src/main/java/org/jabref/gui/ClipBoardManager.java @@ -18,11 +18,11 @@ import org.jabref.architecture.AllowedToUseAwt; import org.jabref.logic.bibtex.BibEntryWriter; import org.jabref.logic.bibtex.FieldWriter; +import org.jabref.logic.preferences.CliPreferences; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.entry.BibtexString; -import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.injection.Injector; import org.slf4j.Logger; @@ -167,11 +167,11 @@ public void setContent(List entries, BibEntryTypesManager entryTypesMa } private String serializeEntries(List entries, BibEntryTypesManager entryTypesManager) throws IOException { - PreferencesService preferencesService = Injector.instantiateModelOrService(PreferencesService.class); + CliPreferences preferences = Injector.instantiateModelOrService(CliPreferences.class); // BibEntry is not Java serializable. Thus, we need to do the serialization manually // At reading of the clipboard in JabRef, we parse the plain string in all cases, so we don't need to flag we put BibEntries here // Furthermore, storing a string also enables other applications to work with the data - BibEntryWriter writer = new BibEntryWriter(new FieldWriter(preferencesService.getFieldPreferences()), entryTypesManager); + BibEntryWriter writer = new BibEntryWriter(new FieldWriter(preferences.getFieldPreferences()), entryTypesManager); return writer.serializeAll(entries, BibDatabaseMode.BIBTEX); } } diff --git a/src/main/java/org/jabref/preferences/GuiPreferences.java b/src/main/java/org/jabref/gui/CoreGuiPreferences.java similarity index 61% rename from src/main/java/org/jabref/preferences/GuiPreferences.java rename to src/main/java/org/jabref/gui/CoreGuiPreferences.java index af79cc49a99..23212a62ed1 100644 --- a/src/main/java/org/jabref/preferences/GuiPreferences.java +++ b/src/main/java/org/jabref/gui/CoreGuiPreferences.java @@ -1,22 +1,13 @@ -package org.jabref.preferences; - -import java.nio.file.Path; -import java.util.List; +package org.jabref.gui; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; -import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleDoubleProperty; -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.logic.util.io.FileHistory; -public class GuiPreferences { +public class CoreGuiPreferences { private final DoubleProperty positionX; private final DoubleProperty positionY; private final DoubleProperty sizeX; @@ -26,36 +17,22 @@ public class GuiPreferences { private final DoubleProperty sidePaneWidth; - // the last libraries that were open when jabref closes and should be reopened on startup - private final ObservableList lastFilesOpened; - - private final ObjectProperty lastFocusedFile; - - // observable list last files opened in the file menu - private final FileHistory fileHistory; - private final StringProperty lastSelectedIdBasedFetcher; - public GuiPreferences(double positionX, - double positionY, - double sizeX, - double sizeY, - boolean windowMaximised, - List lastFilesOpened, - Path lastFocusedFile, - FileHistory fileHistory, - String lastSelectedIdBasedFetcher, - double sidePaneWidth) { + public CoreGuiPreferences(double positionX, + double positionY, + double sizeX, + double sizeY, + boolean windowMaximised, + String lastSelectedIdBasedFetcher, + double sidePaneWidth) { this.positionX = new SimpleDoubleProperty(positionX); this.positionY = new SimpleDoubleProperty(positionY); this.sizeX = new SimpleDoubleProperty(sizeX); this.sizeY = new SimpleDoubleProperty(sizeY); this.windowMaximised = new SimpleBooleanProperty(windowMaximised); - this.lastFilesOpened = FXCollections.observableArrayList(lastFilesOpened); - this.lastFocusedFile = new SimpleObjectProperty<>(lastFocusedFile); this.lastSelectedIdBasedFetcher = new SimpleStringProperty(lastSelectedIdBasedFetcher); this.sidePaneWidth = new SimpleDoubleProperty(sidePaneWidth); - this.fileHistory = fileHistory; } public double getPositionX() { @@ -118,30 +95,6 @@ public void setWindowMaximised(boolean windowMaximised) { this.windowMaximised.set(windowMaximised); } - public ObservableList getLastFilesOpened() { - return lastFilesOpened; - } - - public void setLastFilesOpened(List files) { - lastFilesOpened.setAll(files); - } - - public Path getLastFocusedFile() { - return lastFocusedFile.get(); - } - - public ObjectProperty lastFocusedFileProperty() { - return lastFocusedFile; - } - - public void setLastFocusedFile(Path lastFocusedFile) { - this.lastFocusedFile.set(lastFocusedFile); - } - - public FileHistory getFileHistory() { - return fileHistory; - } - public String getLastSelectedIdBasedFetcher() { return lastSelectedIdBasedFetcher.get(); } diff --git a/src/main/java/org/jabref/gui/DialogService.java b/src/main/java/org/jabref/gui/DialogService.java index 03c505068a8..7248be47511 100644 --- a/src/main/java/org/jabref/gui/DialogService.java +++ b/src/main/java/org/jabref/gui/DialogService.java @@ -22,6 +22,7 @@ import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.util.NotificationService; import org.controlsfx.control.textfield.CustomPasswordField; import org.controlsfx.dialog.ProgressDialog; @@ -29,7 +30,7 @@ /** * This interface provides methods to create dialogs and show them to the user. */ -public interface DialogService { +public interface DialogService extends NotificationService { /** * This will create and display new {@link ChoiceDialog} of type T with a default choice and a collection of possible choices @@ -251,13 +252,6 @@ Optional showCustomButtonDialogAndWait(Alert.AlertType type, String */ Optional showBackgroundProgressDialogAndWait(String title, String content, StateManager stateManager); - /** - * Notify the user in a non-blocking way (i.e., in form of toast in a snackbar). - * - * @param message the message to show. - */ - void notify(String message); - /** * Shows a new file save dialog. The method doesn't return until the * displayed file save dialog is dismissed. The return value specifies the diff --git a/src/main/java/org/jabref/gui/FallbackExceptionHandler.java b/src/main/java/org/jabref/gui/FallbackExceptionHandler.java deleted file mode 100644 index 2f42d2a00a1..00000000000 --- a/src/main/java/org/jabref/gui/FallbackExceptionHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.jabref.gui; - -import org.jabref.gui.util.UiTaskExecutor; - -import com.airhacks.afterburner.injection.Injector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Catch and log any unhandled exceptions. - */ -public class FallbackExceptionHandler implements Thread.UncaughtExceptionHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(FallbackExceptionHandler.class); - - public static void installExceptionHandler() { - Thread.setDefaultUncaughtExceptionHandler(new FallbackExceptionHandler()); - } - - @Override - public void uncaughtException(Thread thread, Throwable exception) { - LOGGER.error("Uncaught exception occurred in {}", thread, exception); - UiTaskExecutor.runInJavaFXThread(() -> { - DialogService dialogService = Injector.instantiateModelOrService(DialogService.class); - dialogService.showErrorDialogAndWait("Uncaught exception occurred in " + thread, exception); - }); - } -} diff --git a/src/main/java/org/jabref/gui/JabRefDialogService.java b/src/main/java/org/jabref/gui/JabRefDialogService.java index 9d907840e43..c3e3ce962d9 100644 --- a/src/main/java/org/jabref/gui/JabRefDialogService.java +++ b/src/main/java/org/jabref/gui/JabRefDialogService.java @@ -41,7 +41,7 @@ import org.jabref.gui.help.ErrorConsoleAction; import org.jabref.gui.icon.IconTheme; -import org.jabref.gui.util.BackgroundTask; +import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.util.BaseDialog; import org.jabref.gui.util.BaseWindow; import org.jabref.gui.util.DirectoryDialogConfiguration; @@ -392,7 +392,7 @@ public Optional showBackgroundProgressDialogAndWait(String title TaskProgressView> taskProgressView = new TaskProgressView<>(); EasyBind.bindContent(taskProgressView.getTasks(), stateManager.getRunningBackgroundTasks()); taskProgressView.setRetainTasks(false); - taskProgressView.setGraphicFactory(BackgroundTask::getIcon); + taskProgressView.setGraphicFactory(task -> ThemeManager.getDownloadIconTitleMap.getOrDefault(task.getTitle(), null)); Label message = new Label(content); diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java index 159d8bf5bea..4ba82c1fed5 100644 --- a/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/src/main/java/org/jabref/gui/JabRefGUI.java @@ -14,16 +14,17 @@ import javafx.stage.Stage; import javafx.stage.WindowEvent; +import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService; import org.jabref.gui.frame.JabRefFrame; import org.jabref.gui.help.VersionWorker; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.keyboard.KeyBindingRepository; import org.jabref.gui.keyboard.TextInputKeyBindings; import org.jabref.gui.openoffice.OOBibBaseConnect; +import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.remote.CLIMessageHandler; import org.jabref.gui.theme.ThemeManager; import org.jabref.gui.undo.CountingUndoManager; -import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.UiTaskExecutor; import org.jabref.logic.UiCommand; import org.jabref.logic.ai.AiService; @@ -32,14 +33,14 @@ import org.jabref.logic.remote.RemotePreferences; import org.jabref.logic.remote.server.RemoteListenerServerManager; import org.jabref.logic.util.BuildInfo; +import org.jabref.logic.util.FallbackExceptionHandler; import org.jabref.logic.util.HeadlessExecutorService; +import org.jabref.logic.util.TaskExecutor; import org.jabref.logic.util.WebViewStore; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.strings.StringUtil; import org.jabref.model.util.DirectoryMonitor; import org.jabref.model.util.FileUpdateMonitor; -import org.jabref.preferences.GuiPreferences; -import org.jabref.preferences.JabRefPreferences; import com.airhacks.afterburner.injection.Injector; import com.tobiasdiez.easybind.EasyBind; @@ -55,11 +56,12 @@ public class JabRefGUI extends Application { private static final Logger LOGGER = LoggerFactory.getLogger(JabRefGUI.class); private static List uiCommands; - private static JabRefPreferences preferencesService; + private static GuiPreferences preferences; private static FileUpdateMonitor fileUpdateMonitor; // AI Service handles chat messages etc. Therefore, it is tightly coupled to the GUI. private static AiService aiService; + private static ChatHistoryService chatHistoryService; private static StateManager stateManager; private static ThemeManager themeManager; @@ -74,10 +76,10 @@ public class JabRefGUI extends Application { private Stage mainStage; public static void setup(List uiCommands, - JabRefPreferences preferencesService, + GuiPreferences preferences, FileUpdateMonitor fileUpdateMonitor) { JabRefGUI.uiCommands = uiCommands; - JabRefGUI.preferencesService = preferencesService; + JabRefGUI.preferences = preferences; JabRefGUI.fileUpdateMonitor = fileUpdateMonitor; } @@ -85,7 +87,12 @@ public static void setup(List uiCommands, public void start(Stage stage) { this.mainStage = stage; - FallbackExceptionHandler.installExceptionHandler(); + FallbackExceptionHandler.installExceptionHandler((exception, thread) -> { + UiTaskExecutor.runInJavaFXThread(() -> { + DialogService dialogService = Injector.instantiateModelOrService(DialogService.class); + dialogService.showErrorDialogAndWait("Uncaught exception occurred in " + thread, exception); + }); + }); initialize(); @@ -93,8 +100,9 @@ public void start(Stage stage) { mainStage, dialogService, fileUpdateMonitor, - preferencesService, + preferences, aiService, + chatHistoryService, stateManager, countingUndoManager, Injector.instantiateModelOrService(BibEntryTypesManager.class), @@ -113,12 +121,12 @@ public void start(Stage stage) { } BuildInfo buildInfo = Injector.instantiateModelOrService(BuildInfo.class); - EasyBind.subscribe(preferencesService.getInternalPreferences().versionCheckEnabledProperty(), enabled -> { + EasyBind.subscribe(preferences.getInternalPreferences().versionCheckEnabledProperty(), enabled -> { if (enabled) { new VersionWorker(buildInfo.version, dialogService, taskExecutor, - preferencesService) + preferences) .checkForNewVersionDelayed(); } }); @@ -135,10 +143,10 @@ public void initialize() { JabRefGUI.stateManager = new StateManager(); Injector.setModelOrService(StateManager.class, stateManager); - Injector.setModelOrService(KeyBindingRepository.class, preferencesService.getKeyBindingRepository()); + Injector.setModelOrService(KeyBindingRepository.class, preferences.getKeyBindingRepository()); JabRefGUI.themeManager = new ThemeManager( - preferencesService.getWorkspacePreferences(), + preferences.getWorkspacePreferences(), fileUpdateMonitor, Runnable::run); Injector.setModelOrService(ThemeManager.class, themeManager); @@ -147,6 +155,7 @@ public void initialize() { Injector.setModelOrService(UndoManager.class, countingUndoManager); Injector.setModelOrService(CountingUndoManager.class, countingUndoManager); + // our Default task executor is the UITaskExecutor which can use the fx thread JabRefGUI.taskExecutor = new UiTaskExecutor(); Injector.setModelOrService(TaskExecutor.class, taskExecutor); @@ -157,23 +166,28 @@ public void initialize() { Injector.setModelOrService(ClipBoardManager.class, clipBoardManager); JabRefGUI.aiService = new AiService( - preferencesService.getAiPreferences(), - preferencesService.getFilePreferences(), - preferencesService.getCitationKeyPatternPreferences(), + preferences.getAiPreferences(), + preferences.getFilePreferences(), + preferences.getCitationKeyPatternPreferences(), dialogService, taskExecutor); Injector.setModelOrService(AiService.class, aiService); + + JabRefGUI.chatHistoryService = new ChatHistoryService( + preferences.getCitationKeyPatternPreferences(), + dialogService); + Injector.setModelOrService(ChatHistoryService.class, chatHistoryService); } private void setupProxy() { - if (!preferencesService.getProxyPreferences().shouldUseProxy() - || !preferencesService.getProxyPreferences().shouldUseAuthentication()) { + if (!preferences.getProxyPreferences().shouldUseProxy() + || !preferences.getProxyPreferences().shouldUseAuthentication()) { return; } - if (preferencesService.getProxyPreferences().shouldPersistPassword() - && StringUtil.isNotBlank(preferencesService.getProxyPreferences().getPassword())) { - ProxyRegisterer.register(preferencesService.getProxyPreferences()); + if (preferences.getProxyPreferences().shouldPersistPassword() + && StringUtil.isNotBlank(preferences.getProxyPreferences().getPassword())) { + ProxyRegisterer.register(preferences.getProxyPreferences()); return; } @@ -183,8 +197,8 @@ private void setupProxy() { Localization.lang("Password")); if (password.isPresent()) { - preferencesService.getProxyPreferences().setPassword(password.get()); - ProxyRegisterer.register(preferencesService.getProxyPreferences()); + preferences.getProxyPreferences().setPassword(password.get()); + ProxyRegisterer.register(preferences.getProxyPreferences()); } else { LOGGER.warn("No proxy password specified"); } @@ -193,24 +207,24 @@ private void setupProxy() { private void openWindow() { LOGGER.debug("Initializing frame"); - GuiPreferences guiPreferences = preferencesService.getGuiPreferences(); - LOGGER.debug("Reading from prefs: isMaximized {}", guiPreferences.isWindowMaximised()); + CoreGuiPreferences coreGuiPreferences = preferences.getGuiPreferences(); + LOGGER.debug("Reading from prefs: isMaximized {}", coreGuiPreferences.isWindowMaximised()); mainStage.setMinWidth(580); mainStage.setMinHeight(330); // maximized target state is stored, because "saveWindowState" saves x and y only if not maximized - boolean windowMaximised = guiPreferences.isWindowMaximised(); + boolean windowMaximised = coreGuiPreferences.isWindowMaximised(); LOGGER.debug("Screens: {}", Screen.getScreens()); debugLogWindowState(mainStage); if (isWindowPositionInBounds()) { LOGGER.debug("The JabRef window is inside screen bounds."); - mainStage.setX(guiPreferences.getPositionX()); - mainStage.setY(guiPreferences.getPositionY()); - mainStage.setWidth(guiPreferences.getSizeX()); - mainStage.setHeight(guiPreferences.getSizeY()); + mainStage.setX(coreGuiPreferences.getPositionX()); + mainStage.setY(coreGuiPreferences.getPositionY()); + mainStage.setWidth(coreGuiPreferences.getSizeX()); + mainStage.setHeight(coreGuiPreferences.getSizeY()); LOGGER.debug("NOT saving window positions"); } else { LOGGER.info("The JabRef window is outside of screen bounds. Position and size will be corrected to 1024x768. Primary screen will be used."); @@ -235,7 +249,7 @@ private void openWindow() { scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> TextInputKeyBindings.call( scene, event, - preferencesService.getKeyBindingRepository())); + preferences.getKeyBindingRepository())); mainStage.setTitle(JabRefFrame.FRAME_TITLE); mainStage.getIcons().addAll(IconTheme.getLogoSetFX()); @@ -257,7 +271,7 @@ public void onShowing(WindowEvent event) { // Open last edited databases if (uiCommands.stream().noneMatch(UiCommand.BlankWorkspace.class::isInstance) - && preferencesService.getWorkspacePreferences().shouldOpenLastEdited()) { + && preferences.getWorkspacePreferences().shouldOpenLastEdited()) { mainFrame.openLastEditedDatabases(); } } @@ -270,12 +284,12 @@ public void onCloseRequest(WindowEvent event) { public void onHiding(WindowEvent event) { saveWindowState(); - preferencesService.flush(); + preferences.flush(); Platform.exit(); } private void saveWindowState() { - GuiPreferences preferences = preferencesService.getGuiPreferences(); + CoreGuiPreferences preferences = JabRefGUI.preferences.getGuiPreferences(); if (!mainStage.isMaximized()) { preferences.setPositionX(mainStage.getX()); preferences.setPositionY(mainStage.getY()); @@ -307,19 +321,19 @@ private void debugLogWindowState(Stage mainStage) { * Tests if the window coordinates are inside any screen */ private boolean isWindowPositionInBounds() { - GuiPreferences guiPreferences = preferencesService.getGuiPreferences(); + CoreGuiPreferences coreGuiPreferences = preferences.getGuiPreferences(); if (LOGGER.isDebugEnabled()) { Screen.getScreens().forEach(screen -> LOGGER.debug("Screen bounds: {}", screen.getBounds())); } - return lowerLeftIsInBounds(guiPreferences) && upperRightIsInBounds(guiPreferences); + return lowerLeftIsInBounds(coreGuiPreferences) && upperRightIsInBounds(coreGuiPreferences); } - private boolean lowerLeftIsInBounds(GuiPreferences guiPreferences) { + private boolean lowerLeftIsInBounds(CoreGuiPreferences coreGuiPreferences) { // Windows/PowerToys somehow removes 10 pixels to the left; they are re-added - double leftX = guiPreferences.getPositionX() + 10.0; - double bottomY = guiPreferences.getPositionY() + guiPreferences.getSizeY(); + double leftX = coreGuiPreferences.getPositionX() + 10.0; + double bottomY = coreGuiPreferences.getPositionY() + coreGuiPreferences.getSizeY(); LOGGER.debug("left x: {}, bottom y: {}", leftX, bottomY); boolean inBounds = Screen.getScreens().stream().anyMatch((screen -> screen.getBounds().contains(leftX, bottomY))); @@ -327,11 +341,11 @@ private boolean lowerLeftIsInBounds(GuiPreferences guiPreferences) { return inBounds; } - private boolean upperRightIsInBounds(GuiPreferences guiPreferences) { + private boolean upperRightIsInBounds(CoreGuiPreferences coreGuiPreferences) { // The upper right corner is checked as there are most probably the window controls. // Windows/PowerToys somehow adds 10 pixels to the right and top of the screen, they are removed - double rightX = guiPreferences.getPositionX() + guiPreferences.getSizeX() - 10.0; - double topY = guiPreferences.getPositionY(); + double rightX = coreGuiPreferences.getPositionX() + coreGuiPreferences.getSizeX() - 10.0; + double topY = coreGuiPreferences.getPositionY(); LOGGER.debug("right x: {}, top y: {}", rightX, topY); boolean inBounds = Screen.getScreens().stream().anyMatch((screen -> screen.getBounds().contains(rightX, topY))); @@ -341,13 +355,13 @@ private boolean upperRightIsInBounds(GuiPreferences guiPreferences) { // Background tasks public void startBackgroundTasks() { - RemotePreferences remotePreferences = preferencesService.getRemotePreferences(); + RemotePreferences remotePreferences = preferences.getRemotePreferences(); BibEntryTypesManager bibEntryTypesManager = Injector.instantiateModelOrService(BibEntryTypesManager.class); if (remotePreferences.useRemoteServer()) { remoteListenerServerManager.openAndStart( new CLIMessageHandler( mainFrame, - preferencesService, + preferences, fileUpdateMonitor, bibEntryTypesManager), remotePreferences.getPort()); diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index d17a0a1871e..93901045848 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -54,6 +54,7 @@ import org.jabref.gui.maintable.BibEntryTableViewModel; import org.jabref.gui.maintable.MainTable; import org.jabref.gui.maintable.MainTableDataModel; +import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.undo.NamedCompound; import org.jabref.gui.undo.RedoAction; @@ -61,9 +62,7 @@ import org.jabref.gui.undo.UndoableFieldChange; import org.jabref.gui.undo.UndoableInsertEntries; import org.jabref.gui.undo.UndoableRemoveEntries; -import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.OptionalObjectProperty; -import org.jabref.gui.util.TaskExecutor; import org.jabref.gui.util.UiTaskExecutor; import org.jabref.logic.citationstyle.CitationStyleCache; import org.jabref.logic.importer.FetcherClientException; @@ -75,6 +74,8 @@ import org.jabref.logic.pdf.FileAnnotationCache; import org.jabref.logic.search.LuceneManager; import org.jabref.logic.shared.DatabaseLocation; +import org.jabref.logic.util.BackgroundTask; +import org.jabref.logic.util.TaskExecutor; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; @@ -97,7 +98,6 @@ import org.jabref.model.util.DirectoryMonitor; import org.jabref.model.util.DirectoryMonitorManager; import org.jabref.model.util.FileUpdateMonitor; -import org.jabref.preferences.PreferencesService; import com.airhacks.afterburner.injection.Injector; import com.google.common.eventbus.Subscribe; @@ -121,7 +121,7 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private final LibraryTabContainer tabContainer; private final CountingUndoManager undoManager; private final DialogService dialogService; - private final PreferencesService preferencesService; + private final GuiPreferences preferences; private final FileUpdateMonitor fileUpdateMonitor; private final StateManager stateManager; private final BibEntryTypesManager entryTypesManager; @@ -178,7 +178,7 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private LibraryTab(BibDatabaseContext bibDatabaseContext, LibraryTabContainer tabContainer, DialogService dialogService, - PreferencesService preferencesService, + GuiPreferences preferences, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, @@ -190,7 +190,7 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext, this.bibDatabaseContext = Objects.requireNonNull(bibDatabaseContext); this.undoManager = undoManager; this.dialogService = dialogService; - this.preferencesService = Objects.requireNonNull(preferencesService); + this.preferences = Objects.requireNonNull(preferences); this.stateManager = Objects.requireNonNull(stateManager); this.fileUpdateMonitor = fileUpdateMonitor; this.entryTypesManager = entryTypesManager; @@ -221,13 +221,13 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { bibDatabaseContext.getMetaData().registerListener(this); this.selectedGroupsProperty = new SimpleListProperty<>(stateManager.getSelectedGroups(bibDatabaseContext)); - this.tableModel = new MainTableDataModel(getBibDatabaseContext(), preferencesService, taskExecutor, stateManager, getLuceneManager(), selectedGroupsProperty(), searchQueryProperty(), resultSizeProperty()); + this.tableModel = new MainTableDataModel(getBibDatabaseContext(), preferences, taskExecutor, stateManager, getLuceneManager(), selectedGroupsProperty(), searchQueryProperty(), resultSizeProperty()); new CitationStyleCache(bibDatabaseContext); - annotationCache = new FileAnnotationCache(bibDatabaseContext, preferencesService.getFilePreferences()); + annotationCache = new FileAnnotationCache(bibDatabaseContext, preferences.getFilePreferences()); importHandler = new ImportHandler( bibDatabaseContext, - preferencesService, + preferences, fileUpdateMonitor, undoManager, stateManager, @@ -245,7 +245,7 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { // ensure that all entry changes mark the panel as changed this.bibDatabaseContext.getDatabase().registerListener(this); - this.getDatabase().registerListener(new UpdateTimestampListener(preferencesService)); + this.getDatabase().registerListener(new UpdateTimestampListener(preferences)); this.entryEditor = createEntryEditor(); @@ -303,7 +303,7 @@ private void onDatabaseLoadingStarted() { } private void onDatabaseLoadingSucceed(ParserResult result) { - OpenDatabaseAction.performPostOpenActions(result, dialogService, preferencesService); + OpenDatabaseAction.performPostOpenActions(result, dialogService, preferences); if (result.getChangedOnMigration()) { this.markBaseChanged(); } @@ -316,7 +316,7 @@ private void onDatabaseLoadingSucceed(ParserResult result) { } public void createLuceneManager() { - luceneManager = new LuceneManager(bibDatabaseContext, taskExecutor, preferencesService.getFilePreferences()); + luceneManager = new LuceneManager(bibDatabaseContext, taskExecutor, preferences.getFilePreferences()); stateManager.setLuceneManager(bibDatabaseContext, luceneManager); } @@ -364,17 +364,17 @@ private void setDatabaseContext(BibDatabaseContext bibDatabaseContext) { public void installAutosaveManagerAndBackupManager() { if (isDatabaseReadyForAutoSave(bibDatabaseContext)) { AutosaveManager autosaveManager = AutosaveManager.start(bibDatabaseContext); - autosaveManager.registerListener(new AutosaveUiManager(this, dialogService, preferencesService, entryTypesManager)); + autosaveManager.registerListener(new AutosaveUiManager(this, dialogService, preferences, entryTypesManager)); } - if (isDatabaseReadyForBackup(bibDatabaseContext) && preferencesService.getFilePreferences().shouldCreateBackup()) { - BackupManager.start(this, bibDatabaseContext, Injector.instantiateModelOrService(BibEntryTypesManager.class), preferencesService); + if (isDatabaseReadyForBackup(bibDatabaseContext) && preferences.getFilePreferences().shouldCreateBackup()) { + BackupManager.start(this, bibDatabaseContext, Injector.instantiateModelOrService(BibEntryTypesManager.class), preferences); } } private boolean isDatabaseReadyForAutoSave(BibDatabaseContext context) { return ((context.getLocation() == DatabaseLocation.SHARED) || ((context.getLocation() == DatabaseLocation.LOCAL) - && preferencesService.getLibraryPreferences().shouldAutoSave())) + && preferences.getLibraryPreferences().shouldAutoSave())) && context.getDatabasePath().isPresent(); } @@ -390,7 +390,7 @@ private boolean isDatabaseReadyForBackup(BibDatabaseContext context) { * Example: *jabref-authors.bib – testbib */ public void updateTabTitle(boolean isChanged) { - boolean isAutosaveEnabled = preferencesService.getLibraryPreferences().shouldAutoSave(); + boolean isAutosaveEnabled = preferences.getLibraryPreferences().shouldAutoSave(); DatabaseLocation databaseLocation = bibDatabaseContext.getLocation(); Optional file = bibDatabaseContext.getDatabasePath(); @@ -485,10 +485,10 @@ private void createMainTable() { this, tabContainer, bibDatabaseContext, - preferencesService, + preferences, dialogService, stateManager, - preferencesService.getKeyBindingRepository(), + preferences.getKeyBindingRepository(), clipBoardManager, entryTypesManager, taskExecutor, @@ -539,7 +539,7 @@ public void setupMainPanel() { * Set up autocompletion for this database */ private void setupAutoCompletion() { - AutoCompletePreferences autoCompletePreferences = preferencesService.getAutoCompletePreferences(); + AutoCompletePreferences autoCompletePreferences = preferences.getAutoCompletePreferences(); if (autoCompletePreferences.shouldAutoComplete()) { suggestionProviders = new SuggestionProviders( getDatabase(), @@ -569,7 +569,7 @@ public void showAndEdit(BibEntry entry) { if (!splitPane.getItems().contains(entryEditor)) { splitPane.getItems().addLast(entryEditor); mode = PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR; - splitPane.setDividerPositions(preferencesService.getEntryEditorPreferences().getDividerPosition()); + splitPane.setDividerPositions(preferences.getEntryEditorPreferences().getDividerPosition()); } // We use != instead of equals because of performance reasons @@ -653,7 +653,7 @@ public BibDatabase getDatabase() { * @return true if user confirm to delete entry */ private boolean showDeleteConfirmationDialog(int numberOfEntries) { - if (preferencesService.getWorkspacePreferences().shouldConfirmDelete()) { + if (preferences.getWorkspacePreferences().shouldConfirmDelete()) { String title = Localization.lang("Delete entry"); String message = Localization.lang("Really delete the selected entry?"); String okButton = Localization.lang("Delete entry"); @@ -671,7 +671,7 @@ private boolean showDeleteConfirmationDialog(int numberOfEntries) { okButton, cancelButton, Localization.lang("Do not ask again"), - optOut -> preferencesService.getWorkspacePreferences().setConfirmDelete(!optOut)); + optOut -> preferences.getWorkspacePreferences().setConfirmDelete(!optOut)); } else { return true; } @@ -682,7 +682,7 @@ private boolean showDeleteConfirmationDialog(int numberOfEntries) { */ private void saveDividerLocation(Number position) { if (mode == PanelMode.MAIN_TABLE_AND_ENTRY_EDITOR) { - preferencesService.getEntryEditorPreferences().setDividerPosition(position.doubleValue()); + preferences.getEntryEditorPreferences().setDividerPosition(position.doubleValue()); } } @@ -736,7 +736,7 @@ private boolean confirmClose() { if (buttonType.equals(saveChanges)) { try { - SaveDatabaseAction saveAction = new SaveDatabaseAction(this, dialogService, preferencesService, Injector.instantiateModelOrService(BibEntryTypesManager.class)); + SaveDatabaseAction saveAction = new SaveDatabaseAction(this, dialogService, preferences, Injector.instantiateModelOrService(BibEntryTypesManager.class)); if (saveAction.save()) { return true; } @@ -751,7 +751,7 @@ private boolean confirmClose() { } if (buttonType.equals(discardChanges)) { - BackupManager.discardBackup(bibDatabaseContext, preferencesService.getFilePreferences().getBackupDirectory()); + BackupManager.discardBackup(bibDatabaseContext, preferences.getFilePreferences().getBackupDirectory()); return true; } @@ -800,8 +800,8 @@ private void onClosed(Event event) { } try { BackupManager.shutdown(bibDatabaseContext, - preferencesService.getFilePreferences().getBackupDirectory(), - preferencesService.getFilePreferences().shouldCreateBackup()); + preferences.getFilePreferences().getBackupDirectory(), + preferences.getFilePreferences().shouldCreateBackup()); } catch (RuntimeException e) { LOGGER.error("Problem when shutting down backup manager", e); } @@ -872,7 +872,7 @@ public void resetChangeMonitor() { fileUpdateMonitor, taskExecutor, dialogService, - preferencesService, + preferences, databaseNotificationPane, undoManager, stateManager)); @@ -890,7 +890,7 @@ public void insertEntries(final List entries) { getUndoManager().addEdit(new UndoableInsertEntries(bibDatabaseContext.getDatabase(), entries)); markBaseChanged(); - if (preferencesService.getEntryEditorPreferences().shouldOpenOnNewEntry()) { + if (preferences.getEntryEditorPreferences().shouldOpenOnNewEntry()) { showAndEdit(entries.getFirst()); } clearAndSelect(entries.getFirst()); @@ -1009,10 +1009,10 @@ private int doDeleteEntry(StandardActions mode, List entries) { if (!linkedFileList.isEmpty()) { List viewModels = linkedFileList.stream() - .map(linkedFile -> linkedFile.toModel(null, bibDatabaseContext, null, null, preferencesService)) + .map(linkedFile -> LinkedFileViewModel.fromLinkedFile(linkedFile, null, bibDatabaseContext, null, null, preferences)) .collect(Collectors.toList()); - new DeleteFileAction(dialogService, preferencesService.getFilePreferences(), bibDatabaseContext, viewModels).execute(); + new DeleteFileAction(dialogService, preferences.getFilePreferences(), bibDatabaseContext, viewModels).execute(); } } @@ -1052,7 +1052,7 @@ public void resetChangedProperties() { public static LibraryTab createLibraryTab(BackgroundTask dataLoadingTask, Path file, DialogService dialogService, - PreferencesService preferencesService, + GuiPreferences preferences, StateManager stateManager, LibraryTabContainer tabContainer, FileUpdateMonitor fileUpdateMonitor, @@ -1067,7 +1067,7 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi context, tabContainer, dialogService, - preferencesService, + preferences, stateManager, fileUpdateMonitor, entryTypesManager, @@ -1088,7 +1088,7 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, LibraryTabContainer tabContainer, DialogService dialogService, - PreferencesService preferencesService, + GuiPreferences preferences, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, @@ -1101,7 +1101,7 @@ public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, databaseContext, tabContainer, dialogService, - preferencesService, + preferences, stateManager, fileUpdateMonitor, entryTypesManager, @@ -1121,7 +1121,7 @@ public void listen(EntriesAddedEvent addedEntriesEvent) { } // Automatically add new entries to the selected group (or set of groups) - if (preferencesService.getGroupsPreferences().shouldAutoAssignGroup()) { + if (preferences.getGroupsPreferences().shouldAutoAssignGroup()) { stateManager.getSelectedGroups(bibDatabaseContext).forEach( selectedGroup -> selectedGroup.addEntriesToGroup(addedEntriesEvent.getBibEntries())); } diff --git a/src/main/java/org/jabref/gui/StateManager.java b/src/main/java/org/jabref/gui/StateManager.java index 42fd8d9f1bc..cf73b00da94 100644 --- a/src/main/java/org/jabref/gui/StateManager.java +++ b/src/main/java/org/jabref/gui/StateManager.java @@ -22,11 +22,11 @@ import org.jabref.gui.edit.automaticfiededitor.LastAutomaticFieldEditorEdit; import org.jabref.gui.search.SearchType; import org.jabref.gui.sidepane.SidePaneType; -import org.jabref.gui.util.BackgroundTask; import org.jabref.gui.util.CustomLocalDragboard; import org.jabref.gui.util.DialogWindowState; import org.jabref.gui.util.OptionalObjectProperty; import org.jabref.logic.search.LuceneManager; +import org.jabref.logic.util.BackgroundTask; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.groups.GroupTreeNode; diff --git a/src/main/java/org/jabref/gui/UpdateTimestampListener.java b/src/main/java/org/jabref/gui/UpdateTimestampListener.java index 2ccc4a72d3c..b975773dee8 100644 --- a/src/main/java/org/jabref/gui/UpdateTimestampListener.java +++ b/src/main/java/org/jabref/gui/UpdateTimestampListener.java @@ -1,9 +1,9 @@ package org.jabref.gui; +import org.jabref.logic.preferences.CliPreferences; import org.jabref.model.entry.event.EntriesEventSource; import org.jabref.model.entry.event.EntryChangedEvent; import org.jabref.model.entry.field.StandardField; -import org.jabref.preferences.PreferencesService; import com.google.common.eventbus.Subscribe; @@ -11,19 +11,19 @@ * Updates the timestamp of changed entries if the feature is enabled */ class UpdateTimestampListener { - private final PreferencesService preferencesService; + private final CliPreferences preferences; - UpdateTimestampListener(PreferencesService preferencesService) { - this.preferencesService = preferencesService; + UpdateTimestampListener(CliPreferences preferences) { + this.preferences = preferences; } @Subscribe public void listen(EntryChangedEvent event) { // The event source needs to be checked, since the timestamp is always updated on every change. The cleanup formatter is an exception to that behaviour, // since it just should move the contents from the timestamp field to modificationdate or creationdate. - if (preferencesService.getTimestampPreferences().shouldAddModificationDate() && event.getEntriesEventSource() != EntriesEventSource.CLEANUP_TIMESTAMP) { + if (preferences.getTimestampPreferences().shouldAddModificationDate() && event.getEntriesEventSource() != EntriesEventSource.CLEANUP_TIMESTAMP) { event.getBibEntry().setField(StandardField.MODIFICATIONDATE, - preferencesService.getTimestampPreferences().now()); + preferences.getTimestampPreferences().now()); } } } diff --git a/src/main/java/org/jabref/preferences/WorkspacePreferences.java b/src/main/java/org/jabref/gui/WorkspacePreferences.java similarity index 99% rename from src/main/java/org/jabref/preferences/WorkspacePreferences.java rename to src/main/java/org/jabref/gui/WorkspacePreferences.java index 57d97a971b6..2948be7582e 100644 --- a/src/main/java/org/jabref/preferences/WorkspacePreferences.java +++ b/src/main/java/org/jabref/gui/WorkspacePreferences.java @@ -1,4 +1,4 @@ -package org.jabref.preferences; +package org.jabref.gui; import java.util.List; diff --git a/src/main/java/org/jabref/gui/actions/ActionHelper.java b/src/main/java/org/jabref/gui/actions/ActionHelper.java index 20376f2f3e2..437d38d9bfe 100644 --- a/src/main/java/org/jabref/gui/actions/ActionHelper.java +++ b/src/main/java/org/jabref/gui/actions/ActionHelper.java @@ -12,13 +12,13 @@ import javafx.scene.control.TabPane; import org.jabref.gui.StateManager; +import org.jabref.logic.preferences.CliPreferences; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; import org.jabref.model.entry.field.Field; -import org.jabref.preferences.PreferencesService; import com.tobiasdiez.easybind.EasyBind; import com.tobiasdiez.easybind.EasyBinding; @@ -66,7 +66,7 @@ public static BooleanExpression isAnyFieldSetForSelectedEntry(List fields return BooleanExpression.booleanExpression(fieldsAreSet); } - public static BooleanExpression isFilePresentForSelectedEntry(StateManager stateManager, PreferencesService preferencesService) { + public static BooleanExpression isFilePresentForSelectedEntry(StateManager stateManager, CliPreferences preferences) { ObservableList selectedEntries = stateManager.getSelectedEntries(); Binding fileIsPresent = EasyBind.valueAt(selectedEntries, 0).mapOpt(entry -> { List files = entry.getFiles(); @@ -79,7 +79,7 @@ public static BooleanExpression isFilePresentForSelectedEntry(StateManager state Optional filename = FileUtil.find( stateManager.getActiveDatabase().get(), files.getFirst().getLink(), - preferencesService.getFilePreferences()); + preferences.getFilePreferences()); return filename.isPresent(); } else { return false; diff --git a/src/main/java/org/jabref/gui/ai/ClearEmbeddingsAction.java b/src/main/java/org/jabref/gui/ai/ClearEmbeddingsAction.java index 6b76d7af67d..91b3e926269 100644 --- a/src/main/java/org/jabref/gui/ai/ClearEmbeddingsAction.java +++ b/src/main/java/org/jabref/gui/ai/ClearEmbeddingsAction.java @@ -5,10 +5,10 @@ import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; -import org.jabref.gui.util.BackgroundTask; -import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.ai.AiService; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.util.BackgroundTask; +import org.jabref.logic.util.TaskExecutor; import org.jabref.model.entry.LinkedFile; import static org.jabref.gui.actions.ActionHelper.needsDatabase; diff --git a/src/main/java/org/jabref/logic/ai/chatting/chathistory/ChatHistoryService.java b/src/main/java/org/jabref/gui/ai/chatting/chathistory/ChatHistoryService.java similarity index 93% rename from src/main/java/org/jabref/logic/ai/chatting/chathistory/ChatHistoryService.java rename to src/main/java/org/jabref/gui/ai/chatting/chathistory/ChatHistoryService.java index acbde14c3a3..872a263c7a1 100644 --- a/src/main/java/org/jabref/logic/ai/chatting/chathistory/ChatHistoryService.java +++ b/src/main/java/org/jabref/gui/ai/chatting/chathistory/ChatHistoryService.java @@ -1,4 +1,4 @@ -package org.jabref.logic.ai.chatting.chathistory; +package org.jabref.gui.ai.chatting.chathistory; import java.util.Comparator; import java.util.HashSet; @@ -11,9 +11,13 @@ import javafx.collections.ObservableList; import org.jabref.gui.StateManager; +import org.jabref.logic.ai.chatting.chathistory.ChatHistoryStorage; +import org.jabref.logic.ai.chatting.chathistory.storages.MVStoreChatHistoryStorage; import org.jabref.logic.ai.util.CitationKeyCheck; import org.jabref.logic.citationkeypattern.CitationKeyGenerator; import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences; +import org.jabref.logic.util.Directories; +import org.jabref.logic.util.NotificationService; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.event.FieldChangedEvent; @@ -29,7 +33,8 @@ /** * Main class for getting and storing chat history for entries and groups. - * Use this class in the logic and UI. + * Use this class in logic and UI. + * It currently resides in the UI package because it relies on the {@link StateManager} to get the open databases and to find the correct {@link BibDatabaseContext} based on an entry. *

    * The returned chat history is a {@link ObservableList}. So chat history exists for every possible * {@link BibEntry} and {@link AbstractGroup}. The chat history is stored in runtime. @@ -51,6 +56,8 @@ public class ChatHistoryService implements AutoCloseable { private static final Logger LOGGER = LoggerFactory.getLogger(ChatHistoryService.class); + private static final String CHAT_HISTORY_FILE_NAME = "chat-histories.mv"; + private final StateManager stateManager = Injector.instantiateModelOrService(StateManager.class); private final CitationKeyPatternPreferences citationKeyPatternPreferences; @@ -72,6 +79,12 @@ private record ChatHistoryManagementRecord(Optional bibDatab return o1 == o2 ? 0 : o1.getGroup().getName().compareTo(o2.getGroup().getName()); }); + public ChatHistoryService(CitationKeyPatternPreferences citationKeyPatternPreferences, NotificationService notificationService) { + this.citationKeyPatternPreferences = citationKeyPatternPreferences; + this.implementation = new MVStoreChatHistoryStorage(Directories.getAiFilesDirectory().resolve(CHAT_HISTORY_FILE_NAME), notificationService); + configureHistoryTransfer(); + } + public ChatHistoryService(CitationKeyPatternPreferences citationKeyPatternPreferences, ChatHistoryStorage implementation) { this.citationKeyPatternPreferences = citationKeyPatternPreferences; diff --git a/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.fxml b/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.fxml index fa24208105e..a479ace35e6 100644 --- a/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.fxml +++ b/src/main/java/org/jabref/gui/ai/components/aichat/AiChatComponent.fxml @@ -1,15 +1,16 @@ - - - - - - - + + + + + + + - + + chatHistory aiService, dialogService, aiPreferences, - filePreferences, + externalApplicationsPreferences, taskExecutor ), 800, diff --git a/src/main/java/org/jabref/gui/ai/components/aichat/chathistory/ChatHistoryComponent.fxml b/src/main/java/org/jabref/gui/ai/components/aichat/chathistory/ChatHistoryComponent.fxml index b204fc467de..20836e0e3bb 100644 --- a/src/main/java/org/jabref/gui/ai/components/aichat/chathistory/ChatHistoryComponent.fxml +++ b/src/main/java/org/jabref/gui/ai/components/aichat/chathistory/ChatHistoryComponent.fxml @@ -1,9 +1,8 @@ - - - + + - - - - - - + + + + + + + + + diff --git a/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.fxml b/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.fxml index b933fc2b7bf..04c53eaab88 100644 --- a/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.fxml +++ b/src/main/java/org/jabref/gui/ai/components/aichat/chatprompt/ChatPromptComponent.fxml @@ -1,11 +1,7 @@ - - - - - - + + rebuildUi()); @@ -33,7 +33,7 @@ public final void rebuildUi() { new PrivacyNoticeComponent( aiPreferences, this::rebuildUi, - filePreferences, + externalApplicationsPreferences, dialogService ) ); diff --git a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml index 6ceb4fdb4ac..2f439beac31 100644 --- a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml +++ b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.fxml @@ -1,10 +1,14 @@ - - - - - + + + + + + + + + diff --git a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java index 724ea24ded7..9681379d60d 100644 --- a/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/privacynotice/PrivacyNoticeComponent.java @@ -9,11 +9,11 @@ import javafx.scene.text.TextFlow; import org.jabref.gui.DialogService; -import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.gui.desktop.os.NativeDesktop; +import org.jabref.gui.frame.ExternalApplicationsPreferences; import org.jabref.logic.ai.AiDefaultPreferences; -import org.jabref.preferences.FilePreferences; -import org.jabref.preferences.ai.AiPreferences; -import org.jabref.preferences.ai.AiProvider; +import org.jabref.logic.ai.AiPreferences; +import org.jabref.model.ai.AiProvider; import com.airhacks.afterburner.views.ViewLoader; import org.slf4j.Logger; @@ -31,13 +31,13 @@ public class PrivacyNoticeComponent extends ScrollPane { private final AiPreferences aiPreferences; private final Runnable onIAgreeButtonClickCallback; private final DialogService dialogService; - private final FilePreferences filePreferences; + private final ExternalApplicationsPreferences externalApplicationsPreferences; - public PrivacyNoticeComponent(AiPreferences aiPreferences, Runnable onIAgreeButtonClickCallback, FilePreferences filePreferences, DialogService dialogService) { + public PrivacyNoticeComponent(AiPreferences aiPreferences, Runnable onIAgreeButtonClickCallback, ExternalApplicationsPreferences externalApplicationsPreferences, DialogService dialogService) { this.aiPreferences = aiPreferences; this.onIAgreeButtonClickCallback = onIAgreeButtonClickCallback; + this.externalApplicationsPreferences = externalApplicationsPreferences; this.dialogService = dialogService; - this.filePreferences = filePreferences; ViewLoader.view(this) .root(this) @@ -102,7 +102,7 @@ private void onDjlPrivacyPolicyClick() { private void openBrowser(String link) { try { - JabRefDesktop.openBrowser(link, filePreferences); + NativeDesktop.openBrowser(link, externalApplicationsPreferences); } catch (IOException e) { LOGGER.error("Error opening the browser to the Privacy Policy page of the AI provider.", e); dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/gui/ai/components/summary/SummaryComponent.java b/src/main/java/org/jabref/gui/ai/components/summary/SummaryComponent.java index 3a164c2739c..ed8e66980e0 100644 --- a/src/main/java/org/jabref/gui/ai/components/summary/SummaryComponent.java +++ b/src/main/java/org/jabref/gui/ai/components/summary/SummaryComponent.java @@ -7,6 +7,8 @@ import org.jabref.gui.DialogService; import org.jabref.gui.ai.components.privacynotice.AiPrivacyNoticeGuardedComponent; import org.jabref.gui.ai.components.util.errorstate.ErrorStateComponent; +import org.jabref.gui.frame.ExternalApplicationsPreferences; +import org.jabref.logic.ai.AiPreferences; import org.jabref.logic.ai.AiService; import org.jabref.logic.ai.processingstatus.ProcessingInfo; import org.jabref.logic.ai.summarization.Summary; @@ -18,8 +20,6 @@ import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; -import org.jabref.preferences.FilePreferences; -import org.jabref.preferences.ai.AiPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,11 +37,11 @@ public SummaryComponent(BibDatabaseContext bibDatabaseContext, BibEntry entry, AiService aiService, AiPreferences aiPreferences, - FilePreferences filePreferences, + ExternalApplicationsPreferences externalApplicationsPreferences, CitationKeyPatternPreferences citationKeyPatternPreferences, DialogService dialogService ) { - super(aiPreferences, filePreferences, dialogService); + super(aiPreferences, externalApplicationsPreferences, dialogService); this.bibDatabaseContext = bibDatabaseContext; this.entry = entry; diff --git a/src/main/java/org/jabref/gui/ai/components/summary/SummaryShowingComponent.fxml b/src/main/java/org/jabref/gui/ai/components/summary/SummaryShowingComponent.fxml index db7698eccf6..f248bccab17 100644 --- a/src/main/java/org/jabref/gui/ai/components/summary/SummaryShowingComponent.fxml +++ b/src/main/java/org/jabref/gui/ai/components/summary/SummaryShowingComponent.fxml @@ -1,10 +1,11 @@ - - - - - + + + + + +