Monday, June 15, 2009

python, javascript or web?

While going through bug reports on bugs.kde.org, I had to install a Plasmoid over the internet using the Add Widgets dialog. It all worked pretty nicely (aside from the usual larger-than-good delay from kbuildsycoca4; I really need to find something to do about that ...), and soon I had a new widget. I dragged it to my desktop and got the "couldn't create a python scriptengine" error. Whoops! My PyKDE is currently not in a good state and I haven't had a chance to fix it yet, so no Python Plasmoids for me at the moment. :(

What was odd, though, was that it said in the description in Add Widgets that it was a JavaScript Tetris game. What would Python be needed for to run JavaScript? So I looked ...


# -*- coding: utf-8 -*-
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyKDE4.plasma import Plasma
from PyKDE4 import plasmascript
from PyKDE4.kdecore import KUrl

class jstetrisApplet(plasmascript.Applet):
def __init__(self,parent,args=None):
plasmascript.Applet.__init__(self,parent)

def init(self):
self.setHasConfigurationInterface(False)

self.theme = Plasma.Svg(self)
self.theme.setImagePath("widgets/background")
self.setBackgroundHints(Plasma.Applet.DefaultBackground)
self.setAspectRatioMode(Plasma.IgnoreAspectRatio)

self.layout = QGraphicsLinearLayout(Qt.Horizontal, self.applet)
webView = Plasma.WebView(self.applet)
webView.setUrl(KUrl("~/.kde/share/apps/plasma/plasmoids/jstetris/contents/jstet.html"))
self.layout.addItem(webView)
self.setLayout(self.layout)
self.resize(340,350)

def CreateApplet(parent):
return jstetrisApplet(parent)


A-ha! So it's creating a web viewer and loading the contents, all implemented in Python.

Unfortunately there are two errors there: first, calling resize there will not have the effect desired and second, there's a literal path to the jstet.html file. I blame myself for this because the scripting is still under-documented.

As penance, I re-wrote it in JavaScript:


plasmoid.hasConfigurationInterface = false
plasmoid.apectRatioMode = IgnoreAspectRatio

layout = new LinearLayout(plasmoid)
webView = new WebView()
webView.url = Url(plasmoid.file("scripts", "jstet.html"))
layout.addItem(webView)


In the metadata.desktop file I put:

X-Plasma-DefautSize=340,350


Both problems are fixed. The solution to the file path was to ask the plasmoid for the file from the package: plasmoid.file("scripts", "jstet.html"). This meant also moving the html (and JavaScript) files to the contents/code/ area of the package. Now there's no assumptions about where the package is installed to!

With JavaScript it's guaranteed to work everywhere (no additional dependencies) and it's even less typing.

Then it dawned on me: this is a web Plasmoid! So I deleted the JavaScript file I'd just made and changed the metadata.desktop file so it said:

X-Plasma-API=webkit
X-Plasma-MainScript=jstet.html


Note that the X-Plasma-MainScript entry only works with web plasmoids in 4.3, though it works with JavaScript, Ruby and Python Plasmoids in 4.2; previous to 4.3, you need to call your main html file main.html (which is still the default in 4.3 of course).

The only downside to this over the JavaScript Plasmoid approach above is that the WebKit ScriptEngine is in kdebase/workspace while the JavaScript ScriptEngine is in kdebase/runtime. I wonder if I should move the WebKit ScriptEngine over to runtime/ as well? Hm.. maybe something for 4.4. In any case, it means writing zero Plasma specific code.

Anyways, what's the result? All three approaches gives us this:



I can't take any credit for the actual hard work here, the JavaScript, was done by one Cezary Tomczak and the original Python plasmoid by Tomatz on kde-look.org. :)

No comments:

Post a Comment