Attachment 'gpersist.c'
Download 1 #include <sys/stat.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <glib-object.h>
5 #include <gtk/gtk.h>
6 #include "gpersist.h"
7 #include <assert.h>
8
9 #define KEY_FILE_SUPPORTS_DOUBLE GLIB_CHECK_VERSION (2,11,0)
10
11 static gchar *
12 _get_app_directory ()
13 {
14 return g_build_filename (g_get_home_dir (),
15 ".gnome2",
16 g_get_application_name (),
17 NULL);
18 }
19
20 static gchar *
21 _get_persist_filename ()
22 {
23 gchar *dir, *filename;
24 dir = _get_app_directory ();
25 filename = g_build_filename (dir, "persist", NULL);
26 g_free (dir);
27 return filename;
28 }
29
30 static void
31 _load_widget_state (GtkWidget *widget, GKeyFile *keyfile)
32 {
33 const gchar *wname = NULL;
34 GError *error = NULL;
35 gchar **keys = NULL;
36 gsize nkeys, i;
37
38 wname = gtk_widget_get_name (widget);
39 if (wname == NULL){
40 printf ("wname returned NULL\n");
41 goto load_children;
42 }
43
44 if (!g_key_file_has_group (keyfile, wname))
45 goto load_children;
46
47 keys = g_key_file_get_keys (keyfile, wname, &nkeys, &error);
48 if (error != NULL)
49 goto load_children;
50
51 for (i = 0; i < nkeys; i++) {
52 if (strcmp (keys[i], "Size") == 0) {
53 gint *size_array;
54 gsize length;
55 size_array = g_key_file_get_integer_list (keyfile,
56 wname,
57 "Size",
58 &length,
59 &error);
60 g_assert (length == 2);
61 if (GTK_IS_WINDOW (widget))
62 gtk_window_resize (GTK_WINDOW (widget), size_array[0], size_array[1]);
63 else
64 gtk_widget_set_size_request (widget, size_array[0], size_array[1]);
65 }
66 else if (strcmp (keys[i], "Position") == 0) {
67 if (GTK_IS_WINDOW (widget)) {
68 }
69 else if (GTK_IS_PANED (widget)) {
70 guint pos;
71 pos = g_key_file_get_integer (keyfile, wname, "Position", &error);
72 gtk_paned_set_position (GTK_PANED (widget), pos);
73 }
74 #if KEY_FILE_SUPPORTS_DOUBLE
75 else if (GTK_IS_RANGE (widget)) {
76 gdouble pos;
77 pos = g_key_file_get_double (keyfile, wname, "Position", &error);
78 gtk_range_set_value (GTK_RANGE (widget), pos);
79 }
80 #endif
81 }
82 else if (strcmp (keys[i], "Selected") == 0) {
83 if (GTK_IS_TREE_VIEW (widget)) {
84 GtkTreeModel *model;
85 GtkTreeSelection *selection;
86 GtkTreeIter iter;
87 gchar *path;
88
89 path = g_key_file_get_string (keyfile, wname, "Selected", &error);
90 model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
91 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
92 gtk_tree_model_get_iter_from_string (model, &iter, path);
93 gtk_tree_selection_select_iter (selection, &iter);
94 }
95 else if (GTK_IS_NOTEBOOK (widget)) {
96 gtk_notebook_set_current_page (GTK_NOTEBOOK (widget),
97 g_key_file_get_integer (keyfile,
98 wname,
99 "Selected",
100 &error));
101 }
102 }
103 else if (strcmp (keys[i], "Maximized") == 0) {
104 gboolean maxed = g_key_file_get_boolean (keyfile, wname, keys[i],
105 &error);
106 if (maxed)
107 gtk_window_maximize (GTK_WINDOW (widget));
108 }
109 else {
110 GParamSpec *spec;
111 spec = g_object_class_find_property (G_OBJECT_GET_CLASS(widget),
112 keys[i]);
113 if (spec == NULL)
114 continue;
115 switch (spec->value_type) {
116 case G_TYPE_BOOLEAN: {
117 g_object_set (widget, keys[i],
118 g_key_file_get_boolean (keyfile, wname, keys[i],
119 &error), NULL);
120 break;
121 }
122 case G_TYPE_INT:
123 case G_TYPE_UINT: {
124 g_object_set (widget, keys[i],
125 g_key_file_get_integer (keyfile, wname, keys[i],
126 &error), NULL);
127 break;
128 }
129 case G_TYPE_DOUBLE: {
130 #if KEY_FILE_SUPPORTS_DOUBLE
131 g_object_set (widget, keys[i],
132 g_key_file_get_double (keyfile, wname, keys[i],
133 &error), NULL);
134 #endif
135 break;
136 }
137 case G_TYPE_STRING: {
138 gchar *strval;
139 strval = g_key_file_get_string (keyfile, wname, keys[i], &error);
140 g_object_set (widget, keys[i], strval, NULL);
141 g_free (strval);
142 break;
143 }
144 default:
145 printf ("Unknown property type\n");
146 }
147 }
148 }
149
150 load_children:
151 if (keys != NULL)
152 g_strfreev (keys);
153
154 if (GTK_IS_CONTAINER(widget))
155 gtk_container_foreach (GTK_CONTAINER(widget),
156 (GtkCallback)_load_widget_state, keyfile);
157 }
158
159 void
160 g_persist_load (GtkWidget *widget)
161 {
162 GKeyFile *keyfile;
163 gchar *filename;
164 const gchar *wname;
165 GError *error = NULL;
166
167 if (widget == NULL)
168 return;
169
170 wname = gtk_widget_get_name (widget);
171 if (wname == NULL)
172 return;
173
174 filename = _get_persist_filename ();
175 keyfile = g_key_file_new ();
176 g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error);
177 g_free (filename);
178 if (error != NULL)
179 return;
180
181 _load_widget_state (widget, keyfile);
182 }
183
184 void
185 g_persist_save(GtkWidget *widget, ...)
186 {
187 va_list var_args;
188
189 va_start (var_args, widget);
190 g_persist_save_valist (widget, var_args);
191 va_end (var_args);
192 }
193
194 void
195 g_persist_save_valist(GtkWidget *widget, va_list var_args)
196 {
197 GKeyFile *keyfile;
198 char *filename, *dir;
199 const char *wname;
200 char *contents;
201 unsigned clength;
202 GPersistFlag flag;
203 GError *error = NULL;
204 struct stat stat_buf;
205
206 if (widget == NULL) {
207 printf ("Passed in a NULL pointer!\n");
208 return;
209 }
210
211 wname = gtk_widget_get_name (widget);
212 if (wname == NULL) {
213 printf ("Widget is not named.\n");
214 return;
215 }
216
217 filename = _get_persist_filename ();
218 keyfile = g_key_file_new ();
219 g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error);
220 error = NULL; // Ignore errors .. it's OK if the file didn't load
221
222 flag = va_arg (var_args, GPersistFlag);
223 while (flag != G_PERSIST_END) {
224
225 switch (flag) {
226 case G_PERSIST_SIZE: {
227 if (GTK_IS_WINDOW (widget)) {
228 gint size_array[2] = {
229 widget->allocation.width,
230 widget->allocation.height
231 };
232 g_key_file_set_integer_list(keyfile, wname, "Size", size_array, 2);
233 }
234 else {
235 // TODO
236 }
237 break;
238 }
239
240 case G_PERSIST_POSITION: {
241 if (GTK_IS_WINDOW (widget)) {
242 /* FIXME: Is this even posible? */
243 }
244 else if (GTK_IS_PANED (widget)) {
245 g_key_file_set_integer (keyfile,
246 wname,
247 "Position",
248 gtk_paned_get_position (GTK_PANED (widget)));
249 }
250 #if KEY_FILE_SUPPORTS_DOUBLE
251 else if (GTK_IS_RANGE (widget)) {
252 g_key_file_set_double (keyfile,
253 wname,
254 "Position",
255 gtk_range_get_value (GTK_RANGE (widget)));
256 }
257 #endif
258 break;
259 }
260
261 case G_PERSIST_SELECTED: {
262
263 if (GTK_IS_TREE_VIEW (widget)) {
264 GtkTreeModel *model;
265 GtkTreeSelection *selection;
266 GtkTreePath *path;
267 GtkTreeIter iter;
268
269 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
270 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
271 goto get_next_flag; /* nothing selected..move along */
272 path = gtk_tree_model_get_path (model, &iter);
273 g_key_file_set_string (keyfile,
274 wname,
275 "Selected",
276 gtk_tree_path_to_string (path));
277 }
278 else if (GTK_IS_NOTEBOOK (widget)) {
279 g_key_file_set_integer (keyfile,
280 wname,
281 "Selected",
282 gtk_notebook_get_current_page (GTK_NOTEBOOK (widget)));
283 }
284
285 break;
286 }
287
288 case G_PERSIST_MAXIMIZED: {
289 gboolean maxed;
290 maxed = gdk_window_get_state (
291 GTK_WIDGET (widget)->window) & GDK_WINDOW_STATE_MAXIMIZED;
292 g_key_file_set_boolean (keyfile, wname, "Maximized", maxed);
293 break;
294 }
295
296 case G_PERSIST_PROPERTY: {
297 gchar *property;
298 GParamSpec *spec;
299
300 property = va_arg (var_args, gchar *);
301 spec = g_object_class_find_property (G_OBJECT_GET_CLASS(widget), property);
302 if (spec == NULL) {
303 printf ("Error in retrieving property specfication for %s\n", property);
304 goto get_next_flag;
305 }
306
307 switch (spec->value_type) {
308 case G_TYPE_BOOLEAN: {
309 gboolean bval;
310 g_object_get (widget, property, &bval, NULL);
311 g_key_file_set_boolean (keyfile, wname, property, bval);
312 break;
313 }
314 case G_TYPE_INT:
315 case G_TYPE_UINT: {
316 gint ival;
317 g_object_get (widget, property, &ival, NULL);
318 g_key_file_set_integer (keyfile, wname, property, ival);
319 break;
320 }
321 case G_TYPE_DOUBLE: {
322 #if KEY_FILE_SUPPORTS_DOUBLE
323 double dval;
324 g_object_get (widget, property, &dval, NULL);
325 g_key_file_set_double (keyfile, wname, property, dval);
326 #endif
327 break;
328 }
329 case G_TYPE_STRING: {
330 gchar *strval;
331 g_object_get (widget, property, &strval, NULL);
332 g_key_file_set_string (keyfile, wname, property, strval);
333 g_free (strval);
334 break;
335 }
336 default:
337 printf ("Unknown property type\n");
338 }
339 }
340 }
341
342 get_next_flag:
343 flag = va_arg (var_args, GPersistFlag);
344 }
345
346 contents = g_key_file_to_data (keyfile, &clength, &error);
347 if (error != NULL) {
348 printf ("an err occur'd: %s\n", error->message);
349 return;
350 }
351
352 dir = _get_app_directory ();
353 /* wtf? g_stat () sets clength to 0! */
354 if (stat (dir, &stat_buf) == -1) {
355 printf ("creating direcory %s\n", dir);
356 g_mkdir (dir, 0750);
357 }
358 g_free (dir);
359
360 FILE *f = fopen (filename, "w");
361 g_free (filename);
362 fwrite (contents, clength, 1, f);
363 fclose (f);
364 }
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.