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.
  • [get | view] (2021-02-25 09:55:42, 11.3 KB) [[attachment:gpersist.c]]
  • [get | view] (2021-02-25 09:55:42, 0.3 KB) [[attachment:gpersist.h]]
  • [get | view] (2021-02-25 09:55:42, 2.6 KB) [[attachment:test.c]]
  • [get | view] (2021-02-25 09:55:42, 9.8 KB) [[attachment:testui.glade]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.