2
* \brief Static class where all preferences handling happens.
5
* Ralf Stephan <ralf@ark.in-berlin.de>
7
* Copyright (C) 2005 Authors
2
* @brief Singleton class to access the preferences file in a convenient way.
5
* Krzysztof Kosi_ski <tweenk.pl@gmail.com>
6
* Jon A. Cruz <jon@joncruz.org>
8
* Copyright (C) 2008,2009 Authors
9
10
* Released under GNU GPL. Read the file 'COPYING' for more information.
12
#ifndef INKSCAPE_PREFERENCES_H
13
#define INKSCAPE_PREFERENCES_H
13
#ifndef INKSCAPE_PREFSTORE_H
14
#define INKSCAPE_PREFSTORE_H
21
#include <glibmm/ustring.h>
22
#include "xml/xml-forward.h"
15
27
namespace Inkscape {
23
static XML::Document *get();
26
static void loadSkeleton();
31
virtual ~ErrorReporter() {}
32
virtual void handleError(Glib::ustring const& primary, Glib::ustring const& secondary ) const = 0;
36
* @brief Preference storage class.
38
* This is a singleton that allows one to access the user preferences stored in
39
* the preferences.xml file. The preferences are stored in a file system-like
40
* hierarchy. They are generally typeless - it's up to the programmer to ensure
41
* that a given preference is always accessed as the correct type. The backend
42
* is not guaranteed to be tolerant to type mismatches.
44
* Preferences are identified by paths similar to file system paths. Components
45
* of the path are separated by a slash (/). As an additional requirement,
46
* the path must start with a slash, and not contain a trailing slash.
47
* An example of a correct path would be "/options/some_group/some_option".
49
* All preferences are loaded when the first singleton pointer is requested.
50
* To save the preferences, the method save() or the static function unload()
53
* In future, this will be a virtual base from which specific backends
54
* derive (e.g. GConf, flat XML file...)
58
// #############################
59
// ## inner class definitions ##
60
// #############################
66
* @brief Base class for preference observers
68
* If you want to watch for changes in the preferences, you'll have to
69
* derive a class from this one and override the notify() method.
72
friend class Preferences;
78
* Since each Observer is assigned to a single path, the base
79
* constructor takes this path as an argument. This prevents one from
80
* adding a single observer to multiple paths, but this is intentional
81
* to simplify the implementation of observers and notifications.
83
* After you add the object with Preferences::addObserver(), you will
84
* receive notifications for everything below the attachment point.
85
* You can also specify a single preference as the watch point.
86
* For example, watching the directory "/foo" will give you notifications
87
* about "/foo/some_pref" as well as "/foo/some_dir/other_pref".
88
* Watching the preference "/options/some_group/some_option" will only
89
* generate notifications when this single preference changes.
91
* @param path Preference path the observer should watch
93
Observer(Glib::ustring const &path);
97
* @brief Notification about a preference change
98
* @param new_val Entry object containing information about
99
* the modified preference
101
virtual void notify(Preferences::Entry const &new_val) = 0;
103
Glib::ustring const observed_path; ///< Path which the observer watches
105
void *_data; ///< additional data used by the implementation while the observer is active
110
* @brief Data type representing a typeless value of a preference
112
* This is passed to the observer in the notify() method.
113
* To retrieve useful data from it, use its member functions. Setting
114
* any preference using the Preferences class invalidates this object,
115
* so use its get methods before doing so.
118
friend class Preferences; // Preferences class has to access _value
121
Entry() : _pref_path(""), _value(NULL) {} // needed to enable use in maps
122
Entry(Entry const &other) : _pref_path(other._pref_path), _value(other._value) {}
125
* @brief Check whether the received entry is valid.
126
* @return If false, the default value will be returned by the getters.
128
bool isValid() const { return _value != NULL; }
131
* @brief Interpret the preference as a Boolean value.
132
* @param def Default value if the preference is not set
134
inline bool getBool(bool def=false) const;
137
* @brief Interpret the preference as an integer.
138
* @param def Default value if the preference is not set
140
inline int getInt(int def=0) const;
143
* @brief Interpret the preference as a limited integer.
145
* This method will return the default value if the interpreted value is
146
* larger than @c max or smaller than @c min. Do not use to store
147
* Boolean values as integers.
149
* @param def Default value if the preference is not set
150
* @param min Minimum value allowed to return
151
* @param max Maximum value allowed to return
153
inline int getIntLimited(int def=0, int min=INT_MIN, int max=INT_MAX) const;
156
* @brief Interpret the preference as a floating point value.
157
* @param def Default value if the preference is not set
159
inline double getDouble(double def=0.0) const;
162
* @brief Interpret the preference as a limited floating point value.
164
* This method will return the default value if the interpreted value is
165
* larger than @c max or smaller than @c min.
167
* @param def Default value if the preference is not set
168
* @param min Minimum value allowed to return
169
* @param max Maximum value allowed to return
171
inline double getDoubleLimited(double def=0.0, double min=DBL_MIN, double max=DBL_MAX) const;
174
* @brief Interpret the preference as an UTF-8 string.
176
* To store a filename, convert it using Glib::filename_to_utf8().
178
inline Glib::ustring getString() const;
181
* @brief Interpret the preference as a CSS style.
182
* @return A CSS style that has to be unrefed when no longer necessary. Never NULL.
184
inline SPCSSAttr *getStyle() const;
187
* @brief Interpret the preference as a CSS style with directory-based
190
* This function will look up the preferences with the same entry name
191
* in ancestor directories and return the inherited CSS style.
193
* @return Inherited CSS style that has to be unrefed after use. Never NULL.
195
inline SPCSSAttr *getInheritedStyle() const;
198
* @brief Get the full path of the preference described by this Entry.
200
Glib::ustring const &getPath() const { return _pref_path; }
203
* @brief Get the last component of the preference's path
205
* E.g. For "/options/some_group/some_option" it will return "some_option".
207
Glib::ustring getEntryName() const;
209
Entry(Glib::ustring const &path, void const *v) : _pref_path(path), _value(v) {}
211
Glib::ustring _pref_path;
218
* @brief Save all preferences to the hard disk.
220
* For some backends, the preferences may be saved as they are modified.
221
* Not calling this method doesn't guarantee the preferences are unmodified
222
* the next time Inkscape runs.
227
* @brief Check whether saving the preferences will have any effect.
229
bool isWritable() { return _writable; }
233
* @brief Return details of the last encountered error, if any.
235
* This method will return true if an error has been encountered, and fill
236
* in the primary and secondary error strings of the last error. If an error
237
* had been encountered, this will reset it.
239
* @param string to set to the primary error message.
240
* @param string to set to the secondary error message.
242
* @return True if an error has occurred since last checking, false otherwise.
244
bool getLastError( Glib::ustring& primary, Glib::ustring& secondary );
247
* @name Iterate over directories and entries.
252
* @brief Get all entries from the specified directory
254
* This method will return a vector populated with preference entries
255
* from the specified directory. Subdirectories will not be represented.
257
std::vector<Entry> getAllEntries(Glib::ustring const &path);
260
* @brief Get all subdirectories of the specified directory
262
* This will return a vector populated with full paths to the subdirectories
263
* present in the specified @c path.
265
std::vector<Glib::ustring> getAllDirs(Glib::ustring const &path);
269
* @name Retrieve data from the preference storage.
274
* @brief Retrieve a Boolean value
275
* @param pref_path Path to the retrieved preference
276
* @param def The default value to return if the preference is not set
278
bool getBool(Glib::ustring const &pref_path, bool def=false) {
279
return getEntry(pref_path).getBool(def);
283
* @brief Retrieve an integer
284
* @param pref_path Path to the retrieved preference
285
* @param def The default value to return if the preference is not set
287
int getInt(Glib::ustring const &pref_path, int def=0) {
288
return getEntry(pref_path).getInt(def);
292
* @brief Retrieve a limited integer
294
* The default value is returned if the actual value is larger than @c max
295
* or smaller than @c min. Do not use to store Boolean values.
297
* @param pref_path Path to the retrieved preference
298
* @param def The default value to return if the preference is not set
299
* @param min Minimum value to return
300
* @param max Maximum value to return
302
int getIntLimited(Glib::ustring const &pref_path, int def=0, int min=INT_MIN, int max=INT_MAX) {
303
return getEntry(pref_path).getIntLimited(def, min, max);
305
double getDouble(Glib::ustring const &pref_path, double def=0.0) {
306
return getEntry(pref_path).getDouble(def);
310
* @brief Retrieve a limited floating point value
312
* The default value is returned if the actual value is larger than @c max
313
* or smaller than @c min.
315
* @param pref_path Path to the retrieved preference
316
* @param def The default value to return if the preference is not set
317
* @param min Minimum value to return
318
* @param max Maximum value to return
320
double getDoubleLimited(Glib::ustring const &pref_path, double def=0.0, double min=DBL_MIN, double max=DBL_MAX) {
321
return getEntry(pref_path).getDoubleLimited(def, min, max);
325
* @brief Retrieve an UTF-8 string
326
* @param pref_path Path to the retrieved preference
328
Glib::ustring getString(Glib::ustring const &pref_path) {
329
return getEntry(pref_path).getString();
333
* @brief Retrieve a CSS style
334
* @param pref_path Path to the retrieved preference
335
* @return A CSS style that has to be unrefed after use.
337
SPCSSAttr *getStyle(Glib::ustring const &pref_path) {
338
return getEntry(pref_path).getStyle();
342
* @brief Retrieve an inherited CSS style
344
* This method will look up preferences with the same entry name in ancestor
345
* directories and return a style obtained by inheriting properties from
348
* @param pref_path Path to the retrieved preference
349
* @return An inherited CSS style that has to be unrefed after use.
351
SPCSSAttr *getInheritedStyle(Glib::ustring const &pref_path) {
352
return getEntry(pref_path).getInheritedStyle();
356
* @brief Retrieve a preference entry without specifying its type
358
Entry const getEntry(Glib::ustring const &pref_path);
362
* @name Update preference values.
367
* @brief Set a Boolean value
369
void setBool(Glib::ustring const &pref_path, bool value);
372
* @brief Set an integer value
374
void setInt(Glib::ustring const &pref_path, int value);
377
* @brief Set a floating point value
379
void setDouble(Glib::ustring const &pref_path, double value);
382
* @brief Set an UTF-8 string value
384
void setString(Glib::ustring const &pref_path, Glib::ustring const &value);
387
* @brief Set a CSS style
389
void setStyle(Glib::ustring const &pref_path, SPCSSAttr *style);
392
* @brief Merge a CSS style with the current preference value
394
* This method is similar to setStyle(), except that it merges the style
395
* rather than replacing it. This means that if @c style doesn't have
396
* a property set, it is left unchanged in the style stored in
399
void mergeStyle(Glib::ustring const &pref_path, SPCSSAttr *style);
403
* @name Receive notifications about preference changes.
408
* @brief Register a preference observer
410
void addObserver(Observer &);
413
* @brief Remove an observer an prevent further notifications to it.
415
void removeObserver(Observer &);
419
* @name Access and manipulate the Preferences object.
424
* @brief Access the singleton Preferences object.
426
static Preferences *get() {
428
_instance = new Preferences();
433
void setErrorHandler(ErrorReporter* handler);
436
* @brief Unload all preferences
437
* @param save Whether to save the preferences; defaults to true
439
* This deletes the singleton object. Calling get() after this function
440
* will reinstate it, so you shouldn't. Pass false as the parameter
441
* to suppress automatic saving.
443
static void unload(bool save=true);
447
/* helper methods used by Entry
448
* This will enable using the same Entry class with different backends.
449
* For now, however, those methods are not virtual. These methods assume
450
* that v._value is not NULL
452
bool _extractBool(Entry const &v);
453
int _extractInt(Entry const &v);
454
double _extractDouble(Entry const &v);
455
Glib::ustring _extractString(Entry const &v);
456
SPCSSAttr *_extractStyle(Entry const &v);
457
SPCSSAttr *_extractInheritedStyle(Entry const &v);
462
void _loadDefaults();
464
void _getRawValue(Glib::ustring const &path, gchar const *&result);
465
void _setRawValue(Glib::ustring const &path, gchar const *value);
466
void _reportError(Glib::ustring const &, Glib::ustring const &);
467
void _keySplit(Glib::ustring const &pref_path, Glib::ustring &node_key, Glib::ustring &attr_key);
468
XML::Node *_getNode(Glib::ustring const &pref_path, bool create=false);
469
XML::Node *_findObserverNode(Glib::ustring const &pref_path, Glib::ustring &node_key, Glib::ustring &attr_key, bool create);
472
Preferences(Preferences const &);
473
Preferences operator=(Preferences const &);
475
std::string _prefs_basename; ///< Basename of the prefs file
476
std::string _prefs_dir; ///< Directory in which to look for the prefs file
477
std::string _prefs_filename; ///< Full filename (with directory) of the prefs file
478
Glib::ustring _lastErrPrimary; ///< Last primary error message, if any.
479
Glib::ustring _lastErrSecondary; ///< Last secondary error message, if any.
480
XML::Document *_prefs_doc; ///< XML document storing all the preferences
481
ErrorReporter* _errorHandler; ///< Pointer to object reporting errors.
482
bool _writable; ///< Will the preferences be saved at exit?
483
bool _hasError; ///< Indication that some error has occurred;
485
/// Wrapper class for XML node observers
486
class PrefNodeObserver;
488
typedef std::map<Observer *, PrefNodeObserver *> _ObsMap;
489
/// Map that keeps track of wrappers assigned to PrefObservers
490
_ObsMap _observer_map;
492
// privilege escalation methods for PrefNodeObserver
493
static Entry const _create_pref_value(Glib::ustring const &, void const *ptr);
494
static void *_get_pref_observer_data(Observer &o) { return o._data; }
496
static Preferences *_instance;
498
friend class PrefNodeObserver;
502
/* Trivial inline Preferences::Entry functions.
503
* In fact only the _extract* methods do something, the rest is delegation
504
* to avoid duplication of code. There should be no performance hit if
505
* compiled with -finline-functions.
508
inline bool Preferences::Entry::getBool(bool def) const
510
if (!this->isValid()) {
513
return Inkscape::Preferences::get()->_extractBool(*this);
517
inline int Preferences::Entry::getInt(int def) const
519
if (!this->isValid()) {
522
return Inkscape::Preferences::get()->_extractInt(*this);
526
inline int Preferences::Entry::getIntLimited(int def, int min, int max) const
528
if (!this->isValid()) {
531
int val = Inkscape::Preferences::get()->_extractInt(*this);
532
return ( val >= min && val <= max ? val : def );
536
inline double Preferences::Entry::getDouble(double def) const
538
if (!this->isValid()) {
541
return Inkscape::Preferences::get()->_extractDouble(*this);
545
inline double Preferences::Entry::getDoubleLimited(double def, double min, double max) const
547
if (!this->isValid()) {
550
double val = Inkscape::Preferences::get()->_extractDouble(*this);
551
return ( val >= min && val <= max ? val : def );
555
inline Glib::ustring Preferences::Entry::getString() const
557
if (!this->isValid()) {
560
return Inkscape::Preferences::get()->_extractString(*this);
564
inline SPCSSAttr *Preferences::Entry::getStyle() const
566
if (!this->isValid()) {
567
return sp_repr_css_attr_new();
569
return Inkscape::Preferences::get()->_extractStyle(*this);
573
inline SPCSSAttr *Preferences::Entry::getInheritedStyle() const
575
if (!this->isValid()) {
576
return sp_repr_css_attr_new();
578
return Inkscape::Preferences::get()->_extractInheritedStyle(*this);
582
inline Glib::ustring Preferences::Entry::getEntryName() const
584
Glib::ustring path_base = _pref_path;
585
path_base.erase(0, path_base.rfind('/') + 1);
31
589
} // namespace Inkscape
33
#endif // INKSCAPE_PREFERENCES_H
591
#endif // INKSCAPE_PREFSTORE_H
38
596
c-file-style:"stroustrup"
39
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
597
c-file-offsets:((innamespace . 0)(inline-open . 0))
40
598
indent-tabs-mode:nil
44
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
602
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :