~ubuntu-branches/debian/sid/geany-plugins/sid

« back to all changes in this revision

Viewing changes to webhelper/src/gwh-settings.c

  • Committer: Package Import Robot
  • Author(s): Evgeni Golov, Evgeni Golov
  • Date: 2011-11-17 20:03:24 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20111117200324-8qmu6tuwjtfpv3n7
Tags: 0.21.1-1
[ Evgeni Golov ]
* [f4007f2] Imported Upstream version 0.21.1
* [5ff622d] install plugins from/to /usr/lib/<arch-triplet>/geany
* [75411d7] bump build-dep to geany 0.21
* [db92155] depend on the virtual geany-abi-XX package
* [dd84769] switch to 3.0 (quilt)
* [3ab76d7] drop readme.source
* [233d44c] refresh patch against 0.21.1
* [030bec1] add lintian override for
            documentation-package-not-architecture-independent
* [aba43d7] use debhelper compat level 9

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  
3
 
 *  Copyright (C) 2010  Colomban Wendling <ban@herbesfolles.org>
 
3
 *  Copyright (C) 2010-2011  Colomban Wendling <ban@herbesfolles.org>
4
4
 *  
5
5
 *  This program is free software: you can redistribute it and/or modify
6
6
 *  it under the terms of the GNU General Public License as published by
19
19
 
20
20
#include "gwh-settings.h"
21
21
 
 
22
#include "config.h"
 
23
 
22
24
#include <string.h>
 
25
#include <stdarg.h>
23
26
#include <glib.h>
 
27
#include <glib/gi18n-lib.h>
24
28
#include <glib-object.h>
25
 
#include <gtk/gtk.h> /* for GtkOrientation */
26
 
 
27
 
#include "gwh-enum-types.h" /* for GwhUiBrowserPosition */
28
 
 
29
 
 
30
 
/* sets @ptr to @value, freeing @ptr before.
31
 
 * note that:
32
 
 *  * ptr can be used to compute @value, assignation is done after comuptation
33
 
 *  * ptr is used twice, so it must be side-effects-free */
34
 
#define setptr(ptr, value)       \
35
 
  G_STMT_START {                 \
36
 
    gpointer new_ptr = (value);  \
37
 
    g_free (ptr);                \
38
 
    ptr = new_ptr;               \
39
 
  } G_STMT_END
 
29
#include <gtk/gtk.h>
40
30
 
41
31
 
42
32
struct _GwhSettingsPrivate
43
33
{
44
 
  gboolean              browser_auto_reload;
45
 
  gchar                *browser_last_uri;
46
 
  GtkOrientation        browser_orientation;
47
 
  GwhBrowserPosition    browser_position;
48
 
  gchar                *browser_separate_window_geometry;
49
 
  gchar                *inspector_window_geometry;
50
 
};
51
 
 
52
 
enum
53
 
{
54
 
  PROP_0,
55
 
  PROP_BROWSER_AUTO_RELOAD,
56
 
  PROP_BROWSER_LAST_URI,
57
 
  PROP_BROWSER_ORIENTATION,
58
 
  PROP_BROWSER_POSITION,
59
 
  PROP_BROWSER_SEPARATE_WINDOW_GEOMETRY,
60
 
  PROP_INSPECTOR_WINDOW_GEOMETRY
 
34
  GPtrArray *prop_array;
61
35
};
62
36
 
63
37
 
72
46
{
73
47
  GwhSettings *self = GWH_SETTINGS (object);
74
48
  
75
 
  switch (prop_id) {
76
 
    case PROP_BROWSER_AUTO_RELOAD:
77
 
      g_value_set_boolean (value, self->priv->browser_auto_reload);
78
 
      break;
79
 
    case PROP_BROWSER_LAST_URI:
80
 
      g_value_set_string (value, self->priv->browser_last_uri);
81
 
      break;
82
 
    case PROP_BROWSER_ORIENTATION:
83
 
      g_value_set_enum (value, self->priv->browser_orientation);
84
 
      break;
85
 
    case PROP_BROWSER_POSITION:
86
 
      g_value_set_enum (value, self->priv->browser_position);
87
 
      break;
88
 
    case PROP_BROWSER_SEPARATE_WINDOW_GEOMETRY:
89
 
      g_value_set_string (value, self->priv->browser_separate_window_geometry);
90
 
      break;
91
 
    case PROP_INSPECTOR_WINDOW_GEOMETRY:
92
 
      g_value_set_string (value, self->priv->inspector_window_geometry);
93
 
      break;
 
49
  if (G_LIKELY (prop_id > 0 && prop_id <= self->priv->prop_array->len)) {
 
50
    GValue *prop_value;
94
51
    
95
 
    default:
96
 
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
52
    prop_value = g_ptr_array_index (self->priv->prop_array, prop_id - 1);
 
53
    g_value_copy (prop_value, value);
 
54
  } else {
 
55
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
97
56
  }
98
57
}
99
58
 
105
64
{
106
65
  GwhSettings *self = GWH_SETTINGS (object);
107
66
  
108
 
  switch (prop_id) {
109
 
    case PROP_BROWSER_AUTO_RELOAD:
110
 
      self->priv->browser_auto_reload = g_value_get_boolean (value);
111
 
      break;
112
 
    case PROP_BROWSER_LAST_URI:
113
 
      setptr (self->priv->browser_last_uri, g_value_dup_string (value));
114
 
      break;
115
 
    case PROP_BROWSER_ORIENTATION:
116
 
      self->priv->browser_orientation = g_value_get_enum (value);
117
 
      break;
118
 
    case PROP_BROWSER_POSITION:
119
 
      self->priv->browser_position = g_value_get_enum (value);
120
 
      break;
121
 
    case PROP_BROWSER_SEPARATE_WINDOW_GEOMETRY:
122
 
      setptr (self->priv->browser_separate_window_geometry,
123
 
              g_value_dup_string (value));
124
 
      break;
125
 
    case PROP_INSPECTOR_WINDOW_GEOMETRY:
126
 
      setptr (self->priv->inspector_window_geometry, g_value_dup_string (value));
127
 
      break;
 
67
  if (G_LIKELY (prop_id > 0 && prop_id <= self->priv->prop_array->len)) {
 
68
    GValue *prop_value;
128
69
    
129
 
    default:
130
 
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
70
    prop_value = g_ptr_array_index (self->priv->prop_array, prop_id - 1);
 
71
    g_value_copy (value, prop_value);
 
72
  } else {
 
73
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
131
74
  }
132
75
}
133
76
 
137
80
                          GObjectConstructParam *properties)
138
81
{
139
82
  static GObject *obj = NULL;
140
 
 
 
83
  
141
84
  if (G_UNLIKELY (! obj)) {
142
85
    obj = G_OBJECT_CLASS (gwh_settings_parent_class)->constructor (gtype,
143
86
                                                                   n_properties,
153
96
}
154
97
 
155
98
static void
 
99
free_prop_item (gpointer data,
 
100
                gpointer user_data)
 
101
{
 
102
  g_value_unset (data);
 
103
  g_free (data);
 
104
}
 
105
 
 
106
static void
156
107
gwh_settings_finalize (GObject *object)
157
108
{
158
109
  GwhSettings *self = GWH_SETTINGS (object);
159
110
  
160
 
  self->priv->browser_auto_reload = FALSE;
161
 
  setptr (self->priv->browser_last_uri, NULL);
162
 
  self->priv->browser_orientation = 0;
163
 
  self->priv->browser_position = 0;
164
 
  setptr (self->priv->inspector_window_geometry, NULL);
 
111
  g_ptr_array_foreach (self->priv->prop_array, free_prop_item, NULL);
 
112
  g_ptr_array_free (self->priv->prop_array, TRUE);
 
113
  self->priv->prop_array = NULL;
165
114
  
166
115
  G_OBJECT_CLASS (gwh_settings_parent_class)->finalize (object);
167
116
}
176
125
  object_class->get_property  = gwh_settings_get_property;
177
126
  object_class->set_property  = gwh_settings_set_property;
178
127
  
179
 
  g_object_class_install_property (object_class, PROP_BROWSER_AUTO_RELOAD,
180
 
                                   g_param_spec_boolean ("browser-auto-reload",
181
 
                                                         "Browser auto reload",
182
 
                                                         "Whether the browser reloads itself upon document saving",
183
 
                                                         TRUE,
184
 
                                                         G_PARAM_READWRITE));
185
 
  g_object_class_install_property (object_class, PROP_BROWSER_LAST_URI,
186
 
                                   g_param_spec_string ("browser-last-uri",
187
 
                                                        "Browser last URI",
188
 
                                                        "Last URI visited by the browser",
189
 
                                                        "about:blank",
190
 
                                                        G_PARAM_READWRITE));
191
 
  g_object_class_install_property (object_class, PROP_BROWSER_ORIENTATION,
192
 
                                   g_param_spec_enum ("browser-orientation",
193
 
                                                      "Browser orientation",
194
 
                                                      "Orientation of the browser widget",
195
 
                                                      GTK_TYPE_ORIENTATION,
196
 
                                                      GTK_ORIENTATION_VERTICAL,
197
 
                                                      G_PARAM_READWRITE));
198
 
  g_object_class_install_property (object_class, PROP_BROWSER_POSITION,
199
 
                                   g_param_spec_enum ("browser-position",
200
 
                                                      "Browser position",
201
 
                                                      "Position of the browser widget in Geany's UI",
202
 
                                                      GWH_TYPE_BROWSER_POSITION,
203
 
                                                      GWH_BROWSER_POSITION_MESSAGE_WINDOW,
204
 
                                                      G_PARAM_READWRITE));
205
 
  g_object_class_install_property (object_class, PROP_BROWSER_SEPARATE_WINDOW_GEOMETRY,
206
 
                                   g_param_spec_string ("browser-separate-window-geometry",
207
 
                                                        "Browser separate window geometry",
208
 
                                                        "Last geometry of the separated browser's window",
209
 
                                                        "400x300",
210
 
                                                        G_PARAM_READWRITE));
211
 
  g_object_class_install_property (object_class, PROP_INSPECTOR_WINDOW_GEOMETRY,
212
 
                                   g_param_spec_string ("inspector-window-geometry",
213
 
                                                        "Inspector window geometry",
214
 
                                                        "Last geometry of the inspector window",
215
 
                                                        "400x300",
216
 
                                                        G_PARAM_READWRITE));
217
 
  
218
128
  g_type_class_add_private (klass, sizeof (GwhSettingsPrivate));
219
129
}
220
130
 
223
133
{
224
134
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GWH_TYPE_SETTINGS,
225
135
                                            GwhSettingsPrivate);
226
 
  self->priv->browser_auto_reload       = TRUE;
227
 
  self->priv->browser_last_uri          = g_strdup ("about:blank");
228
 
  self->priv->browser_orientation       = GTK_ORIENTATION_VERTICAL;
229
 
  self->priv->browser_position          = GWH_BROWSER_POSITION_MESSAGE_WINDOW;
230
 
  self->priv->browser_separate_window_geometry = g_strdup ("400x300");
231
 
  self->priv->inspector_window_geometry = g_strdup ("400x300");
 
136
  self->priv->prop_array = g_ptr_array_new ();
232
137
}
233
138
 
234
139
 
240
145
  return g_object_new (GWH_TYPE_SETTINGS, NULL);
241
146
}
242
147
 
 
148
static gboolean
 
149
is_pspec_installed (GObject          *obj,
 
150
                    const GParamSpec *pspec)
 
151
{
 
152
  GParamSpec  **pspecs;
 
153
  guint         n_props;
 
154
  guint         i;
 
155
  gboolean      installed = FALSE;
 
156
  
 
157
  pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (obj), &n_props);
 
158
  for (i = 0; ! installed && i < n_props; i++) {
 
159
    installed = (pspec->value_type == pspecs[i]->value_type &&
 
160
                 strcmp (pspec->name, pspecs[i]->name) == 0);
 
161
  }
 
162
  g_free (pspecs);
 
163
  
 
164
  return installed;
 
165
}
 
166
 
 
167
void
 
168
gwh_settings_install_property (GwhSettings *self,
 
169
                               GParamSpec  *pspec)
 
170
{
 
171
  GValue *value;
 
172
  
 
173
  g_return_if_fail (GWH_IS_SETTINGS (self));
 
174
  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
175
  
 
176
  /* a bit hackish, but allows to install the same property twice because the
 
177
   * class will not be destroyed if the plugin gets reloaded. safe since the
 
178
   * object is a singleton that will never de destroyed, and the plugin is
 
179
   * resident, so the object is still valid after a reload. */
 
180
  if (is_pspec_installed (G_OBJECT (self), pspec)) {
 
181
    return;
 
182
  }
 
183
  
 
184
  value = g_value_init (g_malloc0 (sizeof *value), pspec->value_type);
 
185
  switch (G_TYPE_FUNDAMENTAL (pspec->value_type)) {
 
186
    #define HANDLE_BASIC_TYPE(NAME, Name, name)                                \
 
187
      case G_TYPE_##NAME:                                                      \
 
188
        g_value_set_##name (value, ((GParamSpec##Name*)pspec)->default_value); \
 
189
        break;
 
190
    
 
191
    HANDLE_BASIC_TYPE (BOOLEAN, Boolean, boolean)
 
192
    HANDLE_BASIC_TYPE (CHAR,    Char,    char)
 
193
    HANDLE_BASIC_TYPE (UCHAR,   UChar,   uchar)
 
194
    HANDLE_BASIC_TYPE (INT,     Int,     int)
 
195
    HANDLE_BASIC_TYPE (UINT,    UInt,    uint)
 
196
    HANDLE_BASIC_TYPE (LONG,    Long,    long)
 
197
    HANDLE_BASIC_TYPE (ULONG,   ULong,   ulong)
 
198
    HANDLE_BASIC_TYPE (INT64,   Int64,   int64)
 
199
    HANDLE_BASIC_TYPE (UINT64,  UInt64,  uint64)
 
200
    HANDLE_BASIC_TYPE (FLOAT,   Float,   float)
 
201
    HANDLE_BASIC_TYPE (DOUBLE,  Double,  double)
 
202
    HANDLE_BASIC_TYPE (ENUM,    Enum,    enum)
 
203
    HANDLE_BASIC_TYPE (FLAGS,   Flags,   flags)
 
204
    HANDLE_BASIC_TYPE (STRING,  String,  string)
 
205
    
 
206
    #undef HANDLE_BASIC_TYPE
 
207
    
 
208
    case G_TYPE_PARAM:
 
209
    case G_TYPE_BOXED:
 
210
    case G_TYPE_POINTER:
 
211
    case G_TYPE_OBJECT:
 
212
      /* nothing to do with these types, default GValue is fine since they have
 
213
       * no default value */
 
214
      break;
 
215
    
 
216
    default:
 
217
      g_critical ("Unsupported property type \"%s\" for property \"%s\"",
 
218
                  G_VALUE_TYPE_NAME (value), pspec->name);
 
219
      g_value_unset (value);
 
220
      g_free (value);
 
221
      return;
 
222
  }
 
223
  g_ptr_array_add (self->priv->prop_array, value);
 
224
  g_object_class_install_property (G_OBJECT_GET_CLASS (self),
 
225
                                   self->priv->prop_array->len, pspec);
 
226
}
 
227
 
243
228
static void
244
229
get_key_and_group_from_property_name (const gchar *name,
245
230
                                      gchar      **group,
347
332
      success = FALSE;
348
333
    } else {
349
334
      success = g_file_set_contents (filename, data, length, error);
 
335
      g_free (data);
350
336
    }
351
337
  }
352
338
  g_key_file_free (key_file);
473
459
 
474
460
 
475
461
 
476
 
 
477
 
 
 
462
/* display/edit widgets stuff */
 
463
 
 
464
/*
 
465
 * gwh_settings_widget_<type>_notify:
 
466
 *   calls user's callback with appropriate arguments
 
467
 * gwh_settings_widget_<type>_notify_callback:
 
468
 *   a callback connected to a signal on the widget.
 
469
 *   calls gwh_settings_widget_<type>_notify
 
470
 * gwh_settings_widget_<type>_new:
 
471
 *   creates the widget
 
472
 * gwh_settings_widget_<type>_sync:
 
473
 *   syncs widget's value with its setting
 
474
 */
 
475
 
 
476
 
 
477
typedef struct _GwhSettingsWidgetNotifyData
 
478
{
 
479
  GwhSettings  *settings;
 
480
  GCallback     callback;
 
481
  gpointer      user_data;
 
482
} GwhSettingsWidgetNotifyData;
 
483
 
 
484
 
 
485
static void
 
486
gwh_settings_widget_boolean_notify (GObject                      *tbutton,
 
487
                                    GwhSettingsWidgetNotifyData  *data)
 
488
{
 
489
  ((GwhSettingsWidgetBooleanNotify)data->callback) (data->settings,
 
490
                                                    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (tbutton)),
 
491
                                                    data->user_data);
 
492
}
 
493
 
 
494
#define gwh_settings_widget_boolean_notify_callback gwh_settings_widget_boolean_notify
478
495
 
479
496
static GtkWidget *
480
 
gwh_settings_widget_new_boolean (GwhSettings   *self,
 
497
gwh_settings_widget_boolean_new (GwhSettings   *self,
481
498
                                 const GValue  *value,
482
499
                                 GParamSpec    *pspec,
483
500
                                 gboolean      *needs_label)
493
510
}
494
511
 
495
512
static void
496
 
gwh_settings_widget_sync_boolean (GwhSettings *self,
497
 
                                  GParamSpec  *pspec,
498
 
                                  GtkWidget   *widget)
499
 
{
500
 
  g_object_set (self, pspec->name,
501
 
                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
502
 
                NULL);
503
 
}
 
513
gwh_settings_widget_boolean_sync (GwhSettings  *self,
 
514
                                  GParamSpec   *pspec,
 
515
                                  const GValue *old_value,
 
516
                                  GtkWidget    *widget)
 
517
{
 
518
  gboolean val = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 
519
  
 
520
  if (g_value_get_boolean (old_value) != val) {
 
521
    g_object_set (self, pspec->name, val, NULL);
 
522
  }
 
523
}
 
524
 
 
525
static void
 
526
gwh_settings_widget_enum_notify (GObject                     *object,
 
527
                                 GwhSettingsWidgetNotifyData *data)
 
528
{
 
529
  GtkTreeIter   iter;
 
530
  GtkComboBox  *cbox = GTK_COMBO_BOX (object);
 
531
  
 
532
  if (gtk_combo_box_get_active_iter (cbox, &iter)) {
 
533
    gint val;
 
534
    
 
535
    gtk_tree_model_get (gtk_combo_box_get_model (cbox), &iter, 0, &val, -1);
 
536
    ((GwhSettingsWidgetEnumNotify)data->callback) (data->settings, val,
 
537
                                                   data->user_data);
 
538
  }
 
539
}
 
540
 
 
541
#define gwh_settings_widget_enum_notify_callback gwh_settings_widget_enum_notify
504
542
 
505
543
static GtkWidget *
506
 
gwh_settings_widget_new_enum (GwhSettings  *self,
 
544
gwh_settings_widget_enum_new (GwhSettings  *self,
507
545
                              const GValue *value,
508
546
                              GParamSpec   *pspec,
509
547
                              gboolean     *needs_label)
523
561
    gtk_list_store_append (store, &iter);
524
562
    gtk_list_store_set (store, &iter,
525
563
                        0, enum_class->values[i].value,
526
 
                        1, enum_class->values[i].value_nick,
 
564
                        1, _(enum_class->values[i].value_nick),
527
565
                        -1);
528
566
    if (g_value_get_enum (value) == enum_class->values[i].value) {
529
567
      active = i;
544
582
}
545
583
 
546
584
static void
547
 
gwh_settings_widget_sync_enum (GwhSettings *self,
548
 
                               GParamSpec  *pspec,
549
 
                               GtkWidget   *widget)
 
585
gwh_settings_widget_enum_sync (GwhSettings   *self,
 
586
                               GParamSpec    *pspec,
 
587
                               const GValue  *old_value,
 
588
                               GtkWidget     *widget)
550
589
{
551
590
  GtkTreeIter iter;
552
591
  
556
595
    
557
596
    model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
558
597
    gtk_tree_model_get (model, &iter, 0, &val, -1);
 
598
    if (g_value_get_enum (old_value) != val) {
 
599
      g_object_set (self, pspec->name, val, NULL);
 
600
    }
 
601
  }
 
602
}
 
603
 
 
604
static void
 
605
gwh_settings_widget_int_notify (GObject                     *spin,
 
606
                                GwhSettingsWidgetNotifyData *data)
 
607
{
 
608
  ((GwhSettingsWidgetIntNotify)data->callback) (data->settings,
 
609
                                                gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin)),
 
610
                                                data->user_data);
 
611
}
 
612
 
 
613
#define gwh_settings_widget_int_notify_callback gwh_settings_widget_int_notify
 
614
 
 
615
static GtkWidget *
 
616
gwh_settings_widget_int_new (GwhSettings  *self,
 
617
                             const GValue *value,
 
618
                             GParamSpec   *pspec,
 
619
                             gboolean     *needs_label)
 
620
{
 
621
  GtkWidget      *button;
 
622
  GtkObject      *adj;
 
623
  GParamSpecInt  *pspec_int = G_PARAM_SPEC_INT (pspec);
 
624
  
 
625
  adj = gtk_adjustment_new ((gdouble)g_value_get_int (value),
 
626
                            (gdouble)pspec_int->minimum,
 
627
                            (gdouble)pspec_int->maximum,
 
628
                            1.0, 10.0, 0.0);
 
629
  button = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 0.0, 0);
 
630
  *needs_label = TRUE;
 
631
  
 
632
  return button;
 
633
}
 
634
 
 
635
static void
 
636
gwh_settings_widget_int_sync (GwhSettings  *self,
 
637
                              GParamSpec   *pspec,
 
638
                              const GValue *old_value,
 
639
                              GtkWidget    *widget)
 
640
{
 
641
  gint val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
 
642
  
 
643
  if (g_value_get_int (old_value) != val) {
559
644
    g_object_set (self, pspec->name, val, NULL);
560
645
  }
561
646
}
562
647
 
 
648
static void
 
649
gwh_settings_widget_string_notify (GObject                     *entry,
 
650
                                   GwhSettingsWidgetNotifyData *data)
 
651
{
 
652
  ((GwhSettingsWidgetStringNotify)data->callback) (data->settings,
 
653
                                                   gtk_entry_get_text (GTK_ENTRY (entry)),
 
654
                                                   data->user_data);
 
655
}
 
656
 
 
657
static void
 
658
gwh_settings_widget_string_notify_callback (GObject                     *object,
 
659
                                            GParamSpec                  *pspec,
 
660
                                            GwhSettingsWidgetNotifyData *data)
 
661
{
 
662
  gwh_settings_widget_string_notify (object, data);
 
663
}
 
664
 
563
665
static GtkWidget *
564
 
gwh_settings_widget_new_string (GwhSettings  *self,
 
666
gwh_settings_widget_string_new (GwhSettings  *self,
565
667
                                const GValue *value,
566
668
                                GParamSpec   *pspec,
567
669
                                gboolean     *needs_label)
576
678
}
577
679
 
578
680
static void
579
 
gwh_settings_widget_sync_string (GwhSettings *self,
580
 
                                 GParamSpec  *pspec,
581
 
                                 GtkWidget   *widget)
 
681
gwh_settings_widget_string_sync (GwhSettings   *self,
 
682
                                 GParamSpec    *pspec,
 
683
                                 const GValue  *old_value,
 
684
                                 GtkWidget     *widget)
582
685
{
583
 
  g_object_set (self, pspec->name, gtk_entry_get_text (GTK_ENTRY (widget)),
584
 
                NULL);
 
686
  const gchar *val      = gtk_entry_get_text (GTK_ENTRY (widget));
 
687
  const gchar *old_val  = g_value_get_string (old_value);
 
688
  
 
689
  if (g_strcmp0 (old_val, val) != 0) {
 
690
    g_object_set (self, pspec->name, val, NULL);
 
691
  }
585
692
}
586
693
 
587
694
 
588
695
#define KEY_PSPEC   "gwh-settings-configure-pspec"
589
696
#define KEY_WIDGET  "gwh-settings-configure-widget"
590
697
 
 
698
/**
 
699
 * gwh_settings_widget_new_full:
 
700
 * @self: A GwhSettings object
 
701
 * @prop_name: the name of the setting for which create a widget
 
702
 * @setting_changed_callback: a callback to be called when the widget's value
 
703
 *                            changes, or %NULL. The type of the callback
 
704
 *                            is GwhSettingsWidget*Notify, depending of the
 
705
 *                            setting type
 
706
 * @user_data: user data to pass to @callback
 
707
 * @notify_flags: notification flags
 
708
 * 
 
709
 * Creates a widgets to configure the value of a setting @prop_name.
 
710
 * This setting will not be changed automatically, you'll need to call
 
711
 * gwh_settings_widget_sync() when you want to synchronize the widget's value to
 
712
 * the setting.
 
713
 * 
 
714
 * Returns: A #GtkWidget that displays and edit @prop_name.
 
715
 */
591
716
GtkWidget *
592
 
gwh_settings_widget_new (GwhSettings *self,
593
 
                         const gchar *prop_name)
 
717
gwh_settings_widget_new_full (GwhSettings            *self,
 
718
                              const gchar            *prop_name,
 
719
                              GCallback               setting_changed_callback,
 
720
                              gpointer                user_data,
 
721
                              GwhSettingsNotifyFlags  notify_flags)
594
722
{
595
723
  GtkWidget  *widget      = NULL;
596
724
  GParamSpec *pspec;
605
733
  g_value_init (&value, pspec->value_type);
606
734
  g_object_get_property (G_OBJECT (self), prop_name, &value);
607
735
  switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (&value))) {
608
 
    #define HANDLE_TYPE(T, h) \
609
 
      case T: widget = ((h) (self, &value, pspec, &needs_label)); break;
 
736
    #define HANDLE_TYPE(T, t, signal)                                          \
 
737
      case G_TYPE_##T:                                                         \
 
738
        widget = gwh_settings_widget_##t##_new (self, &value, pspec,           \
 
739
                                                &needs_label);                 \
 
740
        if (setting_changed_callback) {                                        \
 
741
          GwhSettingsWidgetNotifyData *data = g_malloc (sizeof *data);         \
 
742
                                                                               \
 
743
          data->settings  = self;                                              \
 
744
          data->callback  = setting_changed_callback;                          \
 
745
          data->user_data = user_data;                                         \
 
746
          g_signal_connect_data (widget, signal,                               \
 
747
                                 G_CALLBACK (gwh_settings_widget_##t##_notify_callback),\
 
748
                                 data, (GClosureNotify)g_free, 0);             \
 
749
          if (notify_flags & GWH_SETTINGS_NOTIFY_ON_CONNEXION) {               \
 
750
            gwh_settings_widget_##t##_notify (G_OBJECT (widget), data);        \
 
751
          }                                                                    \
 
752
        }                                                                      \
 
753
        break;
610
754
    
611
 
    HANDLE_TYPE (G_TYPE_BOOLEAN,  gwh_settings_widget_new_boolean)
612
 
    HANDLE_TYPE (G_TYPE_ENUM,     gwh_settings_widget_new_enum)
613
 
    HANDLE_TYPE (G_TYPE_STRING,   gwh_settings_widget_new_string)
 
755
    HANDLE_TYPE (BOOLEAN, boolean,  "toggled")
 
756
    HANDLE_TYPE (ENUM,    enum,     "changed")
 
757
    HANDLE_TYPE (INT,     int,      "value-changed")
 
758
    HANDLE_TYPE (STRING,  string,   "notify::text")
614
759
    
615
760
    #undef HANDLE_TYPE
616
761
    
627
772
      gchar     *label;
628
773
      
629
774
      box = gtk_hbox_new (FALSE, 6);
630
 
      label = g_strdup_printf ("%s:", g_param_spec_get_nick (pspec));
 
775
      label = g_strdup_printf (_("%s:"), g_param_spec_get_nick (pspec));
631
776
      gtk_box_pack_start (GTK_BOX (box), gtk_label_new (label), FALSE, TRUE, 0);
632
777
      g_free (label);
633
778
      gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
644
789
  return widget;
645
790
}
646
791
 
647
 
void
648
 
gwh_settings_widget_sync (GwhSettings *self,
649
 
                          GtkWidget   *widget)
 
792
GtkWidget *
 
793
gwh_settings_widget_new (GwhSettings *self,
 
794
                         const gchar *prop_name)
 
795
{
 
796
  return gwh_settings_widget_new_full (self, prop_name, NULL, NULL, 0);
 
797
}
 
798
 
 
799
static gboolean
 
800
gwh_settings_widget_sync_internal (GwhSettings *self,
 
801
                                   GtkWidget   *widget)
650
802
{
651
803
  GParamSpec *pspec;
 
804
  GValue      value = {0};
652
805
  
653
 
  g_return_if_fail (GWH_IS_SETTINGS (self));
654
 
  g_return_if_fail (G_IS_OBJECT (widget));
 
806
  g_return_val_if_fail (G_IS_OBJECT (widget), FALSE);
655
807
  
656
808
  widget = g_object_get_data (G_OBJECT (widget), KEY_WIDGET);
657
 
  g_return_if_fail (GTK_IS_WIDGET (widget));
 
809
  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
658
810
  pspec = g_object_get_data (G_OBJECT (widget), KEY_PSPEC);
659
 
  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
811
  g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
 
812
  g_value_init (&value, pspec->value_type);
 
813
  g_object_get_property (G_OBJECT (self), pspec->name, &value);
660
814
  switch (G_TYPE_FUNDAMENTAL (pspec->value_type)) {
661
 
    #define HANDLE_TYPE(T, h) case T: (h) (self, pspec, widget); break;
 
815
    #define HANDLE_TYPE(T, t)                                                  \
 
816
      case G_TYPE_##T:                                                         \
 
817
        gwh_settings_widget_##t##_sync (self, pspec, &value, widget);          \
 
818
        break;
662
819
    
663
 
    HANDLE_TYPE (G_TYPE_BOOLEAN,  gwh_settings_widget_sync_boolean)
664
 
    HANDLE_TYPE (G_TYPE_ENUM,     gwh_settings_widget_sync_enum)
665
 
    HANDLE_TYPE (G_TYPE_STRING,   gwh_settings_widget_sync_string)
 
820
    HANDLE_TYPE (BOOLEAN,  boolean)
 
821
    HANDLE_TYPE (ENUM,     enum)
 
822
    HANDLE_TYPE (INT,      int)
 
823
    HANDLE_TYPE (STRING,   string)
666
824
    
667
825
    #undef HANDLE_TYPE
668
826
    
670
828
      g_critical ("Unsupported property type \"%s\"",
671
829
                  g_type_name (pspec->value_type));
672
830
  }
 
831
  g_value_unset (&value);
 
832
  
 
833
  return TRUE;
 
834
}
 
835
 
 
836
/**
 
837
 * gwh_settings_widget_sync_v:
 
838
 * @self: A #GwhSettings object
 
839
 * @...: a %NULL-terminated list of widgets to sync
 
840
 * 
 
841
 * Same as gwh_settings_widget_sync() but emits notifications only after all
 
842
 * widgets got synchronized.
 
843
 */
 
844
void
 
845
gwh_settings_widget_sync_v (GwhSettings *self,
 
846
                            ...)
 
847
{
 
848
  GtkWidget  *widget;
 
849
  va_list     ap;
 
850
  
 
851
  g_return_if_fail (GWH_IS_SETTINGS (self));
 
852
  
 
853
  g_object_freeze_notify (G_OBJECT (self));
 
854
  va_start (ap, self);
 
855
  while ((widget = va_arg (ap, GtkWidget*))) {
 
856
    if (! gwh_settings_widget_sync_internal (self, widget)) {
 
857
      break;
 
858
    }
 
859
  }
 
860
  va_end (ap);
 
861
  g_object_thaw_notify (G_OBJECT (self));
 
862
}
 
863
 
 
864
void
 
865
gwh_settings_widget_sync (GwhSettings *self,
 
866
                          GtkWidget   *widget)
 
867
{
 
868
  g_return_if_fail (GWH_IS_SETTINGS (self));
 
869
  
 
870
  gwh_settings_widget_sync_internal (self, widget);
673
871
}