(How to use/Visible feed/Conclusion) |
|||
| (6 intermediate revisions by 3 users not shown) | |||
| Line 1: | Line 1: | ||
| − | + | ||
{{TutorialBrowser| | {{TutorialBrowser| | ||
| Line 24: | Line 24: | ||
We start with a minimal KDE Appliciation ([http://techbase.kde.org/Development/Languages/Python/Using_PyKDE_4 Using PyKDE4]): | We start with a minimal KDE Appliciation ([http://techbase.kde.org/Development/Languages/Python/Using_PyKDE_4 Using PyKDE4]): | ||
| − | < | + | <syntaxhighlight lang="python"> |
#! /usr/bin/python | #! /usr/bin/python | ||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||
| Line 52: | Line 52: | ||
app = KApplication () | app = KApplication () | ||
| − | </ | + | </syntaxhighlight> |
== Job class == | == Job class == | ||
The first step is to have a look to the [http://api.kde.org]. The intersting on is: | The first step is to have a look to the [http://api.kde.org]. The intersting on is: | ||
| − | * [http://api.kde.org/pykde-4. | + | * [http://api.kde.org/pykde-4.3-api/kdecore/KJob.html KJob(KDE 4.3-PyKDE4)]- unfortunately this documention is only available for KDE 4.3. So we have also a look to the actual C++ Doumentation |
* [http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKJob.html KJob(KJob 4.x-C++API)] | * [http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKJob.html KJob(KJob 4.x-C++API)] | ||
So it is easy to write a small Job-Class: | So it is easy to write a small Job-Class: | ||
| − | < | + | <syntaxhighlight lang="python"> |
from PyQt4.QtCore import QObject,QTimer,QString | from PyQt4.QtCore import QObject,QTimer,QString | ||
from PyKDE4.kdecore import KJob | from PyKDE4.kdecore import KJob | ||
| Line 86: | Line 86: | ||
def doWork(self): | def doWork(self): | ||
| − | + | #the actual work | |
| − | + | try: | |
#if we are killed or suspended just return | #if we are killed or suspended just return | ||
if self.error() or self.isSuspended(): | if self.error() or self.isSuspended(): | ||
| Line 124: | Line 124: | ||
#return True for signaling that we support killing | #return True for signaling that we support killing | ||
return True | return True | ||
| − | </ | + | </syntaxhighlight> |
===What is going on?=== | ===What is going on?=== | ||
| Line 134: | Line 134: | ||
===How to use?=== | ===How to use?=== | ||
Just create a instance of this class and start it: | Just create a instance of this class and start it: | ||
| − | < | + | <syntaxhighlight lang="python"> |
job=MyJob(app) | job=MyJob(app) | ||
job.start() | job.start() | ||
| − | </ | + | </syntaxhighlight> |
===We want to know when the jobs done?=== | ===We want to know when the jobs done?=== | ||
Create a '''SLOT''' to the '''result'''-signal: | Create a '''SLOT''' to the '''result'''-signal: | ||
| − | < | + | <syntaxhighlight lang="python"> |
def handleResult(job): | def handleResult(job): | ||
#handleResult Function | #handleResult Function | ||
| Line 149: | Line 149: | ||
else: | else: | ||
print 'job has terminated successfully' | print 'job has terminated successfully' | ||
| + | |||
| + | #for terimation the complete application | ||
| + | sys.exit() | ||
job.result.connect(handleResult) | job.result.connect(handleResult) | ||
| − | </ | + | </syntaxhighlight> |
| + | |||
| + | 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=== | ===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: | 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: | ||
| − | < | + | <syntaxhighlight lang="python"> |
from PyKDE4.kio import KIO | from PyKDE4.kio import KIO | ||
... | ... | ||
| Line 164: | Line 169: | ||
self.i=0 | self.i=0 | ||
QTimer().singleShot(0, self.doWork) | QTimer().singleShot(0, self.doWork) | ||
| − | </ | + | </syntaxhighlight> |
| + | |||
| + | === 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''': | ||
| + | |||
| + | |||
| + | <syntaxhighlight lang="python"> | ||
| + | def doWork(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) | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | 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 === | === Conclusion === | ||
Here is the [[Development/Languages/Python/PyKDE_Knotify_Tutorial/MyJob.py|full code]] of this example. | Here is the [[Development/Languages/Python/PyKDE_Knotify_Tutorial/MyJob.py|full code]] of this example. | ||
| − | Is is very easy to create a Job and make it visible to normal users | + | Is is very easy to create a Job and make it visible to normal users. |
| Tutorial Series | Python |
| Previous | None |
| What's Next | |
| Further Reading | Qt Signals and Slots in python, Introduction to PyQT4, Using PyKDE4 |
Contents |
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.
To add the Notification part also to this tutorial.
We start with a minimal KDE Appliciation (Using PyKDE4):
#! /usr/bin/python # -*- coding: utf-8 -*- if __name__ == "__main__": import sys from PyKDE4.kdecore import KCmdLineArgs, KAboutData, KLocalizedString, ki18n from PyKDE4.kdeui import 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 = "bugs@sandroknauss.de" aboutData = KAboutData (appName, catalog, programName, version, description, license, copyright, text, homePage, bugEmail) KCmdLineArgs.init (sys.argv, aboutData) app = KApplication ()
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:
from PyQt4.QtCore import QObject,QTimer,QString from PyKDE4.kdecore import KJob class MyJob(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 def start(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) def doWork(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) def doSuspend(self): #the surounding function from KJob makes the isSuspended() become True #returns True for signaling that this class supports to suspend return True def doResume(self): #start with work again QTimer().singleShot( 0, self.doWork ) #return True for signaling that this class supports resuming return True def doKill(self): #return True for signaling that we support killing return True
Just create a instance of this class and start it:
job=MyJob(app) job.start()
Create a SLOT to the result-signal:
def handleResult(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.
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:
from PyKDE4.kio import KIO ... def start(self): #register the Job to the JobTracker KIO.getJobTracker().registerJob(self) self.i=0 QTimer().singleShot(0, self.doWork)
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:
def doWork(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).
Here is the full code of this example.
Is is very easy to create a Job and make it visible to normal users.