Development/Tutorials/Plasma4/Python/GettingStarted: Difference between revisions

From KDE TechBase
(basic formatting)
 
(32 intermediate revisions by 10 users not shown)
Line 1: Line 1:
== Abstract ==
== Abstract ==


In this tutorial we'll cover setting up a very simple plasma applet in Python, and how to install it and run it, basically the edit, install, run and debug cycle. To follow this you will need to have KDE 4.2 or later installed, and also the python support for plasma and related dependencies. I'm going to assume that you are using a unix-style operating system such as Linux of *BSD and aren't adverse to the shell.
In this tutorial we'll cover setting up a very simple plasma applet in Python, and how to install it and run it, basically the edit, install, run and debug cycle. To follow this you will need to have KDE 4.2 or later installed, and also the python support for plasma and related dependencies. I'm going to assume that you are using a unix-style operating system such as Linux or *BSD and aren't adverse to the shell.


== Project Structure ==
== Project Structure ==


The first step for any software project is to set up your project's directory on disk. For this tutorial we are going to create a very simple “hello-python” applet. Create a directory on somewhere called “hello-python” which in turn contains a “content” directory which then contains a “code” directory. This command below will do all this.
The first step for any software project is to set up your project's directory on disk. For this tutorial we are going to create a very simple "hello-python" applet. Create a directory on somewhere called <tt>hello-python</tt> which in turn contains a <tt>contents</tt> directory which then contains a <tt>code</tt> directory. This command below will do all this.
 
<syntaxhighlight lang="bash">
  mkdir -p hello-python/content/code
mkdir -p hello-python/contents/code
 
</syntaxhighlight>
This creates a simple directory structure which also matches the package structure expect by the “plasmapkg” command. More on this later.
This creates a simple directory structure which also matches the package structure expected by the <tt>plasmapkg</tt> command. More on this later.


== Metadata.desktop ==
== Metadata.desktop ==


In the “hello-python” directory create a file called “metadata.desktop” and open it in your text editor. Copy the following code into metadata.desktop.
In the <tt>hello-python</tt> directory create a file called <tt>metadata.desktop</tt> and open it in your text editor. Copy the following code into <tt>metadata.desktop</tt>.


  [Desktop Entry]
<syntaxhighlight lang="ini">
  Encoding=UTF-8
[Desktop Entry]
  Name=Hello Python
Encoding=UTF-8
  Name[nl]=Hallo Python
Name=Hello Python
  Type=Service
Name[nl]=Hallo Python
  ServiceTypes=Plasma/Applet
Type=Service
  Icon=chronometer
ServiceTypes=Plasma/Applet
  X-Plasma-API=python
Icon=chronometer
  X-Plasma-MainScript=code/main.py
X-Plasma-API=python
  X-KDE-PluginInfo-Author=Simon Edwards
X-Plasma-MainScript=code/main.py
X-KDE-PluginInfo-Author=Simon Edwards
  X-KDE-PluginInfo-Name=hello-python
  X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Name=hello-python
  X-KDE-PluginInfo-Website=http://plasma.kde.org/
X-KDE-PluginInfo-Version=1.0
  X-KDE- PluginInfo-Category=Examples
X-KDE-PluginInfo-Website=http://plasma.kde.org/
  X-KDE- PluginInfo-Depends=
X-KDE-PluginInfo-Category=Examples
  X-KDE- PluginInfo-Depends=GPL
X-KDE-PluginInfo-Depends=
  X-KDE- PluginInfo-EnabledByDefault=true
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
</syntaxhighlight>


This “metadata.desktop” file list important information needed by Plasma to load the applet, and also information about what the applet is and who created it. The “Name” field lists the name of the applet. This field can also be listed multiple times as different translations. Here I've just given a Dutch translation of the name. The [nl]indicates the language of the field.
This <tt>metadata.desktop</tt> file list important information needed by Plasma to load the applet, and also information about what the applet is and who created it. The <tt>Name</tt> field lists the name of the applet. This field can also be listed multiple times as different translations. Here I've just given a Dutch translation of the name. The <tt>[nl]</tt> indicates the language of the field.


The “Type” and “ServiceType” fields identify what kind of thing this desktop file is describing. Here we say that we have a plasma applet.
The <tt>Type</tt> and <tt>ServiceType</tt> fields identify what kind of thing this desktop file is describing. Here we say that we have a plasma applet.


The “Icon” field gives the name of the icon to associate with this applet. The icon is typically shown in things such as the “Add widget” dialog in Plasma.
The <tt>Icon</tt> field gives the name of the icon to associate with this applet. The icon is typically shown in things such as the "Add widget" dialog in Plasma. If you want to use a custom icon, you can place it in the package root, along metadata.desktop, and then point to it like this:
<syntaxhighlight lang="text">Icon=/mycustomicon.png</syntaxhighlight>


The “X-Plasma-API” and “X-Plasma-MainScript” fields are used specifically by Plasma to find the correct script-engine to use when loading and running the applet.
The <tt>X-Plasma-API</tt> and <tt>X-Plasma-MainScript</tt> fields are used specifically by Plasma to find the correct script-engine to use when loading and running the applet.


Most of the “X-KDE-PluginInfo-*fields give extra information about who created the applet. “X-KDE- PluginInfo-Category” lists a category which this applet belong to. http://techbase.kde.org/Projects/Plasma/PIG has a list of acceptable category names.
Most of the <tt>X-KDE-PluginInfo-*</tt> fields give extra information about who created the applet. <tt>X-KDE-PluginInfo-Category</tt> lists a category which this applet belongs to. http://techbase.kde.org/Projects/Plasma/PIG has a list of acceptable category names.


== Main script ==
== Main script ==


Create a file in the content/code called main.py, open it up in your text editor and put this code in it and save it.
Create a file in the <tt>contents/code</tt> directory called <tt>main.py</tt>, open it up in your text editor and put this code in it and save it.


  # <Copyright and license information goes here.>
<syntaxhighlight lang="python">
  from PyQt4.QtCore import *
# -*- coding: utf-8 -*-
  from PyQt4.QtGui import *
# <Copyright and license information goes here.>
  from PyKDE4.plasma import Plasma
from PyQt4.QtCore import Qt
  from PyKDE4 import plasmascript
from PyKDE4.plasma import Plasma
from PyKDE4 import plasmascript


  class HelloPython(plasmascript.Applet):
class HelloPython(plasmascript.Applet):
      def __init__(self,parent,args=None):
    def __init__(self,parent,args=None):
          plasmascript.Applet.__init__(self,parent)
        plasmascript.Applet.__init__(self,parent)


      def init(self):
    def init(self):
          self.setHasConfigurationInterface(False)
        self.setHasConfigurationInterface(False)
          self.resize(125, 125)
        self.resize(125, 125)
          self.setAspectRatioMode(Plasma.Square)
        self.setAspectRatioMode(Plasma.Square)


      def paintInterface(self, painter, option, rect):
    def paintInterface(self, painter, option, rect):
          painter.save()
        painter.save()
          painter.setPen(Qt.white)
        painter.setPen(Qt.white)
          painter.drawText(rect, Qt.AlignVCenter | Qt.AlignHCenter, "Hello Python!")
        painter.drawText(rect, Qt.AlignVCenter | Qt.AlignHCenter, "Hello Python!")
          painter.restore()
        painter.restore()


  def CreateApplet(parent):
def CreateApplet(parent):
      return HelloPython(parent)
    return HelloPython(parent)
</syntaxhighlight>


This is basically the simplest applet which actually does something. The code starts out with the usual copyright notice and license information which I've actually left out for now.
This is basically the simplest applet which actually does something. The code starts out with the usual copyright notice and license information which I've actually left out for now.


Next up is a bunch of imports. The Python support in Plasma is an extension of PyQt and PyKDE. So here we pull in a couple of PyQt and PyKDE modules which we will need. There are two plasma related modules which we use. The first, PyKDE4.plasma, are the bindings straight on top of the Plasma C++ API. This gives us access to most of the APIs we need, but not all. To create applets which can be packaged and delivered to users across the network via KDE's Get Hot New Stuff (GHNS) framework, we need to use some extra Python specific classes which are in PyKDE4.plasmascript.
Next up is a bunch of imports. The Python support in Plasma is an extension of PyQt and PyKDE. So here we pull in a couple of PyQt and PyKDE modules which we will need. There are two plasma related modules which we use. The first, <tt>PyKDE4.plasma</tt>, are the bindings straight on top of the Plasma C++ API. This gives us access to most of the APIs we need, but not all. To create applets which can be packaged and delivered to users across the network via KDE's Get Hot New Stuff (GHNS) framework, we need to use some extra Python specific classes which are in <tt>PyKDE4.plasmascript</tt>.
 
Now we define our main applet class. This is our Hello Python applet and it must be a subclass of plasma.Applet. In the <tt>__init__()</tt> method we need to make sure that we give the super class constructor a chance to run. Note that it is recommended to put most of the initialisation code inside the <tt>init()</tt> method and not in the <tt>__init__()</tt>. After Plasma has constructed and initialised the applet, Plasma will call the <tt>init()</tt> method on the applet to let it continue setting itself up. Our <tt>init()</tt> method is rather short. We just tell Plasma that we don't have a configuration dialog and we set up the initial size of the applet.
 
The <tt>paintInterface()</tt> method is where we draw our "Hello Python" message. First we save the state / settings of the given <tt>QPainter</tt> object by calling <tt>save()</tt>. Then we set the color to white and use <tt>drawText()</tt> to draw our message. Finally we call <tt>restore()</tt> which resets the <tt>QPainter</tt> settings back to how it was when <tt>paintInterface()</tt> was called.
 
The <tt>CreateApplet()</tt> function is needed to create an instance of our applet. When Plasma loads a Python based applet it will expect there to be a <tt>CreateApplet()</tt> function which it will call. The task of the <tt>CreateApplet()</tt> function is to create and instance of the applet and pass it back to Plasma.
 
== Packaging, installing & running ==


Now we define our main applet class. This is our Hello Python applet and it must be a subclass of plasma.Applet. In the __init__() method we need to make sure that we give the super class constructor a chance to run. Note that it is recommended to put most of the initialisation code inside the init() method and not in the __init__(). After Plasma has constructed and initialised the applet, Plasma will call the init() method on the applet to let it continue setting itself up. Our init() method is rather short. We just tell Plasma that we don't have a configuration dialog and we set up the initial size of the applet.
Plasma applets can be packaged in zip files and installed using the <tt>plasmapkg</tt> command line tool. The directory structure which we have used for our project matches that need in the zip file. All we have to do is zip it update. Run the following command from inside the hello-python directory.
<syntaxhighlight lang="bash">
zip -r ../hello-python.zip .
</syntaxhighlight>
This will create the hello-python.zip file in the directory just above the hello-python directory. Go to this directory in the shell and run this <tt>plasmapkg</tt> command to install our little hello-python applet.
<syntaxhighlight lang="bash">
plasmapkg -i hello-python.zip
</syntaxhighlight>
This installs the applet into your home directory. Now we can run it. When developing applets it is more convenient to use the <tt>plasmoidviewer</tt>. This is a little utility which displays an applet in a window instead of you having to use your desktop. This command below will run our applet.
<syntaxhighlight lang="bash">
plasmoidviewer hello-python
</syntaxhighlight>
You should now be able to see the fruits of your labor.


The paintInterface() method is where we draw our “Hello Python” message. First we save the state / settings of the given QPainter object by calling save(). Then we set the color to white and use drawText() to draw our message. Finally we call restore() which resets the Qpainter settings back to how it was when paintInterface() was called.
To uninstall our applet we use <tt>plasmapkg</tt> again with its -r option.
<syntaxhighlight lang="bash">
plasmapkg -r hello-python
</syntaxhighlight>


The CreateApplet() function is needed to create an instance of our applet. When Plasma loads a Python based applet it will expect there to be a CreateApplet() function which it will call. The task of the CreateApplet() function is to create and instance of the applet and pass it back to Plasma.
== Conclusion ==


This tutorial covers very basics of developing Plasma applets using Python. Most of the material discussed here is boring but important "boilerplate" stuff which stays mostly the same between every applet project. In future tutorials we can move on to move exciting things than just displaying a single line of static text.


== Packaging, installing & running ==
In the next tutorial we explain how to use Plasma's specialized widgets in your applet instead of manually implementing the <tt>paintInterface()</tt> method. Find out how in the [[../Using widgets|Using widgets tutorial]].


Plasma applets can be packaged in zip files and installed using the “plasmapkg” command line tool. The directory structure which we have used for our project matches that need in the zip file. All we have to do is zip it update. Run the following command from inside the hello-python directory.
== Troubleshooting ==


  zip -r ../hello-python.zip .
'''Error: '''
<syntaxhighlight lang="text">Installation of hello-python.zip failed.</syntaxhighlight>
'''Solution:''' enable more verbose output from plasmapkg. Run kdebugdialog:
<syntaxhighlight lang="text">kdebugdialog --fullmode</syntaxhighlight>
and enable the outputs for ''1209 libplasma''.


This will create the hello-python.zip file in the directory just above the hello-python directory. Go to this directory in the shell and run this plasmapkg command to install our little hello-python applet.
'''Error: '''
<syntaxhighlight lang="text">plasmoidviewer(19580)/libplasma Plasma::Package::isValid: Could not find required file mainscript , look in "/home/user/.kde4/share/apps/plasma/plasmoids/kotnet-login/contents/code/main.py"</syntaxhighlight>
'''Solution:''' check that you have those files (you need a main.py) and that you don't have any wrong names.


  plasmapkg -i hello-python.zip
'''Error: '''
<syntaxhighlight lang="text">Could not create a python scriptengine for "your package name"</syntaxhighlight>
'''Solution:''' check if your plasma installation has the required files (plasma_importer.py, plasmascript.py) and the package python-dev is installed.


This installs the applet into your home directory. Now we can run it. When developing applets it is more convenient to use the “plasmoidviewer”. This is a little utility which displays an applet in a window instead of you having to use your desktop. This command below will run our applet.
Packages for openSUSE are available in the KDE:KDE4:Factory:Desktop repository (python-kdebase4 and python-devel).


  plasmoidviewer hello-python
Source files: http://websvn.kde.org/trunk/KDE/kdebase/workspace/plasma/generic/scriptengines/python/


You should now be able to see the fruits of your labor.


To uninstall our applet we use plasmapkg again with its -r option.


  plasmapkg -r hello-python
'''Error: '''
<syntaxhighlight lang="text">ImportError: /usr/lib/python2.5/lib-dynload/select.so: undefined symbol: PyExc_ValueError</syntaxhighlight>
'''Solution:''' you probably have PyQt compiled against a different version of python than the one that is trying to run the code (python2.5 vs python2.6).


== Conclusion ==
You'll need to find correct packages.  Upgrade your PyQt to 2.6 (recommended) or downgrade your python installation to 2.5


This tutorial covers very basics of developing Plasma applets using Python. Most of the material discussed here is boring but important “boilerplate” stuff which stays mostly the same between every applet project. In future tutorials we can move on to move exciting things than just displaying a single line of static text.
'''Error: '''
<syntaxhighlight lang="text">This object could not be created for the following reason: Could not open the hello-python package required for the Hello Python widget.</syntaxhighlight>
'''Solution:''' Follow the Tutorial closely. You need to create the following file structure:
<pre>
/hello-python/
/hello-python/metadata.desktop
/hello-python/contents/
/hello-python/contents/code/
/hello-python/contents/code/main.py
</pre>

Latest revision as of 23:27, 11 September 2014

Abstract

In this tutorial we'll cover setting up a very simple plasma applet in Python, and how to install it and run it, basically the edit, install, run and debug cycle. To follow this you will need to have KDE 4.2 or later installed, and also the python support for plasma and related dependencies. I'm going to assume that you are using a unix-style operating system such as Linux or *BSD and aren't adverse to the shell.

Project Structure

The first step for any software project is to set up your project's directory on disk. For this tutorial we are going to create a very simple "hello-python" applet. Create a directory on somewhere called hello-python which in turn contains a contents directory which then contains a code directory. This command below will do all this.

mkdir -p hello-python/contents/code

This creates a simple directory structure which also matches the package structure expected by the plasmapkg command. More on this later.

Metadata.desktop

In the hello-python directory create a file called metadata.desktop and open it in your text editor. Copy the following code into metadata.desktop.

[Desktop Entry]
Encoding=UTF-8
Name=Hello Python
Name[nl]=Hallo Python
Type=Service
ServiceTypes=Plasma/Applet
Icon=chronometer
X-Plasma-API=python
X-Plasma-MainScript=code/main.py
X-KDE-PluginInfo-Author=Simon Edwards
X-KDE-PluginInfo-Email=[email protected]
X-KDE-PluginInfo-Name=hello-python
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://plasma.kde.org/
X-KDE-PluginInfo-Category=Examples
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true

This metadata.desktop file list important information needed by Plasma to load the applet, and also information about what the applet is and who created it. The Name field lists the name of the applet. This field can also be listed multiple times as different translations. Here I've just given a Dutch translation of the name. The [nl] indicates the language of the field.

The Type and ServiceType fields identify what kind of thing this desktop file is describing. Here we say that we have a plasma applet.

The Icon field gives the name of the icon to associate with this applet. The icon is typically shown in things such as the "Add widget" dialog in Plasma. If you want to use a custom icon, you can place it in the package root, along metadata.desktop, and then point to it like this:

Icon=/mycustomicon.png

The X-Plasma-API and X-Plasma-MainScript fields are used specifically by Plasma to find the correct script-engine to use when loading and running the applet.

Most of the X-KDE-PluginInfo-* fields give extra information about who created the applet. X-KDE-PluginInfo-Category lists a category which this applet belongs to. http://techbase.kde.org/Projects/Plasma/PIG has a list of acceptable category names.

Main script

Create a file in the contents/code directory called main.py, open it up in your text editor and put this code in it and save it.

# -*- coding: utf-8 -*-
# <Copyright and license information goes here.>
from PyQt4.QtCore import Qt
from PyKDE4.plasma import Plasma
from PyKDE4 import plasmascript

class HelloPython(plasmascript.Applet):
    def __init__(self,parent,args=None):
        plasmascript.Applet.__init__(self,parent)

    def init(self):
        self.setHasConfigurationInterface(False)
        self.resize(125, 125)
        self.setAspectRatioMode(Plasma.Square)

    def paintInterface(self, painter, option, rect):
        painter.save()
        painter.setPen(Qt.white)
        painter.drawText(rect, Qt.AlignVCenter | Qt.AlignHCenter, "Hello Python!")
        painter.restore()

def CreateApplet(parent):
    return HelloPython(parent)

This is basically the simplest applet which actually does something. The code starts out with the usual copyright notice and license information which I've actually left out for now.

Next up is a bunch of imports. The Python support in Plasma is an extension of PyQt and PyKDE. So here we pull in a couple of PyQt and PyKDE modules which we will need. There are two plasma related modules which we use. The first, PyKDE4.plasma, are the bindings straight on top of the Plasma C++ API. This gives us access to most of the APIs we need, but not all. To create applets which can be packaged and delivered to users across the network via KDE's Get Hot New Stuff (GHNS) framework, we need to use some extra Python specific classes which are in PyKDE4.plasmascript.

Now we define our main applet class. This is our Hello Python applet and it must be a subclass of plasma.Applet. In the __init__() method we need to make sure that we give the super class constructor a chance to run. Note that it is recommended to put most of the initialisation code inside the init() method and not in the __init__(). After Plasma has constructed and initialised the applet, Plasma will call the init() method on the applet to let it continue setting itself up. Our init() method is rather short. We just tell Plasma that we don't have a configuration dialog and we set up the initial size of the applet.

The paintInterface() method is where we draw our "Hello Python" message. First we save the state / settings of the given QPainter object by calling save(). Then we set the color to white and use drawText() to draw our message. Finally we call restore() which resets the QPainter settings back to how it was when paintInterface() was called.

The CreateApplet() function is needed to create an instance of our applet. When Plasma loads a Python based applet it will expect there to be a CreateApplet() function which it will call. The task of the CreateApplet() function is to create and instance of the applet and pass it back to Plasma.

Packaging, installing & running

Plasma applets can be packaged in zip files and installed using the plasmapkg command line tool. The directory structure which we have used for our project matches that need in the zip file. All we have to do is zip it update. Run the following command from inside the hello-python directory.

zip -r ../hello-python.zip .

This will create the hello-python.zip file in the directory just above the hello-python directory. Go to this directory in the shell and run this plasmapkg command to install our little hello-python applet.

plasmapkg -i hello-python.zip

This installs the applet into your home directory. Now we can run it. When developing applets it is more convenient to use the plasmoidviewer. This is a little utility which displays an applet in a window instead of you having to use your desktop. This command below will run our applet.

plasmoidviewer hello-python

You should now be able to see the fruits of your labor.

To uninstall our applet we use plasmapkg again with its -r option.

plasmapkg -r hello-python

Conclusion

This tutorial covers very basics of developing Plasma applets using Python. Most of the material discussed here is boring but important "boilerplate" stuff which stays mostly the same between every applet project. In future tutorials we can move on to move exciting things than just displaying a single line of static text.

In the next tutorial we explain how to use Plasma's specialized widgets in your applet instead of manually implementing the paintInterface() method. Find out how in the Using widgets tutorial.

Troubleshooting

Error:

Installation of hello-python.zip failed.

Solution: enable more verbose output from plasmapkg. Run kdebugdialog:

kdebugdialog --fullmode

and enable the outputs for 1209 libplasma.

Error:

plasmoidviewer(19580)/libplasma Plasma::Package::isValid: Could not find required file mainscript , look in "/home/user/.kde4/share/apps/plasma/plasmoids/kotnet-login/contents/code/main.py"

Solution: check that you have those files (you need a main.py) and that you don't have any wrong names.

Error:

Could not create a python scriptengine for "your package name"

Solution: check if your plasma installation has the required files (plasma_importer.py, plasmascript.py) and the package python-dev is installed.

Packages for openSUSE are available in the KDE:KDE4:Factory:Desktop repository (python-kdebase4 and python-devel).

Source files: http://websvn.kde.org/trunk/KDE/kdebase/workspace/plasma/generic/scriptengines/python/


Error:

ImportError: /usr/lib/python2.5/lib-dynload/select.so: undefined symbol: PyExc_ValueError

Solution: you probably have PyQt compiled against a different version of python than the one that is trying to run the code (python2.5 vs python2.6).

You'll need to find correct packages. Upgrade your PyQt to 2.6 (recommended) or downgrade your python installation to 2.5

Error:

This object could not be created for the following reason: Could not open the hello-python package required for the Hello Python widget.

Solution: Follow the Tutorial closely. You need to create the following file structure:

/hello-python/
/hello-python/metadata.desktop
/hello-python/contents/
/hello-python/contents/code/
/hello-python/contents/code/main.py