1 /***************************************************************************
2  *   Copyright (C) 2004-2019 by Thomas Fischer <fischer@unix-ag.uni-kl.de> *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
bench_streaming_small(b: &mut Bencher)11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, see <https://www.gnu.org/licenses/>. *
16  ***************************************************************************/
17 
18 #include "preferences.h"
19 
20 #include <QDebug>
21 
22 #ifdef HAVE_KF5
23 #include <KLocalizedString>
24 #include <KSharedConfig>
25 #include <KConfigWatcher>
26 #include <KConfigGroup>
27 #else // HAVE_KF5
28 #define I18N_NOOP(text) QObject::tr(text)
29 #define i18n(text) QObject::tr(text)
30 #endif // HAVE_KF5
31 
32 #ifdef HAVE_KF5
33 #include "notificationhub.h"
34 #endif // HAVE_KF5
35 
36 const QString Preferences::groupColor = QStringLiteral("Color Labels");
37 const QString Preferences::keyColorCodes = QStringLiteral("colorCodes");
38 const QStringList Preferences::defaultColorCodes {QStringLiteral("#cc3300"), QStringLiteral("#0033ff"), QStringLiteral("#009966"), QStringLiteral("#f0d000")};
39 const QString Preferences::keyColorLabels = QStringLiteral("colorLabels");
40 // FIXME
41 // clazy warns: QString(const char*) being called [-Wclazy-qstring-uneeded-heap-allocations]
42 // ... but using QStringLiteral may break the translation process?
43 const QStringList Preferences::defaultColorLabels {I18N_NOOP("Important"), I18N_NOOP("Unread"), I18N_NOOP("Read"), I18N_NOOP("Watch")};
44 
45 const QString Preferences::groupGeneral = QStringLiteral("General");
bench_decode_hex_escape(b: &mut Bencher)46 const QString Preferences::keyBackupScope = QStringLiteral("backupScope");
47 const Preferences::BackupScope Preferences::defaultBackupScope = LocalOnly;
48 const QString Preferences::keyNumberOfBackups = QStringLiteral("numberOfBackups");
49 const int Preferences::defaultNumberOfBackups = 5;
50 
51 const QString Preferences::groupUserInterface = QStringLiteral("User Interface");
52 const QString Preferences::keyElementDoubleClickAction = QStringLiteral("elementDoubleClickAction");
53 const Preferences::ElementDoubleClickAction Preferences::defaultElementDoubleClickAction = ActionOpenEditor;
54 
55 const QString Preferences::keyEncoding = QStringLiteral("encoding");
56 const QString Preferences::defaultEncoding = QStringLiteral("LaTeX");
big_json() -> string::String57 const QString Preferences::keyStringDelimiter = QStringLiteral("stringDelimiter");
58 const QString Preferences::defaultStringDelimiter = QStringLiteral("{}");
59 const QString Preferences::keyQuoteComment = QStringLiteral("quoteComment");
60 const Preferences::QuoteComment Preferences::defaultQuoteComment = qcNone;
61 const QString Preferences::keyKeywordCasing = QStringLiteral("keywordCasing");
62 const KBibTeX::Casing Preferences::defaultKeywordCasing = KBibTeX::cLowerCase;
63 const QString Preferences::keyProtectCasing = QStringLiteral("protectCasing");
64 const Qt::CheckState Preferences::defaultProtectCasing = Qt::PartiallyChecked;
65 const QString Preferences::keyListSeparator = QStringLiteral("ListSeparator");
66 const QString Preferences::defaultListSeparator = QStringLiteral("; ");
67 
bench_streaming_large(b: &mut Bencher)68 const Preferences::BibliographySystem Preferences::defaultBibliographySystem = Preferences::BibTeX;
69 
70 /**
71  * Preferences for Data objects
72  */
73 const QString Preferences::keyPersonNameFormatting = QStringLiteral("personNameFormatting");
74 const QString Preferences::personNameFormatLastFirst = QStringLiteral("<%l><, %s><, %f>");
75 const QString Preferences::personNameFormatFirstLast = QStringLiteral("<%f ><%l>< %s>");
76 const QString Preferences::defaultPersonNameFormatting = personNameFormatLastFirst;
77 
78 class Preferences::Private
79 {
80 private:
bench_large(b: &mut Bencher)81     Preferences *parent;
82 
83 public:
84 #ifdef HAVE_KF5
85     KSharedConfigPtr config;
86     KConfigWatcher::Ptr watcher;
87 #endif // HAVE_KF5
88 
89     static const QString keyBibliographySystem;
90 #ifdef HAVE_KF5
91     bool bibliographySystemDirtyFlag;
92     Preferences::BibliographySystem bibliographySystemCached;
93 #endif // HAVE_KF5
94 
95     Private(Preferences *_parent)
96             : parent(_parent)
97     {
98 #ifdef HAVE_KF5
99         config = KSharedConfig::openConfig(QStringLiteral("kbibtexrc"));
100         watcher = KConfigWatcher::create(config);
101         bibliographySystemDirtyFlag = true;
102         bibliographySystemCached = defaultBibliographySystem;
103 #endif // HAVE_KF5
104     }
105 };
106 
107 const QString Preferences::Private::keyBibliographySystem = QStringLiteral("BibliographySystem");
108 
109 Preferences &Preferences::instance()
110 {
111     static Preferences singleton;
112     return singleton;
113 }
114 
115 Preferences::Preferences()
116         : d(new Preferences::Private(this))
117 {
118 #ifdef HAVE_KF5
119     QObject::connect(d->watcher.data(), &KConfigWatcher::configChanged, [this](const KConfigGroup & group, const QByteArrayList & names) {
120         QSet<int> eventsToPublish;
121         if (group.name() == QStringLiteral("General")) {
122             if (names.contains(Preferences::Private::keyBibliographySystem.toLatin1())) {
123                 qDebug() << "Bibliography system got changed by another Preferences instance";
124                 d->bibliographySystemDirtyFlag = true;
125                 eventsToPublish.insert(NotificationHub::EventBibliographySystemChanged);
126             }
127         }
128 
129         for (const int eventId : eventsToPublish)
130             NotificationHub::publishEvent(eventId);
131     });
132 
133 #endif // HAVE_KF5
134 }
135 
136 Preferences::~Preferences()
137 {
138     delete d;
139 }
140 
141 Preferences::BibliographySystem Preferences::bibliographySystem()
142 {
143 #ifdef HAVE_KF5
144     if (d->bibliographySystemDirtyFlag) {
145         d->config->reparseConfiguration();
146         static const KConfigGroup configGroup(d->config, QStringLiteral("General"));
147         const int index = configGroup.readEntry(Preferences::Private::keyBibliographySystem, static_cast<int>(defaultBibliographySystem));
148         if (index != static_cast<int>(Preferences::BibTeX) && index != static_cast<int>(Preferences::BibLaTeX)) {
149             qWarning() << "Configuration file setting for Bibliography System has an invalid value, using default as fallback";
150             setBibliographySystem(defaultBibliographySystem);
151             d->bibliographySystemCached = defaultBibliographySystem;
152         } else
153             d->bibliographySystemCached = static_cast<Preferences::BibliographySystem>(index);
154         d->bibliographySystemDirtyFlag = false;
155     }
156     return d->bibliographySystemCached;
157 #else // HAVE_KF5
158     return defaultBibliographySystem;
159 #endif // HAVE_KF5
160 }
161 
162 bool Preferences::setBibliographySystem(const Preferences::BibliographySystem bibliographySystem)
163 {
164 #ifdef HAVE_KF5
165     d->bibliographySystemDirtyFlag = false;
166     d->bibliographySystemCached = bibliographySystem;
167     static KConfigGroup configGroup(d->config, QStringLiteral("General"));
168     const int prevIndex = configGroup.readEntry(Preferences::Private::keyBibliographySystem, static_cast<int>(defaultBibliographySystem));
169     const int newIndex = static_cast<int>(bibliographySystem);
170     if (prevIndex == newIndex) return false; /// If old and new bibliography system are the same, return 'false' directly
171     configGroup.writeEntry(Preferences::Private::keyBibliographySystem, newIndex, KConfig::Notify /** to catch changes via KConfigWatcher */);
172     d->config->sync();
173     NotificationHub::publishEvent(NotificationHub::EventBibliographySystemChanged);
174 #else // HAVE_KF5
175     Q_UNUSED(bibliographySystem);
176 #endif // HAVE_KF5
177     return true;
178 }
179 
180 const QMap<Preferences::BibliographySystem, QString> Preferences::availableBibliographySystems()
181 {
182     static const QMap<Preferences::BibliographySystem, QString> result {{Preferences::BibTeX, i18n("BibTeX")}, {Preferences::BibLaTeX, i18n("BibLaTeX")}};
183     return result;
184 }
185