huzzah! I finally fixed all of plasma-overlay’s known bugs, and made the config ui actually work :) it only took a couple of days to round up the last few things, surprisingly. now I finally have the option to write code that is *not* bugfixes for my damn soc project.
so, join me as we dive into plasmaland and try to create a brand new widget fropm scratch without any of that silly crashy c++ :) right now I have no idea how to do this; I knlow plenty about plasma internals, but almost nothing about the language bindings or how a modern widget needs to be made.
let’s start with techbase. hmm. plasma’s tutorials page has a c++ tutorial… not quite what we’re looking for, and I’m not sure whether it’s up-to-date, but it’s sure to give us *some* useful info.
well, looks like we need a .desktop file to start out (ok… I already knew that from seeing them in every applet’s folder, but I had forgotten). there’s a nice little example here to copy, or I could grab one from an existing applet.
as for other files in the plasmoid… I imagine this will depend on whether I want to make a plasmagik package that can be bundled up and downloaded easily (hooray for GHNS) or just a folder in svn that can be compiled and installed like the oher c++ plasmoids there. hmmm. well, I can only find one scripted plasmoid in playground and it’s not being compiled, so it’s time to ask for help.
ok, so it turns out that while it’s *possible* to have a scripted plasmoid that gets installed when I compile and install from svn, it’s a small amount of extra work (that of writing a proper CMakeLists.txt) and I first have to have a regular plasmagik package anyways. the usual method of getting scripted plasmoids to show up in plasma is either the “install new widgets” button in the add widgets dialog or `plasmapkg -i` – so let’s start with making a regular package and maybe I’ll fiddle with cmake at the end. NTS: the install button only works with zipped packages; unzipped folders can only be installed manually with plasmapkg.
so I guess before I should go any further I should probably tell you what plasmoid I’m writing. :) I’m going to make a little popup menu that lists all the kcm modules (spot the redundancy ;) because I just don’t like the new system settings app. in kde3 I found a little applet that gave me quick access to any config module from my panel, and I miss it. I’ve already memorized where most of the options were in that old tree structure, so I might as well keep using it.
this should be pretty simple: all I need to do is get a list of all the modules, display that list (preferably within categories), and then have the config module launched when its entry is clicked.
so, we start at the very beginning with a folder. I hate thinking up names for things, so… let’s call the plasmoid kconfigmenu. now, according to the plasmagik structure, we need a metadata.desktop and a contents/ folder. apparently we should have a metadata.xml too, but there’s no real explanation of that, so we’ll skip it for now (the tiger plasmoid seems to do just fine without one).
so, what to put in our metadata.desktop? well, let’s steal one of the examples and modify it to suit our needs. change the name and comment, pick an appropriate icon (I’m not going to be making any of my own art for this, just using existing icons), set the author and so on… that techbase page mentions some other options that aren’t shown (like a minimum plasma version) but I’m just going to skip those for now.
now that we’ve got our metadata, maybe we can put in some code. we need a code/ folder in contents/ and then a file called main.js in code/.
so now… what the hell do we put *in* this main file?
from looking at the tiger plasmoid, I get the impression we start with an applet already existing, conveniently called “applet”. ok, let’s try using that.
well, I installed it, and it showed up in the appletbrowser all pretty, but actually running it didn’t go so well. it failed to launch, yes, but with the wonderfully unhelpful message “script initialization failed”.
next step: running it in plasmoidviewer. from there it’s easy to watch the debug output, and among some odd things that make me question the sanity of the bindings, I see this:
QScriptApplet::reportError: Error: "ReferenceError: setFailedToLaunch is not defined" at line 3
so… do the qtscript bindings not expose that function, or am I doing something else wrong?
several hours later…
they don’t have it. they’re also missing a bunch of other stuff. I’m gonna go into technical details now that are farily irrelevant to people only wanting to *use* the bindings and not actually understand them.
So I fixed a blatant bug in libplasma and added a couple of functions; seems we have this AppletScript class that has to exist to expose protected members, because bindings can’t access those and they cover fairly important bits of Applet. had to add some methods to that class; there are probably more things that’ll need adding later, but let’s just get config and failedtolaunch stuff working first.
so then in the qtscript bindngs there’s a QScriptApplet that inherits AppletScript and does some odd binding-magic… it exposes the applet directly, which is fairly useless because only slots (and maybe qinvokables, etc) are actually accessible that way. it also has a half dozen static methods, some of which expose useful Applet functions and some of which do other strange but presumably useful things. I started trying to add functions here to expose AppletScript API, but then I realised that that way lies madness. I also find it really weird that things like update and setLayout are static functions that jump through strange hoops to get an applet pointer. it’s already weird enough that we’ve got some things accessible through applet and some as top-level functions (from the script’s point of view).
I decided the sane way to add a bunch of functions that merely expose AppletScript API would be to put them in their own class and have QScriptApplet expose an instance of that… then I realised that doing that meant I could also give my new class functions to expose bits of Applet that couldn’t be directly accessed. yay! to the script it’ll look like just one happy applet object.
another hour or so later…
huzzah! I have an interface… it only has one function, setFailedToLaunch, but that one function does work. :) now I just have the long task of writing a function for every useful method… *sigh*
we’ll continue writing this applet after I write myself some bindings. ;)
goddamnit fuck. I had another whole day’s worth of writing here, and it just vanished into thin air when I pressed the save button. wordpress and konqueror are both pissing me off a lot recently. :(
I don’t feel like rewrting it all. suffice it to say, qtscript is weird and hates enums and its documentation about them is wrong to boot. still, I made the damn things work in the end. for certain values of ‘work’.
I’ve spent all day working on those bindings. not exactly what I’d planned, but it is fun. :)