[Kde-bindings] XML format

Ashley Winters jahqueel at yahoo.com
Wed Mar 5 08:17:33 UTC 2003


Don't mind me. I'm just thinking out loud. :)

I'm not a big DTD nazi, so here's my human description.

I'm using the XML::Simple module to generate the XML file and read it
back in for the binding generator, so it'll actually escape those pesky
& references. Not to mention it standardizes the data-format used in
the binding generator (I'm notorious for utilizing bizzare
datastructures).

<api name="Qt">    Qt, KDE, KHTML, etc...
 <class name="QWidget">   Obvious

protection and name attributes are REQUIRED for every element

  <base protection="public" name="QObject" />
  <base protection="public" name="QPaintDevice" />

  <enum protection="public" name="FocusPolicy">
   <constant value="0" name="NoFocus" type="enum
QWidget::FocusPolicy"/>
   ...
  </enum>

Notice below that the "type" of a method is treated the same as the
"type" of a member variable. In essence, every method with a
return-value is being treated like a variable.

Here, we have className(), with no arguments.

  <method protection="public" name="className" type="char const*"
call="virtual" this="const" />

Note that "call" has several possible values:
* constructor
* destructor
* static
* virtual
* abstract
* operator

Lets try a constructor:
  <method protection="public" name="QWidget" call="constructor">
   <argument name="parent" type="class QWidget*" />
   <argument name="name" type="char const*" />
   <argument name="f" typedef="WFlags" type="unsigned long int" />
  </method>

Note how the type is in a funky format, yet still valid C++. It's meant
to be parsed easily. The "type" is the type GCC sees for the variable
after handling typedefs. The typedef is the actual type used in the
code. The superfluous 'class' or 'enum' in the type is guaranteed to be
present in the XML file for every type, to make it easier to parse with
a dumb program.

ALSO: Every argument is GUARANTEED to have a name! I'm opening the
possibility of implementing named arguments in PerlQt. I'm using the
name from the C++ source file where possible, and "argX" when
necessary.

Qt::Widget->new(-name => "Cool Widget", -parent => $layout)

Also, note the lack of default argument values. I'm not supporting
them! Therefore, that prototype is incomplete. Here's the rest:

  <method protection="public" name="QWidget" call="constructor">
   <argument name="parent" type="class QWidget*" />
   <argument name="name" type="char const*" />
  </method>
  <method protection="public" name="QWidget" call="constructor">
   <argument name="parent" type="class QWidget*" />
  </method>
  <method protection="public" name="QWidget" call="constructor" />

The XML format WILL have signal/slot info, since it's absurdly easy to
get without parsing the source. There's no reason not to do it.

  <method protection="public" name="setMouseTracking" call="virtual"
connect="slot">
   <argument name="enable" type="bool" />
   <signature style="connect">setMouseTracking(bool)</signature>
  </method>

The signature thing is a bit funky... that particular one provides the
signature Qt would recognize if you wanted to connect to that method.
I've pondered having other signatures as well (like virtual method
signature or C function signature or something) so I wanted an
extensible tag in case I wanna add more in the future.

In addition to the no-default-argument rule, there's also a
no-implicit-virtual-method rule. That means, every virtual method must
be in every class' XML file, even methods from base classes. This is
meant to put all the burden on the -fdump parser.

If a class declares only a single method:

class QFoo : public QWidget {
public:
    void foo();
};

The XML file for QFoo will list 90+ virtual methods as being in that
class. Yes, it's excessively verbose. So what? I use defined="QObject"
or whatever to specify what class it was last defined in if we're using
an inherited virtual method.

Also, here's a couple tricks to keep in mind:

Virtual functions can have default arguments, but only the
complete-argument version of the method is call="virtual".

Slots can have default arguments, and moc recognizes it!

For a given slot...
public slots:
    void foo(int = 1, bool = FALSE, const char*="Nope");

There exists the following slot signatures for Qt:
foo(int,bool,const char*)
foo(int,bool)
foo(int)
foo()

Those signatures are separate and functional from Qt's perspective.
Therefore, connect="slot" for all those prototypes. Same goes for
signals.

Also, member variables should be spit out as well. I just treat them
like methods with no arguments. Or rather, do I treat methods with no
arguments like member variables?

  <member protection="private" name="winid" type="unsigned long int"
typedef="WId" />

 </class>
</api>

Seems I forgot to describe this="const". I didn't need to though, did
I?

XML file forthcoming. I suck at conforming to standards, cause I keep
breaking them. Sorry. :(

So, to summarize:

<?xml version="1.0"?>
<!DOCTYPE api [

<!ENTITY % access "(public | private | protected)">

<!ENTITY % type "type CDATA #IMPLIED
                 typedef CDATA #IMPLIED">

<!ELEMENT api (class+) >
<!ATTLIST api name CDATA #REQUIRED >

<!ELEMENT class (base* | method* | member* | constant* | enum*) >
<!ATTLIST class name CDATA #REQUIRED >

<!ELEMENT base EMPTY >
<!ATTLIST base
          name CDATA #REQUIRED
          protection %access; #REQUIRED >

<!ELEMENT method (argument* | signature*) >
<!ATTLIST method
          name CDATA #REQUIRED
          protection %access; #REQUIRED
          call (constructor | destructor | static |
                virtual | abstract | operator | method)
               "method"
          defined CDATA #IMPLIED
          connect (signal|slot) #IMPLIED
          %type; >

<!ELEMENT argument EMPTY >
<!ATTLIST argument
          name CDATA #REQUIRED
          %type; >

<!ELEMENT signature (#PCDATA) >
<!ATTLIST signature
          style CDATA #REQUIRED >

<!ELEMENT member EMPTY >
<!ATTLIST member
          name CDATA #REQUIRED
          protection %access; #REQUIRED
          %type; >

<!ELEMENT constant EMPTY >
<!ATTLIST constant
          name CDATA #REQUIRED
          protection %access; #IMPLIED
          value CDATA #IMPLIED
          %type;>

<!ELEMENT enum (constant+) >
<!ATTLIST enum
          name CDATA #REQUIRED
          protection %access; #REQUIRED >
]>

I didn't validate that DTD, so don't complain if it's borked. Also, if
you're an Xml Case Nazi, I'm hardly married to the lower-case names.
It's A Pain To Do Pascal Case In Perl Though. Even camel Case is
Annoying sometimes, Even though It's perl's Mascot.

Was this email long enough? Trying to write a DTD on the fly in the
Yahoo! mail composer was an interesting exercise.

Ashley Winters

__________________________________________________
Do you Yahoo!?
Yahoo! Tax Center - forms, calculators, tips, more
http://taxes.yahoo.com/



More information about the Kde-bindings mailing list