User:Chani/DataEngines

    From KDE TechBase

    this is the disorganised beginning of something resembling a dataengine tutorial.


    if your applet gets data regularly, don’t use a qtimer to poll the data engine. have the data engine alert you when it’s got stuff, and set an update interval when you connect to the source. reducing the number of timers makes laptops happy. :)

    there’s no need to worry about connecting to the same source twice, it won’t hurt.

    if you use Plasma::AlignToMinute, you won’t get any updates until the minute rolls around - if your first update was a fake empty one and the actual data was downloaded 5 seconds later, you’ll have to wait another 55 seconds for it. if you were trying to work on a dataengine in the past, and wondering why the update interval wasn’t always updating - it was probably the timing bug that I just fixed, so you can go revisit that code now :)

    remember that if the dataengine creates a source, it hangs around until it’s explicitly killed off, but if an applet requests a source it only stays as long as something’s connected to it.


    if you really really want to send data from an applet to an engine, the current awful hack is to abuse Q_PROPERTY… but please don’t. pretty soon there'll be a dataservice api for this.

    I think I know enough about dataengines that i could write something on how to use them, but figuring out what to say is hard.

    The general idea of the dataengine is that it provides data in a nice, easy-to-use way, so that writing applets is easier. if you have 5 different clocks on your desktop, they’re not all polling for the time individually; they just connect to the time dataengine, tell it how often they want updates, and it’ll send them a regular signal with the data they need (in this case, the time). this means the clock applets don’t need to each have their own QTimer. reducing the number of timers is always a good thing.

    if you just want to make use of an existing dataengine, it should be fairly straightforward. the documentation of DataEngine is good; read it. First off you’ll want to create a dataengine with Applet::dataEngine() - this goes through the engine manager, which makes sure there’s only one of each engine running, and kills it off when nobody’s using it any more.

    you should probably check that you actually got a valid engine back before doing anything with it, just in case something funny happened.

    once you've got your engine pointer, you can query the list of sources, connect to sources, etc - all the stuff mentioned in the DataEngine API. what the API doesn’t tell you, of course, is what kinds of sources are offered by the particular engine you want to use. the sources may not be created until you request them, the engine may expect source names to follow a certain format, etc… these things depend on the individual engine, and I don’t know whether there’s a standard way to document them yet. twitter has a big comment in the .h file right before the engine class; otoh, the time engine only has this mysterious comment: “This class evaluates the basic expressions given in the interface.” I had to read the source code to see that it has sources named by timezone.

    so, what if you want to actually *write* an engine?

    well, you’re going to have to provide data to the applets requesting those sources. there’s two general concepts here: data that can be returned immediately, and asynchronous data that has to be downloaded or something. the first is, of course, easier.

    here, again, DataEngine docs come in handy.

    updateSource is called whenever it’s time to update a source. pretty straightforward, right? so, this function is generally where you figure out what your data is, and setData() on the source. if you’re doing something asynchronous, you’ll want to set that in motion and return false (to show that you don’t really have anything useful yet).

    sourceRequested generally wants to call updateSource(), to get the ball rolling on the new source. asynchronous engines don’t want to bilndly return the return value from updateSource(), because here returning false means that no source was created at all (something you might want if you’re expecting, say, a timezone, and the applet requests “mars”).

    also, for asyncronous engines, when the data finally does come in you should just need to setData() (you remembered to keep track of what source it’s for, right?) and… well, that’s it. see? sending data to applets is easy :) oh, and you might also want to give some thought to how long information is held in the engine. do you want to clear out all the old data from a source when you update it? or would you be better off just appending to it - and then making sure that it doesn’t grow too big, of course. :) sources created for an applet request are removed when nobody’s using them any more - but if your engine creates new sources on its own, should it remove them on its own eventually, or let them hang around until it’s deleted?

    if you want data to go the other direction… well, best to wait until that’s been implemented properly. see these meeting notes for a glimpse of what's coming.