1 /***************************************************************************
2  *   file klfconfig.h
3  *   This file is part of the KLatexFormula Project.
4  *   Copyright (C) 2011 by Philippe Faist
5  *   philippe.faist at bluewin.ch
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 /* $Id: klfconfig.h 969 2016-12-29 07:44:24Z phfaist $ */
23 
24 #ifndef KLFCONFIG_H
25 #define KLFCONFIG_H
26 
27 #include <qglobal.h>
28 #include <QDebug>
29 #include <QString>
30 #include <QFont>
31 #include <QSize>
32 #include <QColor>
33 #include <QSettings>
34 #include <QTextCharFormat>
35 #include <QMap>
36 #include <QHash>
37 #include <QSettings>
38 
39 #include <klfbackend.h>
40 #include <klfutil.h>
41 #include <klfdatautil.h>
42 #include <klfconfigbase.h>
43 
44 
45 template<class T>
46 inline bool klf_config_read_value(QSettings &s, const QString& baseName, T * target,
47 				  const char * listOrMapType  = NULL)
48 {
49   QVariant defVal = QVariant::fromValue<T>(*target);
50   QVariant valstrv = s.value(baseName, QVariant());
51   if (valstrv.isNull()) {
52     klfDbg("No entry "<<baseName<<" in config.") ;
53     return false;
54   }
55   QString valstr = valstrv.toString();
56   QVariant val = klfLoadVariantFromText(valstr.toLatin1(), defVal.typeName(), listOrMapType);
57   if (val.isValid()) {
58     klfDbg("klf_config_read_value: read value for "<<baseName<<" : " << val) ;
59     *target = val.value<T>();
60     return true;
61   }
62   klfDbg("klf_config_read_value: read empty or invalid value for "<<baseName) ;
63   return false;
64 }
65 
66 template<class T>
67 inline void klf_config_read(QSettings &s, const QString& baseName, KLFConfigProp<T> *target,
68 			    const char * listOrMapType = NULL)
69 {
70   T value = *target;
71   if (klf_config_read_value(s, baseName, &value, listOrMapType))
72     *target = value;
73 }
74 template<>
75 inline void klf_config_read<QTextCharFormat>(QSettings &s, const QString& baseName,
76 					     KLFConfigProp<QTextCharFormat> *target,
77 					     const char * /*listOrMapType*/)
78 {
79   qDebug("klf_config_read<QTextCharFormat>(%s)", qPrintable(baseName));
80   QTextFormat fmt = *target;
81   klf_config_read_value(s, baseName, &fmt);
82   *target = fmt.toCharFormat();
83 }
84 
85 template<class T>
klf_config_read_list(QSettings & s,const QString & baseName,KLFConfigProp<QList<T>> * target)86 inline void klf_config_read_list(QSettings &s, const QString& baseName, KLFConfigProp<QList<T> > *target)
87 {
88   QVariantList vlist = klfListToVariantList(target->value());
89   klf_config_read_value(s, baseName, &vlist, QVariant::fromValue<T>(T()).typeName());
90   *target = klfVariantListToList<T>(vlist);
91 }
92 
93 
94 template<class T>
klf_config_write_value(QSettings & s,const QString & baseName,const T * value)95 inline void klf_config_write_value(QSettings &s, const QString& baseName, const T * value)
96 {
97   QVariant val = QVariant::fromValue<T>(*value);
98   QByteArray datastr = klfSaveVariantToText(val);
99   s.setValue(baseName, QVariant::fromValue<QString>(QString::fromLocal8Bit(datastr)));
100 }
101 template<class T>
klf_config_write(QSettings & s,const QString & baseName,const KLFConfigProp<T> * target)102 inline void klf_config_write(QSettings &s, const QString& baseName, const KLFConfigProp<T> * target)
103 {
104   T temp = *target;
105   klf_config_write_value(s, baseName, &temp);
106 }
107 template<>
108 inline void klf_config_write<QTextCharFormat>(QSettings &s, const QString& baseName,
109 					      const KLFConfigProp<QTextCharFormat> * target)
110 {
111   klfDbg("<QTextCharFormat>, baseName="<<baseName) ;
112   QTextFormat f = *target;
113   klf_config_write_value(s, baseName, &f);
114 }
115 template<class T>
klf_config_write_list(QSettings & s,const QString & baseName,const KLFConfigProp<QList<T>> * target)116 inline void klf_config_write_list(QSettings &s, const QString& baseName, const KLFConfigProp<QList<T> > * target)
117 {
118   QVariantList vlist = klfListToVariantList(target->value());
119   klf_config_write_value(s, baseName, &vlist);
120 }
121 
122 
123 
124 class KLFConfig;
125 
126 // /** \brief Utility class for plugins to access their configuration space in KLFConfig
127 //  *
128 //  * KLatexFormula stores its configuration via KLFConfig and the global \c klfconfig object.
129 //  * That structure relies on the config structure being known in advance and the named
130 //  * fields to appear publicly in the KLFConfig class. This scheme is obviously NOT possible
131 //  * for plugins, so a different approach is taken.
132 //  *
133 //  * Plugins are given a pointer to a \c KLFPluginConfigAccess object, which is an interface
134 //  * to access a special part of KLFConfig that stores plugin-related configuration in the
135 //  * form of QVariantMaps. (themselves written in an INI-based config file inside the plugin's
136 //  * local directory, at <tt>~/.klatexformula/plugindata/&lt;plugin>/&lt;plugin>.conf</tt>)
137 //  *
138 //  * KLFConfig transparently takes care of reading the config for plugins at the beginning
139 //  * when launching KLatexFormula and storing the plugin configurations in their respective
140 //  * locations when quitting.
141 //  *
142 //  * Plugins can read values they have set in earlier sessions with readValue(). Default values
143 //  * can be defined with \ref makeDefaultValue().
144 //  *
145 //  * Plugins can write changed settings with \ref writeValue().
146 //  */
147 // class KLF_EXPORT KLFPluginConfigAccess
148 // {
149 //   KLFConfig *_config;
150 //   QString _pluginname;
151 // public:
152 //   KLFPluginConfigAccess();
153 //   KLFPluginConfigAccess(KLFConfig *configObject, const QString& pluginName);
154 //   KLFPluginConfigAccess(const KLFPluginConfigAccess& other);
155 //   virtual ~KLFPluginConfigAccess();
156 
157 //   /** Returns the root directory in which KLatexFormula stores its stuff, usually
158 //    * <tt>~/.klatexformula</tt>.
159 //    */
160 //   virtual QString homeConfigDir() const;
161 
162 //   /** Returns the directory (not necessarily existing) in which installed data that is
163 //    * shared among different users is stored.
164 //    * eg. system-wide installations of plugins/extensions can be placed in:
165 //    * <tt>share-dir/rccresources/<i>*</i>.rcc</tt>.
166 //    */
167 //   virtual QString globalShareDir() const;
168 
169 //   /** Returns a directory in which we can read/write temporary files, eg. "/tmp".
170 //    *
171 //    * This is actually the value of <tt>klfconfig.BackendSettings.tempDir</tt> */
172 //   virtual QString tempDir() const;
173 
174 //   /** Returns a path to a directory in which plugins can manage their data as they want.
175 //    *
176 //    * If the \c createIfNeeded argument is TRUE, then the directory is garanteed to exist,
177 //    * and an empty string is returned if, for whatever reason, the directory can't be
178 //    * created.
179 //    *
180 //    * If the \c createIfNeeded argument is FALSE, then the directory path is returned
181 //    * regardless of whether the directory exists or not.
182 //    *
183 //    * Note that a file named <tt><i>pluginName</i>.conf</tt> is created to store the plugin's
184 //    * settings in that directory (the settings are stored automatically).
185 //    */
186 //   virtual QString homeConfigPluginDataDir(bool createIfNeeded = true) const;
187 
188 //   /** \brief read a value in the config
189 //    *
190 //    * Returns the value of the entry with key \c key. If no such entry exists,
191 //    * it is not created and an invalid QVariant() is returned.
192 //    */
193 //   virtual QVariant readValue(const QString& key) const;
194 
195 //   /** \brief write the value if inexistant in config
196 //    *
197 //    * equivalent to
198 //    * \code
199 //    *  if (readValue(key).isNull())
200 //    *    writeValue(key, defaultValue);
201 //    * \endcode
202 //    *
203 //    * \return the value this key has after this function call, ie. \c defaultValue if no
204 //    *   existing value was found, or the existing value if one already exists. A null QVariant
205 //    *   is returned upon error.
206 //    */
207 //   virtual QVariant makeDefaultValue(const QString& key, const QVariant& defaultValue);
208 
209 //   /** \brief write a value to settings
210 //    *
211 //    * Saves the value of a setting, referenced by \c key, to the given \c value.
212 //    *
213 //    * If \c key hasn't been previously set, creates an entry for \c key with the
214 //    * given \c value.
215 //    */
216 //   virtual void writeValue(const QString& key, const QVariant& value);
217 // };
218 
219 
220 //! Structure that stores klatexformula's configuration in memory
221 /**
222  * This structure is more of a namespace than a class. Access it through the global
223  * object \ref klfconfig.
224  *
225  * See also \ref KLFSettings for a graphical interface for editing these settings.
226  */
227 class KLF_EXPORT KLFConfig : public KLFConfigBase
228 {
229 public:
230 
231   QString homeConfigDir;
232   QString globalShareDir;
233   QString homeConfigSettingsFile; //!< current (now, "new" klatexformula.conf) settings file
234   QString homeConfigSettingsFileIni; //!< OLD config file
235   // QString homeConfigDirRCCResources;
236   // QString homeConfigDirPlugins;
237   // QString homeConfigDirPluginData;
238   QString homeConfigDirI18n;
239   QString homeConfigDirUserScripts;
240 
241   struct {
242 
243     KLFConfigProp<bool> thisVersionMajFirstRun;
244     KLFConfigProp<bool> thisVersionMajMinFirstRun;
245     KLFConfigProp<bool> thisVersionMajMinRelFirstRun;
246     KLFConfigProp<bool> thisVersionExactFirstRun;
247 
248     /** The library file name, relative to homeConfigDir. */
249     KLFConfigProp<QString> libraryFileName;
250     /** The lib scheme to use to store the library. This scheme will be given the full path
251      * to the library in the URL path part. */
252     KLFConfigProp<QString> libraryLibScheme;
253 
254   } Core;
255 
256   struct {
257 
258     KLFConfigProp<QString> locale; //!< When setting this, don't forget to call QLocale::setDefault().
259     KLFConfigProp<bool> useSystemAppFont;
260     KLFConfigProp<QFont> applicationFont;
261     KLFConfigProp<QFont> latexEditFont;
262     KLFConfigProp<QFont> preambleEditFont;
263     KLFConfigProp<bool> editorTabInsertsTab;
264     KLFConfigProp<bool> editorWrapLines;
265     KLFConfigProp<QSize> previewTooltipMaxSize;
266     KLFConfigProp<QSize> labelOutputFixedSize; //!< No Longer used (3.3.0alpha)
267     KLFConfigProp<QSize> smallPreviewSize; //!< Size of preview to store e.g. in history/library items
268     //    KLFConfigProp<QSize> savedWindowSize;
269     KLFConfigProp<QString> detailsSideWidgetType; //!< "ShowHide","Drawer", or "Float" (or any custom type!)
270     KLFConfigProp<QString> lastSaveDir;
271     KLFConfigProp<int> symbolsPerLine;
272     KLFConfigProp<bool> symbolIncludeWithPreambleDefs;
273     KLFConfigProp<QList<QColor> > userColorList;
274     KLFConfigProp<QList<QColor> > colorChooseWidgetRecent;
275     KLFConfigProp<QList<QColor> > colorChooseWidgetCustom;
276     KLFConfigProp<int> maxUserColors;
277     KLFConfigProp<bool> enableToolTipPreview;
278     KLFConfigProp<bool> enableRealTimePreview;
279     KLFConfigProp<bool> realTimePreviewExceptBattery;
280     KLFConfigProp<int> autosaveLibraryMin;
281     KLFConfigProp<bool> showHintPopups;
282     KLFConfigProp<bool> clearLatexOnly;
283     KLFConfigProp<bool> glowEffect;
284     KLFConfigProp<QColor> glowEffectColor;
285     KLFConfigProp<int> glowEffectRadius;
286     KLFConfigProp<QStringList> customMathModes;
287     KLFConfigProp<bool> emacsStyleBackspaceSearch;
288     KLFConfigProp<bool> macBrushedMetalLook;
289 
290   } UI;
291 
292   struct {
293 
294     KLFConfigProp<QString> copyExportProfile;
295     KLFConfigProp<QString> dragExportProfile;
296     KLFConfigProp<bool> showExportProfilesLabel;
297     KLFConfigProp<bool> menuExportProfileAffectsDrag;
298     KLFConfigProp<bool> menuExportProfileAffectsCopy;
299     KLFConfigProp<double> oooExportScale;
300     KLFConfigProp<int> htmlExportDpi;
301     KLFConfigProp<int> htmlExportDisplayDpi;
302 
303   } ExportData;
304 
305   struct {
306 
307     KLFConfigProp<bool> enabled;
308     KLFConfigProp<bool> highlightParensOnly;
309     KLFConfigProp<bool> highlightLonelyParens;
310     //KLFConfigProp<bool> matchParenTypes;
311     KLFConfigProp<QTextCharFormat> fmtKeyword;
312     KLFConfigProp<QTextCharFormat> fmtComment;
313     KLFConfigProp<QTextCharFormat> fmtParenMatch;
314     KLFConfigProp<QTextCharFormat> fmtParenMismatch;
315     KLFConfigProp<QTextCharFormat> fmtLonelyParen;
316 
317   } SyntaxHighlighter;
318 
319   struct {
320 
321     KLFConfigProp<QString> tempDir;
322     KLFConfigProp<QString> execLatex;
323     KLFConfigProp<QString> execDvips;
324     KLFConfigProp<QString> execGs;
325     KLFConfigProp<QString> execEpstopdf;
326     KLFConfigProp<QStringList> execenv;
327     KLFConfigProp<QString> setTexInputs;
328     KLFConfigProp<double> lborderoffset;
329     KLFConfigProp<double> tborderoffset;
330     KLFConfigProp<double> rborderoffset;
331     KLFConfigProp<double> bborderoffset;
332     KLFConfigProp<bool> calcEpsBoundingBox;
333     KLFConfigProp<bool> outlineFonts;
334     KLFConfigProp<bool> wantPDF;
335     KLFConfigProp<bool> wantSVG;
336     KLFConfigProp<QStringList> userScriptAddPath;
337     KLFConfigProp<QVariantMap> userScriptInterpreters;
338 
339   } BackendSettings;
340 
341   struct {
342 
343     KLFConfigProp<QColor> colorFound;
344     KLFConfigProp<QColor> colorNotFound;
345 
346     KLFConfigProp<bool> restoreURLs;
347     KLFConfigProp<bool> confirmClose;
348     KLFConfigProp<bool> groupSubCategories;
349     KLFConfigProp<int> iconViewFlow;
350     KLFConfigProp<bool> historyTagCopyToArchive;
351     KLFConfigProp<QString> lastFileDialogPath;
352 
353     KLFConfigProp<int> treePreviewSizePercent;
354     KLFConfigProp<int> listPreviewSizePercent;
355     KLFConfigProp<int> iconPreviewSizePercent;
356 
357   } LibraryBrowser;
358 
359   // struct {
360 
361   //   QMap<QString, QMap<QString, QVariant> > pluginConfig;
362 
363   // } Plugins;
364 
365   struct {
366 
367     QMap<QString, QMap<QString, QVariant> > userScriptConfig;
368 
369   } UserScripts;
370 
371   /** Not a saved setting. This is set in loadDefaults() */
372   QFont defaultCMUFont;
373   /** Not a saved setting. This is set in loadDefaults() */
374   QFont defaultStdFont;
375   /** Not a saved setting. This is set in loadDefaults() */
376   QFont defaultTTFont;
377 
378   //  KLFPluginConfigAccess getPluginConfigAccess(const QString& name);
379 
380   /** call loadDefaults() before anything, at the beginning, to ensure that the values
381    * in this structure are not undefined. (the constructor doesn't set any values).
382    *
383    * loadDefaults() will set reasonable default values for most settings, but will not
384    * start detecting system settings, specifically look for system executables, possibly other
385    * long detection tasks. To perform that, call detectMissingSettings().
386    *
387    * In practice, main() calls, in order, loadDefaults(), readFromConfig(), and
388    * detectMissingSettings().
389    * */
390   void loadDefaults();
391   int readFromConfig();
392   void detectMissingSettings();
393 
394   int ensureHomeConfigDir();
395 
396   int writeToConfig();
397 
398 
399   /** returns TRUE if the executable paths are valid. */
400   bool checkExePaths();
401 
402 private:
403   int readFromConfig_v2(const QString& fname);
404   int readFromConfig_v1();
405 
406 };
407 
408 
409 
410 
411 KLF_EXPORT extern KLFConfig klfconfig;
412 
413 
414 
415 
416 #define KLF_CONNECT_CONFIG_SH_LATEXEDIT(latexedit)				\
417   klfconfig.SyntaxHighlighter.enabled					\
418   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "highlightEnabled") ; \
419   klfconfig.SyntaxHighlighter.highlightParensOnly			\
420   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "highlightParensOnly") ; \
421   klfconfig.SyntaxHighlighter.highlightLonelyParens			\
422   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "highlightLonelyParens") ; \
423   klfconfig.SyntaxHighlighter.fmtKeyword				\
424   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "fmtKeyword") ; \
425   klfconfig.SyntaxHighlighter.fmtComment				\
426   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "fmtComment") ; \
427   klfconfig.SyntaxHighlighter.fmtParenMatch				\
428   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "fmtParenMatch") ; \
429   klfconfig.SyntaxHighlighter.fmtParenMismatch				\
430   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "fmtParenMismatch") ; \
431   klfconfig.SyntaxHighlighter.fmtLonelyParen				\
432   .connectQObjectProperty((latexedit)->syntaxHighlighter(), "fmtLonelyParen") ;
433 
434 
435 
436 
437 #endif
438