Dev Week -- A WebKit Browser in PyKDE - Jonathan Riddell -- Thu, Sep 4

(02:01:41 PM) Riddell: good evening friends
(02:01:53 PM) Riddell: anyone want to learn a bit of pykde?
(02:02:00 PM) chombium: o/
(02:02:03 PM) techno_freak: \o
(02:02:38 PM) Riddell: this tutorial is to make a very simple web browser program
(02:02:47 PM) Riddell: using Qt's WebKit widget
(02:02:56 PM) Riddell: this comes with Qt 4.4
(02:03:01 PM) riot_le left the room.
(02:03:07 PM) Riddell: by default though hardy only comes with Qt 4.3
(02:03:17 PM) swingnjazz left the room.
(02:03:18 PM) Riddell: so if you're using hardy you need to add some archives
(02:03:22 PM) Riddell: hardy-updates
(02:03:30 PM) Riddell: and kubuntu-members-kde4
(02:03:44 PM) Riddell: oh and hardy-backports
(02:04:02 PM) Riddell: hardy-updates
(02:04:03 PM) JontheEchidna: <kubuntu-members-kde4
(02:04:09 PM) Riddell:
(02:04:17 PM) Riddell: add those to /etc/apt/sources.list
(02:04:21 PM) Riddell: apt-get update
(02:04:40 PM) Riddell: apt-get install python-qt4 python-kde4 libqt4-webkit
(02:04:59 PM) Riddell: if you're in intrepid, you just need python-kde4
(02:05:07 PM) Riddell: which Kubuntu users will have by default
(02:06:21 PM) Riddell: so, our first application
(02:06:36 PM) Riddell: we're going to dive right in and have it show us
(02:06:44 PM) Riddell: you need a text editor
(02:06:49 PM) Riddell: I use kate but any will do
(02:07:11 PM) Riddell: starts off with saying that it's a python app
(02:07:13 PM) Riddell: #!/usr/bin/env python
(02:07:41 PM) Riddell: then we need to import some libraries
(02:07:42 PM) Riddell: import sys
(02:07:42 PM) Riddell: from PyQt4.QtCore import *
(02:07:42 PM) Riddell: from PyQt4.QtGui import *
(02:07:43 PM) Riddell: from PyQt4.QtWebKit import *
(02:07:48 PM) dholbach left the room (quit: "Ex-Chat").
(02:08:05 PM) Riddell: sys is a standard python library, we'll use it to find the command line arguments (we don't have any but it's required for all apps)
(02:08:13 PM) Riddell: then we load the relevant parts of Qt
(02:08:26 PM) Riddell: next we create a QApplication object
(02:08:27 PM) Riddell: app = QApplication(sys.argv)
(02:08:52 PM) Riddell: sys.argv is the command line arguments
(02:09:14 PM) Riddell: now the useful bit, make the webkit widget, which is called a QWebView
(02:09:15 PM) Riddell: web = QWebView()
(02:09:26 PM) Riddell: web.load(QUrl(""))
(02:09:26 PM) Riddell:
(02:09:39 PM) Riddell: that makes the widget, tells it to load a web page and finally shows the widget
(02:09:46 PM) Riddell: pretty self explanatory
(02:09:54 PM) Riddell: finally we run the application
(02:10:00 PM) Riddell: sys.exit(app.exec_())
(02:10:42 PM) Riddell: app.exec_() is Qt's main loop, all graphical applications need a main loop to show the widgets and wait for users to do stuff
(02:10:46 PM) Riddell: and that's it
(02:10:56 PM) Riddell: you can get the full thing from
(02:11:22 PM) Riddell: although I find it's more helpful for understanding to copy these things out for tutorials
(02:11:31 PM) Riddell: save it to a file called
(02:11:43 PM) Riddell: and run it from the comment line with:   python
(02:12:03 PM) Riddell: anyone got it working?
(02:12:21 PM) ***JontheEchidna does
(02:14:05 PM) Riddell: that's a few got it working
(02:14:21 PM) Riddell: so lets move on.  this is a Qt application
(02:14:25 PM) chombium: QUESTION: should we run chmod a+x to run it?
(02:14:47 PM) Riddell: chombium: yes you can, that'll let you run it with   ./  rather than through python
(02:15:15 PM) Riddell: in KDE land we prefer KDE applications over pure Qt applications
(02:15:37 PM) Riddell: this sets some KDE defaults like the widget style
(02:15:53 PM) Riddell: it also lets you use KDE classes, of which there are many useful ones
(02:16:04 PM) Riddell: the main difference here is we need to set some meta data about the application
(02:16:23 PM) Riddell: start by adding some import lines for pyKDE
(02:16:24 PM) Riddell: from PyKDE4.kdecore import ki18n, KAboutData, KCmdLineArgs
(02:16:24 PM) Riddell: from PyKDE4.kdeui import KApplication, KMainWindow
(02:16:46 PM) Riddell: then below the import lines set the necessary meta data
(02:16:50 PM) Riddell: appName = "webkit-tutorial"
(02:16:50 PM) Riddell: catalog = ""
(02:16:50 PM) Riddell: programName = ki18n("WebKit Tutorial")
(02:16:50 PM) Riddell: version = "1.0"
(02:16:50 PM) Riddell: description = ki18n ("A Small Qt WebKit Example")
(02:16:55 PM) Riddell: license = KAboutData.License_GPL
(02:16:55 PM) Riddell: copyright = ki18n ("(c) 2008 Jonathan Riddell")
(02:16:55 PM) Riddell: text = ki18n ("none")
(02:16:56 PM) Riddell: homePage = ""
(02:16:58 PM) Riddell: bugEmail = ""
(02:17:18 PM) Riddell: which tells the app what its called, the licence, copyright, where to find translations
(02:17:21 PM) Riddell: all useful stuff
(02:18:00 PM) Riddell: we then make the application which needs a KAboutData to inclue the above data and a KCmdLineArgs to process any command line arguments
(02:18:04 PM) Riddell: aboutData = KAboutData (appName, catalog, programName, version, description,
(02:18:07 PM) Riddell: license, copyright, text, homePage, bugEmail)
(02:18:09 PM) Riddell: KCmdLineArgs.init(sys.argv, aboutData)
(02:18:12 PM) Riddell: app = KApplication()
(02:18:14 PM) Riddell: the rest is the same
(02:18:29 PM) Riddell: save that as
(02:18:33 PM) Riddell: or grab the full things from
(02:20:21 PM) Riddell: this is mostly very standard for pyKDE apps and you usually start with a template that inclues most of it already
(02:20:38 PM) Riddell: 19:19 < sebner> QUESTION: Am I missing some kde libs since it looks like webkit1?
(02:20:47 PM) Riddell: sebner: it should run and look the same
(02:21:03 PM) Riddell: the different will be it uses the oxygen style, but you may well have Qt set to use that anyway, in which case there won't be a visible difference
(02:27:50 PM) Riddell: so, I've been talking in the wrong room
(02:28:07 PM) Riddell: in we add a layout
(02:28:19 PM) Riddell: widget = QWidget()
(02:28:19 PM) Riddell: layout = QVBoxLayout(widget)
(02:28:19 PM) Riddell: web = QWebView(widget)
(02:28:38 PM) Riddell: 19:26 < Salze_> QUESTION: sys.exit(app.exec_()) <- why exactly is app.exec_ (with underscore) called?
(02:28:46 PM) Riddell: Salze_: that runs the mainloop, if you don't run that, nothing will happen
(02:28:52 PM) Riddell: the main loop shows any widgets
(02:29:11 PM) Riddell: then sits around waiting for mouse clicks and keyboard types
(02:29:23 PM) Riddell: which get passed to the widgets which may do something with them
(02:29:39 PM) Riddell: < acemoo> what is different between app.exec_() and app.exec()?
(02:29:45 PM) Riddell: exec is a reserved word in Python
(02:30:06 PM) Riddell: in c++ it is exec()  but in Python it's renamed to exec_() because exec is used for other things in python
(02:30:58 PM) Riddell: in the next version we add a KMainWidget
(02:31:21 PM) Riddell: this is embarassingly mostly to work around a bug in pyKDE where it crashes if we don't add it
(02:31:42 PM) Riddell: but it's also a useful widget to have for most applications, it makes it very easy to add menus, toolbars and statusbars
(02:31:51 PM) Riddell: so change the QWidget cration to ..
(02:31:52 PM) Riddell: window = KMainWindow()
(02:31:52 PM) Riddell: widget = QWidget()
(02:31:52 PM) Riddell: window.setCentralWidget(widget)
(02:32:15 PM) Riddell: and instead of showing the widget, show the window
(02:32:21 PM) Riddell:
(02:32:27 PM) Riddell:
(02:32:36 PM) Riddell: it won't look any different yet
(02:32:58 PM) Riddell: < acemoo> from the first couple lines in the source i see no ;, are they forgotten or python doesnt uses them?
(02:33:05 PM) Riddell: acemoo: python doesn't use semi colons
(02:33:18 PM) Riddell: there's no reason it should, they just get in the way whenever I go back to C++ programming
(02:33:28 PM) Riddell: python just uses the end of the line for an end of line marker
(02:33:44 PM) Riddell: < Salze_> But why the underscore? I thought that was for functions that are not to be called from public/outside?
(02:34:02 PM) Riddell: Salze_: it's python convention to start private methods with an underscore
(02:34:25 PM) Riddell: but here's it's just used because it can't use exec so exec_ is the closest thing that reads similarly
(02:34:57 PM) Riddell: ok, let's add an address bar
(02:35:13 PM) Riddell: below the line which makes the layout
(02:35:14 PM) Riddell: addressBar = QLineEdit(widget)
(02:35:14 PM) Riddell: layout.addWidget(addressBar)
(02:35:49 PM) Riddell: a  QLineEdit is a common widget for entering a line of text, it'll be used by your GUI IRC applications to type into
(02:36:55 PM) Riddell: here's a screenshot
(02:37:05 PM) Riddell: source is
(02:37:45 PM) Riddell: is that working for everyone?
(02:37:49 PM) mcas_away is now known as mcas
(02:38:22 PM) sebner: Riddell: yep
(02:38:44 PM) Riddell: so let's make that address bar do something
(02:39:22 PM) Riddell: we need to define a method called loadUrl() which takes the text from the addressBar widget and tells the WebView widget to load it
(02:39:27 PM) Riddell: def loadUrl(): print "Loading " + addressBar.text() web.load( QUrl(addressBar.text()) )
(02:39:34 PM) Riddell: hmm, that didn't paste right
(02:39:43 PM) Riddell: def loadUrl():
(02:39:43 PM) Riddell:   print "Loading " + addressBar.text()
(02:39:48 PM) Riddell:   web.load( QUrl(addressBar.text()) )
(02:40:39 PM) Riddell: in python we use spaces to indicate that several lines belong to the code block, so make sure those two lines are indented by your preferred indentation
(02:40:43 PM) Riddell: I use four spaces
(02:41:14 PM) Riddell: that goes below the import lines
(02:41:36 PM) Riddell: next we need to connect the return signal from the line edit to that method
(02:42:03 PM) Riddell: Qt has a nifty signal/slot mechanism where named signals get emitted from widgets when interesting things happen
(02:42:22 PM) Riddell: and we connect those into methods (a connected method is called a slot)
(02:42:35 PM) Riddell: so just before the exec_() line ..
(02:42:42 PM) Riddell: QObject.connect(addressBar, SIGNAL("returnPressed()"), loadUrl)
(02:43:00 PM) Riddell: full thing at
(02:44:46 PM) Riddell: so I can now load another web page
(02:44:55 PM) Riddell: < sebner> Riddell: I have problems loading
(02:45:01 PM) Riddell: sebner: try adding http://  at the start
(02:45:19 PM) sebner: Riddell: working :)
(02:45:38 PM) sebner: Riddell: rendering is pretty bad though ^^
(02:46:02 PM) Riddell: sebner: it should be pretty simple to fix our loadUrl() method to detect if it needs the http:// added at the start
(02:46:40 PM) Riddell: so, voila, our web browser works
(02:46:47 PM) sebner: Riddell: what about being not so strict?
(02:47:04 PM) Riddell: sebner: in what way?
(02:47:28 PM) sebner: Riddell: http://. browser shouldn't care if it's here or not
(02:47:43 PM) Riddell: right, it just takes some programming in the loadUrl() method to work around that
(02:48:02 PM) ebel_ is now known as ebel
(02:48:49 PM) Riddell: this was done without using any objects, a more complex app would typically define a class which inherits from the main widget and adds functionality to that
(02:49:00 PM) Riddell:  does that
(02:49:34 PM) Riddell: there we create a class which inherits a simple QWidget and adds the child widgets to itself
(02:50:29 PM) Riddell: a class is a template for an object if you don't know object oriented programming
(02:51:12 PM) Riddell: so, that's a very simple application using a powerful widget
(02:51:29 PM) Riddell: we use pyKDE a lot in Kubuntu, and Ubuntu generally uses a lot of Python
(02:51:46 PM) Riddell: it makes programming much faster and easier than C++ (and obviously more so than C)
(02:52:52 PM) Riddell: if this has interested you, it would be great if someone would write up this tutorial onto
(02:53:01 PM) Riddell: which is currently lacking in pyKDE starting info
(02:53:11 PM) Riddell: < jrib> QUESTION: is there a python gtk webkit so I can use webkit without qt?
(02:53:12 PM) x_dimitr1 is now known as x_dimitri
(02:53:44 PM) Riddell: yes, I noticed python-gtkwebkit going into the archive in intrepid recently, if you apt-get source it there's an example application which is a lot more full featured than the one we just made here
(02:54:33 PM) Riddell: but well, Qt is so much nicer than Gtk, in the humble opinion of people who have compared the two
(02:54:55 PM) Riddell: < sebner> QUESTION: Aren't you afraid that now >100 new pyKDE webkit browsers appear and disapper?
(02:55:33 PM) Riddell: there's no need for yet another browser, but as a widget webkit and khtml is used quite a lot, in plasma and kopete and khelpcentre and more
(02:56:07 PM) sebner: asac: \o/
(02:56:14 PM) Riddell: < tr_tr_> QUESTION: Riddell Are there any apps in intrepid, that are easy to understand, to learn more?
(02:56:17 PM) sebner: Riddell: there is no need but it's apparently very easy
(02:56:33 PM) Riddell: there are more tutorial apps in the pykde sources  (apt-get source kde4bindings)
(02:57:07 PM) Riddell: in kubuntu our apps include ubiquity, update-notifier-kde, language-selector and various others
(02:57:17 PM) JontheEchidna: jockey-kde, gdebi-kde
(02:57:30 PM) Riddell: printer-applet and system-config-printer-kde too which are now in KDE itself
(02:57:44 PM) Riddell: there's often tasks that need doing on those, so if you'd like to help out join us in #kubuntu-devel and say hi
(02:58:00 PM) mode (+o ChanServ ) by
(02:58:26 PM) Riddell: before I go, I should say there's lots of other useful ways to contribute to Kubuntu
(02:58:36 PM) Riddell: and again, #kubuntu-devel is generally the way to get into it
(02:59:14 PM) Riddell: writing this up as a techbase tutorial would be great as I say
(02:59:25 PM) Riddell: ok, thanks all, hope you found it interesting

MeetingLogs/devweek0809/PyKDEWebkit (last edited 2008-09-05 04:20:10 by pool-68-238-87-204)