diff options
author | Bea Lam <bea.lam@nokia.com> | 2010-07-15 05:29:20 (GMT) |
---|---|---|
committer | Bea Lam <bea.lam@nokia.com> | 2010-07-15 05:41:07 (GMT) |
commit | 7d0b62158471d46db9902ce0d0d7b7244c743cce (patch) | |
tree | 8fc9d4d9ba0df2842d0974a1929c9e63754a89b7 | |
parent | fb8869e00da635be7660d845d4cb631d230bed6e (diff) | |
download | Qt-7d0b62158471d46db9902ce0d0d7b7244c743cce.zip Qt-7d0b62158471d46db9902ce0d0d7b7244c743cce.tar.gz Qt-7d0b62158471d46db9902ce0d0d7b7244c743cce.tar.bz2 |
Add chapter on creating list property types
15 files changed, 136 insertions, 51 deletions
diff --git a/doc/src/declarative/extending-tutorial.qdoc b/doc/src/declarative/extending-tutorial.qdoc index 9170c5c..cc93e86 100644 --- a/doc/src/declarative/extending-tutorial.qdoc +++ b/doc/src/declarative/extending-tutorial.qdoc @@ -48,8 +48,9 @@ Tutorial chapters: \o \l{declarative/tutorials/extending/chapter2-methods}{Connecting to C++ Methods and Signals} \o \l{declarative/tutorials/extending/chapter3-bindings}{Adding Property Bindings} \o \l{declarative/tutorials/extending/chapter4-customPropertyTypes}{Using Custom Property Types} -\o \l{declarative/tutorials/extending/chapter5-plugins}{Writing an Extension Plugin} -\o \l{qml-extending-tutorial6.html}{In Summary} +\o \l{declarative/tutorials/extending/chapter5-listproperties}{Using List Property Types} +\o \l{declarative/tutorials/extending/chapter6-plugins}{Writing an Extension Plugin} +\o \l{qml-extending-tutorial7.html}{In Summary} \endlist */ @@ -339,15 +340,65 @@ Try it out with the code in Qt's \c examples/tutorials/extending/chapter4-custom */ + +/*! +\title Chapter 5: Using List Property Types + +\example declarative/tutorials/extending/chapter5-listproperties + +Right now, a \c PieChart can only have one \c PieSlice. Ideally a chart would +have multiple slices, with different colors and sizes. To do this, we could +have a \c slices property that accepts a list of \c PieSlice items: + +\snippet declarative/tutorials/extending/chapter5-listproperties/app.qml 0 + +\image extending-tutorial-chapter5.png + +To do this, we replace the \c pieSlice property in \c PieChart with a \c slices property, +declared as a QDeclarativeListProperty type. The QDeclarativeListProperty class enables the +creation of list properties in QML extensions. We replace the \c pieSlice() +function with a \c slices() function that returns a list of slices, and add +an internal \c append_slice() function (discussed below). We also use a QList to +store the internal list of slices as \c m_slices: + +\snippet declarative/tutorials/extending/chapter5-listproperties/piechart.h 0 +\dots +\snippet declarative/tutorials/extending/chapter5-listproperties/piechart.h 1 +\dots +\snippet declarative/tutorials/extending/chapter5-listproperties/piechart.h 2 + +Although the \c slices property does not have an associated \c WRITE function, +it is still modifiable because of the way QDeclarativeListProperty works. +In the \c PieChart implementation, we implement \c PieChart::slices() to +return a QDeclarativeListProperty value and indicate that the internal +\c PieChart::append_slice() function is to be called whenever a request is made from QML +to add items to the list: + +\snippet declarative/tutorials/extending/chapter5-listproperties/piechart.cpp 0 + +The \c append_slice() function simply sets the parent item as before, +and adds the new item to the \c m_slices list. As you can see, the append function for a +QDeclarativeListProperty is called with two arguments: the list property, and +the item that is to be appended. + +The \c PieSlice class has also been modified to include \c fromAngle and \c angleSpan +properties and to draw the slice according to these values. This is a straightforward +modification if you have read the previous pages in this tutorial, so the code is not shown here. + +The complete code can be seen in the updated \c examples/tutorials/extending/chapter5-listproperties directory. + +*/ + + /*! -\title Chapter 5: Writing an Extension Plugin +\title Chapter 6: Writing an Extension Plugin -\example declarative/tutorials/extending/chapter5-plugins +\example declarative/tutorials/extending/chapter6-plugins Currently the \c PieChart and \c PieSlice types are used by \c app.qml, which is displayed using a QDeclarativeView in a C++ application. An alternative way to use our QML extension is to create a plugin library to make it available -to the QML engine. This allows us to load \c app.qml using the \l {QML Viewer} +to the QML engine. This allows \c app.qml to be loaded with the \l {QML Viewer} (or some other QML \l{Qt Declarative UI Runtime}{runtime} application) instead of writing a \c main.cpp file and loading our own C++ application. @@ -365,22 +416,22 @@ Q_EXPORT_PLUGIN2 for Qt's \l{How to Create Qt Plugins}{plugin system}. Here is the \c ChartsPlugin definition in \c chartsplugin.h: -\snippet declarative/tutorials/extending/chapter5-plugins/chartsplugin.h 0 +\snippet declarative/tutorials/extending/chapter6-plugins/chartsplugin.h 0 And its implementation in \c chartsplugin.cpp: -\snippet declarative/tutorials/extending/chapter5-plugins/chartsplugin.cpp 0 +\snippet declarative/tutorials/extending/chapter6-plugins/chartsplugin.cpp 0 Then, we write a \c .pro project file that defines the project as a plugin library and specifies with DESTDIR that library files should be built into a "lib" subdirectory: -\quotefile declarative/tutorials/extending/chapter5-plugins/chapter5-plugins.pro +\quotefile declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro Finally, we add a \c qmldir file that is automatically parsed by the QML engine. -Here, we specify that a plugin named "chapter5-plugin" (the name +Here, we specify that a plugin named "chapter6-plugin" (the name of the example project) can be found in the "lib" subdirectory: -\quotefile declarative/tutorials/extending/chapter5-plugins/qmldir +\quotefile declarative/tutorials/extending/chapter6-plugins/qmldir Now we have a plugin, and instead of having a main.cpp and an executable, we can build the project and then load the QML file in the \l {QML Viewer}: @@ -397,9 +448,10 @@ having PieChart.qml and PieSlice.qml files inside the project directory, which c be used by \c app.qml without import statements. */ + /*! -\page qml-extending-tutorial6.html -\title Chapter 6: In Summary +\page qml-extending-tutorial7.html +\title Chapter 7: In Summary In this tutorial, we've shown the basic steps for creating a QML extension: @@ -408,39 +460,28 @@ In this tutorial, we've shown the basic steps for creating a QML extension: \o Add callable methods using Q_INVOKABLE or Qt slots, and connect to Qt signals with an \c onSignal syntax \o Add property bindings by defining \l{Qt's Property System}{NOTIFY} signals \o Define custom property types if the built-in types are not sufficient +\o Define list property types using QDeclarativeListProperty \o Create a plugin library by defining a Qt plugin and writing a \c qmldir file \endlist The \l {Extending QML in C++} reference documentation shows other useful features that can be added to -QML extensions. For example, we could use \l{Object and List Property Types}{list properties} to allow multiple slices for a \c PieChart: - -\code - PieChart { - slices: [ - PieSlice { color: "red" } - PieSlice { color: "blue" } - PieSlice { color: "yellow" } - ] - } -\endcode - -Or use \l{Default Property}{default properties} and avoid an -\c slices property altogether: +QML extensions. For example, we could use \l{Default Property}{default properties} to allow +slices to be added without using the \c slices property: \code PieChart { - PieSlice { color: "red" } - PieSlice { color: "blue" } - PieSlice { color: "yellow" } + PieSlice { ... } + PieSlice { ... } + PieSlice { ... } } \endcode -Or even change the \c color of a \c PieChart from time to time using \l{Property Value Sources}{property value sources}: +Or randomly add and remove slices from time to time using \l{Property Value Sources}{property value sources}: \code PieChart { - PieSliceRandomizer on color {} + PieSliceRandomizer on slices {} } \endcode diff --git a/doc/src/declarative/pics/extending-tutorial-chapter1.png b/doc/src/declarative/pics/extending-tutorial-chapter1.png Binary files differnew file mode 100644 index 0000000..9f5836b --- /dev/null +++ b/doc/src/declarative/pics/extending-tutorial-chapter1.png diff --git a/doc/src/declarative/pics/extending-tutorial-chapter2.png b/doc/src/declarative/pics/extending-tutorial-chapter2.png Binary files differnew file mode 100644 index 0000000..5c8f222 --- /dev/null +++ b/doc/src/declarative/pics/extending-tutorial-chapter2.png diff --git a/doc/src/declarative/pics/extending-tutorial-chapter3.png b/doc/src/declarative/pics/extending-tutorial-chapter3.png Binary files differnew file mode 100644 index 0000000..825553f --- /dev/null +++ b/doc/src/declarative/pics/extending-tutorial-chapter3.png diff --git a/doc/src/declarative/pics/extending-tutorial-chapter5.png b/doc/src/declarative/pics/extending-tutorial-chapter5.png Binary files differnew file mode 100644 index 0000000..0c2e69e --- /dev/null +++ b/doc/src/declarative/pics/extending-tutorial-chapter5.png diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/qmldir b/examples/declarative/tutorials/extending/chapter5-plugins/qmldir deleted file mode 100644 index c3afd6b..0000000 --- a/examples/declarative/tutorials/extending/chapter5-plugins/qmldir +++ /dev/null @@ -1 +0,0 @@ -plugin chapter5-plugins lib diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/app.qml b/examples/declarative/tutorials/extending/chapter6-plugins/app.qml index b06e399..38ceefa 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/app.qml +++ b/examples/declarative/tutorials/extending/chapter6-plugins/app.qml @@ -37,23 +37,32 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - import Qt 4.7 Item { width: 300; height: 200 PieChart { - id: chart anchors.centerIn: parent width: 100; height: 100 - pieSlice: PieSlice { - anchors.fill: parent - color: "red" - } + slices: [ + PieSlice { + anchors.fill: parent + color: "red" + fromAngle: 0; angleSpan: 110 + }, + PieSlice { + anchors.fill: parent + color: "black" + fromAngle: 110; angleSpan: 50 + }, + PieSlice { + anchors.fill: parent + color: "blue" + fromAngle: 160; angleSpan: 100 + } + ] } - - Component.onCompleted: console.log("The pie is colored " + chart.pieSlice.color) } diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/chapter5-plugins.pro b/examples/declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro index 1ffbf29..1ffbf29 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/chapter5-plugins.pro +++ b/examples/declarative/tutorials/extending/chapter6-plugins/chapter6-plugins.pro diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/chartsplugin.cpp b/examples/declarative/tutorials/extending/chapter6-plugins/chartsplugin.cpp index 5aa2a4b..5aa2a4b 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/chartsplugin.cpp +++ b/examples/declarative/tutorials/extending/chapter6-plugins/chartsplugin.cpp diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/chartsplugin.h b/examples/declarative/tutorials/extending/chapter6-plugins/chartsplugin.h index 797d1e7..797d1e7 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/chartsplugin.h +++ b/examples/declarative/tutorials/extending/chapter6-plugins/chartsplugin.h diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/piechart.cpp b/examples/declarative/tutorials/extending/chapter6-plugins/piechart.cpp index 2d7acf7..4e6ee5c 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/piechart.cpp +++ b/examples/declarative/tutorials/extending/chapter6-plugins/piechart.cpp @@ -55,14 +55,17 @@ void PieChart::setName(const QString &name) m_name = name; } -PieSlice *PieChart::pieSlice() const +QDeclarativeListProperty<PieSlice> PieChart::slices() { - return m_pieSlice; + return QDeclarativeListProperty<PieSlice>(this, 0, &PieChart::append_slice); } -void PieChart::setPieSlice(PieSlice *pieSlice) +void PieChart::append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice) { - m_pieSlice = pieSlice; - m_pieSlice->setParentItem(this); + PieChart *chart = qobject_cast<PieChart *>(list->object); + if (chart) { + slice->setParentItem(chart); + chart->m_slices.append(slice); + } } diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/piechart.h b/examples/declarative/tutorials/extending/chapter6-plugins/piechart.h index a8b5b6e..d6e4439 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/piechart.h +++ b/examples/declarative/tutorials/extending/chapter6-plugins/piechart.h @@ -47,8 +47,8 @@ class PieSlice; class PieChart : public QDeclarativeItem { Q_OBJECT + Q_PROPERTY(QDeclarativeListProperty<PieSlice> slices READ slices) Q_PROPERTY(QString name READ name WRITE setName) - Q_PROPERTY(PieSlice* pieSlice READ pieSlice WRITE setPieSlice) public: PieChart(QDeclarativeItem *parent = 0); @@ -56,12 +56,13 @@ public: QString name() const; void setName(const QString &name); - PieSlice *pieSlice() const; - void setPieSlice(PieSlice *pieSlice); + QDeclarativeListProperty<PieSlice> slices(); private: + static void append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice); + QString m_name; - PieSlice *m_pieSlice; + QList<PieSlice *> m_slices; }; #endif diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/pieslice.cpp b/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.cpp index a312da3..65120f5 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/pieslice.cpp +++ b/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.cpp @@ -58,10 +58,31 @@ void PieSlice::setColor(const QColor &color) m_color = color; } +int PieSlice::fromAngle() const +{ + return m_fromAngle; +} + +void PieSlice::setFromAngle(int angle) +{ + m_fromAngle = angle; +} + +int PieSlice::angleSpan() const +{ + return m_angleSpan; +} + +void PieSlice::setAngleSpan(int angle) +{ + m_angleSpan = angle; +} + void PieSlice::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { QPen pen(m_color, 2); painter->setPen(pen); painter->setRenderHints(QPainter::Antialiasing, true); - painter->drawPie(boundingRect(), 90 * 16, 290 * 16); + painter->drawPie(boundingRect(), m_fromAngle * 16, m_angleSpan * 16); } + diff --git a/examples/declarative/tutorials/extending/chapter5-plugins/pieslice.h b/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.h index 6774731..a3afd25 100644 --- a/examples/declarative/tutorials/extending/chapter5-plugins/pieslice.h +++ b/examples/declarative/tutorials/extending/chapter6-plugins/pieslice.h @@ -47,17 +47,27 @@ class PieSlice : public QDeclarativeItem { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor) + Q_PROPERTY(int fromAngle READ fromAngle WRITE setFromAngle) + Q_PROPERTY(int angleSpan READ angleSpan WRITE setAngleSpan) public: PieSlice(QDeclarativeItem *parent = 0); QColor color() const; - void setColor(const QColor &QColor); + void setColor(const QColor &color); + + int fromAngle() const; + void setFromAngle(int angle); + + int angleSpan() const; + void setAngleSpan(int span); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); private: QColor m_color; + int m_fromAngle; + int m_angleSpan; }; #endif diff --git a/examples/declarative/tutorials/extending/chapter6-plugins/qmldir b/examples/declarative/tutorials/extending/chapter6-plugins/qmldir new file mode 100644 index 0000000..a83bf85 --- /dev/null +++ b/examples/declarative/tutorials/extending/chapter6-plugins/qmldir @@ -0,0 +1 @@ +plugin chapter6-plugins lib |