diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-01-22 15:20:47 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-01-22 15:21:06 +0100 |
commit | f286db98ee41a8aa71b9a65a235b6d3e265d79f4 (patch) | |
tree | 16e17d4c52d35f7e55fc2103db5c96850e9bdfff /src | |
parent | ce093497f2d4164fa8abc06cf976f9e36798e11e (diff) | |
parent | b60a5dc9405ce89d7a742abc81b906d5c8cf5f7d (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Change-Id: I4af0bf8ec1569097d97f8ce0bb8bf1a0e4a989ec
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/statemachine/plugin.cpp | 2 | ||||
-rw-r--r-- | src/imports/statemachine/signaltransition.cpp | 68 | ||||
-rw-r--r-- | src/imports/statemachine/signaltransition.h | 27 | ||||
-rw-r--r-- | src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h | 3 | ||||
-rw-r--r-- | src/qml/parser/qqmljs.g | 19 | ||||
-rw-r--r-- | src/qml/qml/qqmlboundsignal.cpp | 22 | ||||
-rw-r--r-- | src/qml/qml/qqmlboundsignal_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcanvasitem.cpp | 8 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquickitemview.cpp | 4 | ||||
-rw-r--r-- | src/quick/items/qquickitemview_p_p.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquicklistview.cpp | 4 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquicktext.cpp | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgdefaultimagenode.cpp | 3 |
17 files changed, 159 insertions, 16 deletions
diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp index 2242ccf5e3..db79751b69 100644 --- a/src/imports/statemachine/plugin.cpp +++ b/src/imports/statemachine/plugin.cpp @@ -72,7 +72,7 @@ public: qmlRegisterUncreatableType<QState>(uri, 1, 0, "QState", "Don't use this, use State instead"); qmlRegisterUncreatableType<QAbstractState>(uri, 1, 0, "QAbstractState", "Don't use this, use State instead"); qmlRegisterUncreatableType<QSignalTransition>(uri, 1, 0, "QSignalTransition", "Don't use this, use SignalTransition instead"); - qmlRegisterType<SignalTransition>(uri, 1, 0, "SignalTransition"); + qmlRegisterCustomType<SignalTransition>(uri, 1, 0, "SignalTransition", new SignalTransitionParser); qmlRegisterType<TimeoutTransition>(uri, 1, 0, "TimeoutTransition"); qmlProtectModule(uri, 1); } diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp index 7eee8af3bc..47efc9ec15 100644 --- a/src/imports/statemachine/signaltransition.cpp +++ b/src/imports/statemachine/signaltransition.cpp @@ -51,9 +51,10 @@ #include <private/qjsvalue_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qqmlcontext_p.h> +#include <private/qqmlboundsignal_p.h> SignalTransition::SignalTransition(QState *parent) - : QSignalTransition(this, SIGNAL(invokeYourself()), parent) + : QSignalTransition(this, SIGNAL(invokeYourself()), parent), m_complete(false), m_signalExpression(Q_NULLPTR) { connect(this, SIGNAL(signalChanged()), SIGNAL(qmlSignalChanged())); } @@ -86,6 +87,15 @@ bool SignalTransition::eventTest(QEvent *event) return result.toBool(); } +void SignalTransition::onTransition(QEvent *event) +{ + if (m_signalExpression) { + QStateMachine::SignalEvent *e = static_cast<QStateMachine::SignalEvent*>(event); + m_signalExpression->evaluate(e->arguments()); + } + QSignalTransition::onTransition(event); +} + const QJSValue& SignalTransition::signal() { return m_signal; @@ -110,6 +120,8 @@ void SignalTransition::setSignal(const QJSValue &signal) QSignalTransition::setSenderObject(sender); QSignalTransition::setSignal(metaMethod.methodSignature()); + + connectTriggered(); } QQmlScriptString SignalTransition::guard() const @@ -131,6 +143,60 @@ void SignalTransition::invoke() emit invokeYourself(); } +void SignalTransition::connectTriggered() +{ + if (!m_complete || !m_cdata) + return; + + QObject *target = senderObject(); + QQmlData *ddata = QQmlData::get(this); + QQmlContextData *ctxtdata = ddata ? ddata->outerContext : 0; + + Q_ASSERT(m_bindings.count() == 1); + const QV4::CompiledData::Binding *binding = m_bindings.at(0); + Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script); + + QV4::ExecutionEngine *jsEngine = QV8Engine::getV4(QQmlEngine::contextForObject(this)->engine()); + QV4::Scope scope(jsEngine); + QV4::Scoped<QV4::QObjectMethod> qobjectSignal(scope, QJSValuePrivate::convertedToValue(jsEngine, m_signal)); + Q_ASSERT(qobjectSignal); + QMetaMethod metaMethod = target->metaObject()->method(qobjectSignal->methodIndex()); + int signalIndex = QMetaObjectPrivate::signalIndex(metaMethod); + + QQmlBoundSignalExpression *expression = ctxtdata ? + new QQmlBoundSignalExpression(target, signalIndex, + ctxtdata, this, m_cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0; + if (expression) + expression->setNotifyOnValueChanged(false); + m_signalExpression = expression; +} + +void SignalTransitionParser::verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props) +{ + for (int ii = 0; ii < props.count(); ++ii) { + const QV4::CompiledData::Binding *binding = props.at(ii); + + QString propName = qmlUnit->stringAt(binding->propertyNameIndex); + + if (propName != QStringLiteral("onTriggered")) { + error(props.at(ii), SignalTransition::tr("Cannot assign to non-existent property \"%1\"").arg(propName)); + return; + } + + if (binding->type != QV4::CompiledData::Binding::Type_Script) { + error(binding, SignalTransition::tr("SignalTransition: script expected")); + return; + } + } +} + +void SignalTransitionParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings) +{ + SignalTransition *st = qobject_cast<SignalTransition*>(object); + st->m_cdata = cdata; + st->m_bindings = bindings; +} + /*! \qmltype QAbstractTransition \inqmlmodule QtQml.StateMachine diff --git a/src/imports/statemachine/signaltransition.h b/src/imports/statemachine/signaltransition.h index e8e064a995..3471aea0c8 100644 --- a/src/imports/statemachine/signaltransition.h +++ b/src/imports/statemachine/signaltransition.h @@ -45,12 +45,17 @@ #include <QtQml/QJSValue> #include <QtQml/qqmlscriptstring.h> +#include <QtQml/qqmlparserstatus.h> +#include <private/qqmlcustomparser_p.h> +#include <private/qqmlboundsignalexpressionpointer_p.h> +#include <private/qqmlcompiler_p.h> QT_BEGIN_NAMESPACE -class SignalTransition : public QSignalTransition +class SignalTransition : public QSignalTransition, public QQmlParserStatus { Q_OBJECT + Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QJSValue signal READ signal WRITE setSignal NOTIFY qmlSignalChanged) Q_PROPERTY(QQmlScriptString guard READ guard WRITE setGuard NOTIFY guardChanged) @@ -60,7 +65,8 @@ public: QQmlScriptString guard() const; void setGuard(const QQmlScriptString &guard); - bool eventTest(QEvent *event); + bool eventTest(QEvent *event) Q_DECL_OVERRIDE; + void onTransition(QEvent *event) Q_DECL_OVERRIDE; const QJSValue &signal(); void setSignal(const QJSValue &signal); @@ -76,9 +82,24 @@ Q_SIGNALS: void qmlSignalChanged(); private: - QByteArray m_data; + void classBegin() Q_DECL_OVERRIDE { m_complete = false; } + void componentComplete() Q_DECL_OVERRIDE { m_complete = true; connectTriggered(); } + void connectTriggered(); + + friend class SignalTransitionParser; QJSValue m_signal; QQmlScriptString m_guard; + bool m_complete; + QQmlRefPointer<QQmlCompiledData> m_cdata; + QList<const QV4::CompiledData::Binding *> m_bindings; + QQmlBoundSignalExpressionPointer m_signalExpression; +}; + +class SignalTransitionParser : public QQmlCustomParser +{ +public: + void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props) Q_DECL_OVERRIDE; + void applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h index aea03d2257..6e6bf8ff68 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h @@ -46,6 +46,9 @@ #include <QtCore/QJsonObject> #include <QtCore/QJsonArray> +#include <QtCore/QJsonObject> +#include <QtCore/QJsonArray> + QT_BEGIN_NAMESPACE class QV4Debugger; diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 1a7028dbb3..161c8ffcde 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -467,7 +467,24 @@ bool Parser::parse(int startToken) token_buffer[0].token = startToken; first_token = &token_buffer[0]; - last_token = &token_buffer[1]; + if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) { + Directives ignoreDirectives; + Directives *directives = driver->directives(); + if (!directives) + directives = &ignoreDirectives; + DiagnosticMessage error; + if (!lexer->scanDirectives(directives, &error)) { + diagnostic_messages.append(error); + return false; + } + token_buffer[1].token = lexer->tokenKind(); + token_buffer[1].dval = lexer->tokenValue(); + token_buffer[1].loc = location(lexer); + token_buffer[1].spell = lexer->tokenSpell(); + last_token = &token_buffer[2]; + } else { + last_token = &token_buffer[1]; + } tos = -1; program = 0; diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index f2acc7352c..9879763c72 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -245,6 +245,28 @@ void QQmlBoundSignalExpression::evaluate(void **a) ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. } +void QQmlBoundSignalExpression::evaluate(const QList<QVariant> &args) +{ + Q_ASSERT (context() && engine()); + + if (!expressionFunctionValid()) + return; + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine()); + QV4::Scope scope(ep->v4engine()); + + ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. + + QV4::ScopedCallData callData(scope, args.count()); + for (int ii = 0; ii < args.count(); ++ii) { + callData->args[ii] = scope.engine->fromVariant(args[ii]); + } + + QQmlJavaScriptExpression::evaluate(callData, 0); + + ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. +} + //////////////////////////////////////////////////////////////////////// diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h index 59ed37c939..10c59b07c1 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -84,6 +84,7 @@ public: // evaluation of a bound signal expression doesn't return any value void evaluate(void **a); + void evaluate(const QList<QVariant> &args); QQmlSourceLocation sourceLocation() const; QString expression() const; diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 3337838a90..b8bd0f7f1d 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -295,7 +295,7 @@ V4_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension); \value Null This QQmlComponent has no data. Call loadUrl() or setData() to add QML content. \value Ready This QQmlComponent is ready and create() may be called. \value Loading This QQmlComponent is loading network data. - \value Error An error has occurred. Call errors() to retrieve a list of \{QQmlError}{errors}. + \value Error An error has occurred. Call errors() to retrieve a list of \l {QQmlError}{errors}. */ /*! @@ -685,7 +685,7 @@ void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::Compilatio } /*! - Return the list of errors that occurred during the last compile or create + Returns the list of errors that occurred during the last compile or create operation. An empty list is returned if isError() is not set. */ QList<QQmlError> QQmlComponent::errors() const diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 74a3129dfb..0e99e4ca89 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1240,7 +1240,7 @@ bool QQmlEngine::outputWarningsToStandardError() const If \a enabled is true, any warning messages generated by QML will be output to stderr and emitted by the warnings() signal. If \a enabled - is false, on the warnings() signal will be emitted. This allows + is false, only the warnings() signal will be emitted. This allows applications to handle warning output themselves. The default value is true. diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index fcb6c2da8f..68f465cc5a 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -228,6 +228,9 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() operations. The Canvas output may be saved as an image file or serialized to a URL. + Rendering to the Canvas is done using a Context2D object, usually as a + result of the \l paint signal. + To define a drawing area in the Canvas item set the \c width and \c height properties. For example, the following code creates a Canvas item which has a drawing area with a height of 100 pixels and width of 200 pixels: @@ -237,6 +240,11 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() id: mycanvas width: 100 height: 200 + onPaint: { + var ctx = getContext("2d"); + ctx.fillStyle = Qt.rgba(1, 0, 0, 1); + ctx.fillRect(0, 0, width, height); + } } \endqml diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 2bfb16a0f4..dec2351de8 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2514,6 +2514,8 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo lastChild = prevTabChildItem(current, -1); } bool isTabFence = current->d_func()->isTabFence; + if (isTabFence && !hasChildren) + return current; // coming from parent: check children if (hasChildren && from == current->parentItem()) { diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 1d581d769f..7009a8e328 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -957,7 +957,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) switch (mode) { case QQuickItemView::Beginning: pos = itemPos; - if (index < 0 && header) + if (header && (index < 0 || hasStickyHeader())) pos -= headerSize(); break; case QQuickItemView::Center: @@ -965,7 +965,7 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) break; case QQuickItemView::End: pos = itemPos - size() + item->size(); - if (index >= model->count() && footer) + if (footer && (index >= model->count() || hasStickyFooter())) pos += footerSize(); break; case QQuickItemView::Visible: diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index 220df577c3..5e104cf208 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -344,6 +344,8 @@ protected: virtual bool showFooterForIndex(int index) const = 0; virtual void updateHeader() = 0; virtual void updateFooter() = 0; + virtual bool hasStickyHeader() const { return false; }; + virtual bool hasStickyFooter() const { return false; }; virtual void createHighlight() = 0; virtual void updateHighlight() = 0; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 0aee8f2067..e42873f459 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -123,8 +123,8 @@ public: bool showFooterForIndex(int index) const Q_DECL_OVERRIDE; void updateHeader() Q_DECL_OVERRIDE; void updateFooter() Q_DECL_OVERRIDE; - bool hasStickyHeader() const; - bool hasStickyFooter() const; + bool hasStickyHeader() const Q_DECL_OVERRIDE; + bool hasStickyFooter() const Q_DECL_OVERRIDE; void changedVisibleIndex(int newIndex) Q_DECL_OVERRIDE; void initializeCurrentItem() Q_DECL_OVERRIDE; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index dc41a4739b..42de98eff7 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -124,7 +124,7 @@ bool QQuickMouseAreaPrivate::isWheelConnected() void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t) { Q_Q(QQuickMouseArea); - if (!propagateComposedEvents) + if (!window || !propagateComposedEvents) return; QPointF scenePos = q->mapToScene(QPointF(event->x(), event->y())); propagateHelper(event, window->contentItem(), scenePos, t); diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index aa9c8d21eb..97e00362be 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -471,7 +471,7 @@ void QQuickTextPrivate::updateSize() } QQuickTextLine::QQuickTextLine() - : QObject(), m_line(0), m_height(0) + : QObject(), m_line(0), m_height(0), m_lineOffset(0) { } diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp index f1d41fcc69..c26092e20c 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp @@ -293,7 +293,8 @@ void QSGDefaultImageNode::preprocess() QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(m_material.texture()); if (t) { doDirty = t->updateTexture(); - updateGeometry(); + if (doDirty) + updateGeometry(); } bool alpha = m_material.flags() & QSGMaterial::Blending; if (m_material.texture() && alpha != m_material.texture()->hasAlphaChannel()) { |