Embeding the Gecko engine in Python applications
I've got to deploy a new desktop based application, created, of course, with Zope 3. When you've got a hammer, everything looks like a nail, indeed. This application uses HTML and CSS as its presentation layer (right, it's a web page), with a bit of Ajax thrown in. Due do time constraints, I'm not even trying to get it to work properly on Internet Explorer (although it looks about 90% right, but I have some problems with Javascript), so I won't be embeding the Internet Explorer this time engine in my Python application, I'll just try to get the Gecko rendering engine, the one used in Firefox.
First, I've installed the ActiveX control for the Gecko engine. Following some ActiveX migration details on wxpython.org, I've generated a wxpython "binding" class, using the genaxmodule.py tool (after a quick dig in the Windows registry to find out which is the Mozilla control class name):
C:\Python24\Lib\site-packages\wx-2.6-msw-unicode\wx\tools>genaxmodule.py "Mozilla.Browser" Gecko
Creating module in: .\Gecko.py
ProgID: Mozilla.Browser.1
CLSID: {1339B54C-3453-11D2-93B9-000000000000}
The python code would that would use the ActiveX control would be something like this:
# -*- coding: ISO-8859-1 -*-
# generated by wxGlade 0.4.1cvs on Sat Mar 10 16:40:22 2007 from C:\Work\CourseBuilder.wxg
import wx
import Gecko
def createGeckoControl(parent, id):
gecko = Gecko.Gecko(parent, id)
return gecko
# begin wxGlade: dependencies
# end wxGlade
class MainFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MainFrame.__init__
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.panel_1 = wx.Panel(self, -1)
self.gecko = createGeckoControl(self.panel_1, -1)
self.__set_properties()
self.__do_layout()
# end wxGlade
self.gecko.SetFocus()
self.gecko.Navigate2('http://slashdot.org', 0)
def __set_properties(self):
# begin wxGlade: MainFrame.__set_properties
self.SetTitle("frame_1")
# end wxGlade
def __do_layout(self):
# begin wxGlade: MainFrame.__do_layout
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
sizer_2.Add(self.gecko, 1, wx.EXPAND, 0)
self.panel_1.SetSizer(sizer_2)
sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
# end wxGlade
# end of class MainFrame
And the main app file:
#!/usr/bin/env python
# -*- coding: ISO-8859-1 -*-
# generated by wxGlade 0.4.1cvs on Sat Mar 10 16:40:22 2007 from C:\Work\CourseBuilder.wxg
import wx
from MainFrame import MainFrame
class CourseBuilderApp(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
main_frame = MainFrame(None, -1, "")
self.SetTopWindow(main_frame)
main_frame.Show()
return 1
# end of class CourseBuilderApp
if __name__ == "__main__":
CourseBuilderBrowser = CourseBuilderApp(0)
CourseBuilderBrowser.MainLoop()
Unfortunately I hit a problem that I can't find a solution for: this application crashes when I type something in the Gecko window. Blah :-( If anyone reading this know the answer, help me! :) Please! (tibi@life.org.ro)
My only option left is to go for the XULRunner and the MyBrowser demo. I'm not extremely happy about this, but at this point I don't see other options. Plus, it will be fun learning some about the Mozilla development platform.
Update: I've tested the Mozilla ActiveX Control using a simple Delphi 7 form and, while I don't get a crash, I still can't get it to accept keyboard input.
Previous: A Zope 3 AJAX viewlet manager