david at boddie.org.uk
Tue Sep 30 01:15:01 BST 2003
On Monday 29 September 2003 20:51, Jim Bublitz wrote:
> On Monday September 29 2003 10:35, David Boddie wrote:
> > The term KPart appears to cover a multitude of sins...
> I believe they're either KPart::ReadOnlyPart or
> KPart::ReadWritePart descendants.
> KParts are also different in KOffice than the rest of KDE if I
> recall correctly ...
Sounds nasty. That will require a separate set of wrappers, won't it?
I'm waiting for the next stable release of KOffice before embarking on that
[My thoughts on casting QObjects which I receive when using my plugin's
> If I read the tutorial correctly (I'm in kind of a rush at the
> moment), that's on the loading side - PyKDE can already load
OK. I'm actually trying to do this from the other end, I think.
> The C++ code is in part.sip, at the end. There is an
> example in the examples/ directory (pyParts.py) - the KTrader
> stuff is broken (doesn't come up with an image viewer to load),
> but the KParts stuff should still work. If you give it a KPart
> it can actually find and load, it should work.
I'll play with this to see if I can find a suitable KPart.
> createReadOnlyPart/createReadWritePart (which are PyKDE specific
> global functions) do all of the work and return a correctly
> typed instance (since about PyKDE3.3 or maybe earlier). Those
> are written to do the steps the docs (and apparently the
> tutorial) require to load the part and cast it.
Yes, I noticed those functions in the docs. I'll see whether I can use them
to replace my KLibFactory hacking.
> There are three possible scenarios:
> Application KPart to load
> ======== ==========
> Python C++ should work
> C++ Python not yet - need .so
This is what I'm trying.
I've managed to do some nasty tricks with sip in order to fool Python that
I've cast the QObject as a KHTMLPart. sip experts, prepare to be appalled at
the following extract from a static Python module:
static PyObject * cast_cast(PyObject *self, PyObject *args)
// This function takes two arguments, the first of which is the object
// to be converted; the second is the required class.
PyObject *object, *new_object;
const void *cppPtr;
if (PyTuple_Size(args) != 2)
object = PyTuple_GetItem(args, 0);
template_class = PyTuple_GetItem(args, 1);
// Obtain a pointer to the corresponding wrapper object.
sipThis = sipMapSelfToThis(object);
// Obtain the pure C++ pointer.
cppPtr = sipThis->u.cppPtr;
// Convert the pointer back to a instance of the template class.
new_object = sipMapCppToSelf(cppPtr, template_class);
I expect that this whole arrangement is likely to cause problems with
either reference counting or memory management.
Anyway, the Python code which avails itself of this is from the above
tutorial and does the following:
# The parent is assumed to be a KHTMLPart
if not self.parent().inherits("KHTMLPart"):
title = i18n( "Cannot validate source" )
text = i18n( "You cannot validate anything except web pages "
"this plugin, sorry." )
QMessageBox.warning( 0, title, text )
part = self.parent()
new_part = cast.cast(part, KHTMLPart)
# Get URL
url = new_part.url()
w3c = self.validateURL( url )
new_part.openURL( w3c )
The part object (a QObject) is cast using the KHTMLPart class from the khtml
module and stored in new_part. Since the part object isn't used after the
cast then potential problems are avoided (or delayed) but I'll have to check
its behaviour more thoroughly.
It's quite convenient to have this sort of casting functionality available
from Python, although I can see that it's a potential source of lots of
More information about the PyQt