]> spindle.queued.net Git - midori/commitdiff
Generate speed dial from key file without JSON
authorPaweł Forysiuk <tuxator@o2.pl>
Tue, 22 Mar 2011 21:59:56 +0000 (22:59 +0100)
committerChristian Dywan <christian@twotoasts.de>
Tue, 22 Mar 2011 22:02:00 +0000 (23:02 +0100)
A timer for speed dial is shown if MIDORI_STARTTIME is defined.

data/speeddial-head.html
midori/midori-browser.c
midori/midori-view.c

index bf38d672c9a08246c73117c73345892d317328f9..b68d1099fc90a91045020b930f1db275286c7d63 100644 (file)
         margin: 0px;
         padding: 5px 0px 0px;
         color: #222;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        overflow: hidden;
     }
 
     div.clear {
 
     <script type="text/javascript">
 
-    var sc = JSON.decode ({json_data});
-
-    var encodeSafe = function (obj) {
-        var str = JSON.encode (obj);
-        str = str.replace (/\'/g, '\\\'');
-        return str;
-    }
-
     var getAction = function (id)
     {
         var a = $(id).getFirst ();
         a.getNext().set('text', name);
 
         var num = id.substr (1) - 1;
-        sc.shortcuts[num].title = name;
 
         a.empty();
         var im = new Element('img', { src: '{stock}/image-loading' });
         a.addClass ('waiter');
         a.grab (im);
 
-        getThumbnail (id, url);
-        return false;
-    }
-
-    var getThumbnail = function (id, url)
-    {
-        console.log ("speed_dial-get-thumbnail " + id + " " + url);
+        console.log ("speed_dial-save-add " + id + " " + url + " " + name);
         return false;
     }
 
-    var setThumbnail = function (id, data, href)
-    {
-        var a = $(id).getFirst ();
-        var im = new Element ('img', { src: 'data:image/png;base64,' + data });
-
-        a.empty ().removeClass ('waiter').grab (im);
-        a.setProperty ('href', href);
-
-        var cross = new Element ('div', { 'html': '' });
-        cross.setProperty ('onclick', 'clearShortcut("' + id + '");');
-        cross.addClass ('cross');
-        cross.inject ($(id), 'top');
-
-        $(id).addClass ('activated');
-
-        var p = a.getNext ();
-        p.setProperty('onclick', 'javascript:renameShortcut("' + id + '");');
-
-        var num = id.substr (1) - 1;
-        sc.shortcuts[num].href = href;
-        sc.shortcuts[num].img = data;
-
-        console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
-    }
-
     var renameShortcut = function (id)
     {
         var num = id.substr (1) - 1;
-        var name = prompt ("{enter_shortcut_name}", sc.shortcuts[num].title);
+        var name = prompt ("{enter_shortcut_name}", $(id).getLast ().get ('html', name));
         if (!name) return;
 
         $(id).getLast ().set ('html', name);
-        sc.shortcuts[num].title = name;
 
-        console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
+        console.log ("speed_dial-save-rename " + id + " " + name);
     }
 
     var clearShortcut = function (id)
         a.setProperty ('href', '#');
         p.empty ().removeProperty ('onclick');
 
-        num -= 1;
-        sc.shortcuts[num].href = "#";
-        sc.shortcuts[num].title = "";
-        sc.shortcuts[num].img = "";
-
-        console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
-    }
-
-    var buildSpeeddial = function ()
-    {
-        var width = 3;
-        var thumb = 160;
-
-        if (sc.thumb)
-        {
-            thumb = sc.thumb;
-            setThumbSize(thumb);
-        }
-
-        if (sc.width)
-        {
-            width = sc.width;
-            $('wrap').style.width = (width * (thumb + 60)) + 'px';
-        }
-
-        sc.shortcuts.each (function (item, index, sc)
-        {
-            var cl = "shortcut";
-
-            if (index < width)
-                cl += " top";
-            if ((index % width) == (width - 1))
-                cl += " right";
-
-            var div = new Element ('div', {
-                'class': cl,
-                'id': item.id
-            });
-
-            var a = new Element ('a', {
-                'href': item.href,
-                'events': {
-                    'click': function () {
-                        return getAction (item.id);
-                    }
-                }
-            });
-
-            var p = new Element ('p', {
-                'text': item.title
-            });
-
-            if (item.href == "#")
-                a.set ('html', '<h1>' + item.id.substr (1) + '</h1><h4><span/></h4>');
-            else
-            {
-                div.addClass ('activated');
-                var im = new Element ('img', { src: 'data:image/png;base64,' + item.img });
-                var cross = new Element ('div', { 'html': '' });
-                cross.setProperty ('onclick', 'clearShortcut("' + item.id + '");');
-                cross.addClass ('cross');
-                cross.inject (div, 'top');
-                a.grab (im);
-                p.setProperty('onclick', 'javascript:renameShortcut("' + item.id + '");');
-            }
-
-            div.grab (a);
-            div.grab (p);
-            $('content').grab (div);
-        });
+        console.log ("speed_dial-save-delete " + id);
     }
 
     var setSize = function ()
     {
-        if (typeof sc.width == 'undefined')
-            sc.width = 3;
-        var rows = Math.ceil (sc.shortcuts.length / sc.width);
-        var size = prompt ("{enter_dial_size}", sc.width + 'x' + rows);
+
+        var size = prompt ("{enter_dial_size}", columns + 'x' + rows);
 
         if (!size) return;
 
             return;
         }
 
-        sc.width = cols;
-
-        var count = cols * rows;
-
-        sc.shortcuts = sc.shortcuts.slice (0, count);
-
-        var i = sc.shortcuts.length;
-        while (i < count)
-        {
-            i++;
-            sc.shortcuts.push ({"id" : "s" + i, "href" : "#", "title" : "", "img" : ""});
-        }
-
-        $('content').empty ();
-        buildSpeeddial ();
-
-        console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
+        console.log ("speed_dial-save-size " + cols  + " " + rows);
     }
 
     var setThumbSize = function (size)
         var i;
         var rules = document.styleSheets[0].cssRules;
 
-        var width = 3;
-        if (sc.width)
-            width = sc.width;
-
+        var width = columns;
         var height = Math.round (size / 1.5);
 
         $('wrap').style.width = (width * (size + 60)) + 'px';
                     break;
             }
         }
-
-       if (sc.thumb != size)
-       {
-            sc.thumb = size;
-            console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
-       }
+        console.log ("speed_dial-save-thumbsize " + size);
     }
 
-    window.addEvent ('domready', function () {
-        buildSpeeddial ();
-    });
-
     var key_id = 's';
     var key_timeout;
 
     </div>
     <div id="wrap">
         <div id="content">
-        </div>
-    </div>
-</body>
-</html>
-
index d552281ea06eb8503d25eba5702137b06ed88a1e..c2e2934bfc169a467301b5946b05aa2dc3ffd20f 100644 (file)
@@ -1111,79 +1111,37 @@ midori_view_save_as_cb (GtkWidget*   menuitem,
 }
 
 static gchar*
-midori_browser_speed_dial_get_next_free_slot (void)
+midori_browser_speed_dial_get_next_free_slot (MidoriView* view)
 {
-    GRegex* regex;
-    GMatchInfo* match_info;
-    gchar* speed_dial_body;
-    gchar* body_fname;
-    gchar* slot_id = NULL;
+    MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (view));
+    GKeyFile* key_file;
+    guint cols, rows, slot = 1;
 
-    body_fname = g_build_filename (sokoke_set_config_dir (NULL),
-                                   "speeddial.json", NULL);
-
-    if (g_access (body_fname, F_OK) != 0)
+    g_object_get (browser, "speed-dial", &key_file, NULL);
+    rows = g_key_file_get_integer (key_file, "settings", "rows", NULL);
+    cols = g_key_file_get_integer (key_file, "settings", "columns", NULL);
+    while (slot <= cols * rows)
     {
-        gchar* filename = g_build_filename ("midori", "res", "speeddial.json", NULL);
-        gchar* filepath = sokoke_find_data_filename (filename);
-        g_free (filename);
-        if (g_file_get_contents (filepath, &speed_dial_body, NULL, NULL))
+        gchar* dial_id = g_strdup_printf ("Dial %d", slot);
+        if (!g_key_file_has_group (key_file, dial_id))
         {
-            g_file_set_contents (body_fname, speed_dial_body, -1, NULL);
-
-            g_free (speed_dial_body);
+            g_free (dial_id);
+            return g_strdup_printf ("s%d", slot);
         }
-        g_free (filepath);
-        g_free (body_fname);
-        return g_strdup ("s1");
-    }
-    else
-        g_file_get_contents (body_fname, &speed_dial_body, NULL, NULL);
-
-    regex = g_regex_new ("\"id\":\"(s[0-9]{1,2})\",\"href\":\"#\"",
-                         G_REGEX_MULTILINE, 0, NULL);
-
-    if (g_regex_match (regex, speed_dial_body, 0, &match_info))
-    {
-        slot_id = g_match_info_fetch (match_info, 1);
-        g_match_info_free (match_info);
+        g_free (dial_id);
+        slot++;
     }
-
-    if (!g_strcmp0 (slot_id, ""))
-        g_free (slot_id);
-
-    g_free (body_fname);
-    g_free (speed_dial_body);
-    g_free (regex);
-
-    return slot_id;
+    return NULL;
 }
 
 static void
 midori_browser_add_speed_dial (MidoriBrowser* browser)
 {
     GdkPixbuf* img;
-    gchar* replace_from;
-    gchar* replace_by;
-    gsize len;
-
     GtkWidget* view = midori_browser_get_current_tab (browser);
-
     gchar* uri = g_strdup (midori_view_get_display_uri (MIDORI_VIEW (view)));
     gchar* title = g_strdup (midori_view_get_display_title (MIDORI_VIEW (view)));
-    gchar* slot_id = midori_browser_speed_dial_get_next_free_slot ();
-
-    GRegex* reg_quotes = g_regex_new ("'", 0, 0, NULL);
-    GRegex* reg_others = g_regex_new ("[\\\"\\\\]", 0, 0, NULL);
-    gchar* temp_title = g_regex_replace_literal (reg_others, title,
-                                                 -1, 0, " ", 0, NULL);
-    g_free (title);
-    title = g_regex_replace_literal (reg_quotes, temp_title, -1, 0,
-                                     "\\\\'", 0, NULL);
-
-    g_free (temp_title);
-    g_regex_unref (reg_quotes);
-    g_regex_unref (reg_others);
+    gchar* slot_id = midori_browser_speed_dial_get_next_free_slot (MIDORI_VIEW (view));
 
     if (slot_id == NULL)
     {
@@ -1192,82 +1150,36 @@ midori_browser_add_speed_dial (MidoriBrowser* browser)
         return;
     }
 
-    if ((len = g_utf8_strlen (title, -1)) > 15)
+    if ((img = midori_view_get_snapshot (MIDORI_VIEW (view), 240, 160)))
     {
-        /**
-          * The case when a quote was escaped with a backslash and the
-          * backslash becomes the last character of the ellipsized string.
-          * This causes JSON parsing to fail.
-          * For example: "My Foo Bar \'b\..."
-          **/
-        GRegex* reg_unsafe = g_regex_new ("([\\\\]+\\.)", 0, 0, NULL);
-
-        gchar* temp;
-        gchar* ellipsized = g_malloc0 ( len + 1);
-
-        g_utf8_strncpy (ellipsized, title, 15);
-        g_free (title);
-
-        temp = g_strdup_printf ("%s...", ellipsized);
-        g_free  (ellipsized);
+        gint i;
+        GKeyFile* key_file;
+        gchar* dial_id = g_strdup_printf ("Dial %s", slot_id + 1);
+        gchar* config_file = g_build_filename (sokoke_set_config_dir (NULL),
+                                               "speeddial", NULL);
+        gchar* file_path = sokoke_build_thumbnail_path (slot_id);
+        g_object_get (browser, "speed-dial", &key_file, NULL);
 
-        title = g_regex_replace_literal (reg_unsafe, temp, -1, 0, ".", 0, NULL);
-        g_free (temp);
+        g_key_file_set_string (key_file, dial_id, "uri", uri);
+        g_key_file_set_string (key_file, dial_id, "title", title);
 
-        g_regex_unref (reg_unsafe);
-    }
+        gdk_pixbuf_save (img, file_path, "png", NULL, "compression", "7", NULL);
+        sokoke_key_file_save_to_file (key_file, config_file, NULL);
 
-    if ((img = midori_view_get_snapshot (MIDORI_VIEW (view), 240, 160)))
-    {
-        GRegex* regex;
-        gchar* replace;
-        gchar* file_content;
-        gchar* encoded;
-        gchar* speed_dial_body;
-        gchar* body_fname;
-        gsize sz;
+        i = 0;
+        while ((view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (
+                                                  browser->notebook), i++)))
+            if (midori_view_is_blank (MIDORI_VIEW (view)))
+                midori_view_reload (MIDORI_VIEW (view), FALSE);
 
-        body_fname = g_build_filename (sokoke_set_config_dir (NULL),
-                                       "speeddial.json", NULL);
 
-        if (g_file_get_contents (body_fname, &speed_dial_body, NULL, NULL))
-        {
-            gint i;
-
-            gdk_pixbuf_save_to_buffer (img, &file_content, &sz, "png", NULL, NULL);
-            encoded = g_base64_encode ((guchar *)file_content, sz);
-
-            replace_from = g_strdup_printf (
-                "\\{\"id\":\"%s\",\"href\":\"#\",\"title\":\"\",\"img\":\"\"\\}",
-                slot_id);
-            replace_by = g_strdup_printf (
-                "{\"id\":\"%s\",\"href\":\"%s\",\"title\":\"%s\",\"img\":\"%s\"}",
-                slot_id, uri, title, encoded);
-
-            regex = g_regex_new (replace_from, G_REGEX_MULTILINE, 0, NULL);
-            replace = g_regex_replace (regex, speed_dial_body, -1,
-                                       1, replace_by, 0, NULL);
-
-            g_file_set_contents (body_fname, replace, -1, NULL);
-
-            i = 0;
-            while ((view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (
-                                                      browser->notebook), i++)))
-                if (midori_view_is_blank (MIDORI_VIEW (view)))
-                    midori_view_reload (MIDORI_VIEW (view), FALSE);
-
-            g_object_unref (img);
-            g_regex_unref (regex);
-            g_free (encoded);
-            g_free (file_content);
-            g_free (speed_dial_body);
-            g_free (replace_from);
-            g_free (replace_by);
-            g_free (replace);
-        }
-        g_free (body_fname);
+        g_object_unref (img);
+        g_free (file_path);
+        g_free (config_file);
+        g_free (dial_id);
     }
     g_free (uri);
+    g_free (title);
     g_free (slot_id);
 }
 
index 5c4de0073f2725dba6707429092f908d318845d1..909508b5fe218566bedb350c9900e4f53060ad70 100644 (file)
@@ -234,12 +234,7 @@ midori_view_settings_notify_cb (MidoriWebSettings* settings,
                                 MidoriView*        view);
 
 static void
-midori_view_speed_dial_get_thumb (GtkWidget*   web_view,
-                                 const gchar* message,
-                                 MidoriView*  view);
-
-static void
-midori_view_speed_dial_save (GtkWidget*   web_view,
+midori_view_speed_dial_save (MidoriView*   view,
                              const gchar* message);
 
 static void
@@ -3050,10 +3045,8 @@ webkit_web_view_console_message_cb (GtkWidget*   web_view,
                                     const gchar* source_id,
                                     MidoriView*  view)
 {
-    if (!strncmp (message, "speed_dial-get-thumbnail", 22))
-        midori_view_speed_dial_get_thumb (web_view, message, view);
-    else if (!strncmp (message, "speed_dial-save", 13))
-        midori_view_speed_dial_save (web_view, message);
+    if (!strncmp (message, "speed_dial-save", 13))
+        midori_view_speed_dial_save (view, message);
     else
         g_signal_emit (view, signals[CONSOLE_MESSAGE], 0, message, line, source_id);
     return TRUE;
@@ -3784,6 +3777,102 @@ static gchar* list_netscape_plugins ()
     return g_string_free (ns_plugins, FALSE);
 }
 
+static gchar*
+prepare_speed_dial_html (MidoriView* view)
+{
+    MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (view));
+    GKeyFile* key_file;
+    GString* markup  = g_string_new (NULL);
+    guint rows, cols, slot = 1;
+    gchar* thumb_size_type;
+    guint thumb_size = 160;
+
+    g_object_get (browser, "speed-dial", &key_file, NULL);
+    if (!key_file)
+        return g_string_free (markup, FALSE);
+    rows = g_key_file_get_integer (key_file, "settings", "rows", NULL);
+    cols = g_key_file_get_integer (key_file, "settings", "columns", NULL);
+    thumb_size_type = g_key_file_get_string (key_file, "settings", "size", NULL);
+    if (thumb_size_type == NULL)
+        thumb_size_type = g_strdup ("MEDIUM");
+
+    if (g_str_equal (thumb_size_type, "SMALL"))
+        thumb_size = 80;
+    else if (g_str_equal (thumb_size_type, "MEDIUM"))
+        thumb_size = 160;
+    else if (g_str_equal (thumb_size_type, "BIG"))
+        thumb_size = 240;
+
+    g_free (thumb_size_type);
+
+    g_string_append_printf (markup,
+            "<script>var columns = %d; var rows = %d;"
+            "setThumbSize(%d);</script>\n",
+            cols, rows, thumb_size);
+
+    while (slot <= rows * cols)
+    {
+        gchar* position;
+        gchar* dial_entry = g_strdup_printf ("Dial %d", slot);
+        if (slot < cols)
+            position = g_strdup (" top");
+        else if (slot == cols)
+            position = g_strdup (" top right");
+        else if (slot > cols && slot % cols == 0)
+            position = g_strdup (" right");
+        else
+            position = g_strdup ("");
+
+        if (g_key_file_has_group (key_file, dial_entry))
+        {
+            gchar* slot_id = g_strdup_printf ("s%d", slot);
+            gchar* thumb_file = sokoke_build_thumbnail_path (slot_id);
+            gchar* uri = g_key_file_get_string (key_file, dial_entry, "uri", NULL);
+            gchar* title = g_key_file_get_string (key_file, dial_entry, "title", NULL);
+            gsize sz;
+            gchar* encoded;
+            gchar* thumb_content;
+
+            g_file_get_contents (thumb_file, &thumb_content, &sz, NULL);
+            encoded = g_base64_encode ((guchar*)thumb_content, sz);
+            g_free  (thumb_file);
+            g_free (thumb_content);
+            g_free (slot_id);
+
+            g_string_append_printf (markup,
+                    "<div class=\"shortcut%s activated\" id=\"s%d\">\n"
+                    "<div onclick='javascript:clearShortcut(\"s%d\");' "
+                    "class='cross'></div>\n<a href=\"%s\">"
+                    "<img src=\"data:image/png;base64,%s\"></a>\n"
+                    "<p onclick='javascript:renameShortcut(\"s%d\");'>"
+                    "‪%s</p></div>\n",
+                    position, slot, slot, uri, encoded, slot, title);
+
+            g_free (uri);
+            g_free (title);
+        }
+        else
+        {
+            g_string_append_printf (markup,
+                    "<div class=\"shortcut%s\" id=\"s%d\">"
+                    "\n<a href=\"#\" onclick='javascript:return"
+                    " getAction(\"s%d\");'>"
+                    "<h1>%d</h1>\n<h4><span></span><h4>"
+                    "</a>\n<p></p></div>\n",
+                    position, slot, slot, slot);
+        }
+
+        slot++;
+        g_free (position);
+        g_free (dial_entry);
+    }
+    g_string_append_printf (markup,
+            "</div>\n</div>\n</body>\n</html>\n");
+
+    return g_string_free (markup, FALSE);
+}
+
+
 /**
  * midori_view_set_uri:
  * @view: a #MidoriView
@@ -3820,9 +3909,14 @@ midori_view_set_uri (MidoriView*  view,
             gchar* res_root;
             gchar* speed_dial_head;
             gchar* speed_dial_body;
-            gchar* body_fname;
             gchar* stock_root;
             gchar* filepath;
+            #ifdef G_ENABLE_DEBUG
+            GTimer* timer = NULL;
+
+            if (g_getenv ("MIDORI_STARTTIME") != NULL)
+                timer = g_timer_new ();
+            #endif
 
             katze_assign (view->uri, g_strdup (""));
             katze_item_set_uri (view->item, "");
@@ -3842,26 +3936,10 @@ midori_view_set_uri (MidoriView*  view,
             res_root = g_strdup_printf ("http://localhost:%d/res", port);
             stock_root = g_strdup_printf ("http://localhost:%d/stock", port);
             #endif
-            body_fname = g_build_filename (sokoke_set_config_dir (NULL),
-                                           "speeddial.json", NULL);
-
-            if (g_access (body_fname, F_OK) != 0)
-            {
-                filepath = sokoke_find_data_filename ("midori/res/speeddial.json");
-                if (g_file_get_contents (filepath,
-                                         &speed_dial_body, NULL, NULL))
-                    g_file_set_contents (body_fname, speed_dial_body, -1, NULL);
-                else
-                    speed_dial_body = g_strdup ("");
-                g_free (filepath);
-            }
-            else
-                g_file_get_contents (body_fname, &speed_dial_body, NULL, NULL);
 
             data = sokoke_replace_variables (speed_dial_head,
                 "{res}", res_root,
                 "{stock}", stock_root,
-                "{json_data}", speed_dial_body,
                 "{title}", _("Speed dial"),
                 "{click_to_add}", _("Click to add a shortcut"),
                 "{enter_shortcut_address}", _("Enter shortcut address"),
@@ -3875,6 +3953,17 @@ midori_view_set_uri (MidoriView*  view,
                 "{set_thumb_normal}", _("Medium"),
                 "{set_thumb_big}", _("Big"),  NULL);
 
+            #ifdef G_ENABLE_DEBUG
+            if (g_getenv ("MIDORI_STARTTIME") != NULL)
+            {
+                g_debug ("Speed Dial: \t%fs", g_timer_elapsed (timer, NULL));
+                g_timer_destroy (timer);
+            }
+            #endif
+
+            speed_dial_body = prepare_speed_dial_html (view);
+            data = g_strdup_printf ("%s\n%s", data, prepare_speed_dial_html (view));
+
             midori_view_load_alternate_string (view,
                 data, res_root, "about:blank", NULL);
 
@@ -3883,7 +3972,6 @@ midori_view_set_uri (MidoriView*  view,
             g_free (data);
             g_free (speed_dial_head);
             g_free (speed_dial_body);
-            g_free (body_fname);
         }
         /* This is not prefectly elegant, but creating
            special pages inline is the simplest solution. */
@@ -5364,31 +5452,22 @@ thumb_view_load_status_cb (MidoriView* thumb_view,
                            MidoriView* view)
 {
     GdkPixbuf* img;
-    gchar* file_content;
-    gchar* encoded;
+    gchar* file_path;
     gchar* dom_id;
-    gchar* js;
-    gsize sz;
 
     if (midori_view_get_load_status (thumb_view) != MIDORI_LOAD_FINISHED)
         return;
 
     gtk_widget_realize (midori_view_get_web_view (MIDORI_VIEW (thumb_view)));
     img = midori_view_get_snapshot (MIDORI_VIEW (thumb_view), 240, 160);
-    gdk_pixbuf_save_to_buffer (img, &file_content, &sz, "png", NULL, "compression", "7", NULL);
-    encoded = g_base64_encode ((guchar *)file_content, sz );
-
-    /* Call Javascript function to replace shortcut's content */
     dom_id = g_object_get_data (G_OBJECT (thumb_view), "dom-id");
-    js = g_strdup_printf ("setThumbnail('%s','%s','%s');",
-                          dom_id, encoded, thumb_view->uri);
-    webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view->web_view), js);
-    g_free (js);
+    file_path  = sokoke_build_thumbnail_path (dom_id);
+    gdk_pixbuf_save (img, file_path, "png", NULL, "compression", "7", NULL);
+
     g_object_unref (img);
 
     g_free (dom_id);
-    g_free (encoded);
-    g_free (file_content);
+    g_free (file_path);
 
     g_signal_handlers_disconnect_by_func (
        thumb_view, thumb_view_load_status_cb, view);
@@ -5453,53 +5532,97 @@ midori_view_speed_dial_inject_thumb (MidoriView* view,
 }
 
 /**
- * midori_view_speed_dial_get_thumb
- * @web_view: a #WebkitView
- * @message: Console log data
- *
- * Load a thumbnail, and set the DOM
+ * midori_view_speed_dial_save
+ * @view: a #MidoriView
+ * @message: message from JavaScript
  *
- * message[0] == console message call
- * message[1] == shortcut id in the DOM
- * message[2] == shortcut uri
+ * Save speed_dial settings
  *
  **/
 static void
-midori_view_speed_dial_get_thumb (GtkWidget*   web_view,
-                                  const gchar* message,
-                                  MidoriView*  view)
+midori_view_speed_dial_save (MidoriView*  view,
+                             const gchar* message)
 {
-    gchar** t_data = g_strsplit (message," ", 4);
+    gchar* action;
+    gchar* config_file;
+    GKeyFile* key_file;
+    MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (view));
+    GtkWidget* notebook;
+    gchar* msg = g_strdup (message + 16);
+    gchar** parts = g_strsplit (msg, " ", 4);
 
-    if (t_data[1] == NULL || t_data[2] == NULL )
-        return;
+    g_object_get (browser, "notebook", &notebook, NULL);
+    g_object_get (browser, "speed-dial", &key_file, NULL);
+    action = parts[0];
 
-    midori_view_speed_dial_inject_thumb (view, NULL,
-        g_strdup (t_data[1]), g_strdup (t_data[2]));
-    g_strfreev (t_data);
-}
+    if (g_str_equal (action, "size"))
+    {
+        g_key_file_set_string (key_file, "settings", "rows", parts[2]);
+        g_key_file_set_string (key_file, "settings", "columns", parts[1]);
+    }
+    else if (g_str_equal (action, "thumbsize"))
+    {
+        gchar* saved_size;
+        gchar* thumb_size_type;
+        guint size = atoi (parts[1]);
+
+        if (size == 80)
+            thumb_size_type = g_strdup ("SMALL");
+        else if (size == 240)
+            thumb_size_type = g_strdup ("BIG");
+        else /* if (size == 160) */
+            thumb_size_type = g_strdup ("MEDIUM");
+
+        saved_size = g_key_file_get_string (key_file, "settings", "size", NULL);
+        if (saved_size != NULL && g_str_equal (saved_size, thumb_size_type))
+        {
+            g_free (action);
+            g_free (msg);
+            g_free (thumb_size_type);
+            g_free (saved_size);
+            return;
+        }
 
-/**
- * midori_view_speed_dial_save
- * @web_view: a #WebkitView
- *
- * Save speed_dial DOM structure to body template
- *
- **/
-static void
-midori_view_speed_dial_save (GtkWidget*   web_view,
-                             const gchar* message)
-{
-    gchar* json = g_strdup (message + 15);
-    gchar* fname = g_build_filename (sokoke_set_config_dir (NULL),
-                                     "speeddial.json", NULL);
+        g_key_file_set_string (key_file, "settings", "size", thumb_size_type);
+        g_free (thumb_size_type);
+        g_free (saved_size);
+    }
+    else if (g_str_equal (action, "add") || g_str_equal (action, "rename")
+          || g_str_equal (action, "delete"))
+    {
+        gchar* tmp = g_strdup (parts[1] + 1);
+        guint slot_id = atoi (tmp);
+        gchar* dial_id = g_strdup_printf ("Dial %d", slot_id);
+        g_free (tmp);
+
+
+        if (g_str_equal (action, "delete"))
+        {
+            gchar* file_path = sokoke_build_thumbnail_path (parts[1]);
+
+            g_key_file_remove_group (key_file, dial_id, NULL);
+            g_unlink (file_path);
+
+            g_free (file_path);
+        }
+        else if (g_str_equal (action, "add"))
+        {
+            g_key_file_set_string (key_file, dial_id, "uri", parts[2]);
+            g_key_file_set_string (key_file, dial_id, "title", parts[3]);
+            midori_view_speed_dial_inject_thumb (view, NULL, parts[1], parts[2]);
+        }
+        else if (g_str_equal (action, "rename"))
+        {
+            g_key_file_set_string (key_file, dial_id, "title", parts[2]);
+        }
+
+        g_free (dial_id);
+    }
 
-    GRegex* reg_double = g_regex_new ("\\\\\"", 0, 0, NULL);
-    gchar* safe = g_regex_replace_literal (reg_double, json, -1, 0, "\\\\\"", 0, NULL);
-    g_file_set_contents (fname, safe, -1, NULL);
+    config_file = g_build_filename (sokoke_set_config_dir (NULL), "speeddial", NULL);
+    sokoke_key_file_save_to_file (key_file, config_file, NULL);
 
-    g_free (fname);
-    g_free (json);
-    g_free (safe);
-    g_regex_unref (reg_double);
+    g_free (msg);
+    g_free (action);
+    g_free (config_file);
 }