Xfce Wiki

Sub domains
 

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
midori:tutorial [2013/07/28 23:28] – [Add a context menu item] kalikianamidori:tutorial [2014/06/06 20:08] (current) – [Add a new extension] axlrose
Line 11: Line 11:
 To develop and build extensions you need a source tree, typically it is a good idea to use the latest trunk to benefit from the latest and greatest features or bug fixes. So if your extension uncovers a bug you can easily report it and get it fixed. To develop and build extensions you need a source tree, typically it is a good idea to use the latest trunk to benefit from the latest and greatest features or bug fixes. So if your extension uncovers a bug you can easily report it and get it fixed.
 For more details see [[contribute]] which also covers how to make a branch and codying style in detail. For more details see [[contribute]] which also covers how to make a branch and codying style in detail.
 +
  
 ====== Add a new extension ===== ====== Add a new extension =====
Line 21: Line 22:
     private class Manager : Midori.Extension {     private class Manager : Midori.Extension {
  
-    internal Manager () { +        internal Manager () { 
-        GLib.Object (name: _("Furry example extension"),+            GLib.Object (name: _("Furry example extension"),
                          description: _("Take care of petting cats"),                          description: _("Take care of petting cats"),
                          version: "0.1" + Midori.VERSION_SUFFIX,                          version: "0.1" + Midori.VERSION_SUFFIX,
                          authors: "Jane Doe <email@domain.tld>");                          authors: "Jane Doe <email@domain.tld>");
-    }+        } 
 +    }    
 } }
    
Line 36: Line 38:
 Now let's proceed to run our rather empty extension. Now let's proceed to run our rather empty extension.
  
-<code bash>./waf +**__The first instrruction__** 
-_build/default/midori/midori -g -c ~/midoridevel</code>+<code bash>user@host:~/midori$ mkdir build ; cd build 
 +user@host:~/midori/build$ cmake .
 +user@host:~/midori/build$ make 
 +user@host:~/midori/build$ ./midori/midori -g -c ~/midoridevel</code> 
 +After any modifiction in "sandcat.vala" you just run: 
 +<code bash>user@host:~/midori/build$ make </code> 
 +If you add a new extention you will run : 
 +<code bash>user@host:~/midori/build$ make clean 
 +user@host:~/midori/build$ cd .. ; rm -rf build</code> 
 +and after you use the **__The first instrruction__**.
  
 Inside Midori, open the Preferences, go to Extensions, and look for your new extension in the list. Activate and be proud of completing the first part of the tutorial! Inside Midori, open the Preferences, go to Extensions, and look for your new extension in the list. Activate and be proud of completing the first part of the tutorial!
- 
 ====== Activating the extension ====== ====== Activating the extension ======
  
Line 46: Line 56:
  
 <code vala> <code vala>
-void browser_added (Midori.Browser browser) { +namespace Sandcat { 
-    stdout.printf ("a new browser was addedyay\n"); +    private class Manager : Midori.Extension { 
-}+  
 +        internal Manager () { 
 +            GLib.Object (name: _("Furry example extension"), 
 +                         description: _("Take care of petting cats"), 
 +                         version: "0.1" + Midori.VERSION_SUFFIX, 
 +                         authors: "Jane Doe <email@domain.tld>"); 
 +            activate.connect (this.activated); //it will run the method activated 
 +            deactivate.connect (this.deactivated); //it will run the method deactivated 
 +        }
  
-void activated (Midori.App app) { +        void browser_added (Midori.Browser browser) { 
-    foreach (var browser in app.get_browsers ()) +            stdout.printf ("a new browser was added, yay\n"); 
-        browser_added (browser); +        } 
-    app.add_browser.connect (browser_added);+  
 +        void activated (Midori.App app) { 
 +            foreach (var browser in app.get_browsers ()) 
 +            browser_added (browser); 
 +            app.add_browser.connect (browser_added); 
 +        } 
 +  
 +        void deactivated () { 
 +            var app = get_app (); 
 +            app.add_browser.disconnect (browser_added); 
 +        } 
 +    }
 } }
  
-void deactivated () { +public Midori.Extension extension_init () { 
-    var app = get_app (); +    return new Sandcat.Manager ();
-    app.add_browser.disconnect (browser_added);+
 } }
 </code> </code>
 +You'll see how when activated the extension gets an "app" which is a running Midori instance. It has among other things knowledge of browser windows. It's good practise to not make any assumptions on how many windows are open.
  
-In your Manager you connect these new callbacks:+====== Working with (web) views =====
  
 <code vala> <code vala>
-this.activate.connect (activated); +namespace Sandcat { 
-this.deactivate.connect (deactivated); +    private class Manager : Midori.Extension { 
-</code>+  
 +        internal Manager () { 
 +            GLib.Object (name: _("Furry example extension"), 
 +                         description: _("Take care of petting cats"), 
 +                         version: "0.1" + Midori.VERSION_SUFFIX, 
 +                         authors: "Jane Doe <email@domain.tld>"); 
 +            activate.connect (this.activated); 
 +            deactivate.connect (this.deactivated); 
 +        }
  
-You'll see how when activated the extension gets an "app" which is a running Midori instanceIt has among other things knowledge of browser windowsIt's good practise to not make any assumptions on how many windows are open.+        void tab_added (Midori.Browser browser, Midori.Tab tab) { 
 +            stdout.printf ("New tab added\n"); 
 +        }
  
-====== Working with (webviews =====+        void tab_switched (Midori.View? old_view, Midori.View? new_view) { 
 +            var title new_view.get_display_title(); 
 +            var uri new_view.get_display_uri()
 +            stdout.printf ("title: %s and  url: %s\n", title, uri); 
 +        }
  
-<code vala> +        void tab_removed () { 
-    void tab_added (Midori.Browser browser, Midori.Tab tab) { +            stdout.printf ("tab removed\n")
-        var view = tab as Midori.View; +        }
-        string uri = tab.uri+
-        string title = tab.title; +
-    }+
  
-    // in browser_added +        void browser_added (Midori.Browser browser) { 
-        foreach (var tab in browser.get_tabs ())+             foreach (var tab in browser.get_tabs ())
                 tab_added (browser, tab);                 tab_added (browser, tab);
-        browser.add_tab.connect (tab_added);+             browser.add_tab.connect (tab_added); 
 +             browser.switch_tab.connect (tab_switched); 
 +             browser.remove_tab.connect (tab_removed); 
 +        }
  
-    // in destroyed +        void activated (Midori.App app) { 
-        foreach (var tab in browser.get_tabs ()) +            foreach (var browser in app.get_browsers ()) 
-            browser.add_tab_disconnect (tab_added); +                browser_added (browser); 
-</code>+            app.add_browser.connect (browser_added); 
 +        }
  
-====== Add a context menu item ======+        void browser_removed (Midori.Browser browser) { 
 +            foreach (var tab in browser.get_tabs ()) { 
 +                browser.add_tab.disconnect (tab_added); 
 +                browser.switch_tab.disconnect (tab_switched); 
 +                browser.remove_tab.disconnect (tab_removed); 
 +            } 
 +        }
  
-**Unfinished API**+        void deactivated () { 
 +            var app = get_app (); 
 +            app.add_browser.disconnect (browser_added); 
 +            foreach (var browser in app.get_browsers ()) 
 +                browser_removed (browser); 
 +        } 
 +    } 
 +
 + 
 +public Midori.Extension extension_init () { 
 +    return new Sandcat.Manager (); 
 +
 +</code> 
 +When you open a new tab you will see in a message "New tab added", if you switch between tabs you will get their title and url, and the last one is, close a tab, you will see a message "tab removed" 
 +====== Add a context menu item ======
  
 <code vala> <code vala>
-    // in tab_added +namespace Sandcat { 
-    tab.context_menu.connect (add_menu_items);+    private class Manager : Midori.Extension { 
 +  
 +        internal Manager () { 
 +            GLib.Object (name: _("Furry example extension"), 
 +                         description: _("Take care of petting cats"), 
 +                         version: "0.1" + Midori.VERSION_SUFFIX, 
 +                         authors: "Jane Doe <email@domain.tld>"); 
 +            activate.connect (this.activated); 
 +            deactivate.connect (this.deactivated); 
 +        }
  
-    void add_menu_items (WebKit.HitTestResult hit_test_result, Midori.ContextAction menu) { +        void tab_added (Midori.Browser browser, Midori.Tab tab) { 
-        if ((hit_test_result.context & WebKit.HitTestResultContext.SELECTION) == 0+            tab.context_menu.connect (add_menu_items); 
-            return;+        }
  
-        var action = new Gtk.Action ("NotesCopySnippet", "Copy _snippet to notes", null, null); +        void add_menu_items (WebKit.HitTestResult hit_test_result, Midori.ContextAction menu) { 
-        action.activate.connect (() => { +            if ((hit_test_result.context & WebKit.HitTestResultContext.SELECTION) == 0) 
-            stdout.printf ("my menu item rocks\n"); +                return; 
-        }); +  
-        menu.add (action); +            var action1 = new Gtk.Action ("NotesCopySnippet", "Copy _snippet to notes", null, null); 
-        var submenu = new Midori.ContextAction ("NotesPaste", "Paste N_otes", null, null); +            var action2 = new Gtk.Action ("NotesPaste", "Paste N_otes", null, null); 
-        for (int i = 0; i < 10; i++) { +            action1.activate.connect (() => { 
-            submenu.add (new Gtk.Action ("NotesSnippet%d".format (i), "Snippet #%i".format (i), null, null);+                stdout.printf ("my menu item1 rocks\n"); 
 +            }); 
 +            action2.activate.connect (() => { 
 +                stdout.printf ("my menu item2 rocks\n"); 
 +            }); 
 +            menu.add (action1); 
 +            menu.add (action2); 
 +             
 +            //Add group of submenu 
 +            var submenu = new Midori.ContextAction("HaveSubmenu", "Have S_ubmenu", null, null); 
 +            var listsubmenu = new List<Gtk.Action>(); 
 +            for (int i = 0; i < 10; i++) 
 +                listsubmenu.append(new Gtk.Action("Submenu%d".printf (i), "Submenu #%i".printf (i), null, null)); 
 + 
 + 
 +            listsubmenu.foreach ((entry) => { 
 +                entry.activate.connect(() => { 
 +                    stdout.printf ("I am a submenu\n"); 
 +                }); 
 +                submenu.add(entry); 
 +            }); 
 +            menu.add (submenu); 
 +        } 
 + 
 +        void browser_added (Midori.Browser browser) { 
 +             foreach (var tab in browser.get_tabs ()) 
 +                tab_added (browser, tab); 
 +             browser.add_tab.connect (tab_added); 
 + 
 +        } 
 + 
 +        void activated (Midori.App app) { 
 +            foreach (var browser in app.get_browsers ()) 
 +                browser_added (browser); 
 +            app.add_browser.connect (browser_added); 
 +        } 
 + 
 +        void browser_removed (Midori.Browser browser) { 
 +            foreach (var tab in browser.get_tabs ()) { 
 +                browser.add_tab.disconnect (tab_added); 
 +            } 
 +        } 
 + 
 +        void deactivated () { 
 +            var app = get_app (); 
 +            app.add_browser.disconnect (browser_added); 
 +            foreach (var browser in app.get_browsers ()) 
 +                browser_removed (browser);
         }         }
-        menu.add (submenu); 
     }     }
-</code>+}
  
 +public Midori.Extension extension_init () {
 +    return new Sandcat.Manager ();
 +}
 +</code>
 +In the Web page try to select a word or a sentence right click and you are going to see three menu item which were added, click on one of them and you will see the magic in the terminal :) . 
 ====== Add an app menu item ====== ====== Add an app menu item ======
 +<code vala>
 +namespace Sandcat {
 +    private class Manager : Midori.Extension {
 +        internal Manager () {
 +            GLib.Object (name: _("Furry example extension"),
 +                         description: _("Take care of petting cats"),
 +                         version: "0.1" + Midori.VERSION_SUFFIX,
 +                         authors: "Jane Doe <email@domain.tld>");
 +            activate.connect (this.activated);
 +            deactivate.connect (this.deactivated);
 +        }
 +        void tool_menu_populated (Gtk.Menu menu) {
 +            var item = new Gtk.MenuItem.with_label("i am here");
 +            menu.add(item);
 +            item.show();
 +        }
  
-whatever+        void browser_added (Midori.Browser browser) { 
 +            browser.populate_tool_menu.connect(tool_menu_populated); 
 +        }
  
 +        void activated (Midori.App app) {
 +            foreach (var browser in app.get_browsers ())
 +                browser_added (browser);
 +            app.add_browser.connect (browser_added);
 +        }
 +
 +        void deactivated () {
 +            var app = get_app ();
 +            app.add_browser.disconnect (browser_added);
 +        }
 +    }
 +}
 +
 +public Midori.Extension extension_init () {
 +    return new Sandcat.Manager ();
 +}
 +</code>
 +
 +Here you are enjoy, it is easy, isn't it ? :-)
 ====== Modify resources or webpages loaded ====== ====== Modify resources or webpages loaded ======
  
Line 125: Line 286:
 ====== Add a statusbar item ====== ====== Add a statusbar item ======
  
-whatever+<code vala> 
 +namespace Sandcat { 
 +    private class Manager : Midori.Extension { 
 +  
 +        internal Manager () { 
 +            GLib.Object (name: _("Furry example extension"), 
 +                         description: _("Take care of petting cats"), 
 +                         version: "0.1" + Midori.VERSION_SUFFIX, 
 +                         authors: "Jane Doe <email@domain.tld>"); 
 +            activate.connect (this.activated); 
 +            deactivate.connect (this.deactivated); 
 +        }
  
 +        void browser_added (Midori.Browser browser) {
 +            var button = new Gtk.Button.with_label ("Click Here!");
 +            var click_counter = 0;
 +            browser.statusbar.pack_start (button, false, false, 3);
 +            button.clicked.connect (() => {
 +                button.label = "You Clicked me (%d) time(s)".printf (++click_counter);
 +            });
 +            button.show ();
 +        }
 +
 +        void activated (Midori.App app) {
 +            foreach (var browser in app.get_browsers ())
 +                browser_added (browser);
 +            app.add_browser.connect (browser_added);
 +        }
 +
 +        void deactivated () {
 +            var app = get_app ();
 +            app.add_browser.disconnect (browser_added);
 +        }
 +    }
 +}
 +
 +public Midori.Extension extension_init () {
 +    return new Sandcat.Manager ();
 +}
 +</code>
 +Enjoy How much time you click :-), you can add any Gtk widget in this StatusBar.
 ====== Add a panel ====== ====== Add a panel ======
  
Line 174: Line 374:
  
 whatever whatever
 +
 +====== Unit testing ======
 +
 +A basic means of quality control, as humans simply don't write flawless code, is to add some automatable tests that can be run repeatedly to verify the code does what it's expected to.
 +
 +<code vala>
 +void test_furry_purr () {
 +    assert (1 == 1);
 +}
 +
 +public void extension_test () {
 +     Test.add_func ("/extensions/furry/purr", test_furry_purr);
 +}
 +</code>
 +
 +With a simple example it will be like this:
 +<code vala>
 +void test_furry_purr () {
 +    assert (1 == 1);
 +}
 + 
 +public void extension_test () {
 +     Test.add_func ("/extensions/furry/purr", test_furry_purr);
 +}
 +
 +void main (string[] args) {
 +    Test.init (ref args);
 +    extension_test();
 +    Test.run ();
 +}</code>
 +The output could look like this.
 +<code bash>
 +/extensions/furry/purr: OK
 +</code>