From bcc95cd92ca12c1783464b8ada6816d430dc0e98 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 18 Dec 2011 03:08:08 -0600 Subject: Initial import of libqt-perl (not yet TQt compatible) --- doc/en/index.html | 1081 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1081 insertions(+) create mode 100644 doc/en/index.html (limited to 'doc/en/index.html') diff --git a/doc/en/index.html b/doc/en/index.html new file mode 100644 index 0000000..6a4cc7b --- /dev/null +++ b/doc/en/index.html @@ -0,0 +1,1081 @@ + + + +Programming PerlQt + + + + + + +

+ + + + + +
+

+

+

Programming PerlQt

+

Germain Garand

+

This document describes a set of Perl bindings for the Qt toolkit. Contact +the author at <germain@ebooksfrance.com>

+

+

+
+

Introduction

+

PerlQt-3 is Ashley Winters' full featured object oriented interface to +Trolltech's C++ Qt toolkit v3.0.

+

It is based on the +SMOKE +library, a language independent low-level wrapper generated from Qt headers by +Richard Dale's +kalyptus +thanks to David Faure's module.

+

This document describes the principles of PerlQt programming. +It assumes you have some basic Perl Object Oriented programming knowledge.

+

Some C++ knowledge is recommended but not required. +It would mostly help you to find your way through Qt's excellent documentation which is our +ultimate and only reference. +If Qt is installed on your system, then you most probably +also have its documentation. Try the $QTDIR/bin/assistant program.

+

+

+
+

Installation

+

+

+

Requirements

+

To compile and use PerlQt, you'll need :

+ +

Perl and Qt's installation is out of the scope of this document. Please refer +to those projects' documentation.

+

+

+

Compilation

+

PerlQt uses GNU's Autoconf framework. However, the standard ./configure script is preferably driven +by the Makefile.PL wrapper. All options are forwarded to ./configure :

+
+ perl Makefile.PL
+

If SMOKE is missing, configure will generate its sources. +Then :

+
+ make
+
+ make install
+

This will install PerlQt, Puic and Smoke (if needed), as well as the pqtsh and pqtapi utilities.

+

The preferred install location for SMOKE and Puic is in the KDE3 file system. +If you don't have KDE3 installed, specify a location with configure's +--prefix option. e.g:

+
+ perl Makefile.PL --prefix=/usr
+

+

+

Troubleshooting and Configure Options

+

If Smoke's linking fails or your Qt library was built with very specific +options, run Makefile.PL again with:

+
+ perl Makefile.PL --with-threshold=0
+

When building smoke, configure will check for OpenGL and try to compile +support for it if it is properly installed and supported by Qt.

+

You may disable this checking with:

+
+ --disable-GL
+

Also, default behaviour is to prefer the Mesa GL library over a proprietary +implementation. +If your system features a proprietary OpenGL library, and you'd like to use +it, specify:

+
+ --without-Mesa
+

+

+

How to install PerlQt with user rights

+

To install PerlQt without super-user rights, simply follow this procedure:

+ +

+

+
+

Anatomy of PerlQt

+

A typical Qt program using GUI components is based on an event loop.

+

This basically means that such a program is no more envisioned as a straight +flow where you would need to handle yourself every single events (such as a +mouse click or a key press).

+

Instead, you just create an Application object, create the GUI components it +uses, +define what objects methods need to be called when an event occurs, +and then start the main event loop.

+

That's all! +Qt will handle all events and dispatch them to the correct subroutine.

+

Lets see how this process is implemented in a minimal PerlQt program.

+

+

+

Hello World

+
+ 1: use Qt;
+ 2: my $a = Qt::Application(\@ARGV);
+ 3: my $hello = Qt::PushButton("Hello World!", undef);
+ 4: $hello->resize(160, 25);
+ 5: $a->setMainWidget($hello);
+ 6: $hello->show;
+ 7: exit $a->exec;
+
+

This program first loads the Qt interface [line 1] and creates the application +object, passing it a reference to the command line arguments array @ARGV +[l.2]. +This application object is unique, and may later be accessed from +anywhere through the Qt::app() pointer.

+

At line 3, we create a PushButton, which has no parent (i.e : it won't be +contained nor owned by another widget). +Therefore, we pass to the constructor an undef value for the parent argument, +which is PerlQt's way of passing a Null pointer.

+

After some layouting at [l.4], we tell the application object that our main +widget is this PushButton [l.5]... that way, it will know that closing the +window associated with this widget means : quit the application.

+

Now the last steps are to make this widget visible (as opposed to +hidden, which is the default) by calling the show method on it [l.6] and +to start the application loop [l.7].

+

Syntax elements summary :

+
    +
  1. +All Qt classes are accessed through the prefix Qt::, which replaces the +initial Q of Qt classes. +When browsing the Qt documentation, you simply need to change the +name of classes so that QFoo reads Qt::Foo. +

    +
  2. +An object is created by calling the constructor of the class. It has the +same name as the class itself. +

    You don't need to say new Qt::Foo or Qt::Foo->new() as most Perl +programmers would have expected.

    +

    Instead, you just say :

    +
    + my $object = Qt::<classname>(arg_1, ..., arg_n);
    +

    If you don't need to pass any argument to the constructor, simply say :

    +
    + my $object = Qt::<classname>;
    +

    +
  3. +Whenever you need to pass a Null pointer as an argument, use Perl's undef +keyword. Do not pass zero. + Beware: this is by far the most common error in PerlQt programs. +

    Pointers are arguments preceded by an * +character in Qt's documentation (e.g: ``QWidget * widget'').

    +

+

+

+

Inheritance and Objects

+

Before we can discuss how Perl subroutines can be called back from Qt, we need +to introduce PerlQt's inheritance mechanism.

+

PerlQt was designed to couple as tightly as possible Qt's simplicity and Perl's +power and flexibility.

+

In order to achieve that goal, the classical Object Oriented Perl paradigm had +to be extended, much in the same way than Qt itself +had to extend C++'s paradigm with metaobjects.

+

+

+

A Custom Widget

+

Lets rewrite the ``Hello World!'' program, this time using a custom version +of PushButton:

+
+  1: use strict;
+  2: 
+  3: package Button;
+  4: use Qt;
+  5: use Qt::isa qw(Qt::PushButton);
+  6: 
+  7: sub NEW
+  8: {
+  9:   shift->SUPER::NEW(@_[0..2]);
+ 10:   resize(130, 40);
+ 11: }
+ 12: 
+ 13: 1;
+ 14: 
+ 15: package main;
+ 16: 
+ 17: use Qt;
+ 18: use Button;
+ 19: 
+ 20: my $a = Qt::Application(\@ARGV);
+ 21: my $w = Button("Hello World!", undef);
+ 22: $a->setMainWidget($w);
+ 23: $w->show;
+ 24: exit $a->exec;
+

Here, we want to create our own version of the PushButton widget. +Therefore, we create a new package for it [l.3] and import Qt [l.4].

+

We now want to declare our widget as subclassing PushButton. +This is done through the use of the Qt::isa pragma [l.5], which accepts a +list of one or more parent Qt classes.

+

It is now time to create a constructor for our new widget. +This is done by creating a subroutine called NEW (note the capitalized +form, which differentate it from the usual ``new'' constructor. PerlQt's NEW +constructor is called implicitly as can be seen on line 21).

+

Since we want our widget to call its parent's constructor first, we call the +superclass's constructor (here: Qt::PushButton) on line 9, passing it all +arguments we received.

+

At this time, a class instance has been created and stored into a special +object holder named this (not $this but really just this).

+

Each time you invoke a method from within your package, you may now +indifferently say method() or this->method();

+

+

+

Using Attributes

+

When building a new composite widget, you may just create its different +parts inside my variables, since widgets are only deleted by their parents +and not necessarily when their container goes out of scope.

+

In other words, PerlQt performs clever reference counting to prevent +indesirable deletion of objects.

+

Now, you'll often want to keep an access to those parts from anywhere inside +your package. +For this purpose, you may use the this object's blessed hash, as is usual in Perl, +but that isn't really convenient and you don't have any compile time +checking...

+

Here come Attributes. Attributes are data holders where you can +store any kind of properties for your object.

+

Declaring new attributes is done through the use Qt::attributes pragma, as is +demonstrated in the following package implementation :

+
+  1: use strict;
+  2:
+  3: package Button;
+  4: use Qt;
+  5: use Qt::isa qw(Qt::PushButton);
+  6: use Qt::attributes qw(
+  7:     itsTime
+  8:     pData
+  9: );
+ 10:
+ 11: sub NEW
+ 12: {
+ 13:   shift->SUPER::NEW(@_[0..2]);
+ 14:   itsTime = Qt::Time;
+ 15:   itsTime->start;   
+ 16:   pData = " Foo ";
+ 17: }
+ 18: 
+ 19: sub resizeEvent
+ 20: {
+ 21:    setText( "w: ". width() ." h: ". height() .
+ 22:             "\nt: ". itsTime->elapsed . pData );
+ 23: }
+ 24:
+ 25: 1;
+
+

An attribute itsTime is declared at line 7, and loaded with a Qt::Time object +at line 14.

+

Since we reimplement the virtual function ``resizeEvent'' [l.19]. +each time the main widget is resized, this function will be triggered and +our Button's text updated with values coming from the object [l.21] and from the +attributes we defined [l.22].

+

Recapitulation

+ +

+

+

Signals and Slots

+

We'll now learn how Qt objects can communicate with each other, +allowing an event occuring, for instance, in a given widget to trigger the +execution of one or several subroutines anywhere inside your program.

+

Most other toolkits use callbacks for that purpose, but Qt has a much more +powerful and flexible mechanism called Signals and Slots.

+

Signals and slots are used for communication between objects.

+

This can be thought off as something similar to the wiring between several Hi-fI +components : an amplificator, for instance, has a set of output signals, wich are +emitted wether a listening device is connected to them or not. Also, a tape +recorder deck can start to record when it receives a signal wired to it's input +slot, and it doesn't need to know that this signal is also received by a CD +recorder device, or listened through headphones.

+

A Qt component behaves just like that. It has several output Signals and +several input Slots - and each signal can be connected to an unlimited number +of listening slots of the same type, wether they are inside or outside the +component.

+

The general syntax of this connection process is either :

+

Qt::Object::connect( sender, SIGNAL 'mysignal(arg_type)', +receiver, SLOT 'myslot(arg_type)');

+

or

+

myObject->connect( sender, SIGNAL 'mysignal(arg_type)', SLOT +'myslot(arg_type)');

+

This mechanism can be extended at will by the declaration of custom Signals and +Slots, through the use Qt::signals and use Qt::slots pragma +(see also the other syntax, later on).

+

Each declared slot will call the corresponding subroutine in your object, +each declared signal can be raised through the emit keyword.

+

As an example, lets rewrite again our Button package :

+
+  1: use strict;
+  2:
+  3: package Button;
+  4: use Qt;
+  5: use Qt::isa qw(Qt::PushButton);
+  6: use Qt::attributes qw(itsTime);
+  7: use Qt::slots 
+  8:     wasClicked => [],
+  9:     change     => ['int', 'int'];
+ 10: use Qt::signals
+ 11:     changeIt   => ['int', 'int'];
+ 12:
+ 13: sub NEW
+ 14: {
+ 15:   shift->SUPER::NEW(@_[0..2]);
+ 16:   itsTime = Qt::Time;
+ 17:   itsTime->start;   
+ 18:   this->connect(this, SIGNAL 'clicked()', SLOT 'wasClicked()');
+ 19:   this->connect(this, SIGNAL 'changeIt(int,int)', SLOT 'change(int,int)');
+ 20: }
+ 21: 
+ 22: sub wasClicked
+ 23: {
+ 24:    my $w = width();
+ 25:    my $h = height();
+ 26:    setText( "w: $w h: $h\nt: ". itsTime->elapsed );
+ 27:    emit changeIt($w, $h);          
+ 28: }
+ 29:
+ 30: sub change
+ 31: {
+ 32:    my ($w, $h) = @_;
+ 33:    print STDERR "w: $w h: $h \n";
+ 34: }
+ 35:
+ 36: 1;
+

In this package, we define two extra slots and one extra signal.

+

We know from the Qt Documentation that a clicked PushButton emits a clicked() +signal, so we connect it to our new slot at line 18.

+

We also connect our signal changeIt to our own change slot- which is +quite stupid, but as an example.

+

Now, whenever our Button is clicked, the clicked() signal is raised and +triggers the wasClicked() slot. wasClicked then proceeds to emit +the changeIt(int,int) signal [l.27], hence triggering the change(int,int) +slot with two arguments.

+

Finally, since PerlQt-3.008, an alternative syntax can be used to declare Signals and Slots:

+
+ sub a_slot : SLOT(int, QString)
+ { 
+        $int = shift;
+        $string = shift;
+        # do something
+ }
+

and

+
+ sub a_signal : SIGNAL(QString);
+

This syntax is perfectly compatible with the traditional +use Qt::signals and use Qt::slots declarations.

+

Eventually, it can prove good programming practice to mix both syntaxes, by first declaring +Signals/Slots with use Qt::slots/signals, then repeat this declaration +in the actual implementation with the second syntax.

+

Declarations will be checked for consistency at compile time, and any mismatch +in arguments would trigger a warning.

+

+

+
+

RAD prototyping with Qt Designer and Puic

+

+

+

Introduction

+ +

As efficient and intuitive as Qt can be, building a complete GUI from scratch +is often a tedious task.

+

Hopefully, Qt comes with a very sophisticated GUI Builder named Qt +Designer, which is close to a complete integrated development environment. +It features Project management, drag'n drop GUI building, a complete object +browser, graphical interconnection of signals and slots, and much much more.

+

Qt Designer's output is XML which can be parsed by several command line tools, +among whose is puic (the PerlQt User Interface Compiler).

+

Assuming you have already built an interface file with the Designer, +translating it to a PerlQt program is simply a matter of issuing +one command :

+
+ puic -x -o program.pl program.ui
+

This will generate the package defined in your ui file and a basic main package +for testing purposes.

+

You may prefer :

+
+ puic -o package.pm program.ui
+

This will only generate the package, which can then be used by a separate +program.

+

+

+

Embedding Images

+

If you need to embed images or icons, it can be done in two ways +:

+ +

+

+

Working With .ui Files

+

It will often happen that you need to regenerate your user interface -either +because you changed your initial design, or you want to extend it. +Thus writing your program's code straight in the auto-generated Perl file is +quite a bad idea. +You'd run constantly the risk of overwriting your handcrafted code, or end +up doing lot of copy-paste.

+

Instead, you may :

+ +

+

+
+

More development tools

+

PerlQt comes bundled with two simple programs that can help you to find your way through +the Qt API:

+

+

+

pqtapi

+

pqtapi is a commandline driven introspection tool.

+
+ usage: pqtapi [-r <re>] [<class>]
+
+ options:
+        -r <re> : find all functions matching regular expression/keyword <re>
+        -i : together with -r, performs a case insensitive search
+        -v : print PerlQt and Qt versions
+        -h : print this help message
+

e.g:

+
+ $>pqtapi -ir 'setpoint.* int'
+        void QCanvasLine::setPoints(int, int, int, int)
+        void QPointArray::setPoint(uint, int, int)
+

+

+

pqtsh

+

pqtsh is a graphical shell that can be used to test the API interactively. +It is fairly self explanatory and includes an interactive example (Help->Example)

+
+

+

+
+

Known Limitations

+

Templated classes aren't available yet (classes derived from templated classes are).

+

+

+
+

Credits

+

PerlQt-3 is (c) 2002 Ashley Winters (and (c) 2003 Germain Garand)

+

Kalyptus and the Smoke generation engine are (c) David Faure and Richard Dale

+

Puic is (c) TrollTech AS., Phil Thompson and Germain Garand,

+

The mentioned software is released under the GNU Public Licence v.2 or later.

+

+

+
+

Appendix 1 : C++ conventions and their Perl counterpart

+

Whenever you want to use a class/method described in Qt's +documentation (see also the 'assistant' program bundled with Qt) +from PerlQt, you need to follow some simple translation rules.

+
+
Classnames
+
+ +
Functions
+
+ +
Arguments
+
+ +
Enumerations
+
+
+Enumerations are sort of named aliases for numeric values that would be hard to +remember otherwise. +
+
+

A C++ example would be :

+
+
+
+ enum Strange { Apple, Orange, Lemon }
+
+
+

where Strange is the generic enumeration name, and Apple, Orange, +Lemon its possible values, which are only aliases for numbers (here 0, 1 +and 2).

+
+
+

Access to enumerations values in Perl Qt is very similar to a static function +call. In fact, it is a static function call.

+
+
+

Therefore, since you probably want to avoid some readability problems, we +recommend the use of the alternate function call syntax : &function.

+
+
+

Lets now go back to our Strange example.

+
+
+

If its definition was encountered in the class QFruits, you'd write from +PerlQt :

+
+
+
+ $apple_plus_orange = &Qt::Fruit::Apple + &Qt::Fruit::Orange;
+
+

+
Operators
+
+
+Within PerlQt, operators overloading works transparently. +If a given operator is overloaded in a Qt class (which means using it triggers a custom method) +it will behave identically in PerlQt. +Beware though that due to limitations of the Smoke binding library, not all overloaded operators are +available in PerlQt. +You can check the availability of a given operator by using the pqtapi program. +Also, due to outstanding differences between C++'s and Perl's object paradigm, the copy constructor operator (a.k.a '=') +has been disabled. +
+
+

e.g-1: '+=' overload

+
+
+
+ $p1 = Qt::Point(10, 10)
+ $p2 = Qt::Point(30,40)
+ $p2 += $p1; # $p2 becomes (40,50)
+ 
+e.g-2: '<<' overload
+
+
+
+ $f = Qt::File("example");
+ $f->open( IO_WriteOnly ); # see 'Constants' below
+ $s = Qt::TextStream( $f );
+ $s << "What can I do with " << 12 << " apples?";
+
+

+
Constants
+
+
+Qt doesn't use many constants, but there is at least one place where they are used : for setting +Input/Output flags on files. +In order to avoid the namespace pollution induced by global constants, PerlQt group them in the Qt::constants module. +For instance, requesting the importation of all IO constants into the current namespace would be done with: +
+
+
+ use Qt::constants;
+
+
+

You may also import specific symbols:

+
+
+
+ use Qt::constants qw( IO_ReadOnly IO_WriteOnly );
+
+

+
Global Functions
+
+
+Qt has also some utilitarian functions such as bitBlt, qCompress, etc. +
+
+

Those were global scope functions and have been grouped in a common namespace: +Qt::GlobalSpace.

+
+
+

Hence, you shall access this namespace either with a fully qualified call:

+
+
+
+ Qt::GlobalSpace::qUncompress( $buffer )
+
+
+

Or directly, after importation in the current namespace:

+
+
+
+ use Qt::GlobalSpace;
+ qUncompress( $buffer )
+
+
+

Of course, you may selectively import a few functions:

+
+
+
+ use Qt::GlobalSpace qw( qUncompress bitBlt )
+
+
+

Note: GlobalSpace has also operators, such has the one performing an addition on two +Qt::Point(). Those operators are called automatically.

+
+
+

e.g:

+
+
+
+ $p1 = Qt::Point(10, 10) + Qt::Point(20, 20)
+
+

+

+

+
+

Appendix 2 : Internationalization

+

PerlQt handles internationalization by always converting QString back to utf8 in Perl.

+

Conversions from Perl strings to QStrings are made according to context :

+ +

Once a string contains utf8, you can convert it back to any locale by setting up converters :

+
+ $tr1=Qt::TextCodec::codecForLocale(); # this one will use current locale
+ $tr2=Qt::TextCodec::codecForName("KOI8-R"); # that one forces a specific locale (Russian)
+
+ print $tr1->fromUnicode(Qt::DateTime::currentDateTime()->toString)."\n\n";
+ print $tr2->fromUnicode($my_utf8_string);
+

Or, with Perl >= 5.8.0, you may use Perl's Encode modules (see perldoc Encode).

+

+

+

disabling utf-8

+

Developers who don't want to use UTF-8 or want to temporarily disable UTF-8 marshalling +for handling legacy programs may use the use bytes pragma (and the corresponding no bytes).

+

Within the scope of this pragma, QStrings are marshalled back to ISO-Latin1 (default) or to your locale +(if use locale has been set).

+

Frivole use of this pragma is strongly discouraged as it ruins worldwide standardization efforts.

+

+

+
+

Appendix 3 : Debugging Channels

+

The Qt::debug module offers various debugging channels/features.

+
+ use Qt::debug;
+
+ use Qt::debug qw|calls autoload verbose|;
+

With the simple use Qt::debug statement, the verbose and ambiguous channels are activated. +If you specify a list of channels within the use statement, then only the specified channels will be enabled.

+

Available channels :

+ +

+

+
+

Appendix 4 : Marshallers

+

A marshaller is a piece of ``glue code'' translating a given datatype to another.

+

Within PerlQt, most Qt objects keep their object nature, so that one may invoke methods on them. +However, some classes and datatypes map so naturally to some Perl types that keeping their object nature would +would feel unnatural and clumsy.

+

For instance, instead of returning a Qt::StringList object, which would require an iterator to retrieve its content, +PerlQt will translate it to an array reference containing all the object's strings.

+

In the other way, instead of providing a Qt::StringList object as an argument of a method, one would simply +provide the reference to an array of Perl strings.

+

Here is the list of Marshallers as of PerlQt-3.008 :

+
+ -----------------------------------------------------------------
+ float, double                         <=>       Perl real (NV)
+ char, uchar, int, uint, enum
+ long, ulong, short, ushort            <=>       Perl integer (IV)
+ QString, -&, -*                        =>       Perl string (utf8)
+ QString, -&, -*                       <=        Perl string (utf8 or iso-latin1 or locale)
+ QCString, -&, -*                      <=>       Perl string (utf8 or bytes, according to content or "bytes" pragma)
+ QByteArray, -&, -*                    <=>       Perl string (bytes)
+ QStringList, -&, -*                    =>       Reference to an array of Perl strings (utf8)
+ QString, -&, -*                        =>       Perl string (utf8 or iso-latin1 or locale)
+ int&, -*                              <=>       Perl integer (IV)
+ bool&, -*                             <=>       Perl boolean
+ char*                                 <=>       Perl string (bytes)
+ char**                                <=        Reference to an array of Perl strings (bytes)
+ uchar*                                <=        Perl string (bytes)
+ QRgb*                                 <=        Reference to an array of Perl integers (IV)
+ QCOORD*                               <=        Reference to an array of Perl integers (IV)
+ void*                                 <=>       Reference to a Perl integer (IV)
+ QValueList<int>, - *, - &             <=>       Reference to an array of Perl integers (IV)
+ QCanvasItemList, - *, - &              =>       Reference to an array of Qt::CanvasItem
+ QWidgetList, - *, - &                 <=>       Reference to an array of Qt::Widget
+ QObjectList, - *, - &                 <=>       Reference to an array of Qt::Object
+ QFileInfoList, - *, - &               <=>       Reference to an array of Qt::FileInfo
+ QPtrList<QTab>, - *, - &              <=>       Reference to an array of Qt::Tab
+ QPtrList<QToolBar>, - *, - &          <=>       Reference to an array of Qt::ToolBar
+ QPtrList<QNetworkOperation>, - *, - & <=>       Reference to an array of Qt::NetworkOperation
+ QPtrList<QDockWindow>, - *, - &       <=>       Reference to an array of Qt::DockWindow
+ (QUObject*)
+
+
+ + + + -- cgit v1.2.1