aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2016-01-22 15:20:47 +0100
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2016-01-22 15:21:06 +0100
commitf286db98ee41a8aa71b9a65a235b6d3e265d79f4 (patch)
tree16e17d4c52d35f7e55fc2103db5c96850e9bdfff /src
parentce093497f2d4164fa8abc06cf976f9e36798e11e (diff)
parentb60a5dc9405ce89d7a742abc81b906d5c8cf5f7d (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Diffstat (limited to 'src')
-rw-r--r--src/imports/statemachine/plugin.cpp2
-rw-r--r--src/imports/statemachine/signaltransition.cpp68
-rw-r--r--src/imports/statemachine/signaltransition.h27
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h3
-rw-r--r--src/qml/parser/qqmljs.g19
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp22
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h1
-rw-r--r--src/qml/qml/qqmlcomponent.cpp4
-rw-r--r--src/qml/qml/qqmlengine.cpp2
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp8
-rw-r--r--src/quick/items/qquickitem.cpp2
-rw-r--r--src/quick/items/qquickitemview.cpp4
-rw-r--r--src/quick/items/qquickitemview_p_p.h2
-rw-r--r--src/quick/items/qquicklistview.cpp4
-rw-r--r--src/quick/items/qquickmousearea.cpp2
-rw-r--r--src/quick/items/qquicktext.cpp2
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp3
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()) {