Jump to content
KDE TechBase

Languages/Python/PyKDE Knotify Tutorial

From KDE TechBase


This page has been archived
The information on this page is outdated or no longer in use but is kept for historical purposes. Please see the Category:Archives for similar pages.
Warning
This tutorial uses Qt4, PyQt4, and PyKDE4.


Python KNotify Tutorial
Tutorial Series   Python
Previous   None
What's Next  

Abstract

The aim of this tutorial is to give a sample class to include Notifications and Jobs to your own python programms, so the user can see what is going on (for example a backup system, that tells you that is backuping right now). It assumes a basic working knowledge of Python and PyKDE4. For now only the Job part is mentioned, 'cause that is the only part I've created right now.

Further plans

To add the Notification part also to this tutorial.

Instruction

We start with a minimal KDE Appliciation (Using PyKDE4):

#! /usr/bin/python
# -*- coding: utf-8 -*-
if __name__ == "__main__":
 importsys
 
 fromPyKDE4.kdecoreimport KCmdLineArgs, KAboutData, KLocalizedString, ki18n
 fromPyKDE4.kdeuiimport KApplication 
 
 appName = "default"
 catalog = ""
 programName = ki18n ("default") 
 version = "1.0"
 description = ki18n ("Default Example") 
 license = KAboutData.License_GPL
 copyright = ki18n ("(c) 2010 Sandro Knauß") 
 text = ki18n ("none") 
 homePage = "techbase.kde.org"
 bugEmail = "[email protected]"
 aboutData = KAboutData (appName, catalog, programName, version, description,
 license, copyright, text, homePage, bugEmail)
 
 KCmdLineArgs.init (sys.argv, aboutData)
 
 app = KApplication ()

Job class

The first step is to have a look to the [1]. The intersting on is:

So it is easy to write a small Job-Class:

fromPyQt4.QtCoreimport QObject,QTimer,QString
fromPyKDE4.kdecoreimport KJob
classMyJob(KJob):
 def__init__(self,parent=QObject()):
 KJob.__init__(self,parent)
 #We want to have a Suspenable and Killable Job
 self.setCapabilities(KJob.Capabilities(KJob.Suspendable|KJob.Killable))
 #Just a maximum Variable
 self.max=25
 #index
 self.i=0
 defstart(self):
 #initalizing for work
 self.i=0
 
 #start the actual work in another thread
 #this function has to terminate, before the work is done
 QTimer().singleShot(0, self.doWork)
 
 defdoWork(self): 
 #the actual work 
 try: 
 #if we are killed or suspended just return 
 if self.error() or self.isSuspended(): 
 return
 except RuntimeError:
 #if this class is killed before a RuntimeError will raise
 return
 #do a peace of hard work
 self.i+=1
 #fortunately we have made a peace of work 
 #-> show this to everybody
 KJob.setPercent(self,self.i*4)
 
 if self.i==self.max:
 #jeah we have done the bunch of work
 #send the result signal for showing, that we ended the work
 self.emitResult()
 return 
 #just go to sleep for 1000ms than go on
 QTimer().singleShot(1000, self.doWork)
 
 defdoSuspend(self):
 #the surounding function from KJob makes the isSuspended() become True
 #returns True for signaling that this class supports to suspend
 return True
 defdoResume(self):
 #start with work again
 QTimer().singleShot( 0, self.doWork )
 #return True for signaling that this class supports resuming
 return True
 defdoKill(self):
 #return True for signaling that we support killing
 return True

What is going on?

  • MyJob.__init__: First we create the class and initialize the counter i and the maximum max. To make is visible for others we set the Capacities, so this job is suspendable and killable.
  • MyJob.start: Here the pre working setting are made, we will se later for what we use this. After initalizing the Work we start the actual work by using a QTimer. The start method should start the asyncron.
  • MyJob.doWork: Do actual work and handle, if this job is killed or suspended.
  • MyJob.doSuspend/MyJob.doResume/MyJob.doKill: These function indicate that this feature is supported by this class.

How to use?

Just create a instance of this class and start it:

job=MyJob(app)
job.start()

We want to know when the jobs done?

Create a SLOT to the result-signal:

defhandleResult(job):
 #handleResult Function
 #it is called when the job is terminating
 if job.error():
 print 'error happend'
 else:
 print 'job has terminated successfully'
 
 #for terimation the complete application
 sys.exit()
job.result.connect(handleResult)

Now we also add app.exec_() at the end of the main part, to prevent the program to stop before the job is stopped.

Visual feedback

Till now, a normal user doesn't see anything what is going on. To change it we have to register the Job to a JobTracker. Now a user will see a progressbar and a suspend and a stop button. So we modify the start method:

fromPyKDE4.kioimport KIO
...
 defstart(self):
 #register the Job to the JobTracker
 KIO.getJobTracker().registerJob(self)
 self.i=0
 QTimer().singleShot(0, self.doWork)

Setting the job title and description

Now you have the running job and a user can see nice progressbar. However, there is no visible information what job is currently running and what it is doing. To change it we have to emit signal KJob.description in our method MyJob.doWork:


 defdoWork(self): 
 #the actual work 
 try: 
 #if we are killed or suspended just return 
 if self.error() or self.isSuspended(): 
 return
 except RuntimeError:
 #if this class is killed before a RuntimeError will raise
 return
 #do a peace of hard work
 self.i+=1
 #fortunately we have made a peace of work 
 #-> show this to everybody
 KJob.setPercent(self,self.i*4)
 self.description.emit(self, "Our Splendid Job", ("Source","counter"), ("Destination","dummy"))
 
 if self.i==self.max:
 #jeah we have done the bunch of work
 #send the result signal for showing, that we ended the work
 self.emitResult()
 return 
 #just go to sleep for 1000ms than go on
 QTimer().singleShot(1000, self.doWork)

The parameters of this signal are the sending job (anything else than self doesn't make sense here), job title, and two tuples consising of two strings arbitrary that can be used to denote some job details. (consider them as a key-value pair).

Conclusion

Here is the full code of this example.

Is is very easy to create a Job and make it visible to normal users.

AltStyle によって変換されたページ (->オリジナル) /