1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
|
/****************************************************************************
**
** Explanation of the TQt object model
**
** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved.
**
** This file is part of the TQt GUI Toolkit.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free TQt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** This file may be used under the terms of the Q Public License as
** defined by Trolltech ASA and appearing in the file LICENSE.QPL
** included in the packaging of this file. Licensees holding valid Qt
** Commercial licenses may use this file in accordance with the Qt
** Commercial License Agreement provided with the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/
/*!
\page object.html
\title TQt Object Model
The standard C++ Object Model provides very efficient runtime support
for the object paradigm. But the C++ Object Model's static nature is
inflexibile in certain problem domains. Graphical User Interface
programming is a domain that requires both runtime efficiency and a
high level of flexibility. TQt provides this, by combining the speed of
C++ with the flexibility of the TQt Object Model.
Qt adds these features to C++:
\list
\i a very powerful mechanism for seamless object
communication called \link signalsandslots.html signals and
slots \endlink;
\i queryable and designable \link properties.html object
properties \endlink;
\i powerful \link eventsandfilters.html events and event filters \endlink,
\i contextual \link i18n.html string translation for internationalization \endlink;
\i sophisticated interval driven \link timers.html timers \endlink
that make it possible to elegantly integrate many tasks in an
event-driven GUI;
\i hierarchical and queryable \link objecttrees.html object
trees \endlink that organize object ownership in a natural way;
\i guarded pointers, \l TQGuardedPtr, that are automatically
set to 0 when the referenced object is destroyed, unlike normal C++
pointers which become "dangling pointers" when their objects are destroyed.
\endlist
Many of these TQt features are implemented with standard C++
techniques, based on inheritance from \l TQObject. Others, like the
object communication mechanism and the dynamic property system,
require the \link metaobjects.html Meta Object System \endlink provided
by Qt's own \link moc.html Meta Object Compiler (moc) \endlink.
The Meta Object System is a C++ extension that makes the language
better suited to true component GUI programming. Although templates can
be used to extend C++, the Meta Object System provides benefits using
standard C++ that cannot be achieved with templates; see \link
templates.html Why doesn't TQt use templates for signals and
slots? \endlink.
*/
/*!
\page timers.html
\title Timers
\l TQObject, the base class of all TQt objects, provides the basic timer
support in Qt. With \l TQObject::startTimer(), you start a timer with
an \e interval in milliseconds as argument. The function returns a
unique integer timer id. The timer will now "fire" every \e interval
milliseconds, until you explicitly call \l TQObject::killTimer() with
the timer id.
For this mechanism to work, the application must run in an event
loop. You start an event loop with \l QApplication::exec(). When a
timer fires, the application sends a TQTimerEvent, and the flow of
control leaves the event loop until the timer event is processed. This
implies that a timer cannot fire while your application is busy doing
something else. In other words: the accuracy of timers depends on the
granularity of your application.
There is practically no upper limit for the interval value (more than
one year is possible). The accuracy depends on the underlying operating
system. Windows 95/98 has 55 millisecond (18.2 times per second)
accuracy; other systems that we have tested (UNIX X11 and Windows NT)
can handle 1 millisecond intervals.
The main API for the timer functionality is \l TQTimer. That class
provides regular timers that emit a signal when the timer fires, and
inherits \l TQObject so that it fits well into the ownership structure
of most GUI programs. The normal way of using it is like this:
\code
TQTimer * counter = new TQTimer( this );
connect( counter, TQ_SIGNAL(timeout()),
this, TQ_SLOT(updateCaption()) );
counter->start( 1000 );
\endcode
The counter timer is made into a child of this widget, so that when
this widget is deleted, the timer is deleted too. Next, its timeout
signal is connected to the slot that will do the work, and finally
it's started.
TQTimer also provides a simple one-shot timer API. \l TQButton uses this
to show the button being pressed down and then (0.1 seconds later) be
released when the keyboard is used to "press" a button, for example:
\code
TQTimer::singleShot( 100, this, TQ_SLOT(animateTimeout()) );
\endcode
0.1 seconds after this line of code is executed, the same button's
animateTimeout() slot is called.
Here is an outline of a slightly longer example that combines object
communication via signals and slots with a TQTimer object. It
demonstrates how to use timers to perform intensive calculations in a
single-threaded application without blocking the user interface.
\code
// The Mandelbrot class uses a TQTimer to calculate the mandelbrot
// set one scanline at a time without blocking the CPU. It
// inherits TQObject to use signals and slots. Calling start()
// starts the calculation. The done() signal is emitted when it
// has finished. Note that this example is not complete, just an
// outline.
class Mandelbrot : public TQObject
{
TQ_OBJECT // required for signals/slots
public:
Mandelbrot( TQObject *parent=0, const char *name );
...
public slots:
void start();
signals:
void done();
private slots:
void calculate();
private:
TQTimer timer;
...
};
//
// Constructs and initializes a Mandelbrot object.
//
Mandelbrot::Mandelbrot( TQObject *parent=0, const char *name )
: TQObject( parent, name )
{
connect( &timer, TQ_SIGNAL(timeout()), TQ_SLOT(calculate()) );
...
}
//
// Starts the calculation task. The internal calculate() slot
// will be activated every 10 milliseconds.
//
void Mandelbrot::start()
{
if ( !timer.isActive() ) // not already running
timer.start( 10 ); // timeout every 10 ms
}
//
// Calculates one scanline at a time.
// Emits the done() signal when finished.
//
void Mandelbrot::calculate()
{
... // perform the calculation for a scanline
if ( finished ) { // no more scanlines
timer.stop();
emit done();
}
}
\endcode
*/
/*!
\page properties.html
\title Properties
Qt provides a sophisticated property system similar to those supplied
by some compiler vendors. However, as a compiler- and
platform-independent library, TQt cannot rely on non-standard compiler
features like \c __property or \c [property]. Our solution works with
\e any standard C++ compiler on every platform we support. It's based
on the meta-object system that also provides object communication
through \link signalsandslots.html signals and slots\endlink.
The \c TQ_PROPERTY macro in a class declaration declares a
property. Properties can only be declared in classes that inherit \l
TQObject. A second macro, \c TQ_OVERRIDE, can be used to override some
aspects of an inherited property in a subclass. (See \link #override
TQ_OVERRIDE\endlink.)
To the outer world, a property appears to be similar to a data member.
But properties have several features that distinguish them from
ordinary data members:
\list
\i A read function. This always exists.
\i A write function. This is optional: read-only properties like \l
TQWidget::isDesktop() do not have one.
\i An attribute "stored" that indicates persistence. Most properties
are stored, but a few virtual properties are not. For example, \l
TQWidget::minimumWidth() isn't stored, since it's just a view of
\l TQWidget::minimumSize(), and has no data of its own.
\i A reset function to set a property back to its context specific
default value. This is very rare, but for example, \l TQWidget::font()
needs this, since no call to \l TQWidget::setFont() can mean 'reset to
the context specific font'.
\i An attribute "designable" that indicates whether it makes sense to
make the property available in a GUI builder (e.g. \link
designer-manual.book TQt Designer\endlink). For most properties this
makes sense, but not for all, e.g. \l TQButton::isDown(). The user can
press buttons, and the application programmer can make the program
press its own buttons, but a GUI design tool can't press buttons.
\endlist
The read, write, and reset functions must be public member functions
from the class in which the property is defined.
Properties can be read and written through generic functions in
TQObject without knowing anything about the class in use. These two
function calls are equivalent:
\code
// TQButton *b and TQObject *o point to the same button
b->setDown( TRUE );
o->setProperty( "down", TRUE );
\endcode
Equivalent, that is, except that the first is faster, and provides
much better diagnostics at compile time. When practical, the first is
better. However, since you can get a list of all available properties
for any TQObject through its \l QMetaObject, \l TQObject::setProperty()
can give you control over classes that weren't available at compile
time.
As well as TQObject::setProperty(), there is a corresponding \l
TQObject::property() function. \l QMetaObject::propertyNames() returns
the names of all available properties. \l QMetaObject::property()
returns the property data for a named property: a \l QMetaProperty
object.
Here's a simple example that shows the most important property
functions in use:
\code
class MyClass : public TQObject
{
TQ_OBJECT
public:
MyClass( TQObject * parent=0, const char * name=0 );
~MyClass();
enum Priority { High, Low, VeryHigh, VeryLow };
void setPriority( Priority );
Priority priority() const;
};
\endcode
The class has a property "priority" that is not yet known to the meta
object system. In order to make the property known, you must
declare it with the \c TQ_PROPERTY macro. The syntax is as follows:
\code
TQ_PROPERTY( type name READ getFunction [WRITE setFunction]
[RESET resetFunction] [DESIGNABLE bool]
[SCRIPTABLE bool] [STORED bool] )
\endcode
For the declaration to be valid, the get function must be const and
to return either the type itself, a pointer to it, or a reference to
it. The optional write function must return void and must take exactly
one argument, either the type itself, a pointer or a const reference
to it. The meta object compiler enforces this.
The type of a property can be any \l QVariant supported type or an
enumeration type declared in the class itself. Since \c MyClass uses
the enumeration type \c Priority for the property, this type must be
registered with the property system as well.
There are two exceptions to the above: The type of a property can also
be either \link TQValueList TQValueList\<QVariant\>\endlink or \link
TQMap TQMap\<TQString,QVariant\>\endlink. In
these cases the type must be specified as \c TQValueList or as \c TQMap
(i.e. without their template parameters).
It is possible to set a value by name, like this:
\code
obj->setProperty( "priority", "VeryHigh" );
\endcode
In the case of \c TQValueList and \c TQMap properties the value passes
is a QVariant whose value is the entire list or map.
Enumeration types are registered with the \c TQ_ENUMS macro. Here's the
final class declaration including the property related declarations:
\code
class MyClass : public TQObject
{
TQ_OBJECT
TQ_PROPERTY( Priority priority READ priority WRITE setPriority )
TQ_ENUMS( Priority )
public:
MyClass( TQObject * parent=0, const char * name=0 );
~MyClass();
enum Priority { High, Low, VeryHigh, VeryLow };
void setPriority( Priority );
Priority priority() const;
};
\endcode
Another similar macro is \c TQ_SETS. Like \c TQ_ENUMS, it registers an
enumeration type but marks it in addition as a "set", i.e. the
enumeration values can be OR-ed together. An I/O class might have
enumeration values "Read" and "Write" and accept "Read|Write": such an
enum is best handled with \c TQ_SETS, rather than \c TQ_ENUMS.
The remaining keywords in the \c TQ_PROPERTY section are \c RESET, \c
DESIGNABLE, \c SCRIPTABLE and \c STORED.
\c RESET names a function that will set the property to its default
state (which may have changed since initialization). The function
must return void and take no arguments.
\c DESIGNABLE declares whether this property is suitable for
modification by a GUI design tool. The default is \c TRUE for
writable properties; otherwise \c FALSE. Instead of \c TRUE or \c
FALSE, you can specify a boolean member function.
\c SCRIPTABLE declares whether this property is suited for access by a
scripting engine. The default is \c TRUE. Instead of \c TRUE or \c FALSE,
you can specify a boolean member function.
\c STORED declares whether the property's value must be remembered
when storing an object's state. Stored makes only sense for writable
properties. The default value is \c TRUE. Technically superfluous
properties (like TQPoint pos if TQRect geometry is already a property)
define this to be \c FALSE.
Connected to the property system is an additional macro, "TQ_CLASSINFO",
that can be used to attach additional name/value-pairs to a class'
meta object, for example:
\code
TQ_CLASSINFO( "Version", "3.0.0" )
\endcode
Like other meta data, class information is accessible at runtime
through the meta object, see \l QMetaObject::classInfo() for details.
\target override
\section1 TQ_OVERRIDE
When you inherit a TQObject subclass you may wish to override some
aspects of some of the class's properties.
For example, in TQWidget we have the autoMask property defined like
this:
\code
TQ_PROPERTY( bool autoMask READ autoMask WRITE setAutoMask DESIGNABLE false SCRIPTABLE false )
\endcode
But we need to make the auto mask property designable in some TQWidget
subclasses. Similarly some classes will need this property to be
scriptable (e.g. for QSA). This is achieved by overriding these
features of the property in a subclass. In TQCheckBox, for example, we
achieve this using the following code:
\code
TQ_OVERRIDE( bool autoMask DESIGNABLE true SCRIPTABLE true )
\endcode
Another example is TQToolButton. By default TQToolButton has a read-only
"toggleButton" property, because that's what it inherits from TQButton:
\code
TQ_PROPERTY( bool toggleButton READ isToggleButton )
\endcode
But we want to make our tool buttons able to be toggled, so we write a
WRITE function in TQToolButton, and use the following property override
to make it acessible:
\code
TQ_OVERRIDE( bool toggleButton WRITE setToggleButton )
\endcode
The result is read-write (and scriptable and designable, since we now
have a WRITE function) boolean property "toggleButton" for tool
buttons.
*/
/*!
\page eventsandfilters.html
\title Events and Event Filters
In Qt, an event is an object that inherits \l TQEvent. Events are
delivered to objects that inherit \l TQObject through calling \l
TQObject::event(). Event delivery means that an event has occurred, the
TQEvent indicates precisely what, and the TQObject needs to respond. Most
events are specific to \l TQWidget and its subclasses, but there are
important events that aren't related to graphics, for example, socket
activation, which is the event used by \l TQSocketNotifier for its
work.
Some events come from the window system, e.g. \l QMouseEvent, some
from other sources, e.g. \l TQTimerEvent, and some come from the
application program. TQt is symmetric, as usual, so you can send
events in exactly the same ways as Qt's own event loop does.
Most events types have special classes, most commonly \l QResizeEvent,
\l TQPaintEvent, \l QMouseEvent, \l QKeyEvent and \l QCloseEvent.
There are many others, perhaps forty or so, but most are rather odd.
Each class subclasses TQEvent and adds event-specific functions; see,
for example, \l QResizeEvent. In the case of QResizeEvent, \l
QResizeEvent::size() and \l QResizeEvent::oldSize() are added.
Some classes support more than one event type. \l QMouseEvent
supports mouse moves, presses, shift-presses, drags, clicks,
right-presses, etc.
Since programs need to react in varied and complex ways, Qt's
event delivery mechanisms are flexible. The documentation for
\l QApplication::notify() concisely tells the whole story, here we
will explain enough for 99% of applications.
The normal way for an event to be delivered is by calling a virtual
function. For example, \l TQPaintEvent is delivered by calling \l
TQWidget::paintEvent(). This virtual function is responsible for
reacting appropriately, normally by repainting the widget. If you
do not perform all the necessary work in your implementation of the
virtual function, you may need to call the base class's
implementation; for example:
\code
MyTable::contentsMouseMoveEvent( QMouseEvent *me )
{
// my implementation
TQTable::contentsMouseMoveEvent( me ); // hand it on
}
\endcode
If you want to replace the base class's function then you must
implement everything yourself; but if you only want to extend the base
class's functionality, then you implement what you want and then call
the base class.
Occasionally there isn't such an event-specific function, or the
event-specific function isn't sufficient. The most common example is
tab key presses. Normally, those are interpreted by TQWidget to move
the keyboard focus, but a few widgets need the tab key for themselves.
These objects can reimplement \l TQObject::event(), the general event
handler, and either do their event handling before or after the usual
handling, or replace it completely. A very unusual widget that both
interprets tab and has an application-specific custom event might
contain:
\code
bool MyClass:event( TQEvent *evt ) {
if ( evt->type() == TQEvent::KeyPress ) {
QKeyEvent *ke = (QKeyEvent *)evt;
if ( ke->key() == Key_Tab ) {
// special tab handling here
ke->accept();
return TRUE;
}
} else if ( evt->type() >= TQEvent::User ) {
QCustomEvent *ce = (QCustomEvent*) evt;
// custom event handling here
return TRUE;
}
return TQWidget::event( evt );
}
\endcode
More commonly, an object needs to look at another's events. Qt
supports this using \l TQObject::installEventFilter() (and the
corresponding remove). For example, dialogs commonly want to filter
key presses for some widgets, e.g. to modify Return-key handling.
An event filter gets to process events before the target object does.
The filter's \l TQObject::eventFilter() implementation is called, and
can accept or reject the filter, and allow or deny further processing
of the event. If all the event filters allow further processing of an
event, the event is sent to the target object itself. If one of them
stops processing, the target and any later event filters don't get to
see the event at all.
It's also possible to filter \e all events for the entire application,
by installing an event filter on \l QApplication. This is what \l
TQToolTip does in order to see \e all the mouse and keyboard activity.
This is very powerful, but it also slows down event delivery of every
single event in the entire application, so it's best avoided.
The global event filters are called before the object-specific
filters.
Finally, many applications want to create and send their own events.
Creating an event of a built-in type is very simple: create an object
of the relevant type, and then call \l QApplication::sendEvent() or \l
QApplication::postEvent().
sendEvent() processes the event immediately - when sendEvent()
returns, (the event filters and) the object have already processed the
event. For many event classes there is a function called isAccepted()
that tells you whether the event was accepted or rejected by the last
handler that was called.
postEvent() posts the event on a queue for later dispatch. The next
time Qt's main event loop runs, it dispatches all posted events, with
some optimization. For example, if there are several resize events,
they are are compacted into one. The same applies to paint events: \l
TQWidget::update() calls postEvent(), which minimizes flickering and
increases speed by avoiding multiple repaints.
postEvent() is also often used during object initialization, since the
posted event will typically be dispatched very soon after the
initialization of the object is complete.
To create events of a custom type, you need to define an event number,
which must be greater than \c TQEvent::User, and probably you also need
to subclass \l QCustomEvent in order to pass characteristics about
your custom event. See the documentation to \l QCustomEvent for
details.
*/
/*!
\page objecttrees.html
\title Object Trees and Object Ownership
\link TQObject TQObjects\endlink organize themselves in object trees.
When you create a TQObject with another object as parent, it's added to
the parent's \link TQObject::children() children() \endlink list, and
is deleted when the parent is. It turns out that this approach fits
the needs of GUI objects very well. For example, a \l QAccel (keyboard
accelerator) is a child of the relevant window, so when the user closes
that window, the accelerator is deleted too.
The static function \l TQObject::objectTrees() provides access to all
the root objects that currently exist.
\l TQWidget, the base class of everything that appears on the screen,
extends the parent-child relationship. A child normally also becomes a
child widget, i.e. it is displayed in its parent's coordinate system
and is graphically clipped by its parent's boundaries. For example,
when the an application deletes a message box after it has been
closed, the message box's buttons and label are also deleted, just as
we'd want, because the buttons and label are children of the message
box.
You can also delete child objects yourself, and they will remove
themselves from their parents. For example, when the user removes a
toolbar it may lead to the application deleting one of its \l TQToolBar
objects, in which case the tool bar's \l TQMainWindow parent would
detect the change and reconfigure its screen space accordingly.
The debugging functions \l TQObject::dumpObjectTree() and \l
TQObject::dumpObjectInfo() are often useful when an application looks or
acts strangely.
*/
/*!
\page templates.html
\title Why doesn't TQt use templates for signals and slots?
A simple answer is that when TQt was designed, it was not possible to
fully exploit the template mechanism in multi-platform applications due
to the inadequacies of various compilers. Even today, many widely used
C++ compilers have problems with advanced templates. For example, you
cannot safely rely on partial template instantiation, which is essential
for some non-trivial problem domains. Thus Qt's usage of templates has
to be rather conservative. Keep in mind that TQt is a multi-platform
toolkit, and progress on the Linux/g++ platform does not necessarily
improve the situation elsewhere.
Eventually those compilers with weak template implementations will
improve. But even if all our users had access to a fully standards
compliant modern C++ compiler with excellent template support, we would
not abandon the string-based approach used by our meta object compiler.
Here are five reasons why:
<h3>1. Syntax matters</h3>
Syntax isn't just sugar: the syntax we use to express our algorithms can
significantly affect the readability and maintainability of our code.
The syntax used for Qt's signals and slots has proved very successful in
practice. The syntax is intuitive, simple to use and easy to read.
People learning TQt find the syntax helps them understand and utilize the
signals and slots concept -- despite its highly abstract and generic
nature. Furthermore, declaring signals in class definitions ensures that
the signals are protected in the sense of protected C++ member
functions. This helps programmers get their design right from the very
beginning, without even having to think about design patterns.
<h3>2. Precompilers are good</h3>
Qt's <tt>moc</tt> (Meta Object Compiler) provides a clean way to go
beyond the compiled language's facilities. It does so by generating
additional C++ code which can be compiled by any standard C++ compiler.
The <tt>moc</tt> reads C++ source files. If it finds one or more class
declarations that contain the "TQ_OBJECT" macro, it produces another C++
source file which contains the meta object code for those classes. The
C++ source file generated by the <tt>moc</tt> must be compiled and
linked with the implementation of the class (or it can be
<tt>#included</tt> into the class's source file). Typically <tt>moc</tt>
is not called manually, but automatically by the build system, so it
requires no additional effort by the programmer.
There are other precompilers, for example, <tt>rpc</tt> and
<tt>idl</tt>, that enable programs or objects to communicate over
process or machine boundaries. The alternatives to precompilers are
hacked compilers, proprietary languages or graphical programming tools
with dialogs or wizards that generate obscure code. Rather than locking
our customers into a proprietary C++ compiler or into a particular
Integrated Development Environment, we enable them to use whatever tools
they prefer. Instead of forcing programmers to add generated code into
source repositories, we encourage them to add our tools to their build
system: cleaner, safer and more in the spirit of UNIX.
<h3>3. Flexibility is king</h3>
C++ is a standarized, powerful and elaborate general-purpose language.
It's the only language that is exploited on such a wide range of
software projects, spanning every kind of application from entire
operating systems, database servers and high end graphics
applications to common desktop applications. One of the keys to C++'s
success is its scalable language design that focuses on maximum
performance and minimal memory consumption whilst still maintaining
ANSI-C compatibility.
For all these advantages, there are some downsides. For C++, the static
object model is a clear disadvantage over the dynamic messaging approach
of Objective C when it comes to component-based graphical user interface
programming. What's good for a high end database server or an operating
system isn't necessarily the right design choice for a GUI frontend.
With <tt>moc</tt>, we have turned this disadvantage into an advantage,
and added the flexibility required to meet the challenge of safe and
efficient graphical user interface programming.
Our approach goes far beyond anything you can do with templates. For
example, we can have object properties. And we can have overloaded
signals and slots, which feels natural when programming in a language
where overloads are a key concept. Our signals add zero bytes to the
size of a class instance, which means we can add new signals without
breaking binary compatibility. Because we do not rely on excessive
inlining as done with templates, we can keep the code size smaller.
Adding new connections just expands to a simple function call rather
than a complex template function.
Another benefit is that we can explore an object's signals and slots at
runtime. We can establish connections using type-safe call-by-name,
without having to know the exact types of the objects we are connecting.
This is impossible with a template based solution. This kind of runtime
introspection opens up new possibilities, for example GUIs that are
generated and connected from TQt Designer's XML <tt>ui</tt> files.
<h3>4. Calling performance is not everything</h3>
Qt's signals and slots implementation is not as fast as a template-based
solution. While emitting a signal is approximately the cost of four
ordinary function calls with common template implementations, Qt
requires effort comparable to about ten function calls. This is not
surprising since the TQt mechanism includes a generic marshaller,
introspection and ultimately scriptability. It does not rely on
excessive inlining and code expansion and it provides unmatched runtime
safety. Qt's iterators are safe while those of faster template-based
systems are not. Even during the process of emitting a signal to several
receivers, those receivers can be deleted safely without your program
crashing. Without this safety, your application would eventually crash
with a difficult to debug free'd memory read or write error.
Nonetheless, couldn't a template-based solution improve the performance
of an application using signals and slots? While it is true that TQt adds
a small overhead to the cost of calling a slot through a signal, the
cost of the call is only a small proportion of the entire cost of a
slot. Benchmarking against Qt's signals and slots system is typically
done with empty slots. As soon as you do anything useful in your slots,
for example a few simple string operations, the calling overhead becomes
negligible. Qt's system is so optimized that anything that requires
operator new or delete (for example, string operations or
inserting/removing something from a template container) is significantly
more expensive than emitting a signal.
Aside: If you have a signals and slots connection in a tight inner loop
of a performance critical task and you identify this connection as the
bottleneck, think about using the standard listener-interface pattern
rather than signals and slots. In cases where this occurs, you probably
only require a 1:1 connection anyway. For example, if you have an object
that downloads data from the network, it's a perfectly sensible design
to use a signal to indicate that the requested data arrived. But if you
need to send out every single byte one by one to a consumer, use a
listener interface rather than signals and slots.
<h3>5. No limits</h3>
Because we had the <tt>moc</tt> for signals and slots, we could add
other useful things to it that could not not be done with templates.
Among these are scoped translations via a generated <tt>tr()</tt>
function, and an advanced property system with introspection and
extended runtime type information. The property system alone is a great
advantage: a powerful and generic user interface design tool like Qt
Designer would be a lot harder to write - if not impossible - without a
powerful and introspective property system.
C++ with the <tt>moc</tt> preprocessor essentially gives us the
flexibility of Objective-C or of a Java Runtime Environment, while
maintaining C++'s unique performance and scalability advantages. It is
what makes TQt the flexible and comfortable tool we have today.
*/
|