Tuesday, April 24, 2012

Making GtkWebKit Inspector and enable-developer-extras actually work in Python


I have become quite fascinated by using HTML5 for rendering my GUIs on my Ubuntu applications. I love doing this, because I can continue to use Python as my library and desktop integration point, while being free to use cutting edge presentation technology.

I sat down with didrocks yesterday and we set off to create a simple Quickly template out of some of the code I've written for bootstrapping these projects. The template will be very very simple. All it will do is set up communication between HTML and Javascript in an GtkWebKit window, and a Python back end. Developers will be free to choose how to use the WebKit window. For example, they could use JQuery or a host of other javascript libraries if they chose.

Didrocks was adamant that we should expose the excellent debugger (called The Inspector) that comes with WebKit in the template. However, I have found that for GtkWebKit, the doucmentation is sketchy (at best), and the API is unpredictable in it's behavior. So, it took us 2 hours of experimentation and trolling source code to make an implementation that actually worked for showing The Inspector.

So, if you have been trolling the web looking for how to make this work .. I hope this works for you! Without further ado, here is a commented minimial example of a WebKit window that shows the Inspector. I also pushed a branch with just the code in case you find that easier to read or work with.
 from gi.repository import WebKit  
 from gi.repository import Gtk  
 import os  
 #The activate_inspector function gets called when the user  
 #activates the inspector. The splitter is a Gtk.Splitter and is user  
 #data that I passed in when I connected the signals below.  
 #The important work to be done is to create a new WebView  
 #and return it in the function. WebKit will use this new View  
 #for displaying The Inspector. Along the way, we need to add  
 # the view to the splitter  
 def activate_inspector(inspector, target_view, splitter):  
   inspector_view = WebKit.WebView()  
   splitter.add2(inspector_view)  
   return inspector_view  
 #create the container widgets  
 window = Gtk.Window()  
 window.set_size_request(400,300)  
 window.connect("destroy",Gtk.main_quit)  
 splitter = Gtk.Paned(orientation=Gtk.Orientation.VERTICAL)  
 window.add(splitter)  
 #create the WebView  
 view = WebKit.WebView()  
 #Use set_property to turn on enable-developer-extras. This will  
 #cause "Inspect Element" to be added to the WebKit's context menu.  
 #Do not use view.get_settings().enable_developer_extras = True,   
 #this does not work. Only using "set_property" works.  
 view.get_settings().set_property("enable-developer-extras",True)  
 #Get the inspector and wire the activate_inspector function.  
 #Pass the splitter as user data so the callback function has  
 #a place to add the Inspector to the GUI.  
 inspector = view.get_inspector()  
 inspector.connect("inspect-web-view",activate_inspector, splitter)  
 #make a scroller pane to host the main WebView  
 sw = Gtk.ScrolledWindow()   
 sw.add(view)   
 splitter.add1(sw)  
 #put something in the WebView  
 html_string = "<HTML><HEAD></HEAD><BODY>Hello World</BODY></HTML>"  
 root_web_dir = os.path.dirname(os.path.dirname(__file__))  
 root_web_dir = "file://%s/" % root_web_dir  
 view.load_html_string(html_string, root_web_dir)  
 #show the window and run the program  
 window.show_all()  
 Gtk.main()