Fix hildon-desktop crashing if snap-grid == 0, and bump values up a bit.
[tweakr] / modules / tweakr-desktop.c
index 0aa8a6e..e07412a 100644 (file)
@@ -3,10 +3,17 @@
  */ 
 
 #include <config.h>
+#include <glib.h>
+#include <glib/gi18n-lib.h>
 
 #include <gtk/gtk.h>
 #include <hildon/hildon-picker-button.h>
 #include <hildon/hildon-touch-selector.h>
+#include <hildon/hildon-button.h>
+#include <hildon/hildon-entry.h>
+#include <hildon/hildon-pannable-area.h>
+#include <hildon/hildon-defines.h>
+#include <gconf/gconf-client.h>
 
 #include "libtweakr-section/tweakr-section.h"
 #include "libtweakr-section/tweakr-module.h"
@@ -26,6 +33,8 @@
         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
         TWEAKR_TYPE_DESKTOP_SECTION))
 
+#define GCONF_BOOKMARKS "/apps/osso/hildon-home/bookmarks"
+#define GCONF_APPLETS   "/apps/osso/hildon-desktop/applets"
 
 enum
 {
@@ -37,10 +46,10 @@ enum
 
 enum
 {
-    SNAP_NONE_VALUE,
-    SNAP_SMALL_VALUE = 8,
-    SNAP_LARGE_VALUE = 16,
-    SNAP_HUGE_VALUE = 32
+    SNAP_NONE_VALUE = 4,
+    SNAP_SMALL_VALUE = 16,
+    SNAP_LARGE_VALUE = 32,
+    SNAP_HUGE_VALUE = 48
 };
 
 static gint snap_values [] = {
@@ -50,6 +59,13 @@ static gint snap_values [] = {
     SNAP_HUGE_VALUE
 };
 
+typedef struct
+{
+    gchar *path;
+    gchar *value;
+    guint modified : 1;
+} bookmark_t;
+
 typedef struct _TweakrDesktopSection TweakrDesktopSection;
 typedef struct _TweakrDesktopSectionClass
                TweakrDesktopSectionClass;
@@ -60,6 +76,13 @@ struct _TweakrDesktopSection
 
     GKeyFile *ini;
     GtkWidget *snap_button;
+
+    GConfClient *gconf;
+    GtkWidget *bookmarks_button;
+    GtkWidget *bookmarks_dialog;
+    GtkWidget *bookmarks_box;
+    GHashTable *bookmarks_table;
+    guint save_bookmarks : 1;
 };
 
 struct _TweakrDesktopSectionClass
@@ -140,7 +163,14 @@ tweakr_desktop_section_class_init
 
 GtkWidget * _build_snap_to_grid (void)
 {
-    const gchar *options[] = {"No", "Small", "Large", "Huge", NULL};
+    const gchar *options[] =
+    {
+        _("No"),
+        _("Small"),
+        _("Large"),
+        _("Huge"),
+        NULL
+    };
     gint i = 0;
     GtkWidget *button, *selector;
 
@@ -156,7 +186,7 @@ GtkWidget * _build_snap_to_grid (void)
     hildon_gtk_widget_set_theme_size (button, HILDON_SIZE_FINGER_HEIGHT);
 
     hildon_button_set_title (HILDON_BUTTON (button),
-                             "Snap icons to grid");
+                             _("Snap icons to grid"));
     gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
     hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
                                        HILDON_TOUCH_SELECTOR (selector));
@@ -166,54 +196,253 @@ GtkWidget * _build_snap_to_grid (void)
 }
 
 static void
-tweakr_desktop_section_init (TweakrDesktopSection *section)
+_bookmark_t_destroy (bookmark_t *b)
 {
-    TweakrSection *iface;
+    g_free (b->path);
+    g_free (b->value);
+    g_free (b);
+}
 
-    gint snap_value = SNAP_NONE_VALUE;
+static void
+_bookmark_clicked (HildonButton *button, TweakrDesktopSection *section)
+{
+    GtkWidget *dialog, *entry;
+    gint ret;
 
-    section->snap_button = _build_snap_to_grid ();
+    dialog = gtk_dialog_new_with_buttons
+            (_("Edit label"),
+             GTK_WINDOW (section->bookmarks_dialog),
+             GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
+             GTK_STOCK_OK, GTK_RESPONSE_OK,
+             NULL);
 
-    section->ini = g_key_file_new ();
+    entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT);
+    hildon_entry_set_text (HILDON_ENTRY (entry),
+                           hildon_button_get_title (button));
 
-    if (!g_key_file_load_from_file (section->ini, TRANSITIONS,
-                                    G_KEY_FILE_NONE, NULL))
+    gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
+    gtk_widget_show (entry);
+
+    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), entry,
+                        TRUE, TRUE, 0);
+
+    ret = gtk_dialog_run (GTK_DIALOG (dialog));
+    if (ret == GTK_RESPONSE_OK)
     {
-        g_warning ("%s: failed to load %s", G_STRFUNC, TRANSITIONS);
-        return;
+        bookmark_t *b;
+        const gchar *label;
+
+        label = hildon_entry_get_text (HILDON_ENTRY (entry));
+        if (label && label[0])
+        {
+            hildon_button_set_title (button, label);
+
+            b = g_hash_table_lookup (section->bookmarks_table, button);
+            if (b)
+            {
+                g_free (b->value);
+                b->value = g_strdup (label);
+                b->modified = TRUE;
+            }
+        }
     }
 
-    snap_value = g_key_file_get_integer (section->ini, "edit_mode",
-                                         "snap_grid_size", NULL);
+    gtk_widget_destroy (dialog);
+}
+
+static void
+_add_bookmark (gchar *bookmark, TweakrDesktopSection *section)
+{
+    bookmark_t *b;
+    gchar *title, *value, *url;
+    GtkWidget *button;
+
+    gchar *bookmark_name;
+    gchar *applet_path;
+    gchar *view_path;
+
+    b = g_new0 (bookmark_t, 1);
+    b->path = g_strconcat (bookmark, "/label", NULL);
+
+    url   = g_strconcat (bookmark, "/url",   NULL);
+    title = gconf_client_get_string (section->gconf, b->path, NULL);
+    value = gconf_client_get_string (section->gconf, url,     NULL);
+
+    g_free (url);
+
+    bookmark_name = g_path_get_basename (bookmark);
+    applet_path = g_strconcat (GCONF_APPLETS, "/BookmarkShortcut:",
+                               bookmark_name, NULL);
+    view_path = g_strconcat (applet_path, "/view", NULL);
+    if (applet_path &&
+        gconf_client_dir_exists (section->gconf, applet_path, NULL) &&
+        gconf_client_get_int (section->gconf, view_path, NULL) != 0)
+    {
+        button = hildon_button_new_with_text
+            (HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL,
+             title, value);
+        gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
+        gtk_box_pack_start (GTK_BOX (section->bookmarks_box), button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (button, "clicked", G_CALLBACK (_bookmark_clicked),
+                                              section);
 
-    if (snap_value < SNAP_SMALL_VALUE)
+        if (section->bookmarks_table == NULL)
+        {
+            section->bookmarks_table = g_hash_table_new_full
+                (g_direct_hash, g_direct_equal, NULL,
+                 (GDestroyNotify) _bookmark_t_destroy);
+        }
+        g_hash_table_insert (section->bookmarks_table, button, b);
+    }
+    else
     {
-        hildon_picker_button_set_active
-            (HILDON_PICKER_BUTTON (section->snap_button), SNAP_NONE);
+        _bookmark_t_destroy (b);
     }
-    else if (snap_value < SNAP_LARGE_VALUE)
+
+    g_free (title);
+    g_free (value);
+    g_free (bookmark_name);
+    g_free (applet_path);
+    g_free (view_path);
+}
+
+static void
+_edit_bookmarks_clicked (GtkButton *button, TweakrDesktopSection *section)
+{
+    GSList *bookmarks;
+
+    bookmarks = gconf_client_all_dirs (section->gconf, GCONF_BOOKMARKS,
+                                       NULL);
+    if (bookmarks && g_slist_length (bookmarks) > 0)
     {
-        hildon_picker_button_set_active
-            (HILDON_PICKER_BUTTON (section->snap_button), SNAP_SMALL);
+        GtkWidget *panarea;
+        gint ret;
+
+        if (section->bookmarks_dialog == NULL)
+        {
+            section->bookmarks_dialog = gtk_dialog_new_with_buttons
+                (_("Edit desktop bookmarks"),
+                 GTK_WINDOW (gtk_widget_get_ancestor
+                             (tweakr_section_get_widget
+                              (TWEAKR_SECTION (section)),
+                              GTK_TYPE_WINDOW)),
+                 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
+                 GTK_STOCK_OK, GTK_RESPONSE_OK,
+                 NULL);
+
+            panarea = hildon_pannable_area_new ();
+            section->bookmarks_box = gtk_vbox_new (FALSE, 0);
+            hildon_pannable_area_add_with_viewport
+                (HILDON_PANNABLE_AREA (panarea), section->bookmarks_box);
+            g_object_set (G_OBJECT (panarea), "height-request",
+                          MIN (350, g_slist_length (bookmarks) * 70), NULL);
+
+            g_slist_foreach (bookmarks, (GFunc) _add_bookmark, section);
+
+            gtk_box_pack_start
+                (GTK_BOX (GTK_DIALOG (section->bookmarks_dialog)->vbox),
+                 panarea, TRUE, TRUE, 0);
+        }
+        gtk_widget_show_all (GTK_DIALOG (section->bookmarks_dialog)->vbox);
+        ret = gtk_dialog_run (GTK_DIALOG (section->bookmarks_dialog));
+        if (ret == GTK_RESPONSE_OK)
+        {
+            section->save_bookmarks = TRUE;
+        }
+        gtk_widget_hide (section->bookmarks_dialog);
+
+        g_slist_foreach (bookmarks, (GFunc) g_free, NULL);
+        g_slist_free (bookmarks);
     }
-    else if (snap_value < SNAP_HUGE_VALUE)
+}
+
+static GtkWidget *
+_build_bookmarks_button (TweakrDesktopSection *section)
+{
+    GtkWidget *button;
+
+    if (!gconf_client_dir_exists (section->gconf, GCONF_BOOKMARKS, NULL))
     {
-        hildon_picker_button_set_active
-            (HILDON_PICKER_BUTTON (section->snap_button), SNAP_LARGE);
+        return NULL;
     }
-    else
+
+    button = hildon_button_new_with_text (HILDON_SIZE_AUTO,
+                                          HILDON_BUTTON_ARRANGEMENT_VERTICAL,
+                                          _("Edit desktop bookmarks"), "");
+    gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
+    hildon_gtk_widget_set_theme_size (button, HILDON_SIZE_FINGER_HEIGHT);
+
+    g_signal_connect (button, "clicked",
+                      G_CALLBACK (_edit_bookmarks_clicked), section);
+    gtk_widget_show (button);
+    return button;
+}
+
+static void
+tweakr_desktop_section_init (TweakrDesktopSection *section)
+{
+    TweakrSection *iface;
+
+    gint snap_value = SNAP_NONE_VALUE;
+
+    section->ini = g_key_file_new ();
+
+    if (!g_key_file_load_from_file (section->ini, TRANSITIONS,
+                                    G_KEY_FILE_NONE, NULL))
     {
-        hildon_picker_button_set_active
-            (HILDON_PICKER_BUTTON (section->snap_button), SNAP_HUGE);
+        g_warning ("%s: failed to load %s", G_STRFUNC, TRANSITIONS);
+        return;
     }
 
+    if (g_key_file_has_key (section->ini, "edit_mode", "snap_grid_size",
+                            NULL))
+    {
+        section->snap_button = _build_snap_to_grid ();
+
+        snap_value = g_key_file_get_integer (section->ini, "edit_mode",
+                                             "snap_grid_size", NULL);
 
+        if (snap_value < SNAP_SMALL_VALUE)
+        {
+            hildon_picker_button_set_active
+                (HILDON_PICKER_BUTTON (section->snap_button), SNAP_NONE);
+        }
+        else if (snap_value < SNAP_LARGE_VALUE)
+        {
+            hildon_picker_button_set_active
+                (HILDON_PICKER_BUTTON (section->snap_button), SNAP_SMALL);
+        }
+        else if (snap_value < SNAP_HUGE_VALUE)
+        {
+            hildon_picker_button_set_active
+                (HILDON_PICKER_BUTTON (section->snap_button), SNAP_LARGE);
+        }
+        else
+        {
+            hildon_picker_button_set_active
+                (HILDON_PICKER_BUTTON (section->snap_button), SNAP_HUGE);
+        }
+    }
+    section->gconf = gconf_client_get_default ();
+    section->bookmarks_button = _build_bookmarks_button (section);
 
     iface = TWEAKR_SECTION (section);
-    iface->name = "Desktop";
+    iface->name = _("Desktop");
     iface->widget = gtk_vbox_new (FALSE, 0);
-    gtk_box_pack_start (GTK_BOX (iface->widget), section->snap_button,
-                        FALSE, FALSE, 0);
+
+    if (section->snap_button)
+    {
+        gtk_box_pack_start (GTK_BOX (iface->widget), section->snap_button,
+                            FALSE, FALSE, 0);
+    }
+    if (section->bookmarks_button)
+    {
+        gtk_box_pack_start (GTK_BOX (iface->widget),
+                            section->bookmarks_button,
+                            FALSE, FALSE, 0);
+    }
 }
 
 static void
@@ -226,13 +455,34 @@ tweakr_desktop_section_dispose (GObject *obj)
         section->ini = NULL;
     }
 
+    if (section->gconf)
+    {
+        g_object_unref (section->gconf);
+        section->gconf = NULL;
+    }
+
+    if (section->bookmarks_table)
+    {
+        g_hash_table_destroy (section->bookmarks_table);
+        section->bookmarks_table = NULL;
+    }
+
     G_OBJECT_CLASS (tweakr_desktop_section_parent_class)->dispose
         (obj);
 }
 
+static void
+_save_bookmarks (HildonButton *button, bookmark_t *b,
+                 TweakrDesktopSection *section)
+{
+    if (b->modified)
+    {
+        gconf_client_set_string (section->gconf, b->path, b->value, NULL);
+    }
+}
 
-static gboolean  _save (TweakrSection *section,
-                        gboolean *requires_restart)
+static gboolean _save (TweakrSection *section,
+                       gboolean *requires_restart)
 {
     gchar *argv[3];
     gint active;
@@ -252,6 +502,14 @@ static gboolean  _save (TweakrSection *section,
     g_free (argv[0]);
     g_free (argv[1]);
 
+    if (TWEAKR_DESKTOP_SECTION (section)->save_bookmarks)
+    {
+        g_hash_table_foreach
+            (TWEAKR_DESKTOP_SECTION (section)->bookmarks_table,
+             (GHFunc) _save_bookmarks, section);
+        *requires_restart = TRUE;
+    }
+
     return TRUE;
 }