As you have seen in the using DataEngines tutorial, Plasma applets can make use of DataEngines to visualize data of many different kinds. In fact, the already available DataEngines offer many options for your applets. But what if you have a specific need, not covered by those?
The problem is easily solved by writing your own Plasma DataEngine, and this tutorial will show you how to create one.
As with applets, DataEngines need the same directory structure (see the Getting Started tutorial), so the first step is to create the appropriate directories. The difference with respect to applets lies in the metadata.desktop file:
Name=Python Date and Time
Comment=Python Time data for Plasmoids
X-KDE-PluginInfo-Author=Simon Edwards X-KDE-PluginInfo-Emailemail@example.com X-KDE-PluginInfo-Name=plasma-dataengine-pytime X-KDE-PluginInfo-Version=1.0 X-KDE-PluginInfo-Website=http://plasma.kde.org/ X-KDE-PluginInfo-Category=Python Date and Time X-KDE-PluginInfo-Depends= X-KDE-PluginInfo-License=LGPL X-KDE-PluginInfo-EnabledByDefault=true
Take a look at the ServiceType line. When using applets, it was "Plasma/Applet", but since now we're dealing with DataEngines, its value is "Plasma/DataEngine".
For this tutorial we'll use the plasma-dataengine-pytime code, which is available on KDE's SVN. This DataEngine is an equivalent to the C++ time DataEngine we connected to in the using DataEngines tutorial. Its function is to display time and date with respect to the current timezone. You can view the main.py file online. As the file is rather long, we'll take a look at it in sections.
from PyQt4.QtCore import * from PyKDE4.kdecore import * from PyKDE4 import plasmascript
def __init__(self,parent,args=None): plasmascript.DataEngine.__init__(self,parent)
def init(self): self.setMinimumPollingInterval(333)
We start with the copyright information, followed by importing the required modules (PyQt4.QtCore and plasmascript). Since we're dealing with time and timezones, we also import kdecore to make use of what KDE offers.
In __init__ we just initialize the class. In init() instead, we set the minimum polling interval, that is the minimum time (in milliseconds) that needs to pass between one data request (from an applet, for example) and another.
sources = ["Local"] sources.extend(KSystemTimeZones.zones().keys()) return sources
def sourceRequestEvent(self, name): return self.updateSourceEvent(name)
The sources() function is called from applets to request what data sources a DataEngine has (for example, if your applet needs to connect to an online service, the DataEngine could offer a list of suitable services). In this case we first create a list with the "Local" name (which refers to the local time on your computer) and then we extend the list using KSystemTimeZones.zones().keys(). This adds the time zones known to KDE to the sources. As a final step, we return this list.
sourceRequestEvent is a function that is called when the applet accesses the DataEngine and requests a specific source (name). This function is usually used to make preparations (for example, setting up a connection) before the data can be received. In this case, we simply return updateSourceEvent with the source name.
def updateSourceEvent(self, tz): localName = "Local" if tz == localName: self.setData(localName, "Time", QVariant(QTime.currentTime())) self.setData(localName, "Date", QVariant(QDate.currentDate())) # this is relatively cheap - KSTZ::local() is cached timezone = KSystemTimeZones.local().name() else: newTz = KSystemTimeZones.zone(tz) if not newTz.isValid(): return False dt = KDateTime.currentDateTime(KDateTime.Spec(newTz)) self.setData(tz, "Time", QVariant(dt.time())) self.setData(tz, "Date", QVariant(dt.date())) timezone = tz
trTimezone = timezone self.setData(tz, "Timezone", QVariant(trTimezone)); tzParts = str(trTimezone).split("/") if len(tzParts)>=2: self.setData(tz, "Timezone Continent", QVariant(tzParts)) self.setData(tz, "Timezone City", QVariant(tzParts))
updateSourceEvent is the main function needed for a DataEngine, as it takes care of updating and storing the data from a specific source (in our case, tz, a timezone). As a first step, we set localName to be "Local", and we compare the timezone supplied to the function to it. If they're the same, i.e. local time on the computer, we set the data to current time and date (QTime.currentTime() and QDate.currentDate()), and then we get the name of the timezone using KSystemTimeZones.local().name().
The important part here is setData. That is how we put data inside a DataEngine. setData accepts a source name, a key which will be used to look up the information, and the actual information, stored as a QVariant.