JAN
20
2009

Dr Seigo cured my ruboids

Have you ever been a bit irritated by a wart on an API, that gives you a slightly uncomfortable feeling when you think about it, and an itch to try an fix it? Once such wart was in the way standard Plasma plasmoid packages worked; you could call the main script any name you like as long as it was 'main'. That meant that if you looked at your Ruby, Python or JavaScript applet code in Kate it didn't have any syntax highlighting as the editor depends on a '.rb', '.py' or '.js' suffix.

An additional problem with Ruby is that the name of the applet's class is derived from the source file name, and so the class could be called anything as long as it was 'Main'. I had added a custom package for Ruby called 'Ruboid' whose sole purpose was to allow you to name your script 'main.rb', so that at least the syntax highlighting problem was solved.

I pleased to say that last week Aaron and his assistant David Palacio fixed this particular wart. The Ruboid code was surgically removed from kdebase, Dr Seigo stitched in a small number of lines of code into private/packages.cpp in kdelibs and Assistant David sliced out the lines in the Applet and DataEngine's .desktop files to refer to the Ruboid package. It was all over very quickly and by the end of the day we had a new way of specifying the main script for a plasmoid via 'X-Plasma-MainScript'. Here is an example:

Type=Service
ServiceTypes=Plasma/Applet
X-KDE-PluginInfo-Name=jungle-animals
X-Plasma-API=ruby-script
X-Plasma-MainScript=code/fierce_tiger.rb

In a the code for a ruby applet, the X-KDE-PluginInfo-Name value is used to derive the enclosing module namespace, and the X-Plasma-MainScript value is used to derive the class of the applet. So in the case above the outline of the code would look like this:

module JungleAnimals
  class FierceTiger < PlasmaScripting::Applet
    def initialize(parent, args = nil)
      super
    end
  end
end

Some other good news for Ruby Plasma scripting fans is that Niels Slot is working on a couple of tutorials on the TechBase Wiki. I had a look at the preliminary version and he's done a great job, and it should be up soon.

It is a little know fact that the Mono/C# bindings for Plasma are in really good shape, and Arno Rehn added a 'Completed' entry for Plasma support to the KDE 4.2 release plan today. We'll try and do a tutorial for C# on TechBase too, and translate Niels's Ruby stuff. Arno has added a neat feature to CLR based applets - you can put them into a package as source code and they are then compile on the fly at load time. Today he has got the Mono bindings working with the X-Plasma-MainScript option and they don't have to be called 'main' anymore.

If you think a CLR language like C# is a bit mainstream, here is what a Boo source code script looks like - you just add a '# language:xxxx' line at the top the tells the dynamic compilation system what language is expected:

# language:boo

# boo is cool, instead of referencing assemblies in the meta
# comment above with references:MyFancyAssembly we can do
#
# import MyFancyNamespace from "MyFancyAssembly"

import System
import Qyoto
import Kimono

public class Main(PlasmaScripting.Applet):
  m_svg as Plasma.Svg
  m_icon as KIcon

  def constructor(script as Plasma.AppletScript):
    super(script)
    m_svg = Plasma.Svg(self)
    m_icon = KIcon("plasma")
        
    SetBackgroundHints(cast(uint, Plasma.Applet.BackgroundHint.DefaultBackground))
    m_svg.ImagePath = "widget/background"
    PlasmaApplet.Resize(200, 200)
    
  override def PaintInterface(p as QPainter, option as QStyleOptionGraphicsItem, contentsRect as QRect):
    p.SetRenderHint(QPainter.RenderHint.SmoothPixmapTransform)
    p.SetRenderHint(QPainter.RenderHint.Antialiasing)
        
    # Now we draw the applet, starting with our svg
    m_svg.Resize(contentsRect.Width(), contentsRect.Height())
    m_svg.Paint(p, contentsRect.Left(), contentsRect.Top())
        
    # We place the icon and text
    p.DrawPixmap(7, 0, m_icon.Pixmap(contentsRect.Width(), contentsRect.Width() - 14))
    p.Save()
    p.SetPen(Qt.GlobalColor.white)
    p.DrawText(contentsRect, cast(int, (Qt.AlignmentFlag.AlignBottom or Qt.AlignmentFlag.AlignHCenter)), "Boo!")
    p.Restore()

I quite like the idea of small Plasma languages that nobody much knows about. Members of the 'Cult of the Boo' can send each other plasmoids in source code form confident in the knowledge that nobody much else will have a clue what they are doing. The advantage of getting the source code, rather than a compiled assembly is that you can always hack it a little to suit your own purposes, just like you can with Python or Ruby..