One of the most important concepts in Plasma is that of the "DataEngine". DataEngines are used to deliver data from somewhere, often from an internet service for example, to your applet. In this tutorial we'll discuss DataEngines, what they are, and how to use them from your Plasma applet.
As already mentioned, DataEngines are objects which serve to deliver some kind of data to Plasma applets. Plasma supports many different DataEngines out of the box which deliver all sorts of varied information about the state of the machine, e.g. CPU usage, memory usage, position of the mouse pointer; to things such as the current weather report, current time or the latest comic from the internet. DataEngines are used to supply the raw data which an applet can display. Separating the part of the code which fetches data from the part which displays the data means that one DataEngine can be reused by many applets, regardless of which language the DataEngine is written in. It also makes it easy for people to display the same data using different applets which may tuned to different tasks of screen form factors.
Plasma comes with a handy tool called plasmaengineexplorer to list the running DataEngines and examine them to see what kind of data and fields them send. plasmaengineexplorer can be simply started from the shell as so.
Select the "time" in the pulldown list and then click on "Request". This will fetch the list of data sources which the "time" DataEngine makes available.
The "time" DataEngine periodically publishes the current time for many different timezones. The first timezone in the list ("/etc/localtime") is special and simply refers to the current local time on the computer without referring to a specific timezone. If you open the "/etc/localtime" node in the tree you can see which data fields the "time" DataEngine provides. The most important fields are the "Time" and "Date". The plasmaengineexplorer also lists what kind of data type the field is, e.g. a QString, QTime or QDate. This information is needed when hooking up a DataEngine to your applet.
Explore some of the other DataEngines in the list. Perhaps it will give you some good ideas for new and interesting applets.
The Python clock example code is a good example of how to connect to the "time" DateEngine. You can view the main.py code online here online. Let's look at how the Python clock does it.
The code to connect to the "time" DataEngine is in the clock's connectToEngine() method.
self.timeEngine = self.dataEngine("time") if self.showSecondHand: self.timeEngine.connectSource(self.currentTimezone, self, 500) else: self.timeEngine.connectSource(self.currentTimezone, self, 6000, Plasma.AlignToMinute)
This method is called from the clock's init() method. It first calls the dateEngine() method on the plasmascript.Applet class to get a reference to the "time" DataEngine.
The connectSource() method on the DataEngine binds it to this applet. The first parameter is the "DataSource" name. This corresponds to the "DataSouce" column in plasmaengineexplorer. For the "time" DataEngine, it selects which timezone you want the time for. The next parameter is where the data should be sent. In this case it is quite simple, just send the data to this applet. The number is the "polling interval" in milliseconds. This is how often the data should be updated. Depending on how often the clock needs to update its display, it calls the connectSource() method with either 500 or 6000 milliseconds as the polling interval.
Plasma.AlignToMinute indicates to Plasma whether the updates should be syncronised to the system clock. Many many applets syncronise to the same way, then Plasma can handle the updates in large batches instead of many small updates. This is important on mobile devices which throttle the CPU down to save battery power. It is more efficient for these devices if updates are done in big batches instead of many small batches.
Data is injected in the applet via the dataUpdate() method.
@pyqtSignature("dataUpdated(const QString &, const Plasma::DataEngine::Data &)")
def dataUpdated(self, sourceName, data):
self.time = data[QString("Time")].toTime()
if self.time.minute() == self.lastTimeSeen.minute() and \ self.time.second() == self.lastTimeSeen.second(): # avoid unnecessary repaints return
self.lastTimeSeen = self.time self.update()
The dataUpdated() takes the normal Python self parameter in first place, then the name of the data source (sourceName) which called dataUpdated() and the data itself. The big @pyqtSignature() line just before dataUpdated() is a Python decorator which marks this Python method as having const QString &, const Plasma::DataEngine::Data & as its C++ method signature. This is needed so that Qt and find the correct method on our applet.
The code just ignores the sourceName parameter because it knows that the data must be from the "time" DataEngine, and just concentrates on the data. The data is delivered as a Python dict mapping QString keys to QVariant object values. When looking up the "Time" key you need to be careful to use a QString as a key and not just a normal Python string. Notice how the code also extracts a QTime object from the QVariant using the toTime() method.
Next the dataUpdated() method has some code to make sure that the clock's display is only updated if really necessary, followed by some code which actually updates the time and redraws the display.
As you can see DataEngines are a great way of delivering data to applets which can also be easily reused by different applets. Connecting a DataEngine to your applet is a simple matter of fetching the data engine itself, connecting up to the wanted data source and then accepting the processing the data in your own dataUpdated() method.