root/trunk/src/Config.cxx

Revision 267, 13.1 kB (checked in by jordi, 19 months ago)

Added two patches that fixed some memory leaks, thanks to Tilman Sauerbeck for them.

Line 
1// ePDFView - A lightweight PDF Viewer.
2// Copyright (C) 2006 Emma's Software.
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
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, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18#include <config.h>
19#include <glib/gstdio.h>
20#include "epdfview.h"
21
22using namespace ePDFView;
23
24// Constants
25static const gchar *DEFAULT_EXTERNAL_BROWSER_COMMAND_LINE = "firefox %s";
26static const gchar *DEFAULT_OPEN_FILE_FOLDER = NULL;
27static const gchar *DEFAULT_SAVE_FILE_FOLDER = NULL;
28static const gboolean DEFAULT_SHOW_STATUSBAR = TRUE;
29static const gboolean DEFAULT_SHOW_TOOLBAR = TRUE;
30static const gint DEFAULT_WINDOW_HEIGHT = 650;
31static const gint DEFAULT_WINDOW_WIDTH = 600;
32static const gint DEFAULT_WINDOW_X = 0;
33static const gint DEFAULT_WINDOW_Y = 0;
34static const gboolean DEFAULT_ZOOM_TO_FIT = FALSE;
35static const gboolean DEFAULT_ZOOM_TO_WIDTH = FALSE;
36
37// Static member attributes.
38Config *Config::m_Config = NULL;
39gboolean Config::m_LoadFile = TRUE;
40
41// Forward declarations.
42gchar *getConfigFileName (void);
43
44///
45/// @brief Constructs a new Config object.
46///
47/// It creates and load from a file the configuration, unless the
48/// Config::loadFile() was called with FALSE.
49///
50Config::Config ()
51{
52    m_Values = g_key_file_new ();
53    if ( m_LoadFile )
54    {
55        gchar *configFile = getConfigFileName ();
56        GError *error = NULL;
57        if ( !g_key_file_load_from_file (m_Values, configFile,
58                                         G_KEY_FILE_NONE, &error ) )
59        {
60            g_warning ("Couldn't load config file '%s': %s\n", configFile,
61                       error->message);
62            g_error_free (error);
63        }
64        g_free (configFile);
65    }
66}
67
68///
69/// @brief Destroys all dynamically allocated memory for Config.
70///
71Config::~Config ()
72{
73    g_key_file_free (m_Values);
74}
75
76///
77/// @brief Destroys the configuration object.
78///
79/// This function is mainly used by the test suite to delete the
80/// singleton config object between test cases.
81///
82void
83Config::destroy ()
84{
85    delete m_Config;
86    m_Config = NULL;
87}
88
89///
90/// @brief Gets the configuration object.
91///
92/// This is the main "entry point" for the configuration. All classes that
93/// want to get configuration must call this function to retrieve the
94/// configuration object. The first time this function is called creates
95/// the object.
96///
97/// @return The reference to the configuration object.
98///
99Config &
100Config::getConfig ()
101{
102    if ( NULL == m_Config )
103    {
104        m_Config = new Config;
105    }
106
107    g_assert (NULL != m_Config && "The configuration is NULL.");
108    return *m_Config;
109}
110
111///
112/// @brief Gets a boolean configuration option.
113///
114/// @param group Configuration group where the key belongs.
115/// @param key The key name to retrieve its value.
116/// @param defaultValue The default value to return if @a key doesn't exists.
117///
118/// @return The value of the @a key in @a group or @a defaultValue if @a key
119///         doesn't exists.
120///
121gboolean
122Config::getBoolean (const gchar *group, const gchar *key, gboolean defaultValue)
123{
124    gboolean value = defaultValue;
125
126    if ( g_key_file_has_key (m_Values, group, key, NULL) )
127    {
128        GError *error = NULL;
129        gboolean savedValue =
130            g_key_file_get_boolean (m_Values, group, key, &error);
131        if ( NULL == error )
132        {
133            value = savedValue;
134        }
135        else
136        {
137            g_warning ("Error reading key '%s' from group '%s': %s\n",
138                       key, group, error->message);
139            g_error_free (error);
140        }
141    }
142
143    return value;
144}
145
146///
147/// @brief Gets the command line to use to execute the external browser.
148///
149/// The external browser is used, for example, when the user clicks on
150/// an external hyperlink in the document. The command line to execute
151/// is given by this function and it should contains a %s in the place
152/// where the URL should go.
153///
154/// @return The command line to use to execute the external browser. The
155///         user must free this pointer.
156///
157gchar *
158Config::getExternalBrowserCommandLine ()
159{
160    return getString ("command line", "browser",
161                      DEFAULT_EXTERNAL_BROWSER_COMMAND_LINE);
162}
163
164///
165/// @brief Gets an integer configuration option.
166///
167/// @param group Configuration group where the key belongs.
168/// @param key The key name to retrieve its value.
169/// @param defaultValue The default value to return if @a key doesn't exists.
170///
171/// @return The value of the @a key in @a group or @a defaultValue if @a key
172///         doesn't exists.
173///
174gint
175Config::getInteger (const gchar *group, const gchar *key, gint defaultValue)
176{
177    gint value = defaultValue;
178
179    if ( g_key_file_has_key (m_Values, group, key, NULL) )
180    {
181        GError *error = NULL;
182        gint savedValue = g_key_file_get_integer (m_Values, group, key, &error);
183        if ( NULL == error )
184        {
185            value = savedValue;
186        }
187        else
188        {
189            g_warning ("Error reading key '%s' from group '%s': %s\n",
190                       key, group, error->message);
191            g_error_free (error);
192        }       
193    }
194
195    return value;
196}
197
198///
199/// @brief Gets the last folder used to open a file.
200///
201/// @return The path to the last folder that was used to open a file.
202///         This string must be freed using g_free(). NULL if no folder
203///         has been used yet, which means to use the current working directory.
204///
205gchar *
206Config::getOpenFileFolder ()
207{
208    return getString ("open dialog", "folder", DEFAULT_OPEN_FILE_FOLDER);
209}
210
211///
212/// @brief Gets the last folder used to save a file.
213///
214/// @return The path to the last folder that was used to save a file.
215///         This string must be freed using g_free(). NULL if no folder
216///         has been used yet, which means to use the current working directory.
217///
218gchar *
219Config::getSaveFileFolder ()
220{
221    return getString ("save dialog", "folder", DEFAULT_SAVE_FILE_FOLDER);
222}
223
224///
225/// @brief Gets an string configuration option.
226///
227/// @param group Configuration group where the key belongs.
228/// @param key The key name to retrieve its value.
229/// @param defaultValue The default value to return if @a key doesn't exists.
230///
231/// @return The value of the @a key in @a group or @a defaultValue if @a key
232///         doesn't exists.
233///
234gchar *
235Config::getString (const gchar *group, const gchar *key,
236                   const gchar *defaultValue)
237{
238    gchar *value = g_strdup (defaultValue);
239    if ( g_key_file_has_key (m_Values, group, key, NULL) )
240    {
241        GError *error = NULL;
242        gchar *savedValue =
243            g_key_file_get_string (m_Values, group, key, &error);
244        if ( NULL == error )
245        {
246            g_free (value);
247            value = savedValue;
248        }
249        else
250        {
251            g_warning ("Error reading key '%s' from group '%s': %s\n",
252                       key, group, error->message);
253            g_error_free (error);
254        }
255    }
256
257    return value;
258}
259
260///
261/// @brief Gets the main window's height.
262///
263/// @return The saved height value of the main window.
264///
265gint
266Config::getWindowHeight ()
267{
268    return getInteger ("main window", "height", DEFAULT_WINDOW_HEIGHT);
269}
270
271///
272/// @brief Gets the main window's width.
273///
274/// @return The saved width value of the main window.
275///
276gint
277Config::getWindowWidth ()
278{
279    return getInteger ("main window", "width", DEFAULT_WINDOW_WIDTH);
280}
281
282///
283/// @brief Gets main window's X position.
284///
285/// @return The saved X position value of the main window.
286///
287gint
288Config::getWindowX ()
289{   
290    return getInteger ("main window", "x", DEFAULT_WINDOW_X);
291}
292
293///
294/// @brief Gets main window's Y position.
295///
296/// @return the saved Y position value of the main window.
297///
298gint
299Config::getWindowY ()
300{
301    return getInteger ("main window", "y", DEFAULT_WINDOW_Y);
302}
303
304///
305/// @brief Sets if load the configuration value.
306///
307/// This is mainly for testing only purposes. If it's called before
308/// the first call to getConfig(), then the configuration file is not
309/// loaded.
310///
311/// @param load Set to TRUE to load the file, to FALSE to prevent loading it.
312///
313void
314Config::loadFile (gboolean load)
315{
316    m_LoadFile = load;
317}
318
319///
320/// @brief Save the current configuration to a file.
321///
322void
323Config::save ()
324{
325    gsize length = 0;
326    gchar *contents = g_key_file_to_data (m_Values, &length, NULL);
327    gchar *configFileName = getConfigFileName ();
328    FILE *configFile = g_fopen (configFileName, "w+t");
329    if ( NULL != configFile )
330    {
331        fwrite (contents, sizeof (gchar), length, configFile);
332        fclose (configFile);
333    }
334    g_free (contents);
335    g_free (configFileName);
336}
337
338///
339/// @brief Saves the command line to use to execute the external browser.
340///
341/// @param commandLine the browser's command line to save.
342///
343void
344Config::setExternalBrowserCommandLine (const gchar *commandLine)
345{
346    g_key_file_set_string (m_Values, "command line", "browser", commandLine);
347}
348
349///
350/// @brief Saves the last folder used to open a file.
351///
352/// @param folder The path to the last folder used.
353///
354void
355Config::setOpenFileFolder (const gchar *folder)
356{
357    g_key_file_set_string (m_Values, "open dialog", "folder", folder);
358}
359
360///
361/// @brief Saves the last folder used to osave a file.
362///
363/// @param folder The path to the last folder used.
364///
365void
366Config::setSaveFileFolder (const gchar *folder)
367{
368    g_key_file_set_string (m_Values, "save dialog", "folder", folder);
369}
370
371///
372/// @brief Save if show the status bar.
373///
374/// @param show TRUE to show the status bar, FALSE otherwise.
375///
376void
377Config::setShowStatusbar (gboolean show)
378{
379    g_key_file_set_boolean (m_Values, "main window", "showStatusbar", show);
380}
381
382///
383/// @brief Saves if show the tool bar.
384///
385/// @param show TRUE to show the tool bar, FALSE otherwise.
386///
387void
388Config::setShowToolbar (gboolean show)
389{
390    g_key_file_set_boolean (m_Values, "main window", "showToolbar", show);
391}
392
393///
394/// @brief Saves the current window's size.
395///
396/// @param width The window's width.
397/// @param height The window's height.
398///
399void
400Config::setWindowSize (gint width, gint height)
401{
402    g_key_file_set_integer (m_Values, "main window", "width", width);
403    g_key_file_set_integer (m_Values, "main window", "height", height);
404}
405
406///
407/// @brief Saves the current window's position.
408///
409/// @param x The X position of the window.
410/// @param y The Y position of the window.
411///
412void
413Config::setWindowPos (gint x, gint y)
414{
415    g_key_file_set_integer (m_Values, "main window", "x", x);
416    g_key_file_set_integer (m_Values, "main window", "y", y);
417}
418
419///
420/// @brief Sets the zoom to fit option.
421///
422/// @param activate Set to TRUE to activate the zoom to fit option. FALSE
423///        otherwise.
424///
425void
426Config::setZoomToFit (gboolean activate)
427{
428    g_key_file_set_boolean (m_Values, "main window", "zoomToFit", activate);
429    g_key_file_set_boolean (m_Values, "main window", "zoomToWidth",
430            !activate && zoomToWidth ());
431}
432
433///
434/// @brief Sets the zoom to with option.
435///
436/// @param activate Set to TRUE to activate the zoom to width option. FALSE
437///        otherwise.
438///
439void
440Config::setZoomToWidth (gboolean activate)
441{
442    g_key_file_set_boolean (m_Values, "main window", "zoomToFit",
443            !activate && zoomToFit ());
444    g_key_file_set_boolean (m_Values, "main window", "zoomToWidth", activate);
445}
446
447///
448/// @brief Gets if show the status bar.
449///
450/// @return TRUE if the status bar should be shown, FALSE otherwise.
451///
452gboolean
453Config::showStatusbar ()
454{
455    return getBoolean ("main window", "showStatusbar", DEFAULT_SHOW_STATUSBAR);
456}
457
458///
459/// @brief Gets if show the tool bar
460///
461/// @return TRUE if the tool bar should be shown, FALSE otherwise.
462///
463gboolean
464Config::showToolbar ()
465{
466    return getBoolean ("main window", "showToolbar", DEFAULT_SHOW_TOOLBAR);
467}
468
469///
470/// @brief Gets the zoom to fit option.
471///
472/// @return TRUE if the zoom to fit option is activated. FALSE otherwise.
473///
474gboolean
475Config::zoomToFit ()
476{
477    return getBoolean ("main window", "zoomToFit", DEFAULT_ZOOM_TO_FIT);
478}
479
480///
481/// @brief Gets the zoom to width option.
482///
483/// @return TRUE if the zoom to width option is activated. FALSE otherwise.
484///
485gboolean
486Config::zoomToWidth ()
487{
488    return getBoolean ("main window", "zoomToWidth", DEFAULT_ZOOM_TO_WIDTH);
489}
490
491///
492/// @brief Gets the configuration file name.
493///
494/// This function creates the directory where the configuration file should
495/// go, if it doesn't exist yet.
496///
497/// @return The full path to the configuration file.
498///
499gchar *
500getConfigFileName ()
501{
502    gchar *configDir =
503        g_build_filename (g_get_user_config_dir (), PACKAGE, NULL);
504    g_mkdir_with_parents (configDir, 0700);
505    gchar *configFile = g_build_filename (configDir, "main.conf", NULL);
506    g_free (configDir);
507
508    return configFile;
509}
Note: See TracBrowser for help on using the browser.