This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Kde systemsettings module in python

Tags: pykde, systemsettings, module pykde, systemsettings, module pykde, systemsettings, module
(comma "," separated)
sjkwizard
Registered Member
Posts
20
Karma
0
OS

Kde systemsettings module in python

Tue Dec 14, 2010 11:30 am
Hi all,
it's the first time that I try to write a kde software. So I'm a real noob.

I want ask you how can I write a systemsettings module in python using pykde. I want to design the interface trough Qt Designer and compiling it with pykdeuic4. After that I want to know wich code I should add to create this kind of module.

Thanks.
User avatar
bcooksley
Administrator
Posts
19765
Karma
87
OS
This is possible. I suggest you look at the printer module included in KDE SC as reference documentation.


KDE Sysadmin
[img]content/bcooksley_sig.png[/img]
sjkwizard
Registered Member
Posts
20
Karma
0
OS
I searched around in the code of kde for the module you mentioned but I couldn't find it...can you tell me exactly where can I find it, please?
sjkwizard
Registered Member
Posts
20
Karma
0
OS
sjkwizard wrote:I searched around in the code of kde for the module you mentioned but I couldn't find it...can you tell me exactly where can I find it, please?


I found it...it was in the kdeadmin package!
sjkwizard
Registered Member
Posts
20
Karma
0
OS
I need some more help about the systemsettings module.

I created a desktop file and i putted it in /usr/share/kde4/services so now I can see a new icon on systemsettings
Here is the contente of that file

Code: Select all
[Desktop Entry]
Exec=kcmshell4 appName
Icon=appName
Type=Service

X-KDE-ServiceTypes=KCModule
X-KDE-Library=kpythonpluginfactory
X-KDE-ParentApp=kcontrol
X-KDE-PluginKeyword=???

X-KDE-System-Settings-Parent-Category=system-administration
X-KDE-Weight=60


And here is the content of my file appName.py

Code: Select all
#!/usr/bin/python

#import sys
#from PyKDE4 import kdeui, kdecore
from PyQt4.QtGui import *
from PyKDE4.kdecore import *
from PyKDE4.kdeui import *

class PyKcm(kdeui.KCModule):
    def __init__(self, component_data, parent):
        print("PyKcm constructor")
        KCModule.__init__(self, component_data, parent)
        print("PyKcm constructor done")
        self.setButtons(KCModule.Apply)

    def save(self):
        print "hello"

    def load(self):
        print "hello world"

def CreatePlugin(widget_parent, parent, component_data):
        print("WIdget parent")
        return PyKcm(component_data, widget_parent)


This simple code should work, or not? But I'm wondering...where should I put my appName.py file? What is X-KDE-PluginKeyword=? Do I need something else? What is exactly the kpythonpluginfactory?

Thanks in advance.
User avatar
bcooksley
Administrator
Posts
19765
Karma
87
OS
X-KDE-PluginKeyword appears to be a reference to the *.py file to load in order to begin running the control module.

kpythonpluginfactory is likely a System Settings module which wraps Python based modules and allows for them to be loaded and used.


KDE Sysadmin
[img]content/bcooksley_sig.png[/img]
sjkwizard
Registered Member
Posts
20
Karma
0
OS
I found how to create a kcmodule with pykde

You can find an example here: http://websvn.kde.org/trunk/KDE/kdebind ... e_example/

It's enough to write a python file like this:

Code: Select all
class appName(KCModule):
    def __init__(self, component_data, parent):
        KCModule.__init__(self,component_data, parent)
        uic.loadUi(unicode("/PATH/appName.ui"), self)

def CreatePlugin(widget_parent, parent, component_data):
    return appName(component_data, widget_parent)


The function CreatePlugin is called from the parent app (like systemsettings) and it should return a class inerhit from KCModule.
Then you should put this file in /usr/share/kde4/apps/appName/appName.py
Finally you should create a appName.desktop file containg this:

Code: Select all
[Desktop Entry]
Exec=kcmshell4 appName
Icon=SomeIcon
Type=Service

X-DocPath=kcontrol/appName/index.html

X-KDE-ServiceTypes=KCModule
X-KDE-Library=kpythonpluginfactory
X-KDE-ParentApp=kcontrol
X-KDE-PluginKeyword=appName/appName.py

X-KDE-System-Settings-Parent-Category=computer-administration
X-KDE-System-Settings-Parent-Category-V2=system-administration
X-KDE-Weight=65

Name=AppName
Comment=Some comment

X-KDE-Keywords=appName

Categories=Qt;KDE;System;


...and put it in /usr/share/kde4/services
(and you should even create a ui file for the interface)

I hope this explanation can be useful for someone.


Now I still have some questions..

I analyzed the code of the printer configuration module (that is written in pykde) and I didn't understand the structure.

It define a class PyKCM (inehrit from KCModule) and a class GUI().
In the class GUI it define a function makegui that return a class PyKCM
In the CreatePlugin function it create a class GUI and then it call and return the function makeui.

Is this structure logically correct? If I just define in my class appName (inherit from KCModule ) all the functions, I connect the button with the function in the constructor and then I return just this class from the CreatePlugin function is the same? Why doing this in two step?
Maybe is because in this way you have an object 'self' that contain the functions and a subobject 'self.ui' that represent just the real gui ( buttons & co), maybe is just for making the code more clear?
I hope I've been enough clear.
I really want to set up everything in the correct way so I can start to write the real code for implementing all the functions.
Thanks.

Here is the code:

Code: Select all
class PyKcm(KCModule):
    def __init__(self, component_data, parent, gui):
        KCModule.__init__(self, component_data, parent)

        uic.loadUi(unicode(APPDIR + "/" + "system-config-printer.ui"), self)
        self.setButtons(KCModule.Apply)
        self.gui = gui
       
    def changed(self, state):
        """a setting has changed, activate the Apply button"""
        self.emit(SIGNAL("changed(bool)"), state)

    def save(self):
        self.gui.on_btnPrinterPropertiesApply_clicked()

    def load(self):
        self.gui.on_btnRevert_clicked()


Code: Select all
class GUI(QWidget):

    [OMITTED CODE]

    def makeui(self, component_data, parent):
        self.ui = PyKcm(component_data, parent, self)


    [OMITTED CODE]

   self.ui.connect(self.ui.mainlist, SIGNAL("itemSelectionChanged()"), self.on_tvMainList_cursor_changed)
        self.ui.connect(self.ui.mainlist, SIGNAL("currentItemChanged (QTreeWidgetItem*, QTreeWidgetItem*)"), self.on_tvMainList_changed)

    [OMITTED CODE]

    return self.ui


Code: Select all
def CreatePlugin(widget_parent, parent, component_data):
    u = GUI()
    KGlobal.locale().insertCatalog("system-config-printer-kde")
    kcm = u.makeui(component_data, widget_parent)
    return kcm
User avatar
einar
Administrator
Posts
3402
Karma
7
OS
sjkwizard wrote:I analyzed the code of the printer configuration module (that is written in pykde) and I didn't understand the structure.

While I haven't had the time to do KCMs yet, I would suggest against using that application as an example, as it was a rather hackish port of the GNOME applet, with huge (4K LoC is a lot for Python standards) modules and extremely poor internal documentation.


"Violence is the last refuge of the incompetent."
Image
Plasma FAQ maintainer - Plasma programming with Python
sjkwizard
Registered Member
Posts
20
Karma
0
OS
Thanks. Actually I used the printer module and the userconfig module as start point and this is the result:

Code: Select all
class appName (KCModule):
    def __init__(self, component_data, parent):
        KCModule.__init__(self,component_data, parent)
       
        #Loading the UI module
        self.ui = uic.loadUi(unicode("PATH/main.ui"))
        self.ui.status = uic.loadUi(unicode("PATH/status.ui"))
        self.ui.limits = uic.loadUi(unicode("PATH/limits.ui"))
       
        #Create the layout using group box
        self.ui.statusLayout = QVBoxLayout(self.ui.statusGroupBox)
        self.ui.statusLayout.addWidget(self.ui.status)
       
        self.ui.limitsLayout = QVBoxLayout(self.ui.limitsGroupBox)
        self.ui.limitsLayout.addWidget(self.ui.limits)           
       
        self.mainLayout = QVBoxLayout(self)
        self.mainLayout.addWidget(self.ui)


I design with Qt creator a main.ui with two groupbox inside (and some other stuff) then I design two forms (limits.ui and status.ui) and I dinamically load it inside the two groupbox (so if i want to change from group box to tab it will be easy). In this way I can even access to them through "hierarchy name":
self represent the class
self.ui represent the UI (in particular main.ui)
self.ui.status represent (the module status.ui that is logically inside main.ui)
self.ui.limits represent (the module limits.ui that is logically inside main.ui)

What do you think about it? Are the name too long? (In this way I think that all the code will be more clear)
Is it a good start point?

Reading the code of userconfig module I see some strange behaviour:
1)when you run userconfig the module appear outside from systemsettings
2)there is some code for running it standalone but this is unuseful since you can run a kcmodule standalone through kcmshell4
3)the buttons provided by kcmodule are not used and so all the changes are applied real time without pressing the apply button so you can't cancel the changes (and even the other standard buttons are not used)
sjkwizard
Registered Member
Posts
20
Karma
0
OS
One last thing. I can't set the buttons through self.setButtons(KCModule.Apply)

If I call that function in the constructor the button apply remain grayed out.
sjkwizard
Registered Member
Posts
20
Karma
0
OS
I still have problem with KCModule

In the desktop file i used: X-KDE-RootOnly

This directive should do this:
If this is set to "true", the module must be executed with root permissions. The module loader will then show the module in greyed-out (disabled) state with a warning until the "modify" button is pressed which allows running the module in an root environment using kdesu and QXEmbed.

Instead the behavior is different: When I click on my module in systemsettings a messagge box pop up asking for the root password and then the module is loaded OUTSIDE systemsettings. Is it possible to fix this in some way?

I'm supposing that this is even the cause because I can't set the Apply button active.
User avatar
bcooksley
Administrator
Posts
19765
Karma
87
OS
This functionality should only work in the KDE 3.x series, as KDE 4 does not support root mode, it uses the KAuth framework.


KDE Sysadmin
[img]content/bcooksley_sig.png[/img]
sjkwizard
Registered Member
Posts
20
Karma
0
OS
Ok. I read that some distribution a made a patch for supporting this functionality, but I'll migrate to KAuth. Thanks.
sjkwizard
Registered Member
Posts
20
Karma
0
OS
Anyone know if the helper can be implemented in python? Or have I to implement it in C++? There is no documentation about this (there is just documentation for the C++ version)


Bookmarks



Who is online

Registered users: Bing [Bot], Evergrowing, Google [Bot], rockscient