From 57a3d4250ea438b2607d7f62ef26b8b83eb0f66c Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 6 Jan 2011 11:16:49 +1000 Subject: Doc fixes for introduction page and Item docs Moved 'Identity' and 'Property Change Signals' sections from Item docs to the intro page, which previously had a section on ids but this has been moved out of the 'Properties' section since an id isn't an ordinary property. --- doc/src/declarative/qdeclarativeintro.qdoc | 213 +++++++++++++-------- src/declarative/graphicsitems/qdeclarativeitem.cpp | 28 --- 2 files changed, 130 insertions(+), 111 deletions(-) diff --git a/doc/src/declarative/qdeclarativeintro.qdoc b/doc/src/declarative/qdeclarativeintro.qdoc index 4e41fda..20db248 100644 --- a/doc/src/declarative/qdeclarativeintro.qdoc +++ b/doc/src/declarative/qdeclarativeintro.qdoc @@ -37,7 +37,7 @@ interface is specified as a tree of objects with properties. This introduction is meant for those with little or no programming experience. JavaScript is used as a scripting language in QML, so you may want -to learn a bit more about it (\l{Javascript Guide}) before diving +to learn a bit more about it (see the \l{Javascript Guide}) before diving deeper into QML. It's also helpful to have a basic understanding of other web technologies like HTML and CSS, but it's not required. @@ -60,13 +60,13 @@ Rectangle { } \endcode -Objects are specified by their type, followed by a pair of braces. Object -types always begin with a capital letter. In the above example, there are -two objects, a \l Rectangle, and an \l Image. Between the braces, we can specify -information about the object, such as its properties. +Here we create two objects, a \l Rectangle object and its child +\l Image object. Objects are specified by their type, followed by a pair of +braces in between which additional data can be defined for the object, such as +its property values and any child objects. -Properties are specified as \c {property: value}. In the above example, we -can see the Image has a property named \c source, which has been assigned the +Properties are specified with a \c {property: value} syntax. In the above example, we +can see the \l Image object has a property named \c source, which has been assigned the value \c "pics/logo.png". The property and its value are separated by a colon. Properties can be specified one-per-line: @@ -87,45 +87,13 @@ Rectangle { width: 100; height: 100 } When multiple property/value pairs are specified on a single line, they must be separated by a semicolon. -The \c import statement imports the \c Qt \l{QML Modules}{module}, which contains all of the +The \c import statement imports the \c QtQuick \l{QML Modules}{module}, which contains all of the standard \l {QML Elements}. Without this import statement, the \l Rectangle and \l Image elements would not be available. -\section1 Expressions - -In addition to assigning values to properties, you can also assign -expressions written in JavaScript. - -\code -Rotation { - angle: 360 * 3 -} -\endcode - -These expressions can include references to other objects and properties, in which case -a \e binding is established: when the value of the expression changes, the property the -expression has been assigned to is automatically updated to that value. - -\code -Item { - Text { - id: text1 - text: "Hello World" - } - Text { - id: text2 - text: text1.text - } -} -\endcode - -In the example above, the \c text2 object will display the same text as \c text1. If \c text1 is changed, -\c text2 is automatically changed to the same value. -Note that to refer to other objects, we use their \e id values. (See below for more -information on the \e id property.) -\section1 QML Comments +\section1 Comments Commenting in QML is similar to JavaScript. \list @@ -149,27 +117,95 @@ Text { } \endcode -In the above example, the Text object will have normal opacity, since the +In the above example, the \l Text object will have normal opacity, since the line opacity: 0.5 has been turned into a comment. -\section1 Properties -\target intro-properties -\section2 Property naming -Properties begin with a lowercase letter (with the exception of \l{Attached Properties}). +\section1 Object identifiers + +Each object can be given a special \e id value that allows the object to be identified +and referred to by other objects. + +For example, below we have two \l Text objects. The first \l Text object +has an \c id value of "text1". The second \l Text object can now set its own +\c text property value to be the same as that of the first object, by referring to +\c text1.text: + +\qml +import QtQuick 1.0 + +Row { + Text { + id: text1 + text: "Hello World" + } + + Text { text: text1.text } +} +\endqml + +An object can be referred to by its \c id from anywhere within the \l {QML Documents}{component} +in which it is declared. Therefore, an \c id value must always be unique within a single component. + +The \c id value is a special value for a QML object and should not be thought of as an +ordinary object property; for example, it is not possible to access \c text1.id in the +above example. Once an object is created, its \c id cannot be changed. + +Note that an \c id must begin with a lower-case letter or an underscore, and cannot contain +characters other than letters, numbers and underscores. + + + +\section1 Expressions + +JavaScript expressions can be used to assign property values. For example: + +\code +Item { + width: 100 * 3 + height: 50 + 22 +} +\endcode + +These expressions can include references to other objects and properties, in which case +a \l{Property Binding}{binding} is established: when the value of the expression changes, +the property to which the expression is assigned is automatically updated to the +new value. For example: + +\code +Item { + width: 300 + height: 300 + + Rectangle { + width: parent.width - 50 + height: 100 + color: "yellow" + } +} +\endcode + +Here, the \l Rectangle object's \c width property is set relative to the width +of its parent. Whenever the parent's width changes, the width of the \l Rectangle is +automatically updated. -\section2 Property types -QML supports properties of many types (see \l{QML Basic Types}). The basic types include int, -real, bool, string, color, and lists. + +\section1 Properties +\target intro-properties + +\section2 Basic property types + +QML supports properties of many types (see \l{QML Basic Types}). The basic types include \c int, +\c real, \c bool, \c string and \c color. \code Item { x: 10.5 // a 'real' property - ... state: "details" // a 'string' property focus: true // a 'bool' property + ... } \endcode @@ -183,31 +219,30 @@ Item { } \endcode -\section3 The \c id property +Note that with the exception of \l {Attached Properties}, properties always begin with a lowercase +letter. -Each object can be given a special unique property called an \e id. No other object within the -same QML component (see \l{QML Documents}) can have the same \c id value. Assigning an id enables the object -to be referred to by other objects and scripts. -The first Rectangle element below has an \e id, "myRect". The second Rectangle element defines its -own width by referring to \tt myRect.width, which means it will have the same \tt width -value as the first Rectangle element. +\section2 Property change notifications -\code -Item { - Rectangle { - id: myRect - width: 100 - height: 100 - } - Rectangle { - width: myRect.width - height: 200 - } +When a property changes value, it can send a signal to notify others of this change. + +To receive these signals, simply create a \e {signal handler} named with an \c onChanged +syntax. For example, the \l Rectangle element has \l {Item::}{width} and \l {Rectangle::}{color} +properties. Below, we have a \l Rectangle object that has defined two signal handlers, +\c onWidthChanged and \c onColorChanged, which will automaticallly be called whenever these +properties are modified: + +\qml +Rectangle { + width: 100; height: 100 + + onWidthChanged: console.log("Width has changed to:", width) + onColorChanged: console.log("Color has changed to:", color) } -\endcode +\endqml -Note that an \e id must begin with a lower-case letter or an underscore, and cannot contain characters other than letters, numbers and underscores. +Signal handlers are explained further \l {Signal Handlers}{below}. \section2 List properties @@ -293,7 +328,9 @@ Some objects attach properties to another object. Attached Properties are of the form \e {Type.property} where \e Type is the type of the element that attaches \e property. -For example: +For example, the \l ListView element attaches the \e ListView.isCurrentItem property +to each delegate it creates: + \code Component { id: myDelegate @@ -307,9 +344,6 @@ ListView { } \endcode -The \l ListView element attaches the \e ListView.isCurrentItem property -to each delegate it creates. - Another example of attached properties is the \l Keys element which attaches properties for handling key presses to any visual Item, for example: @@ -321,27 +355,40 @@ Item { } \endcode -\section2 Signal Handlers +\section1 Signal Handlers -Signal handlers allow actions to be taken in response to an event. For instance, -the \l MouseArea element has signal handlers to handle mouse press, release -and click: +Signal handlers allow JavaScript code to be executed in response to an event. For +example, the \l MouseArea element has an \l {MouseArea::}{onClicked} handler that can +be used to respond to a mouse click. Below, we use this handler to print a +message whenever the mouse is clicked: \code -MouseArea { - onPressed: console.log("mouse button pressed") +Item { + width: 100; height: 100 + + MouseArea { + anchors.fill: parent + onClicked: { + console.log("mouse button clicked") + } + } } \endcode All signal handlers begin with \e "on". -Some signal handlers include an optional parameter, for example -the MouseArea onPressed signal handler has a \e mouse parameter: +Some signal handlers include an optional parameter. For example +the MouseArea \l{MouseArea::}{onPressed} signal handler has a \c mouse parameter +that contains information about the mouse press. This parameter can be referred to in +the JavaScript code, as below: \code MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton - onPressed: if (mouse.button == Qt.RightButton) console.log("Right mouse button pressed") + onPressed: { + if (mouse.button == Qt.RightButton) + console.log("Right mouse button pressed") + } } \endcode diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 24d9b03..922fa8f 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -1333,23 +1333,6 @@ QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObjec } \endqml - \section1 Identity - - Each item has an "id" - the identifier of the Item. - - The identifier can be used in bindings and other expressions to - refer to the item. For example: - - \qml - Text { id: myText; ... } - Text { text: myText.text } - \endqml - - The identifier is available throughout to the \l {components}{component} - where it is declared. The identifier must be unique in the component. - - The id should not be thought of as a "property" - it makes no sense - to write \c myText.id, for example. \section1 Key Handling @@ -1376,17 +1359,6 @@ QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObjec \endqml See the \l {Keys}{Keys} attached property for detailed documentation. - - \section1 Property Change Signals - - Most properties on Item and Item derivatives have a signal - emitted when they change. By convention, the signals are - named Changed, e.g. xChanged will be emitted when an item's - x property changes. Note that these also have signal handers e.g. - the onXChanged signal handler will be called when an item's x property - changes. For many properties in Item or Item derivatives this can be used - to add a touch of imperative logic to your application (when absolutely - necessary). */ /*! -- cgit v0.12 From 1d7b672fd46abab51a0124ad19aad18e5d14f1a8 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 6 Jan 2011 14:10:35 +1000 Subject: Update docs - calling overloaded functions from QML is now supported --- doc/src/declarative/qtbinding.qdoc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/src/declarative/qtbinding.qdoc b/doc/src/declarative/qtbinding.qdoc index 04b8ca6..8ee7247 100644 --- a/doc/src/declarative/qtbinding.qdoc +++ b/doc/src/declarative/qtbinding.qdoc @@ -96,7 +96,7 @@ There are a number of ways to extend your QML application through C++. For examp \list \o Load a QML component and manipulate it (or its children) from C++ \o Embed a C++ object and its properties directly into a QML component (for example, to make a -particular C++ object callable from QML, or to replace a dummy list model data with a real data set) +particular C++ object callable from QML, or to replace a dummy list model with a real data set) \o Define new QML elements (through QObject-based C++ classes) and create them directly from your QML code \endlist @@ -297,17 +297,20 @@ methods on the \c myObject object, which has been set using QDeclarativeContext: \snippet doc/src/snippets/declarative/qtbinding/functions-cpp/main.cpp 0 \endtable -Note that QML does not support overloaded functions. If a C++ has more than one function with the -same name, there is no guarantee which overloaded function will be called from QML. +QML supports the calling of overloaded C++ functions. If there are multiple C++ functions with the +same name but different arguments, the correct function will be called according to the number and +the types of arguments that are provided. \section2 Receiving signals All QML signals are automatically available to C++, and can be connected to using QObject::connect() -like any ordinary Qt C++ signal. +like any ordinary Qt C++ signal. In return, any C++ signal can be received by a QML object using +\l {Signal Handlers}{signal handlers}. Here is a QML component with a signal named \c qmlSignal. This signal is connected to a C++ object's -slot using QObject::connect(): +slot using QObject::connect(), so that the \c cppSlot() method is called whenever the \c qmlSignal +is emitted: \table \row -- cgit v0.12 From 1ba3e41f09ea719249286fede5d3fe96621ccb61 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 6 Jan 2011 15:48:52 +1000 Subject: PathView: update modelCount before attempting to regenerate delegates. If the model is a VisualDataModel, the count will initally be zero and modelCount is not updated due to itemsInserted() before the component is completed. Task-number: QTBUG-16357 Reviewed-by: Bea Lam --- .../graphicsitems/qdeclarativepathview.cpp | 4 +++- .../declarative/qdeclarativepathview/data/vdm.qml | 28 ++++++++++++++++++++++ .../tst_qdeclarativepathview.cpp | 14 +++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativepathview/data/vdm.qml diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index e3987d0..74d3418 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -1318,8 +1318,10 @@ void QDeclarativePathView::componentComplete() // It is possible that a refill has already happended to to Path // bindings being handled in the componentComplete(). If so // don't do it again. - if (d->items.count() == 0) + if (d->items.count() == 0 && d->model) { + d->modelCount = d->model->count(); d->regenerate(); + } d->updateHighlight(); } diff --git a/tests/auto/declarative/qdeclarativepathview/data/vdm.qml b/tests/auto/declarative/qdeclarativepathview/data/vdm.qml new file mode 100644 index 0000000..012db3f --- /dev/null +++ b/tests/auto/declarative/qdeclarativepathview/data/vdm.qml @@ -0,0 +1,28 @@ +import QtQuick 1.0 + +PathView { + id: pathView + width: 240; height: 320 + + pathItemCount: 4 + preferredHighlightBegin : 0.5 + preferredHighlightEnd : 0.5 + + path: Path { + startX: 120; startY: 20; + PathLine { x: 120; y: 300 } + } + + ListModel { + id: mo + ListElement { value: "one" } + ListElement { value: "two" } + ListElement { value: "three" } + } + + model: VisualDataModel { + delegate: Text { text: model.value } + model : mo + } +} + diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index 9193707..90b1056 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -87,6 +87,7 @@ private slots: void emptyModel(); void closed(); void pathUpdate(); + void visualDataModel(); private: QDeclarativeView *createView(); @@ -839,6 +840,19 @@ void tst_QDeclarativePathView::pathUpdate() delete canvas; } +void tst_QDeclarativePathView::visualDataModel() +{ + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/vdm.qml")); + + QDeclarativePathView *obj = qobject_cast(c.create()); + QVERIFY(obj != 0); + + QCOMPARE(obj->count(), 3); + + delete obj; +} + QDeclarativeView *tst_QDeclarativePathView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); -- cgit v0.12 From 05b9137fe1974aa123ce6d9c16b733e1f77d8269 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 6 Jan 2011 16:57:06 +1000 Subject: PathView crashed when the path is provided with undefined values. Task-number: QTBUG-16356 Reviewed-by: Bea Lam --- src/declarative/graphicsitems/qdeclarativepath.cpp | 8 +++++++- .../qdeclarativepathview/data/undefinedpath.qml | 17 +++++++++++++++++ .../qdeclarativepathview/tst_qdeclarativepathview.cpp | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativepathview/data/undefinedpath.qml diff --git a/src/declarative/graphicsitems/qdeclarativepath.cpp b/src/declarative/graphicsitems/qdeclarativepath.cpp index 966c51b..e63a2c3 100644 --- a/src/declarative/graphicsitems/qdeclarativepath.cpp +++ b/src/declarative/graphicsitems/qdeclarativepath.cpp @@ -46,6 +46,8 @@ #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -367,9 +369,11 @@ void QDeclarativePath::createPointCache() const { Q_D(const QDeclarativePath); qreal pathLength = d->_path.length(); + if (pathLength <= 0 || qIsNaN(pathLength)) + return; // more points means less jitter between items as they move along the // path, but takes longer to generate - const int points = int(pathLength*5); + const int points = qCeil(pathLength*5); const int lastElement = d->_path.elementCount() - 1; d->_pointCache.resize(points+1); @@ -418,6 +422,8 @@ QPointF QDeclarativePath::pointAt(qreal p) const Q_D(const QDeclarativePath); if (d->_pointCache.isEmpty()) { createPointCache(); + if (d->_pointCache.isEmpty()) + return QPointF(); } int idx = qRound(p*d->_pointCache.size()); if (idx >= d->_pointCache.size()) diff --git a/tests/auto/declarative/qdeclarativepathview/data/undefinedpath.qml b/tests/auto/declarative/qdeclarativepathview/data/undefinedpath.qml new file mode 100644 index 0000000..5a647cb --- /dev/null +++ b/tests/auto/declarative/qdeclarativepathview/data/undefinedpath.qml @@ -0,0 +1,17 @@ +import QtQuick 1.0 + +PathView { + id: pathView + width: 240; height: 200 + path: Path { + startX: pathView.undef/2.0; startY: 0 + PathLine { x: pathView.undef/2.0; y: 0 } + } + + delegate: Text { text: value } + model: ListModel { + ListElement { value: "one" } + ListElement { value: "two" } + ListElement { value: "three" } + } +} diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index 90b1056..bd8baab 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -88,6 +88,7 @@ private slots: void closed(); void pathUpdate(); void visualDataModel(); + void undefinedPath(); private: QDeclarativeView *createView(); @@ -853,6 +854,19 @@ void tst_QDeclarativePathView::visualDataModel() delete obj; } +void tst_QDeclarativePathView::undefinedPath() +{ + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/undefinedpath.qml")); + + QDeclarativePathView *obj = qobject_cast(c.create()); + QVERIFY(obj != 0); + + QCOMPARE(obj->count(), 3); + + delete obj; +} + QDeclarativeView *tst_QDeclarativePathView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); -- cgit v0.12