diff options
50 files changed, 1870 insertions, 5 deletions
diff --git a/doc/src/declarative/extending-examples.qdoc b/doc/src/declarative/extending-examples.qdoc new file mode 100644 index 0000000..09239c1 --- /dev/null +++ b/doc/src/declarative/extending-examples.qdoc @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\example declarative/extending/adding +\title Extending QML - Adding Types Example + +The Adding Types Example shows how to add a new element type, \c Person, to QML. +The \c Person type can be used from QML like this: + +\snippet examples/declarative/extending/adding/example.qml 0 + +\section1 Declare the Person class + +All QML elements map to C++ types. Here we declare a basic C++ Person class +with the two properties we want accessible on the QML type - name and shoeSize. +Although in this example we use the same name for the C++ class as the QML +element, the C++ class can be named differently, or appear in a namespace. + +\snippet examples/declarative/extending/adding/person.h 0 + +Following the class declaration, we include the QML_DECLARE_TYPE() macro. This +is necessary to declare the type to QML. It also includes the logic necessary +to expose the class to Qt's meta system - that is, it includes the +Q_DECLARE_METATYPE() functionality. + +\section1 Define the Person class + +\snippet examples/declarative/extending/adding/person.cpp 0 + +The Person class implementation is quite basic. The property accessors simply +return members of the object instance. + +The implementation must also include the QML_DEFINE_TYPE() macro. This macro +registers the Person class with QML, and defines the mapping between the C++ +and QML class names. + +\section1 Running the example + +The main.cpp file in the example includes a simple shell application that +loads and runs the QML snippet shown at the beginning of this page. +*/ + +/*! +\example declarative/extending/properties +\title Extending QML - Object and List Property Types Example + +This example builds on: +\list +\o \l {Extending QML - Adding Types Example} +\endlist + +The Object and List Property Types example shows how to add object and list +properties in QML. This example adds a BirthdayParty element that specifies +a birthday party, consisting of a celebrant and a list of guests. People are +specified using the People QML type built in the previous example. + +\snippet examples/declarative/extending/properties/example.qml 0 + +\section1 Declare the BirthdayParty + +The BirthdayParty class is declared like this: + +\snippet examples/declarative/extending/properties/birthdayparty.h 0 +\snippet examples/declarative/extending/properties/birthdayparty.h 1 +\snippet examples/declarative/extending/properties/birthdayparty.h 2 +\snippet examples/declarative/extending/properties/birthdayparty.h 3 + +The class contains a member to store the celebrant object, and also a +QmlConcreteList<Person *> member. + +In QML, the type of a list properties - and the guests property is a list of +people - are all of type QmlList<T *>*. QmlList is an abstract list interface +that allows a developer to react to QML accessing and modifying the contents of +the list. This is useful for implementing "virtual lists" or other advanced +scenarios, but can't be used directly for the common case of just wanting a +regular list of things. For this a concrete implementation, QmlConcreteList, is +provided and that is used here. + +\section2 Define the BirthdayParty + +The implementation of BirthdayParty property accessors is straight forward. + +\snippet examples/declarative/extending/properties/birthdayparty.cpp 0 + +\section1 Running the example + +The main.cpp file in the example includes a simple shell application that +loads and runs the QML snippet shown at the beginning of this page. +*/ + +/*! +\example declarative/extending/coercion +\title Extending QML - Inheritance and Coercion Example + +This example builds on: +\list +\o \l {Extending QML - Object and List Property Types Example} +\o \l {Extending QML - Adding Types Example} +\endlist + +The Inheritance and Coercion Example shows how to use base classes to assign +elements of more than one type to a property. It specializes the Person element +developed in the previous examples into two elements - a \c Boy and a \c Girl. + +\snippet examples/declarative/extending/coercion/example.qml 0 + +\section1 Declare Boy and Girl + +\snippet examples/declarative/extending/coercion/person.h 0 + +The Person class remains unaltered in this example and the Boy and Girl C++ +classes are trivial extensions of it. As an example, the inheritance used here +is a little contrived, but in real applications it is likely that the two +extensions would add additional properties or modify the Person classes +behavior. + +\section2 Define People as a base class + +The implementation of the People class itself has not changed since the the +previous example. However, as we have repurposed the People class as a common +base for Boy and Girl, we want to prevent it from being instantiated from QML +directly - an explicit Boy or Girl should be instantiated instead. + +\snippet examples/declarative/extending/coercion/person.cpp 0 + +While we want to disallow instantiating Person from within QML, it still needs +to be registered with the QML engine, so that it can be used as a property type +and other types can be coerced to it. To register a type, without defining a +named mapping into QML, we use the QML_DEFINE_NOCREATE_TYPE() macro instead of +the QML_DEFINE_TYPE() macro used previously. + +\section2 Define Boy and Girl + +The implementation of Boy and Girl are trivial. + +\snippet examples/declarative/extending/coercion/person.cpp 1 + +All that is necessary is to implement the constructor, and to register the types +and their QML name with the QML engine. + +\section1 Running the example + +The BirthdayParty element has not changed since the previous example. The +celebrant and guests property still use the People type. + +\snippet examples/declarative/extending/coercion/birthdayparty.h 0 + +However, as all three types, Person, Boy and Girl, have been registered with the +QML system, on assignment QML automatically (and type-safely) converts the Boy +and Girl objects into a Person. + +The main.cpp file in the example includes a simple shell application that +loads and runs the QML snippet shown at the beginning of this page. +*/ + +/*! +\example declarative/extending/default +\title Extending QML - Default Property Example + +This example builds on: +\list +\o \l {Extending QML - Inheritance and Coercion Example} +\o \l {Extending QML - Object and List Property Types Example} +\o \l {Extending QML - Adding Types Example} +\endlist + +The Default Property Example is a minor modification of the +\l {Extending QML - Inheritance and Coercion Example} that simplifies the +specification of a BirthdayParty through the use of a default property. + +\snippet examples/declarative/extending/default/example.qml 0 + +\section1 Declaring the BirthdayParty class + +The only difference between this example and the last, is the addition of the +\c DefaultProperty class info annotation. + +\snippet examples/declarative/extending/default/birthdayparty.h 0 + +The default property specifies the property to assign to whenever an explicit +property is not specified, in the case of the BirthdayParty element the guest +property. It is purely a syntactic simplification, the behavior is identical +to specifying the property by name, but it can add a more natural feel in many +situations. The default property must be either an object or list property. + +\section1 Running the example + +The main.cpp file in the example includes a simple shell application that +loads and runs the QML snippet shown at the beginning of this page. +*/ + +/*! +\example declarative/extending/grouped +\title Extending QML - Grouped Properties Example + +This example builds on: +\list +\o \l {Extending QML - Default Property Example} +\o \l {Extending QML - Inheritance and Coercion Example} +\o \l {Extending QML - Object and List Property Types Example} +\o \l {Extending QML - Adding Types Example} +\endlist + +*/ + +/*! +\example declarative/extending/grouped +\title Extending QML - Attached Properties Example + +This example builds on: +\list +\o \l {Extending QML - Grouped Properties Example} +\o \l {Extending QML - Default Property Example} +\o \l {Extending QML - Inheritance and Coercion Example} +\o \l {Extending QML - Object and List Property Types Example} +\o \l {Extending QML - Adding Types Example} +\endlist + +*/ diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 7163a93..138ccb2 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -1,3 +1,376 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page qml-extending.html +\title Extending QML + +The QML syntax declaratively describes how to construct an in memory object +tree. In Qt, QML is mainly used to describe a visual scene graph, but it is +not conceptually limited to this: the QML format is an abstract description of +any object tree. All the QML element types included in Qt are implemented using +the C++ extension mechanisms describe on this page. Programmers can use these +APIs to add new types that interact with the existing Qt types, or to repurpose +QML for their own independent use. + +\tableofcontents + +\section1 Adding Types + +\snippet examples/declarative/extending/adding/example.qml 0 + +The QML snippet shown above instantiates one \c Person instance and sets +the name and shoeSize properties on it. Everything in QML ultimately comes down +to either instantiating an object instance, or assigning a property a value. +QML relies heavily on Qt's meta object system and can only instantiate classes +that derive from QObject. + +The QML engine has no intrinsic knowledge of any class types. Instead the +programmer must define the C++ types, and their corresponding QML name. + +Custom C++ types are made available to QML using these two macros: + +\quotation +\code +#define QML_DECLARE_TYPE(T) +#define QML_DEFINE_TYPE(T,QmlName) +\endcode + +Register the C++ type \a T with the QML system, and make it available in QML +under the name \a QmlName. \a T and \a QmlName may be the same. + +Generally the QML_DECLARE_TYPE() macro should be included immediately following +the type declaration (usually in its header file), and the QML_DEFINE_TYPE() +macro in the implementation file. QML_DEFINE_TYPE() must not be present in +a header file. + +Type \a T must be a concrete type that inherits QObject and has a default +constructor. +\endquotation + +Once registered, all of the \l {Qt's Property System}{properties} of a supported +type are available for use within QML. QML has intrinsic support for properties +of these types: + +\list +\o bool +\o unsigned int, int +\o float, double, qreal +\o QString +\o QUrl +\o QColor +\o QDate, QTime, QDateTime +\o QPoint, QPointF +\o QSize, QSizeF +\o QRect, QRectF +\o QVariant +\endlist + +QML is typesafe. Attempting to assign an invalid value to a property will +generate an error. For example, assuming the name property of the \c Person +element had a type of QString, this would cause an error: + +\code +Person { + // Will NOT work + name: 12 +} +\endcode + +\l {Extending QML - Adding Types Example} shows the complete code used to create +the \c Person type. + +\section1 Object and List Property Types + +\snippet examples/declarative/extending/properties/example.qml 0 + +The QML snippet shown above assigns a \c Person object to the \c BirthdayParty's +celebrant property, and assigns three \c Person objects to the guests property. + +QML can set properties of types that are more complex than basic intrinsics like +integers and strings. Properties can also be object pointers, Qt interface +pointers, lists of object points, and lists of Qt interface pointers. As QML +is typesafe it ensures that only valid types are assigned to these properties, +just like it does for primitive types. + +Properties that are pointers to objects or Qt interfaces are declared with the +Q_PROPERTY() macro, just like other properties. The celebrant property +declaration looks like this: + +\snippet examples/declarative/extending/properties/birthdayparty.h 1 + +As long as the property type, in this case Person, is registered with QML the +property can be assigned. + +QML also supports assigning Qt interfaces. To assign to a property whose type +is a Qt interface pointer, the interface must also be registered with QML. As +they cannot be instantiated directly, registering a Qt interface is different +from registering a new QML type. The following macros are used instead: + +\quotation +\code + #define QML_DECLARE_INTERFACE(T) + #define QML_DEFINE_INTERFACE(T) +\endcode + +Register the C++ interface \a T with the QML system. + +Generally the QML_DECLARE_INTERFACE() macro should be included immediately +following the interface declaration (usually in its header file), and the +QML_DEFINE_INTERFACE() macro in an implementation file. QML_DEFINE_INTERFACE() +must not be present in a header file. + +Following registration, QML can coerce objects that implement this interface +for assignment to appropriately typed properties. +\endquotation + +The guests property is a list of \c Person objects. Properties that are lists +of objects or Qt interfaces are also declared with the Q_PROPERTY() macro, just +like other properties. List properties must have the type \c {QmlList<T *>*}. +As with object properties, the type \a T must be registered with QML. + +The guest property declaration looks like this: + +\snippet examples/declarative/extending/properties/birthdayparty.h 2 + +\l {Extending QML - Object and List Property Types Example} shows the complete +code used to create the \c BirthdayParty type. + +\section1 Inheritance and Coercion + +\snippet examples/declarative/extending/coercion/example.qml 0 + +The QML snippet shown above assigns a \c Boy object to the \c BirthdayParty's +celebrant property, and assigns three other objects to the guests property. + +QML supports C++ inheritance heirarchies and can freely coerce between known, +valid object types. This enables the creation of common base classes that allow +the assignment of specialized classes to object or list properties. In the +snippet shown, both the celebrant and the guests properties retain the Person +type used in the previous section, but the assignment is valid as both the Boy +and Girl objects inherit from Person. + +To assign to a property, the property's type must have been registered with QML. +Both the QML_DEFINE_TYPE() and QML_DEFINE_INTERFACE() macros already shown can +be used to register a type with QML. Additionally, if a type that acts purely +as a base class that cannot be instantiated from QML needs to be +registered these macros can be used: + +\quotation +\code + #define QML_DECLARE_TYPE(T) + #define QML_DEFINE_NOCREATE_TYPE(T) +\endcode + +Register the C++ type \a T with the QML system. QML_DEFINE_NOCREATE_TYPE() +differs from QML_DEFINE_TYPE() in that it does not define a mapping between the +C++ class and a QML element name, so the type is not instantiable from QML, but +it is available for type coercion. + +Generally the QML_DECLARE_TYPE() macro should be included immediately following +the type declaration (usually in its header file), and the +QML_DEFINE_NOCREATE_TYPE() macro in the implementation file. +QML_DEFINE_NOCREATE_TYPE() must not be present in a header file. + +Type \a T must inherit QObject, but there are no restrictions on whether it is +concrete or the signature of its constructor. +\endquotation + +QML will automatically coerce C++ types when assigning to either an object +property, or to a list property. Only if coercion fails does an assignment +error occur. + +\l {Extending QML - Inheritance and Coercion Example} shows the complete +code used to create the \c Boy and \c Girl types. + +\section1 Default Property + +\snippet examples/declarative/extending/default/example.qml 0 + +The QML snippet shown above assigns a collection of objects to the +\c BirthdayParty's default property. + +The default property is a syntactic convenience that allows a type designer to +specify a single property as the type's default. The default property is +assigned to whenever no explicit property is specified. As a convenience, it is +behaviorally identical to assigning the default property explicitly by name. + +From C++, type designers mark the default property using a Q_CLASSINFO() +annotation: + +\quotation +\code +Q_CLASSINFO("DefaultProperty", "property") +\endcode + +Mark \a property as the class's default property. \a property must be either +an object property, or a list property. + +A default property is optional. A derived class inherits its base class's +default property, but may override it in its own declaration. \a property can +refer to a property declared in the class itself, or a property inherited from a +base class. +\endquotation + +\l {Extending QML - Default Property Example} shows the complete code used to +specify a default property. + +\section1 Grouped Properties + +\snippet examples/declarative/extending/grouped/example.qml 1 + +The QML snippet shown above assigns a number properties to the \c Boy object, +including four properties using the grouped property syntax. + +Grouped properties collect similar properties together into a single named +block. Grouped properties can be used to present a nicer API to developers, and +may also simplify the implementation of common property collections across +different types through implementation reuse. + +A grouped property block is implemented as a read-only object property. The +shoe property shown is declared like this: + +\snippet examples/declarative/extending/grouped/person.h 1 + +The ShoeDescription type declares the properties available to the grouped +property block - in this case the size, color, brand and price properties. + +Grouped property blocks may declared and accessed be recusively. + +\l {Extending QML - Grouped Properties Example} shows the complete code used to +implement the \c shoe property grouping. + +\section1 Attached Properties + +\snippet examples/declarative/extending/attached/example.qml 1 + +The QML snippet shown above assigns the rsvp property using the attached +property syntax. + +Attached properties allow unrelated types to annotate other types with some +additional properties, generally for their own use. Attached properties are +identified through the use of the attacher type name, in the case shown +\c BirthdayParty, as a suffix to the property name. + +In the example shown, \c BirthdayParty is called the attaching type, and the +Box instance the attachee object instance. + +For the attaching type, an attached property block is implemented as a new +QObject derived type, called the attachment object. The properties on the +attachment object are those that become available for use as the attached +property block. + +Any QML type can become an attaching type by declaring the +\c qmlAttachedProperties() public function: + +\quotation +\code +static AttachedPropertiesType *qmlAttachedProperties(QObject *object) +\endcode +Return an attachment object, of type \a AttachedPropertiesType, for the +attachee \a object instance. It is customary, though not strictly required, for +the attachment object to be parented to \a object to prevent memory leaks. + +\a AttachedPropertiesType must be a QObject derived type. The properties on +this type will be accessible through the attached properties syntax. + +This method will be called at most once for each attachee object instance. The +QML engine will cache the returned instance pointer for subsequent attached +property accesses. Consequently the attachment object may not be deleted until +\a object is destroyed. +\endquotation + +Conceptually, attached properties are a \e type exporting a set of additional +properties that can be set on \e any other object instance. Attached properties +cannot be limited to only attaching to a sub-set of object instances, although +their effect may be so limited. + +For example, a common usage scenario is for a type to enhance the properties +available to its children in order to gather instance specific data. Here we +add a rsvp field to all the guests coming to a birthday party: +\code +BirthdayParty { + Boy { BirthdayParty.rsvp: "2009-06-01" } +} +\endcode +However, as a type cannot limit the instances to which the attachment object +must attach, the following is also allowed, even though adding a birthday party +rsvp in this context will have no effect. +\code +GraduationParty { + Boy { BirthdayParty.rsvp: "2009-06-01" } +} +\endcode + +From C++, including the attaching type implementation, the attachment object for +an instance can be accessed using the following method: + +\quotation +\code +template<typename T> +QObject *qmlAttachedPropertiesObject<T>(QObject *attachee, bool create = true); +\endcode +Returns the attachment object attached to \a attachee by the attaching type +\a T. If type \a T is not a valid attaching type, this method always returns 0. + +If \a create is true, a valid attachment object will always be returned, +creating it if it does not already exist. If \a create is false, the attachment +object will only be returned if it has previously been created. +\endquotation + +\l {Extending QML - Attached Properties Example} shows the complete code used to +implement the rsvp attached property. + +\section1 Property Binding + +\section1 Signal support + +\section1 Extension Objects + +\section1 Parser Status + +\section1 Property Value Sources +*/ + + /*! \page qml-extending-types.html \title Extending types from QML diff --git a/doc/src/declarative/qmlformat.qdoc b/doc/src/declarative/qmlformat.qdoc new file mode 100644 index 0000000..fd22ab5 --- /dev/null +++ b/doc/src/declarative/qmlformat.qdoc @@ -0,0 +1,6 @@ +/*! + \page qmlformat.html + \title QML Format + + Format reference here... +*/ diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index c945b24..c5d32fe 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -81,11 +81,13 @@ QML Reference: \list + \o \l {QML Format} \o \l {elements}{Qml Elements} \endlist C++ Reference: \list + \o \l {Extending QML} \o \l {qtbinding}{C++ Data Binding} \o \l {cppitem}{C++ Components} \endlist diff --git a/examples/declarative/extending/adding/adding.pro b/examples/declarative/extending/adding/adding.pro new file mode 100644 index 0000000..c02a35f --- /dev/null +++ b/examples/declarative/extending/adding/adding.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +TARGET = adding +DEPENDPATH += . +INCLUDEPATH += . +QT += declarative + +# Input +SOURCES += main.cpp \ + person.cpp +HEADERS += person.h +RESOURCES += adding.qrc diff --git a/examples/declarative/extending/adding/adding.qrc b/examples/declarative/extending/adding/adding.qrc new file mode 100644 index 0000000..e2fa01d --- /dev/null +++ b/examples/declarative/extending/adding/adding.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>example.qml</file> +</qresource> +</RCC> diff --git a/examples/declarative/extending/adding/example.qml b/examples/declarative/extending/adding/example.qml new file mode 100644 index 0000000..5550cec --- /dev/null +++ b/examples/declarative/extending/adding/example.qml @@ -0,0 +1,6 @@ +// ![0] +Person { + name: "Bob Jones" + shoeSize: 12 +} +// ![0] diff --git a/examples/declarative/extending/adding/main.cpp b/examples/declarative/extending/adding/main.cpp new file mode 100644 index 0000000..3d78ded --- /dev/null +++ b/examples/declarative/extending/adding/main.cpp @@ -0,0 +1,22 @@ +#include <QCoreApplication> +#include <QmlEngine> +#include <QmlComponent> +#include <QDebug> +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QmlEngine engine; + QmlComponent component(&engine, QUrl::fromLocalFile(":example.qml")); + Person *person = qobject_cast<Person *>(component.create()); + if (person) { + qWarning() << "The person's name is" << person->name(); + qWarning() << "They wear a" << person->shoeSize() << "sized shoe"; + } else { + qWarning() << "An error occured"; + } + + return 0; +} diff --git a/examples/declarative/extending/adding/person.cpp b/examples/declarative/extending/adding/person.cpp new file mode 100644 index 0000000..4198b63 --- /dev/null +++ b/examples/declarative/extending/adding/person.cpp @@ -0,0 +1,30 @@ +#include "person.h" + +// ![0] +Person::Person(QObject *parent) +: QObject(parent), m_shoeSize(0) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +int Person::shoeSize() const +{ + return m_shoeSize; +} + +void Person::setShoeSize(int s) +{ + m_shoeSize = s; +} + +QML_DEFINE_TYPE(Person, Person); +// ![0] diff --git a/examples/declarative/extending/adding/person.h b/examples/declarative/extending/adding/person.h new file mode 100644 index 0000000..3bef2d4 --- /dev/null +++ b/examples/declarative/extending/adding/person.h @@ -0,0 +1,27 @@ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +// ![0] +#include <qml.h> + +class Person : public QObject { +Q_OBJECT +Q_PROPERTY(QString name READ name WRITE setName) +Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) +public: + Person(QObject *parent = 0); + + QString name() const; + void setName(const QString &); + + int shoeSize() const; + void setShoeSize(int); +private: + QString m_name; + int m_shoeSize; +}; +QML_DECLARE_TYPE(Person); +// ![0] + +#endif // PERSON_H diff --git a/examples/declarative/extending/attached/attached.pro b/examples/declarative/extending/attached/attached.pro new file mode 100644 index 0000000..b0f3fea --- /dev/null +++ b/examples/declarative/extending/attached/attached.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = attached +DEPENDPATH += . +INCLUDEPATH += . +QT += declarative + +# Input +SOURCES += main.cpp \ + person.cpp \ + birthdayparty.cpp +HEADERS += person.h \ + birthdayparty.h +RESOURCES += attached.qrc diff --git a/examples/declarative/extending/attached/attached.qrc b/examples/declarative/extending/attached/attached.qrc new file mode 100644 index 0000000..e2fa01d --- /dev/null +++ b/examples/declarative/extending/attached/attached.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>example.qml</file> +</qresource> +</RCC> diff --git a/examples/declarative/extending/attached/birthdayparty.cpp b/examples/declarative/extending/attached/birthdayparty.cpp new file mode 100644 index 0000000..49ed5a3 --- /dev/null +++ b/examples/declarative/extending/attached/birthdayparty.cpp @@ -0,0 +1,45 @@ +#include "birthdayparty.h" + +BirthdayPartyAttached::BirthdayPartyAttached(QObject *object) +: QObject(object) +{ +} + +QDate BirthdayPartyAttached::rsvp() const +{ + return m_rsvp; +} + +void BirthdayPartyAttached::setRsvp(const QDate &d) +{ + m_rsvp = d; +} + +QML_DEFINE_NOCREATE_TYPE(BirthdayPartyAttached); + +BirthdayParty::BirthdayParty(QObject *parent) +: QObject(parent), m_celebrant(0) +{ +} + +Person *BirthdayParty::celebrant() const +{ + return m_celebrant; +} + +void BirthdayParty::setCelebrant(Person *c) +{ + m_celebrant = c; +} + +QmlList<Person *> *BirthdayParty::guests() +{ + return &m_guests; +} + +BirthdayPartyAttached *BirthdayParty::qmlAttachedProperties(QObject *object) +{ + return new BirthdayPartyAttached(object); +} + +QML_DEFINE_TYPE(BirthdayParty, BirthdayParty); diff --git a/examples/declarative/extending/attached/birthdayparty.h b/examples/declarative/extending/attached/birthdayparty.h new file mode 100644 index 0000000..8249af5 --- /dev/null +++ b/examples/declarative/extending/attached/birthdayparty.h @@ -0,0 +1,45 @@ +#ifndef BIRTHDAYPARTY_H +#define BIRTHDAYPARTY_H + +#include <QObject> +#include <QDate> +#include <qml.h> +#include "person.h" + +class BirthdayPartyAttached : public QObject +{ +Q_OBJECT +Q_PROPERTY(QDate rsvp READ rsvp WRITE setRsvp); +public: + BirthdayPartyAttached(QObject *object); + + QDate rsvp() const; + void setRsvp(const QDate &); + +private: + QDate m_rsvp; +}; +QML_DECLARE_TYPE(BirthdayPartyAttached); + +class BirthdayParty : public QObject +{ +Q_OBJECT +Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant) +Q_PROPERTY(QmlList<Person *> *guests READ guests) +Q_CLASSINFO("DefaultProperty", "guests") +public: + BirthdayParty(QObject *parent = 0); + + Person *celebrant() const; + void setCelebrant(Person *); + + QmlList<Person *> *guests(); + + static BirthdayPartyAttached *qmlAttachedProperties(QObject *); +private: + Person *m_celebrant; + QmlConcreteList<Person *> m_guests; +}; +QML_DECLARE_TYPE(BirthdayParty); + +#endif // BIRTHDAYPARTY_H diff --git a/examples/declarative/extending/attached/example.qml b/examples/declarative/extending/attached/example.qml new file mode 100644 index 0000000..2645eac --- /dev/null +++ b/examples/declarative/extending/attached/example.qml @@ -0,0 +1,27 @@ +BirthdayParty { + celebrant: Boy { + name: "Bob Jones" + shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 } + } + + // ![1] + Boy { + name: "Joan Hodges" + BirthdayParty.rsvp: "2009-07-06" + shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 } + } + // ![1] + Boy { + name: "Jack Smith" + shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 } + } + Girl { + name: "Anne Brown" + BirthdayParty.rsvp: "2009-07-01" + shoe.size: 7 + shoe.color: "red" + shoe.brand: "Marc Jacobs" + shoe.price: 699.99 + } +} + diff --git a/examples/declarative/extending/attached/main.cpp b/examples/declarative/extending/attached/main.cpp new file mode 100644 index 0000000..1f10cd0 --- /dev/null +++ b/examples/declarative/extending/attached/main.cpp @@ -0,0 +1,44 @@ +#include <QCoreApplication> +#include <QmlEngine> +#include <QmlComponent> +#include <QDebug> +#include "birthdayparty.h" +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QmlEngine engine; + QmlComponent component(&engine, QUrl::fromLocalFile(":example.qml")); + BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create()); + + if (party && party->celebrant()) { + qWarning() << party->celebrant()->name() << "is having a birthday!"; + + if (qobject_cast<Boy *>(party->celebrant())) + qWarning() << "He is inviting:"; + else + qWarning() << "She is inviting:"; + + for (int ii = 0; ii < party->guests()->count(); ++ii) { + Person *guest = party->guests()->at(ii); + + QDate rsvpDate; + QObject *attached = + qmlAttachedPropertiesObject<BirthdayParty>(guest, false); + if (attached) + rsvpDate = attached->property("rsvp").toDate(); + + if (rsvpDate.isNull()) + qWarning() << " " << guest->name() << "RSVP date: Hasn't RSVP'd"; + else + qWarning() << " " << guest->name() << "RSVP date:" << qPrintable(rsvpDate.toString()); + } + + } else { + qWarning() << "An error occured"; + } + + return 0; +} diff --git a/examples/declarative/extending/attached/person.cpp b/examples/declarative/extending/attached/person.cpp new file mode 100644 index 0000000..48a94e8 --- /dev/null +++ b/examples/declarative/extending/attached/person.cpp @@ -0,0 +1,83 @@ +#include "person.h" + +ShoeDescription::ShoeDescription(QObject *parent) +: QObject(parent), m_size(0), m_price(0) +{ +} + +int ShoeDescription::size() const +{ + return m_size; +} + +void ShoeDescription::setSize(int s) +{ + m_size = s; +} + +QColor ShoeDescription::color() const +{ + return m_color; +} + +void ShoeDescription::setColor(const QColor &c) +{ + m_color = c; +} + +QString ShoeDescription::brand() const +{ + return m_brand; +} + +void ShoeDescription::setBrand(const QString &b) +{ + m_brand = b; +} + +qreal ShoeDescription::price() const +{ + return m_price; +} + +void ShoeDescription::setPrice(qreal p) +{ + m_price = p; +} +QML_DEFINE_NOCREATE_TYPE(ShoeDescription); + +Person::Person(QObject *parent) +: QObject(parent) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +ShoeDescription *Person::shoe() +{ + return &m_shoe; +} + +QML_DEFINE_NOCREATE_TYPE(Person); + +Boy::Boy(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Boy, Boy); + +Girl::Girl(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Girl, Girl); diff --git a/examples/declarative/extending/attached/person.h b/examples/declarative/extending/attached/person.h new file mode 100644 index 0000000..07dfe0e --- /dev/null +++ b/examples/declarative/extending/attached/person.h @@ -0,0 +1,67 @@ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +#include <QColor> +#include <qml.h> + +class ShoeDescription : public QObject { +Q_OBJECT +Q_PROPERTY(int size READ size WRITE setSize) +Q_PROPERTY(QColor color READ color WRITE setColor) +Q_PROPERTY(QString brand READ brand WRITE setBrand) +Q_PROPERTY(qreal price READ price WRITE setPrice) +public: + ShoeDescription(QObject *parent = 0); + + int size() const; + void setSize(int); + + QColor color() const; + void setColor(const QColor &); + + QString brand() const; + void setBrand(const QString &); + + qreal price() const; + void setPrice(qreal); +private: + int m_size; + QColor m_color; + QString m_brand; + qreal m_price; +}; +QML_DECLARE_TYPE(ShoeDescription); + +class Person : public QObject { +Q_OBJECT +Q_PROPERTY(QString name READ name WRITE setName) +Q_PROPERTY(ShoeDescription *shoe READ shoe); +public: + Person(QObject *parent = 0); + + QString name() const; + void setName(const QString &); + + ShoeDescription *shoe(); +private: + QString m_name; + ShoeDescription m_shoe; +}; +QML_DECLARE_TYPE(Person); + +class Boy : public Person { +Q_OBJECT +public: + Boy(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Boy); + +class Girl : public Person { +Q_OBJECT +public: + Girl(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Girl); + +#endif // PERSON_H diff --git a/examples/declarative/extending/coercion/birthdayparty.cpp b/examples/declarative/extending/coercion/birthdayparty.cpp new file mode 100644 index 0000000..cdff6e1 --- /dev/null +++ b/examples/declarative/extending/coercion/birthdayparty.cpp @@ -0,0 +1,23 @@ +#include "birthdayparty.h" + +BirthdayParty::BirthdayParty(QObject *parent) +: QObject(parent), m_celebrant(0) +{ +} + +Person *BirthdayParty::celebrant() const +{ + return m_celebrant; +} + +void BirthdayParty::setCelebrant(Person *c) +{ + m_celebrant = c; +} + +QmlList<Person *> *BirthdayParty::guests() +{ + return &m_guests; +} + +QML_DEFINE_TYPE(BirthdayParty, BirthdayParty); diff --git a/examples/declarative/extending/coercion/birthdayparty.h b/examples/declarative/extending/coercion/birthdayparty.h new file mode 100644 index 0000000..2557d1a --- /dev/null +++ b/examples/declarative/extending/coercion/birthdayparty.h @@ -0,0 +1,29 @@ +#ifndef BIRTHDAYPARTY_H +#define BIRTHDAYPARTY_H + +#include <QObject> +#include <qml.h> +#include "person.h" + +class BirthdayParty : public QObject +{ +Q_OBJECT +// ![0] +Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant) +Q_PROPERTY(QmlList<Person *> *guests READ guests) +// ![0] +public: + BirthdayParty(QObject *parent = 0); + + Person *celebrant() const; + void setCelebrant(Person *); + + QmlList<Person *> *guests(); + +private: + Person *m_celebrant; + QmlConcreteList<Person *> m_guests; +}; +QML_DECLARE_TYPE(BirthdayParty); + +#endif // BIRTHDAYPARTY_H diff --git a/examples/declarative/extending/coercion/coercion.pro b/examples/declarative/extending/coercion/coercion.pro new file mode 100644 index 0000000..136b210 --- /dev/null +++ b/examples/declarative/extending/coercion/coercion.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = coercion +DEPENDPATH += . +INCLUDEPATH += . +QT += declarative + +# Input +SOURCES += main.cpp \ + person.cpp \ + birthdayparty.cpp +HEADERS += person.h \ + birthdayparty.h +RESOURCES += coercion.qrc diff --git a/examples/declarative/extending/coercion/coercion.qrc b/examples/declarative/extending/coercion/coercion.qrc new file mode 100644 index 0000000..e2fa01d --- /dev/null +++ b/examples/declarative/extending/coercion/coercion.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>example.qml</file> +</qresource> +</RCC> diff --git a/examples/declarative/extending/coercion/example.qml b/examples/declarative/extending/coercion/example.qml new file mode 100644 index 0000000..8bcb45a --- /dev/null +++ b/examples/declarative/extending/coercion/example.qml @@ -0,0 +1,13 @@ +// ![0] +BirthdayParty { + celebrant: Boy { + name: "Bob Jones" + shoeSize: 12 + } + guests: [ + Boy { name: "Joan Hodges" }, + Boy { name: "Jack Smith" }, + Girl { name: "Anne Brown" } + ] +} +// ![0] diff --git a/examples/declarative/extending/coercion/main.cpp b/examples/declarative/extending/coercion/main.cpp new file mode 100644 index 0000000..7439ba9 --- /dev/null +++ b/examples/declarative/extending/coercion/main.cpp @@ -0,0 +1,30 @@ +#include <QCoreApplication> +#include <QmlEngine> +#include <QmlComponent> +#include <QDebug> +#include "birthdayparty.h" +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QmlEngine engine; + QmlComponent component(&engine, QUrl::fromLocalFile(":example.qml")); + BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create()); + + if (party && party->celebrant()) { + qWarning() << party->celebrant()->name() << "is having a birthday!"; + + if (qobject_cast<Boy *>(party->celebrant())) + qWarning() << "He is inviting:"; + else + qWarning() << "She is inviting:"; + for (int ii = 0; ii < party->guests()->count(); ++ii) + qWarning() << " " << party->guests()->at(ii)->name(); + } else { + qWarning() << "An error occured"; + } + + return 0; +} diff --git a/examples/declarative/extending/coercion/person.cpp b/examples/declarative/extending/coercion/person.cpp new file mode 100644 index 0000000..4605db9 --- /dev/null +++ b/examples/declarative/extending/coercion/person.cpp @@ -0,0 +1,46 @@ +#include "person.h" + +Person::Person(QObject *parent) +: QObject(parent), m_shoeSize(0) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +int Person::shoeSize() const +{ + return m_shoeSize; +} + +void Person::setShoeSize(int s) +{ + m_shoeSize = s; +} + +// ![0] +QML_DEFINE_NOCREATE_TYPE(Person); +// ![0] + +// ![1] +Boy::Boy(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Boy, Boy); + +Girl::Girl(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Girl, Girl); +// ![1] diff --git a/examples/declarative/extending/coercion/person.h b/examples/declarative/extending/coercion/person.h new file mode 100644 index 0000000..de14019 --- /dev/null +++ b/examples/declarative/extending/coercion/person.h @@ -0,0 +1,41 @@ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +#include <qml.h> + +class Person : public QObject { +Q_OBJECT +Q_PROPERTY(QString name READ name WRITE setName) +Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) +public: + Person(QObject *parent = 0); + + QString name() const; + void setName(const QString &); + + int shoeSize() const; + void setShoeSize(int); +private: + QString m_name; + int m_shoeSize; +}; +QML_DECLARE_TYPE(Person); + +// ![0] +class Boy : public Person { +Q_OBJECT +public: + Boy(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Boy); + +class Girl : public Person { +Q_OBJECT +public: + Girl(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Girl); +// ![0] + +#endif // PERSON_H diff --git a/examples/declarative/extending/default/birthdayparty.cpp b/examples/declarative/extending/default/birthdayparty.cpp new file mode 100644 index 0000000..cdff6e1 --- /dev/null +++ b/examples/declarative/extending/default/birthdayparty.cpp @@ -0,0 +1,23 @@ +#include "birthdayparty.h" + +BirthdayParty::BirthdayParty(QObject *parent) +: QObject(parent), m_celebrant(0) +{ +} + +Person *BirthdayParty::celebrant() const +{ + return m_celebrant; +} + +void BirthdayParty::setCelebrant(Person *c) +{ + m_celebrant = c; +} + +QmlList<Person *> *BirthdayParty::guests() +{ + return &m_guests; +} + +QML_DEFINE_TYPE(BirthdayParty, BirthdayParty); diff --git a/examples/declarative/extending/default/birthdayparty.h b/examples/declarative/extending/default/birthdayparty.h new file mode 100644 index 0000000..084da10 --- /dev/null +++ b/examples/declarative/extending/default/birthdayparty.h @@ -0,0 +1,30 @@ +#ifndef BIRTHDAYPARTY_H +#define BIRTHDAYPARTY_H + +#include <QObject> +#include <qml.h> +#include "person.h" + +// ![0] +class BirthdayParty : public QObject +{ +Q_OBJECT +Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant) +Q_PROPERTY(QmlList<Person *> *guests READ guests) +Q_CLASSINFO("DefaultProperty", "guests") +public: + BirthdayParty(QObject *parent = 0); + + Person *celebrant() const; + void setCelebrant(Person *); + + QmlList<Person *> *guests(); + +private: + Person *m_celebrant; + QmlConcreteList<Person *> m_guests; +}; +// ![0] +QML_DECLARE_TYPE(BirthdayParty); + +#endif // BIRTHDAYPARTY_H diff --git a/examples/declarative/extending/default/default.pro b/examples/declarative/extending/default/default.pro new file mode 100644 index 0000000..0d5d45c --- /dev/null +++ b/examples/declarative/extending/default/default.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = default +DEPENDPATH += . +INCLUDEPATH += . +QT += declarative + +# Input +SOURCES += main.cpp \ + person.cpp \ + birthdayparty.cpp +HEADERS += person.h \ + birthdayparty.h +RESOURCES += default.qrc diff --git a/examples/declarative/extending/default/default.qrc b/examples/declarative/extending/default/default.qrc new file mode 100644 index 0000000..e2fa01d --- /dev/null +++ b/examples/declarative/extending/default/default.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>example.qml</file> +</qresource> +</RCC> diff --git a/examples/declarative/extending/default/example.qml b/examples/declarative/extending/default/example.qml new file mode 100644 index 0000000..4023abb --- /dev/null +++ b/examples/declarative/extending/default/example.qml @@ -0,0 +1,12 @@ +// ![0] +BirthdayParty { + celebrant: Boy { + name: "Bob Jones" + shoeSize: 12 + } + + Boy { name: "Joan Hodges" } + Boy { name: "Jack Smith" } + Girl { name: "Anne Brown" } +} +// ![0] diff --git a/examples/declarative/extending/default/main.cpp b/examples/declarative/extending/default/main.cpp new file mode 100644 index 0000000..7439ba9 --- /dev/null +++ b/examples/declarative/extending/default/main.cpp @@ -0,0 +1,30 @@ +#include <QCoreApplication> +#include <QmlEngine> +#include <QmlComponent> +#include <QDebug> +#include "birthdayparty.h" +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QmlEngine engine; + QmlComponent component(&engine, QUrl::fromLocalFile(":example.qml")); + BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create()); + + if (party && party->celebrant()) { + qWarning() << party->celebrant()->name() << "is having a birthday!"; + + if (qobject_cast<Boy *>(party->celebrant())) + qWarning() << "He is inviting:"; + else + qWarning() << "She is inviting:"; + for (int ii = 0; ii < party->guests()->count(); ++ii) + qWarning() << " " << party->guests()->at(ii)->name(); + } else { + qWarning() << "An error occured"; + } + + return 0; +} diff --git a/examples/declarative/extending/default/person.cpp b/examples/declarative/extending/default/person.cpp new file mode 100644 index 0000000..c47bfb7 --- /dev/null +++ b/examples/declarative/extending/default/person.cpp @@ -0,0 +1,42 @@ +#include "person.h" + +Person::Person(QObject *parent) +: QObject(parent), m_shoeSize(0) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +int Person::shoeSize() const +{ + return m_shoeSize; +} + +void Person::setShoeSize(int s) +{ + m_shoeSize = s; +} + +QML_DEFINE_NOCREATE_TYPE(Person); + +Boy::Boy(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Boy, Boy); + +Girl::Girl(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Girl, Girl); diff --git a/examples/declarative/extending/default/person.h b/examples/declarative/extending/default/person.h new file mode 100644 index 0000000..872186c --- /dev/null +++ b/examples/declarative/extending/default/person.h @@ -0,0 +1,39 @@ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +#include <qml.h> + +class Person : public QObject { +Q_OBJECT +Q_PROPERTY(QString name READ name WRITE setName) +Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) +public: + Person(QObject *parent = 0); + + QString name() const; + void setName(const QString &); + + int shoeSize() const; + void setShoeSize(int); +private: + QString m_name; + int m_shoeSize; +}; +QML_DECLARE_TYPE(Person); + +class Boy : public Person { +Q_OBJECT +public: + Boy(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Boy); + +class Girl : public Person { +Q_OBJECT +public: + Girl(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Girl); + +#endif // PERSON_H diff --git a/examples/declarative/extending/grouped/birthdayparty.cpp b/examples/declarative/extending/grouped/birthdayparty.cpp new file mode 100644 index 0000000..cdff6e1 --- /dev/null +++ b/examples/declarative/extending/grouped/birthdayparty.cpp @@ -0,0 +1,23 @@ +#include "birthdayparty.h" + +BirthdayParty::BirthdayParty(QObject *parent) +: QObject(parent), m_celebrant(0) +{ +} + +Person *BirthdayParty::celebrant() const +{ + return m_celebrant; +} + +void BirthdayParty::setCelebrant(Person *c) +{ + m_celebrant = c; +} + +QmlList<Person *> *BirthdayParty::guests() +{ + return &m_guests; +} + +QML_DEFINE_TYPE(BirthdayParty, BirthdayParty); diff --git a/examples/declarative/extending/grouped/birthdayparty.h b/examples/declarative/extending/grouped/birthdayparty.h new file mode 100644 index 0000000..3d53319 --- /dev/null +++ b/examples/declarative/extending/grouped/birthdayparty.h @@ -0,0 +1,28 @@ +#ifndef BIRTHDAYPARTY_H +#define BIRTHDAYPARTY_H + +#include <QObject> +#include <qml.h> +#include "person.h" + +class BirthdayParty : public QObject +{ +Q_OBJECT +Q_PROPERTY(Person *celebrant READ celebrant WRITE setCelebrant) +Q_PROPERTY(QmlList<Person *> *guests READ guests) +Q_CLASSINFO("DefaultProperty", "guests") +public: + BirthdayParty(QObject *parent = 0); + + Person *celebrant() const; + void setCelebrant(Person *); + + QmlList<Person *> *guests(); + +private: + Person *m_celebrant; + QmlConcreteList<Person *> m_guests; +}; +QML_DECLARE_TYPE(BirthdayParty); + +#endif // BIRTHDAYPARTY_H diff --git a/examples/declarative/extending/grouped/example.qml b/examples/declarative/extending/grouped/example.qml new file mode 100644 index 0000000..b9e5e6b --- /dev/null +++ b/examples/declarative/extending/grouped/example.qml @@ -0,0 +1,31 @@ +// ![0] +BirthdayParty { + celebrant: Boy { + name: "Bob Jones" + shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 } + } + + Boy { + name: "Joan Hodges" + shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 } + } + // ![1] + Boy { + name: "Jack Smith" + shoe { + size: 8 + color: "blue" + brand: "Puma" + price: 19.95 + } + } + // ![1] + Girl { + name: "Anne Brown" + shoe.size: 7 + shoe.color: "red" + shoe.brand: "Marc Jacobs" + shoe.price: 699.99 + } +} +// ![0] diff --git a/examples/declarative/extending/grouped/grouped.pro b/examples/declarative/extending/grouped/grouped.pro new file mode 100644 index 0000000..8fde8e8 --- /dev/null +++ b/examples/declarative/extending/grouped/grouped.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = grouped +DEPENDPATH += . +INCLUDEPATH += . +QT += declarative + +# Input +SOURCES += main.cpp \ + person.cpp \ + birthdayparty.cpp +HEADERS += person.h \ + birthdayparty.h +RESOURCES += grouped.qrc diff --git a/examples/declarative/extending/grouped/grouped.qrc b/examples/declarative/extending/grouped/grouped.qrc new file mode 100644 index 0000000..e2fa01d --- /dev/null +++ b/examples/declarative/extending/grouped/grouped.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>example.qml</file> +</qresource> +</RCC> diff --git a/examples/declarative/extending/grouped/main.cpp b/examples/declarative/extending/grouped/main.cpp new file mode 100644 index 0000000..0c9bb97 --- /dev/null +++ b/examples/declarative/extending/grouped/main.cpp @@ -0,0 +1,40 @@ +#include <QCoreApplication> +#include <QmlEngine> +#include <QmlComponent> +#include <QDebug> +#include "birthdayparty.h" +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QmlEngine engine; + QmlComponent component(&engine, QUrl::fromLocalFile(":example.qml")); + BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create()); + + if (party && party->celebrant()) { + qWarning() << party->celebrant()->name() << "is having a birthday!"; + + if (qobject_cast<Boy *>(party->celebrant())) + qWarning() << "He is inviting:"; + else + qWarning() << "She is inviting:"; + + Person *bestShoe = 0; + for (int ii = 0; ii < party->guests()->count(); ++ii) { + Person *guest = party->guests()->at(ii); + qWarning() << " " << guest->name(); + + if (!bestShoe || bestShoe->shoe()->price() < guest->shoe()->price()) + bestShoe = guest; + } + if (bestShoe) + qWarning() << bestShoe->name() << "is wearing the best shoes!"; + + } else { + qWarning() << "An error occured"; + } + + return 0; +} diff --git a/examples/declarative/extending/grouped/person.cpp b/examples/declarative/extending/grouped/person.cpp new file mode 100644 index 0000000..48a94e8 --- /dev/null +++ b/examples/declarative/extending/grouped/person.cpp @@ -0,0 +1,83 @@ +#include "person.h" + +ShoeDescription::ShoeDescription(QObject *parent) +: QObject(parent), m_size(0), m_price(0) +{ +} + +int ShoeDescription::size() const +{ + return m_size; +} + +void ShoeDescription::setSize(int s) +{ + m_size = s; +} + +QColor ShoeDescription::color() const +{ + return m_color; +} + +void ShoeDescription::setColor(const QColor &c) +{ + m_color = c; +} + +QString ShoeDescription::brand() const +{ + return m_brand; +} + +void ShoeDescription::setBrand(const QString &b) +{ + m_brand = b; +} + +qreal ShoeDescription::price() const +{ + return m_price; +} + +void ShoeDescription::setPrice(qreal p) +{ + m_price = p; +} +QML_DEFINE_NOCREATE_TYPE(ShoeDescription); + +Person::Person(QObject *parent) +: QObject(parent) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +ShoeDescription *Person::shoe() +{ + return &m_shoe; +} + +QML_DEFINE_NOCREATE_TYPE(Person); + +Boy::Boy(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Boy, Boy); + +Girl::Girl(QObject * parent) +: Person(parent) +{ +} + +QML_DEFINE_TYPE(Girl, Girl); diff --git a/examples/declarative/extending/grouped/person.h b/examples/declarative/extending/grouped/person.h new file mode 100644 index 0000000..b83eb5b --- /dev/null +++ b/examples/declarative/extending/grouped/person.h @@ -0,0 +1,69 @@ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +#include <QColor> +#include <qml.h> + +class ShoeDescription : public QObject { +Q_OBJECT +Q_PROPERTY(int size READ size WRITE setSize) +Q_PROPERTY(QColor color READ color WRITE setColor) +Q_PROPERTY(QString brand READ brand WRITE setBrand) +Q_PROPERTY(qreal price READ price WRITE setPrice) +public: + ShoeDescription(QObject *parent = 0); + + int size() const; + void setSize(int); + + QColor color() const; + void setColor(const QColor &); + + QString brand() const; + void setBrand(const QString &); + + qreal price() const; + void setPrice(qreal); +private: + int m_size; + QColor m_color; + QString m_brand; + qreal m_price; +}; +QML_DECLARE_TYPE(ShoeDescription); + +class Person : public QObject { +Q_OBJECT +Q_PROPERTY(QString name READ name WRITE setName) +// ![1] +Q_PROPERTY(ShoeDescription *shoe READ shoe); +// ![1] +public: + Person(QObject *parent = 0); + + QString name() const; + void setName(const QString &); + + ShoeDescription *shoe(); +private: + QString m_name; + ShoeDescription m_shoe; +}; +QML_DECLARE_TYPE(Person); + +class Boy : public Person { +Q_OBJECT +public: + Boy(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Boy); + +class Girl : public Person { +Q_OBJECT +public: + Girl(QObject * parent = 0); +}; +QML_DECLARE_TYPE(Girl); + +#endif // PERSON_H diff --git a/examples/declarative/extending/properties/example.qml b/examples/declarative/extending/properties/example.qml new file mode 100644 index 0000000..63bb77b --- /dev/null +++ b/examples/declarative/extending/properties/example.qml @@ -0,0 +1,13 @@ +// ![0] +BirthdayParty { + celebrant: Person { + name: "Bob Jones" + shoeSize: 12 + } + guests: [ + Person { name: "Joan Hodges" }, + Person { name: "Jack Smith" }, + Person { name: "Anne Brown" } + ] +} +// ![0] diff --git a/examples/declarative/extending/properties/main.cpp b/examples/declarative/extending/properties/main.cpp new file mode 100644 index 0000000..7b80914 --- /dev/null +++ b/examples/declarative/extending/properties/main.cpp @@ -0,0 +1,26 @@ +#include <QCoreApplication> +#include <QmlEngine> +#include <QmlComponent> +#include <QDebug> +#include "birthdayparty.h" +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QmlEngine engine; + QmlComponent component(&engine, QUrl::fromLocalFile(":example.qml")); + BirthdayParty *party = qobject_cast<BirthdayParty *>(component.create()); + + if (party && party->celebrant()) { + qWarning() << party->celebrant()->name() << "is having a birthday!"; + qWarning() << "They are inviting:"; + for (int ii = 0; ii < party->guests()->count(); ++ii) + qWarning() << " " << party->guests()->at(ii)->name(); + } else { + qWarning() << "An error occured"; + } + + return 0; +} diff --git a/examples/declarative/extending/properties/person.cpp b/examples/declarative/extending/properties/person.cpp new file mode 100644 index 0000000..cf66a30 --- /dev/null +++ b/examples/declarative/extending/properties/person.cpp @@ -0,0 +1,28 @@ +#include "person.h" + +Person::Person(QObject *parent) +: QObject(parent), m_shoeSize(0) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +int Person::shoeSize() const +{ + return m_shoeSize; +} + +void Person::setShoeSize(int s) +{ + m_shoeSize = s; +} + +QML_DEFINE_TYPE(Person, Person); diff --git a/examples/declarative/extending/properties/person.h b/examples/declarative/extending/properties/person.h new file mode 100644 index 0000000..2bc98c1 --- /dev/null +++ b/examples/declarative/extending/properties/person.h @@ -0,0 +1,25 @@ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +#include <qml.h> + +class Person : public QObject { +Q_OBJECT +Q_PROPERTY(QString name READ name WRITE setName) +Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) +public: + Person(QObject *parent = 0); + + QString name() const; + void setName(const QString &); + + int shoeSize() const; + void setShoeSize(int); +private: + QString m_name; + int m_shoeSize; +}; +QML_DECLARE_TYPE(Person); + +#endif // PERSON_H diff --git a/examples/declarative/extending/properties/properties.pro b/examples/declarative/extending/properties/properties.pro new file mode 100644 index 0000000..6355644 --- /dev/null +++ b/examples/declarative/extending/properties/properties.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = properties +DEPENDPATH += . +INCLUDEPATH += . +QT += declarative + +# Input +SOURCES += main.cpp \ + person.cpp \ + birthdayparty.cpp +HEADERS += person.h \ + birthdayparty.h +RESOURCES += properties.qrc diff --git a/examples/declarative/extending/properties/properties.qrc b/examples/declarative/extending/properties/properties.qrc new file mode 100644 index 0000000..e2fa01d --- /dev/null +++ b/examples/declarative/extending/properties/properties.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>example.qml</file> +</qresource> +</RCC> diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h index 1990b7f..cd01f6a 100644 --- a/src/declarative/qml/qml.h +++ b/src/declarative/qml/qml.h @@ -93,10 +93,10 @@ class QmlEngine; Q_DECLARATIVE_EXPORT void qmlExecuteDeferred(QObject *); Q_DECLARATIVE_EXPORT QmlContext *qmlContext(const QObject *); Q_DECLARATIVE_EXPORT QmlEngine *qmlEngine(const QObject *); -Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *); +Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true); template<typename T> -QObject *qmlAttachedPropertiesObject(const QObject *obj) +QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true) { // ### is this threadsafe? static int idx = -1; @@ -107,7 +107,7 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj) if (idx == -1 || !obj) return 0; - return qmlAttachedPropertiesObjectById(idx, obj); + return qmlAttachedPropertiesObjectById(idx, obj, create); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 9eb169e..01a0494 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -707,13 +707,13 @@ QmlEngine *qmlEngine(const QObject *obj) return context?context->engine():0; } -QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object) +QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create) { QmlExtendedDeclarativeData *edata = QmlExtendedDeclarativeData::get(const_cast<QObject *>(object), true); QObject *rv = edata->attachedProperties.value(id); - if (rv) + if (rv || !create) return rv; QmlAttachedPropertiesFunc pf = QmlMetaType::attachedPropertiesFuncById(id); |