PyKDE4 - FAQ
Prev |

## Frequently Asked Questions

1. Why is there no menu text in my program's menus?
2. Why doesn't pykdedocs have menus?
3. How do I set the icon for my program?
4. How do I set the logo in the "about application" dialog box?
5. Nothing happens when I click a link in KHTMLPart
6. My program doesn't use KApplication ...
7. What is "QWidget: Must construct a QApplication before a QPaintDevice"?
8. My program doesn't have KMainWindow (or descendant) ...
9. My program works, but crashes when I quit
10. What is "underlying C/C++ object deleted"?

Why is there no menu text in my program's menus?

Why doesn't pykdedocs have menus?

pykdedocs should display both a traditional menu bar (File, etc) and toolbar with icons. Your application, if you've written it to display a menubar (see the 'Getting Started' tutorial), should also display its menus.

One reason menus don't display text (you'll find the icons are there and the menus function - they just don't display any text) in PyKDE4 for KDE 4.0.0 and 4.0.1 is that both KDE versions default to the 'Oxygen' theme, and PyKDE4 won't display menu text correctly with that theme.

To display menu text in pykdedocs or your application, you need to change the theme. If KDE4 is your principle desktop application (not KDE4 running under KDE3, as in SuSE 10.3, for example), you can use Desktop Configuration or the Control Center to change the theme.

If you're running SuSE 10.3 or a similar distribution that uses KDE3 for the desktop but allows you to run KDE4 applications, you need to run the following command at the command line (in a konsole, for example):

            kcmshell4 style

That should pop up a window that displays the style control module which will allow you to change the theme (to 'Plastique', or 'CleanLook', for example). If kcmshell4 isn't in your path or isn't installed, you'll need to locate it or install it to change the theme for systems where KDE4 isn't the principle desktop.

How do I set the icon for my program?

Your program should subclass KMainWindow (or KXmlGuiWindow, or KParts::MainWindow). If the name of your instance is "mainWindow" then add:

    mainWindow.setWindowIcon (KIcon (<icon name or path>))

Or inside the main window constructor:

    self.setWindowIcon (KIcon (<icon name or path>))

How do I set the logo in the "about application" dialog box?

The method that allows you to set the logo shown in the "About Application" dialog box from the Help menu is:

    KAboutData.setProgramLogo (image)

but there are several problems with using this. First, the image must be contained within a QVariant, and with PyQt4, the only method call available to put a QImage inside a variant is

    QVariant (int, void*)

where the second parameter has to be an actual C++ pointer to void. The int is an int equivalent of the enumerator QVariant.Image. There are two possible ways to accomplish this. The first is to use the PyKDE4 predefined method:

    from PyKDE4 setprogramlogo import setprogramlogo
    ...
    image = QImage (<path to your image file>)
    aboutData = KAboutData (<arguments>)

    setprogramlogo (aboutData, image)

The alternative is to duplicate the setprogramlogo code in your file:

    import sip
    ...
    image = QImage (<path to your image file>)
    aboutData = KAboutData (<arguments>)

    vptr  = sip.voidptr (sip.unwrapinstance (image))
    vtype = int (QVariant.Image)
    aboutData.setProgramLogo (QVariant (vtype, vptr))

Of course you need to do the required PyKDE4 and PyQt4 imports as well, which aren't shown here.

Nothing happens when I click a link in KHTMLPart

Actually, something does happen - you just have to figure out how to connect to it. KHTMLPart itself doesn't handle link clicks. The signal emitted when a link is clicked comes instead from a KParts.BrowserExtension that your KHTMLPart instance already owns. You connect to it like this:

    self.htmlpart  = KHTMLPart (self)
    self.extension = self.htmlpart.browserExtension ()

    self.connect (self.extension,
                  SIGNAL ('openUrlRequest (const KUrl&, const KParts::OpenUrlArguments&, const KParts::BrowserArguments&)'),
                  self.slotOpenURL)

The slot you connect to then has to hand the link's URL back to KHTMLPart to load. However, before doing that, you also need to determine the mime type of the content at the link. KHTMLPart only displays HTML, not .pdf or .tar.gz files (actually, it will display those, but as binary). One way to check is:

    mimetype = KIO.NetAccess.mimetype (url, None)
    if mimetype != "text/html":
        <insert code to handle non-HTML here>

KIO.NetAccess.mimetype is slow and it's also synchronous (you have to wait for it to complete before moving on with the rest of your code). There are asynchronous KIO.Job ways of determining the mime type. If you expect a lot of local files (as pykdedocs does), it may be faster to check for those first using os.path.exists () and checking for a ".html" extension.

My program doesn't use KApplication ...

That's probably not a good thing. Most of KDE relies on the existence of a KApplication object, and most KDE code won't work without either a KApplication or KUniqueApplication instance.

QApplication can't be substituted for KApplication, either.

See the next question for what happens when you don't have a KApplication.

What is "QWidget: Must construct a QApplication before a QPaintDevice"?

Your application hasn't created a KApplication or KUniqueApplication instance. See the previous question.

Note that the error message comes from Qt, so it refers to QApplication, but for PyKDE4, KApplication is what you have to use.

My program works, but crashes when I quit

Does your program use KMainWindow (or a KMainWindow subclass, like KXmlGuiWindow or KParts.MainWindow) as its main widget?

If it doesn't, that's likely the cause of the crash (see next question). If it does, it may be a PyKDE4 bug and should be reported.

My program doesn't have KMainWindow (or descendant) ...

That's not as big a problem as not having a KApplication instance, but it may still cause a problem. The shutdown code (run when your program exits) more or less expects a KMainWindow (or KMainWindow subclass like KXmlGuiWindow or KParts::MainWindow) to own the objects to be destroyed at exit.

Not having a KMainWindow or similar class that "owns" the GUI can lead to crashes at exit, as objects are not destroyed in the proper order. This is more of a problem in PyKDE than in KDE itself - it may work fine in C++, but may not work in Python.

From my perspective, troubleshooting exit code problems is nasty and fixing them reliably is not alway possible - what works for one situation may cause others to fail. It's simpler just to subclass KMainWindow when writing your application.

What is "underlying C/C++ object deleted"?

You've probably subclassed a PyKDE4 or PyQt4 class, but you forgot to call the original class's __init__ method. The error is caused by doing something like this:

    class WidgetSubClass (QWidget):
        def __ init__ (self, parent):
    	self.parent = parent

        def someOtherMethod (self):
    	...

What you need to do is

    class WidgetSubClass (QWidget):
        def __ init__ (self, parent):
            QWidget.__init__ (self, parent) # don't forget this !
    	self.parent = parent

        def someOtherMethod (self):
    	...

and make sure you pass "self" as the first argument.

The QWidget__init__ call (or whatever is equivalent in your code) doesn't have to be the first statement in your object's __init__ method, but it has to be there. And it has to be there before you start attempting to use the parent class's methods.

Prev | Table of Contents |
PyKDE4 and QtDesigner |