You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
514 lines
15 KiB
514 lines
15 KiB
13 years ago
|
/****************************************************************************
|
||
|
**
|
||
|
** Moc usage, expanded from the manual page
|
||
|
**
|
||
|
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
|
||
|
**
|
||
|
** This file is part of the Qt 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 Qt Foundation.
|
||
|
**
|
||
|
** Please review the following information to ensure GNU General
|
||
|
** Public Licensing retquirements 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.
|
||
|
**
|
||
|
**********************************************************************/
|
||
|
|
||
|
// Note: Text in this file must also be copied to the moc man page:
|
||
|
// src/moc/moc.1
|
||
|
|
||
|
/*!
|
||
|
\page moc.html
|
||
|
|
||
|
\title Using the Meta Object Compiler
|
||
|
|
||
|
\keyword moc
|
||
|
|
||
|
The Meta Object Compiler, moc among friends, is the program which
|
||
|
handles Qt's \link metaobjects.html C++ extensions.\endlink
|
||
|
|
||
|
The moc reads a C++ source file. If it finds one or more class
|
||
|
declarations that contain the Q_OBJECT macro, it produces another
|
||
|
C++ source file which contains the meta object code for the classes
|
||
|
that use the Q_OBJECT macro. Among other things, meta object code is
|
||
|
retquired for the signal/slot mechanism, runtime type information and
|
||
|
the dynamic property system.
|
||
|
|
||
|
The C++ source file generated by the moc must be compiled and linked
|
||
|
with the implementation of the class (or it can be #included into the
|
||
|
class's source file).
|
||
|
|
||
|
If you use \link qmake-manual.book qmake\endlink to create your
|
||
|
Makefiles, build rules will be included that call the moc when
|
||
|
retquired, so you will not need to use the moc directly. For more
|
||
|
background information on moc, see \link templates.html Why doesn't Qt
|
||
|
use templates for signals and slots?\endlink.
|
||
|
|
||
|
\section1 Usage
|
||
|
|
||
|
The moc is typically used with an input file containing class declarations
|
||
|
like this:
|
||
|
|
||
|
\code
|
||
|
class MyClass : public QObject
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
MyClass( QObject * parent=0, const char * name=0 );
|
||
|
~MyClass();
|
||
|
|
||
|
signals:
|
||
|
void mySignal();
|
||
|
|
||
|
public slots:
|
||
|
void mySlot();
|
||
|
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
In addition to the signals and slots shown above, the moc also
|
||
|
implements object properties as in the next example. The Q_PROPERTY
|
||
|
macro declares an object property, while Q_ENUMS declares a list of
|
||
|
enumeration types within the class to be usable inside the
|
||
|
\link properties.html property system\endlink. In this particular
|
||
|
case we declare a property of the enumeration type \c Priority that is
|
||
|
also called "priority" and has a get function \c priority() and a set
|
||
|
function \c setPriority().
|
||
|
|
||
|
\code
|
||
|
class MyClass : public QObject
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
Q_PROPERTY( Priority priority READ priority WRITE setPriority )
|
||
|
Q_ENUMS( Priority )
|
||
|
public:
|
||
|
MyClass( QObject * parent=0, const char * name=0 );
|
||
|
~MyClass();
|
||
|
|
||
|
enum Priority { High, Low, VeryHigh, VeryLow };
|
||
|
void setPriority( Priority );
|
||
|
Priority priority() const;
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
Properties can be modified in subclasses with the Q_OVERRIDE
|
||
|
macro. The Q_SETS macro declares enums that are to be used as
|
||
|
sets, i.e. OR'ed together. Another macro, Q_CLASSINFO, can be used to
|
||
|
attach additional name/value-pairs to the class' meta object:
|
||
|
|
||
|
\code
|
||
|
class MyClass : public QObject
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
Q_CLASSINFO( "Author", "Oscar Peterson")
|
||
|
Q_CLASSINFO( "Status", "Active")
|
||
|
public:
|
||
|
MyClass( QObject * parent=0, const char * name=0 );
|
||
|
~MyClass();
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
The three concepts, signals and slots, properties and class
|
||
|
meta-data, can be combined.
|
||
|
|
||
|
The output produced by the moc must be compiled and linked, just like
|
||
|
the other C++ code in your program; otherwise the build will fail in
|
||
|
the final link phase. By convention, this is done in one of the
|
||
|
following two ways:
|
||
|
|
||
|
<dl>
|
||
|
|
||
|
<dt><b>Method A: The class declaration is found in a header
|
||
|
(\e .h) file</b>
|
||
|
|
||
|
<dd>If the class declaration above is found in the file
|
||
|
\e myclass.h, the moc output should be put in a file called
|
||
|
\e moc_myclass.cpp. This file should then be compiled as
|
||
|
usual, resulting in an object file \e moc_myclass.o (on Unix)
|
||
|
or \e moc_myclass.obj (on Windows). This object should then be
|
||
|
included in the list of object files that are linked together in the
|
||
|
final building phase of the program.
|
||
|
|
||
|
|
||
|
<dt><b>Method B: The class declaration is found in an implementation
|
||
|
(\e .cpp) file</b>
|
||
|
|
||
|
<dd>If the class declaration above is found in the file
|
||
|
\e myclass.cpp, the moc output should be put in a file called
|
||
|
\e myclass.moc. This file should be #included in the
|
||
|
implementation file, i.e. \e myclass.cpp should contain the
|
||
|
line
|
||
|
\code
|
||
|
#include "myclass.moc"
|
||
|
\endcode
|
||
|
at the end. This will cause the moc-generated code to be compiled and
|
||
|
linked together with the normal class definition in \e myclass.cpp, so
|
||
|
it is not necessary to compile and link it separately, as in Method A.
|
||
|
|
||
|
</dl>
|
||
|
|
||
|
Method A is the normal method. Method B can be used in cases where you
|
||
|
want the implementation file to be self-contained, or in cases where
|
||
|
the Q_OBJECT class is implementation-internal and thus should not be
|
||
|
visible in the header file.
|
||
|
|
||
|
|
||
|
\section1 Automating moc Usage with Makefiles
|
||
|
|
||
|
For anything but the simplest test programs, it is recommended that
|
||
|
you automate running the moc. By adding some rules to your program's
|
||
|
Makefile, \e make can take care of running moc when necessary and
|
||
|
handling the moc output.
|
||
|
|
||
|
We recommend using Trolltech's free makefile generation tool, \link
|
||
|
qmake-manual.book qmake\endlink, for building your Makefiles. This tool
|
||
|
recognizes both Method A and B style source files, and generates a
|
||
|
Makefile that does all the necessary moc handling.
|
||
|
|
||
|
If you want to create your Makefiles yourself, here are some tips on
|
||
|
how to include moc handling.
|
||
|
|
||
|
For Q_OBJECT class declarations in header files, here is a useful
|
||
|
makefile rule if you only use GNU make:
|
||
|
|
||
|
\code
|
||
|
moc_%.cpp: %.h
|
||
|
moc $< -o $@
|
||
|
\endcode
|
||
|
|
||
|
If you want to write portably, you can use individual rules with the
|
||
|
following form:
|
||
|
|
||
|
\code
|
||
|
moc_NAME.cpp: NAME.h
|
||
|
moc $< -o $@
|
||
|
\endcode
|
||
|
|
||
|
You must also remember to add \e moc_NAME.cpp to your SOURCES
|
||
|
(substitute your favorite name) variable and \e moc_NAME.o or
|
||
|
\e moc_NAME.obj to your OBJECTS variable.
|
||
|
|
||
|
(While we prefer to name our C++ source files .cpp, the moc doesn't
|
||
|
care, so you can use .C, .cc, .CC, .cxx or even .c++ if you
|
||
|
prefer.)
|
||
|
|
||
|
For Q_OBJECT class declarations in implementation (.cpp) files, we
|
||
|
suggest a makefile rule like this:
|
||
|
|
||
|
\code
|
||
|
NAME.o: NAME.moc
|
||
|
|
||
|
NAME.moc: NAME.cpp
|
||
|
moc -i $< -o $@
|
||
|
\endcode
|
||
|
|
||
|
This guarantees that make will run the moc before it compiles
|
||
|
\e NAME.cpp. You can then put
|
||
|
|
||
|
\code
|
||
|
#include "NAME.moc"
|
||
|
\endcode
|
||
|
|
||
|
at the end of \e NAME.cpp, where all the classes declared in
|
||
|
that file are fully known.
|
||
|
|
||
|
|
||
|
\section1 Invoking moc
|
||
|
|
||
|
Here are the command-line options supported by the moc:
|
||
|
|
||
|
\table
|
||
|
\header \i Option \i Meaning
|
||
|
\row
|
||
|
\i -o \e file
|
||
|
\i Write output to \e file rather than to stdout.
|
||
|
\row
|
||
|
\i -f
|
||
|
\i Force the generation of an #include statement in the
|
||
|
output. This is the default for files whose name matches the regular
|
||
|
expression \.[hH][^.]* (i.e. the extension starts with H or h). This
|
||
|
option is only useful if you have header files that do not follow the
|
||
|
standard naming conventions.
|
||
|
\row
|
||
|
\i -i
|
||
|
\i Do not generate an #include statement in the output.
|
||
|
This may be used to run the moc on on a C++ file containing one or
|
||
|
more class declarations. You should then #include the meta object
|
||
|
code in the .cpp
|
||
|
file. If both -i and -f are present, the last one wins.
|
||
|
\row
|
||
|
\i -nw
|
||
|
\i Do not generate any warnings. Not recommended.
|
||
|
\row
|
||
|
\i -ldbg
|
||
|
\i Write a flood of lex debug information to stdout.
|
||
|
\row
|
||
|
\i -p \e path
|
||
|
\i Makes the moc prepend \e {path}/ to
|
||
|
the file name in the generated #include statement (if one is
|
||
|
generated).
|
||
|
\row
|
||
|
\i -q \e path
|
||
|
\i Makes the moc prepend \e {path}/ to
|
||
|
the file name of qt #include files in the generated code.
|
||
|
\endtable
|
||
|
|
||
|
You can explicitly tell the moc not to parse parts of a header
|
||
|
file. It recognizes any C++ comment (//) that contains the substrings
|
||
|
MOC_SKIP_BEGIN or MOC_SKIP_END. They work as you would expect and you
|
||
|
can have several levels of them. The net result as seen by the moc is
|
||
|
as if you had removed all lines between a MOC_SKIP_BEGIN and a
|
||
|
MOC_SKIP_END.
|
||
|
|
||
|
|
||
|
\section1 Diagnostics
|
||
|
|
||
|
The moc will warn you about a number of dangerous or illegal
|
||
|
constructs in the Q_OBJECT class declarations.
|
||
|
|
||
|
If you get linkage errors in the final building phase of your
|
||
|
program, saying that YourClass::className() is undefined or that
|
||
|
YourClass lacks a vtbl, something has been done wrong. Most often,
|
||
|
you have forgotten to compile or #include the moc-generated C++ code, or
|
||
|
(in the former case) include that object file in the link command.
|
||
|
|
||
|
|
||
|
\section1 Limitations
|
||
|
|
||
|
The moc does not expand #include or #define, it simply skips any
|
||
|
preprocessor directives it encounters. This is regrettable, but is
|
||
|
not usually a problem in practice.
|
||
|
|
||
|
The moc does not handle all of C++. The main problem is that class
|
||
|
templates cannot have signals or slots. Here is an example:
|
||
|
|
||
|
\code
|
||
|
class SomeTemplate<int> : public QFrame {
|
||
|
Q_OBJECT
|
||
|
...
|
||
|
signals:
|
||
|
void bugInMocDetected( int );
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
Less importantly, the following constructs are illegal. All of them
|
||
|
have alternatives which we think are usually better, so removing these
|
||
|
limitations is not a high priority for us.
|
||
|
|
||
|
\section2 Multiple inheritance retquires QObject to be first
|
||
|
|
||
|
If you are using multiple inheritance, moc assumes that the \e first
|
||
|
inherited class is a subclass of QObject. Also, be sure that \e only
|
||
|
the first inherited class is a QObject.
|
||
|
|
||
|
\code
|
||
|
class SomeClass : public QObject, public OtherClass {
|
||
|
...
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
(This limitation is almost impossible to remove; since the moc does not expand
|
||
|
#include or #define, it cannot find out which one of the base classes
|
||
|
is a QObject.)
|
||
|
|
||
|
\section2 Function pointers cannot be arguments to signals or slots
|
||
|
|
||
|
In most cases where you would consider using function pointers as
|
||
|
signal/slot arguments, we think inheritance is a better alternative.
|
||
|
Here is an example of illegal syntax:
|
||
|
|
||
|
\code
|
||
|
class SomeClass : public QObject {
|
||
|
Q_OBJECT
|
||
|
...
|
||
|
public slots:
|
||
|
// illegal
|
||
|
void apply( void (*apply)(List *, void *), char * );
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
You can work around this restriction like this:
|
||
|
\code
|
||
|
typedef void (*ApplyFunctionType)( List *, void * );
|
||
|
|
||
|
class SomeClass : public QObject {
|
||
|
Q_OBJECT
|
||
|
...
|
||
|
public slots:
|
||
|
void apply( ApplyFunctionType, char * );
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
It may sometimes be even better to replace the function pointer with
|
||
|
inheritance and virtual functions, signals or slots.
|
||
|
|
||
|
\section2 Friend declarations cannot be placed in signals or slots sections
|
||
|
|
||
|
Sometimes it will work, but in general, friend declarations cannot be
|
||
|
placed in signals or slots sections. Put them in the private,
|
||
|
protected or public sections instead. Here is an example of the
|
||
|
illegal syntax:
|
||
|
|
||
|
\code
|
||
|
class SomeClass : public QObject {
|
||
|
Q_OBJECT
|
||
|
...
|
||
|
signals:
|
||
|
friend class ClassTemplate<char>; // WRONG
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
\section2 Signals and slots cannot be upgraded
|
||
|
|
||
|
The C++ feature of upgrading an inherited member function to
|
||
|
public status is not extended to cover signals and slots. Here is an
|
||
|
illegal example:
|
||
|
|
||
|
\code
|
||
|
class Whatever : public QButtonGroup {
|
||
|
...
|
||
|
public slots:
|
||
|
QButtonGroup::buttonPressed; // WRONG
|
||
|
...
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
The QButtonGroup::buttonPressed() slot is protected.
|
||
|
|
||
|
C++ tquiz: What happens if you try to upgrade a protected member
|
||
|
function which is overloaded?
|
||
|
\list 1
|
||
|
\i All the functions are overloaded.
|
||
|
\i That is not legal C++.
|
||
|
\endlist
|
||
|
|
||
|
\omit
|
||
|
C++ ARM, section r.11.3
|
||
|
\endomit
|
||
|
|
||
|
\section2 Type macros cannot be used for signal and slot parameters
|
||
|
|
||
|
Since the moc does not expand #define, type macros that take an argument
|
||
|
will not work in signals and slots. Here is an illegal example:
|
||
|
|
||
|
\code
|
||
|
#ifdef ultrix
|
||
|
#define SIGNEDNESS(a) unsigned a
|
||
|
#else
|
||
|
#define SIGNEDNESS(a) a
|
||
|
#endif
|
||
|
|
||
|
class Whatever : public QObject {
|
||
|
...
|
||
|
signals:
|
||
|
void someSignal( SIGNEDNESS(int) );
|
||
|
...
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
A #define without parameters will work as expected.
|
||
|
|
||
|
\section2 Nested classes cannot be in the signals or slots sections nor have
|
||
|
signals or slots
|
||
|
|
||
|
Here's an example:
|
||
|
|
||
|
\code
|
||
|
class A {
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
class B {
|
||
|
public slots: // WRONG
|
||
|
void b();
|
||
|
...
|
||
|
};
|
||
|
signals:
|
||
|
class B { // WRONG
|
||
|
void b();
|
||
|
...
|
||
|
}:
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
\section2 Constructors cannot be used in signals or slots sections
|
||
|
|
||
|
It is a mystery to us why anyone would put a constructor in
|
||
|
either the signals or slots sections. You can't anyway (except
|
||
|
that it happens to work in some cases). Put them in private,
|
||
|
protected or public sections, where they belong. Here is an example
|
||
|
of the illegal syntax:
|
||
|
|
||
|
\code
|
||
|
class SomeClass : public QObject {
|
||
|
Q_OBJECT
|
||
|
public slots:
|
||
|
SomeClass( QObject *parent, const char *name )
|
||
|
: QObject( parent, name ) { } // WRONG
|
||
|
...
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
\section2 Properties need to be declared before the public section that
|
||
|
contains the respective get and set functions
|
||
|
|
||
|
Declaring the first property within or after the public section that
|
||
|
contains the type definition and the respective get and set functions
|
||
|
does not work as expected. The moc will complain that it can neither
|
||
|
find the functions nor resolve the type. Here is an example of the
|
||
|
illegal syntax:
|
||
|
|
||
|
\code
|
||
|
class SomeClass : public QObject {
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
...
|
||
|
Q_PROPERTY( Priority priority READ priority WRITE setPriority ) // WRONG
|
||
|
Q_ENUMS( Priority ) // WRONG
|
||
|
enum Priority { High, Low, VeryHigh, VeryLow };
|
||
|
void setPriority( Priority );
|
||
|
Priority priority() const;
|
||
|
...
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
Work around this limitation by declaring all properties at the
|
||
|
beginning of the class declaration, right after Q_OBJECT:
|
||
|
|
||
|
\code
|
||
|
class SomeClass : public QObject {
|
||
|
Q_OBJECT
|
||
|
Q_PROPERTY( Priority priority READ priority WRITE setPriority )
|
||
|
Q_ENUMS( Priority )
|
||
|
public:
|
||
|
...
|
||
|
enum Priority { High, Low, VeryHigh, VeryLow };
|
||
|
void setPriority( Priority );
|
||
|
Priority priority() const;
|
||
|
...
|
||
|
};
|
||
|
\endcode
|
||
|
|
||
|
*/
|