diff options
Diffstat (limited to 'src')
51 files changed, 982 insertions, 237 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 0187d06e6a..4f08e71fd0 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -661,7 +661,7 @@ public: void registerTypes(const char *uri) { Q_ASSERT(QLatin1String(uri) == "QtQuick.LocalStorage"); - qmlRegisterModuleApi(uri, 2, 0, module_api_factory); + qmlRegisterModuleApi<QQuickLocalStorage>(uri, 2, 0, module_api_factory); } }; diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.cpp b/src/plugins/accessible/quick/qaccessiblequickitem.cpp index 45db9fa795..d282b04eaf 100644 --- a/src/plugins/accessible/quick/qaccessiblequickitem.cpp +++ b/src/plugins/accessible/quick/qaccessiblequickitem.cpp @@ -135,7 +135,14 @@ QList<QQuickItem *> QAccessibleQuickItem::childItems() const role() == QAccessible::PageTab || role() == QAccessible::ProgressBar) return QList<QQuickItem *>(); - return item()->childItems(); + + QList<QQuickItem *> items; + Q_FOREACH (QQuickItem *child, item()->childItems()) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(child); + if (itemPrivate->isAccessible) + items.append(child); + } + return items; } QAccessible::State QAccessibleQuickItem::state() const diff --git a/src/plugins/accessible/quick/qaccessiblequickview.cpp b/src/plugins/accessible/quick/qaccessiblequickview.cpp index 1823dfea42..2df1f243b8 100644 --- a/src/plugins/accessible/quick/qaccessiblequickview.cpp +++ b/src/plugins/accessible/quick/qaccessiblequickview.cpp @@ -41,6 +41,8 @@ #include "qaccessiblequickview.h" +#include <QtGui/qguiapplication.h> + #include <QtQuick/qquickitem.h> #include <QtQuick/private/qquickitem_p.h> @@ -83,7 +85,12 @@ QAccessible::Role QAccessibleQuickView::role() const QAccessible::State QAccessibleQuickView::state() const { - return QAccessible::State(); // FIXME + QAccessible::State st; + if (view() == QGuiApplication::focusWindow()) + st.active = true; + if (!view()->isVisible()) + st.invisible = true; + return st; } QRect QAccessibleQuickView::rect() const @@ -120,7 +127,7 @@ static QQuickItem *childAt_helper(QQuickItem *item, int x, int y) } QScopedPointer<QAccessibleInterface> accessibleInterface(QAccessible::queryAccessibleInterface(item)); - if (accessibleInterface->childCount() == 0) { + if (accessibleInterface && accessibleInterface->childCount() == 0) { return (itemScreenRect(item).contains(x, y)) ? item : 0; } diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro index 2d4de57540..33bda11dcc 100644 --- a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro +++ b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro @@ -15,7 +15,8 @@ SOURCES += \ selectiontool.cpp \ qquickviewinspector.cpp \ ../shared/abstracttool.cpp \ - ../shared/abstractviewinspector.cpp + ../shared/abstractviewinspector.cpp \ + zoomtool.cpp HEADERS += \ qtquick2plugin.h \ @@ -25,7 +26,8 @@ HEADERS += \ ../shared/abstracttool.h \ ../shared/abstractviewinspector.h \ ../shared/qqmlinspectorprotocol.h \ - ../shared/qmlinspectorconstants.h + ../shared/qmlinspectorconstants.h \ + zoomtool.h OTHER_FILES += qtquick2plugin.json diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp index 200c66ee35..0a73540b40 100644 --- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp +++ b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp @@ -44,6 +44,7 @@ #include "qqmlinspectorprotocol.h" #include "highlight.h" #include "selectiontool.h" +#include "zoomtool.h" #include <QtQuick/private/qquickitem_p.h> @@ -120,6 +121,7 @@ QQuickViewInspector::QQuickViewInspector(QQuickView *view, QObject *parent) : m_view(view), m_overlay(new QQuickItem), m_selectionTool(new SelectionTool(this)), + m_zoomTool(0), m_designMode(true) { // Try to make sure the overlay is always on top @@ -176,7 +178,9 @@ void QQuickViewInspector::changeTool(InspectorProtocol::Tool tool) emit selectToolActivated(); break; case InspectorProtocol::ZoomTool: - // TODO + if (!m_zoomTool) + m_zoomTool = new ZoomTool(this, m_view); + setCurrentTool(m_zoomTool); emit zoomToolActivated(); break; } diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h index fbc3c17b87..e8fdf351de 100644 --- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h +++ b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h @@ -57,6 +57,7 @@ namespace QtQuick2 { class SelectionTool; class SelectionHighlight; +class ZoomTool; class QQuickViewInspector : public AbstractViewInspector { @@ -99,6 +100,7 @@ private: QQuickItem *m_overlay; SelectionTool *m_selectionTool; + ZoomTool *m_zoomTool; QList<QWeakPointer<QQuickItem> > m_selectedItems; QHash<QQuickItem*, SelectionHighlight*> m_highlightItems; diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.cpp new file mode 100644 index 0000000000..171f1a52e9 --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "zoomtool.h" +#include "qquickviewinspector.h" + +#include <QtCore/QLineF> +#include <QtGui/QMouseEvent> +#include <QtGui/QWheelEvent> +#include <QtGui/QTouchEvent> +#include <QtGui/QKeyEvent> + +#include <QtQuick/QQuickView> +#include <QtQuick/QQuickItem> + +namespace QmlJSDebugger { +namespace QtQuick2 { + +ZoomTool::ZoomTool(QQuickViewInspector *inspector, QQuickView *view) : + AbstractTool(inspector), + m_dragStarted(false), + m_pinchStarted(false), + m_currentScale(1.0f), + m_smoothScaleFactor(0.05f), + m_minScale(0.125f), + m_maxScale(48.0f), + m_tapScaleCounter(0) +{ + m_rootItem = view->rootItem(); + m_originalSmooth = m_rootItem->smooth(); + if (!m_originalSmooth) + m_rootItem->setSmooth(true); + m_originalPosition = m_rootItem->pos(); + m_originalScale = m_rootItem->scale(); +} + +ZoomTool::~ZoomTool() +{ + // restoring the original states. + m_rootItem->setScale(m_originalScale); + m_rootItem->setPos(m_originalPosition); + if (!m_originalSmooth) + m_rootItem->setSmooth(m_originalSmooth); +} + +void ZoomTool::mousePressEvent(QMouseEvent *event) +{ + m_mousePosition = event->posF(); + if (event->buttons() & Qt::LeftButton) { + m_dragStartPosition = event->posF(); + m_dragStarted = false; + } +} + +void ZoomTool::mouseMoveEvent(QMouseEvent *event) +{ + if (m_pinchStarted) + return; + + m_mousePosition = event->posF(); + if (!m_dragStarted + && event->buttons() & Qt::LeftButton + && ((m_dragStartPosition - event->posF()).manhattanLength() + > Constants::DragStartDistance)) { + m_dragStarted = true; + } + if (m_dragStarted) { + m_adjustedOrigin += event->posF() - m_dragStartPosition; + m_dragStartPosition = event->posF(); + m_rootItem->setPos(m_adjustedOrigin); + } +} + +void ZoomTool::hoverMoveEvent(QMouseEvent *event) +{ + m_mousePosition = event->posF(); +} + +void ZoomTool::wheelEvent(QWheelEvent *event) +{ + if (event->orientation() != Qt::Vertical) + return; + + Qt::KeyboardModifier smoothZoomModifier = Qt::ControlModifier; + if (event->modifiers() & smoothZoomModifier) { + int numDegrees = event->delta() / 8; + qreal newScale = m_currentScale + m_smoothScaleFactor * (numDegrees / 15.0f); + scaleView(newScale / m_currentScale, m_mousePosition, m_mousePosition); + } else if (!event->modifiers()) { + if (event->delta() > 0) { + zoomIn(); + } else if (event->delta() < 0) { + zoomOut(); + } + } +} + +void ZoomTool::mouseDoubleClickEvent(QMouseEvent *event) +{ + m_mousePosition = event->posF(); + zoomTo100(); +} + +void ZoomTool::keyReleaseEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Plus: + zoomIn(); + break; + case Qt::Key_Minus: + zoomOut(); + break; + case Qt::Key_1: + case Qt::Key_2: + case Qt::Key_3: + case Qt::Key_4: + case Qt::Key_5: + case Qt::Key_6: + case Qt::Key_7: + case Qt::Key_8: + case Qt::Key_9: { + qreal newScale = ((event->key() - Qt::Key_0) * 1.0f); + scaleView(newScale / m_currentScale, m_mousePosition, m_mousePosition); + break; + } + default: + break; + } +} + +void ZoomTool::touchEvent(QTouchEvent *event) +{ + QList<QTouchEvent::TouchPoint> touchPoints = event->touchPoints(); + + switch (event->type()) { + case QEvent::TouchBegin: + // fall through.. + case QEvent::TouchUpdate: { + if ((touchPoints.count() == 2) + && (!(event->touchPointStates() & Qt::TouchPointReleased))) { + // determine scale factor + const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first(); + const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last(); + + qreal touchScaleFactor = + QLineF(touchPoint0.pos(), touchPoint1.pos()).length() + / QLineF(touchPoint0.lastPos(), touchPoint1.lastPos()).length(); + + QPointF oldcenter = (touchPoint0.lastPos() + touchPoint1.lastPos()) / 2; + QPointF newcenter = (touchPoint0.pos() + touchPoint1.pos()) / 2; + + m_pinchStarted = true; + m_tapScaleCounter = 0; + scaleView(touchScaleFactor, newcenter, oldcenter); + } + break; + } + case QEvent::TouchEnd: { + if (m_pinchStarted) { + m_pinchStarted = false; + } else if ((touchPoints.count() == 1) + &&(!m_dragStarted)) { + ++m_tapScaleCounter; + qreal factor = 1.0f + (1.0f / (m_tapScaleCounter + 1)); + scaleView(factor, touchPoints.first().pos(), + touchPoints.first().pos()); + } + break; + } + default: + break; + } +} + +void ZoomTool::scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter) +{ + if (((m_currentScale * factor) > m_maxScale) + || ((m_currentScale * factor) < m_minScale)) { + return; + } + //New position = new center + scalefactor * (oldposition - oldcenter) + m_adjustedOrigin = newcenter + (factor * (m_adjustedOrigin - oldcenter)); + m_currentScale *= factor; + + m_rootItem->setScale(m_currentScale); + m_rootItem->setPos(m_adjustedOrigin); +} + +void ZoomTool::zoomIn() +{ + qreal newScale = nextZoomScale(ZoomIn); + scaleView(newScale / m_currentScale, m_mousePosition, m_mousePosition); +} + +void ZoomTool::zoomOut() +{ + qreal newScale = nextZoomScale(ZoomOut); + scaleView(newScale / m_currentScale, m_mousePosition, m_mousePosition); +} + +void ZoomTool::zoomTo100() +{ + m_currentScale = 1.0; + m_adjustedOrigin = QPointF(0, 0); + m_tapScaleCounter = 0; + + m_rootItem->setPos(m_adjustedOrigin); + m_rootItem->setScale(m_currentScale); +} + +qreal ZoomTool::nextZoomScale(ZoomDirection direction) +{ + static QList<qreal> zoomScales = + QList<qreal>() + << 0.125f + << 1.0f / 6.0f + << 0.25f + << 1.0f / 3.0f + << 0.5f + << 2.0f / 3.0f + << 1.0f + << 2.0f + << 3.0f + << 4.0f + << 5.0f + << 6.0f + << 7.0f + << 8.0f + << 12.0f + << 16.0f + << 32.0f + << 48.0f; + + if (direction == ZoomIn) { + for (int i = 0; i < zoomScales.length(); ++i) { + if (zoomScales[i] > m_currentScale) + return zoomScales[i]; + } + return zoomScales.last(); + } else { + for (int i = zoomScales.length() - 1; i >= 0; --i) { + if (zoomScales[i] < m_currentScale) + return zoomScales[i]; + } + return zoomScales.first(); + } + + return 1.0f; +} + +} // namespace QtQuick2 +} // namespace QmlJSDebugger diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.h b/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.h new file mode 100644 index 0000000000..02ed8e09df --- /dev/null +++ b/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ZOOMTOOL_H +#define ZOOMTOOL_H + +#include "abstracttool.h" + +#include <QtCore/QPointF> + +QT_FORWARD_DECLARE_CLASS(QQuickView) +QT_FORWARD_DECLARE_CLASS(QQuickItem) + +namespace QmlJSDebugger { +namespace QtQuick2 { + +class QQuickViewInspector; + +class ZoomTool : public AbstractTool +{ + Q_OBJECT + +public: + enum ZoomDirection { + ZoomIn, + ZoomOut + }; + + explicit ZoomTool(QQuickViewInspector *inspector, QQuickView *view); + virtual ~ZoomTool(); + void leaveEvent(QEvent *) {} + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *) {} + void mouseDoubleClickEvent(QMouseEvent *event); + + void hoverMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + + void keyPressEvent(QKeyEvent *) {} + void keyReleaseEvent(QKeyEvent *event); + + void touchEvent(QTouchEvent *event); + +private: + qreal nextZoomScale(ZoomDirection direction); + void scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter); + void zoomTo100(); + void zoomIn(); + void zoomOut(); + +private: + bool m_originalSmooth; + bool m_dragStarted; + bool m_pinchStarted; + QQuickItem *m_rootItem; + QPointF m_adjustedOrigin; + QPointF m_dragStartPosition; + QPointF m_mousePosition; + QPointF m_originalPosition; + qreal m_currentScale; + qreal m_smoothScaleFactor; + qreal m_minScale; + qreal m_maxScale; + qreal m_tapScaleCounter; + qreal m_originalScale; +}; + +} // namespace QtQuick2 +} // namespace QmlJSDebugger + +#endif // ZOOMTOOL_H diff --git a/src/plugins/qmltooling/shared/abstracttool.h b/src/plugins/qmltooling/shared/abstracttool.h index 35817064e2..7e5ba65fd4 100644 --- a/src/plugins/qmltooling/shared/abstracttool.h +++ b/src/plugins/qmltooling/shared/abstracttool.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE class QMouseEvent; class QKeyEvent; class QWheelEvent; +class QTouchEvent; QT_END_NAMESPACE namespace QmlJSDebugger { @@ -76,6 +77,8 @@ public: virtual void keyPressEvent(QKeyEvent *event) = 0; virtual void keyReleaseEvent(QKeyEvent *keyEvent) = 0; + virtual void touchEvent(QTouchEvent *) {} + private: AbstractViewInspector *m_inspector; }; diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.cpp b/src/plugins/qmltooling/shared/abstractviewinspector.cpp index 33e47d270d..135da1b8b7 100644 --- a/src/plugins/qmltooling/shared/abstractviewinspector.cpp +++ b/src/plugins/qmltooling/shared/abstractviewinspector.cpp @@ -50,6 +50,7 @@ #include <QtQml/private/qqmlinspectorservice_p.h> #include <QtGui/QMouseEvent> +#include <QtGui/QTouchEvent> namespace QmlJSDebugger { @@ -220,6 +221,12 @@ bool AbstractViewInspector::eventFilter(QObject *obj, QEvent *event) if (wheelEvent(static_cast<QWheelEvent*>(event))) return true; break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + if (touchEvent(static_cast<QTouchEvent*>(event))) + return true; + break; default: break; } @@ -300,6 +307,12 @@ bool AbstractViewInspector::wheelEvent(QWheelEvent *event) return true; } +bool AbstractViewInspector::touchEvent(QTouchEvent *event) +{ + m_currentTool->touchEvent(event); + return true; +} + void AbstractViewInspector::handleMessage(const QByteArray &message) { QDataStream ds(message); diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.h b/src/plugins/qmltooling/shared/abstractviewinspector.h index 0dacc92233..04ca02917e 100644 --- a/src/plugins/qmltooling/shared/abstractviewinspector.h +++ b/src/plugins/qmltooling/shared/abstractviewinspector.h @@ -56,6 +56,8 @@ class QQmlInspectorService; class QKeyEvent; class QMouseEvent; class QWheelEvent; +class QTouchEvent; + QT_END_NAMESPACE namespace QmlJSDebugger { @@ -128,6 +130,7 @@ protected: virtual bool keyReleaseEvent(QKeyEvent *keyEvent); virtual bool mouseDoubleClickEvent(QMouseEvent *event); virtual bool wheelEvent(QWheelEvent *event); + virtual bool touchEvent(QTouchEvent *event); private slots: void sendColorChanged(const QColor &color); diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h index 8036032150..318e0bd71f 100644 --- a/src/qml/debugger/qqmldebug.h +++ b/src/qml/debugger/qqmldebug.h @@ -51,12 +51,14 @@ QT_BEGIN_NAMESPACE struct Q_QML_EXPORT QQmlDebuggingEnabler { - QQmlDebuggingEnabler(); + QQmlDebuggingEnabler(bool printWarning = true); }; // Execute code in constructor before first QQmlEngine is instantiated -#if defined(QT_DECLARATIVE_DEBUG) -static QQmlDebuggingEnabler qmlEnableDebuggingHelper; +#if defined(QT_DECLARATIVE_DEBUG_NO_WARNING) +static QQmlDebuggingEnabler qmlEnableDebuggingHelper(false); +#elif defined(QT_DECLARATIVE_DEBUG) +static QQmlDebuggingEnabler qmlEnableDebuggingHelper(true); #endif QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 7f0bf7ca33..cd09b69e48 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -223,7 +223,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message, int childrenCount = children.count(); for (int ii = 0; ii < children.count(); ++ii) { - if (qobject_cast<QQmlContext*>(children[ii]) || QQmlBoundSignal::cast(children[ii])) + if (qobject_cast<QQmlContext*>(children[ii])) --childrenCount; } @@ -235,19 +235,41 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message, QObject *child = children.at(ii); if (qobject_cast<QQmlContext*>(child)) continue; - QQmlBoundSignal *signal = QQmlBoundSignal::cast(child); - if (signal) { - if (!dumpProperties) + if (recur) + buildObjectDump(message, child, recur, dumpProperties); + else + message << objectData(child); + } + + if (!dumpProperties) { + message << 0; + return; + } + + QList<int> propertyIndexes; + for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) { + if (object->metaObject()->property(ii).isScriptable()) + propertyIndexes << ii; + } + + QQmlData *ddata = QQmlData::get(object); + if (ddata && ddata->signalHandlers) { + QQmlAbstractBoundSignal *signalHandler = ddata->signalHandlers; + + while (signalHandler) { + if (!dumpProperties) { + signalHandler = signalHandler->m_nextSignal; continue; + } QQmlObjectProperty prop; prop.type = QQmlObjectProperty::SignalProperty; prop.hasNotifySignal = false; - QQmlExpression *expr = signal->expression(); + QQmlExpression *expr = signalHandler->expression(); if (expr) { prop.value = expr->expression(); QObject *scope = expr->scopeObject(); if (scope) { - QString methodName = QString::fromLatin1(scope->metaObject()->method(signal->index()).name()); + QString methodName = QString::fromLatin1(scope->metaObject()->method(signalHandler->index()).name()); if (!methodName.isEmpty()) { prop.name = QLatin1String("on") + methodName[0].toUpper() + methodName.mid(1); @@ -255,23 +277,9 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message, } } fakeProperties << prop; - } else { - if (recur) - buildObjectDump(message, child, recur, dumpProperties); - else - message << objectData(child); - } - } - if (!dumpProperties) { - message << 0; - return; - } - - QList<int> propertyIndexes; - for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) { - if (object->metaObject()->property(ii).isScriptable()) - propertyIndexes << ii; + signalHandler = signalHandler->m_nextSignal; + } } message << propertyIndexes.size() + fakeProperties.count(); diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h index 2b4cafb615..2e351792cc 100644 --- a/src/qml/debugger/qqmlprofilerservice_p.h +++ b/src/qml/debugger/qqmlprofilerservice_p.h @@ -205,16 +205,16 @@ struct QQmlHandlingSignalProfiler { { enabled = QQmlProfilerService::instance ? QQmlProfilerService::instance->profilingEnabled() : false; - if (enabled) { - QQmlProfilerService *service = QQmlProfilerService::instance; - service->startRange(QQmlProfilerService::HandlingSignal); - service->rangeData(QQmlProfilerService::HandlingSignal, - QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ") - + expression->expression()); - service->rangeLocation(QQmlProfilerService::HandlingSignal, - expression->sourceFile(), expression->lineNumber(), - expression->columnNumber()); - } + if (enabled) + init(signal, expression); + } + + QQmlHandlingSignalProfiler(QObject *object, int index, QQmlExpression *expression) + { + enabled = QQmlProfilerService::instance + ? QQmlProfilerService::instance->profilingEnabled() : false; + if (enabled) + init(object->metaObject()->method(index), expression); } ~QQmlHandlingSignalProfiler() @@ -224,6 +224,19 @@ struct QQmlHandlingSignalProfiler { } bool enabled; + +private: + void init(const QMetaMethod &signal, QQmlExpression *expression) + { + QQmlProfilerService *service = QQmlProfilerService::instance; + service->startRange(QQmlProfilerService::HandlingSignal); + service->rangeData(QQmlProfilerService::HandlingSignal, + QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ") + + expression->expression()); + service->rangeLocation(QQmlProfilerService::HandlingSignal, + expression->sourceFile(), expression->lineNumber(), + expression->columnNumber()); + } }; struct QQmlObjectCreatingProfiler { diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index 32da2c616e..5b500e0814 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -421,7 +421,7 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi uri, versionMajor, versionMinor, - callback, 0 + callback, 0, 0 }; return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); @@ -435,7 +435,22 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi uri, versionMajor, versionMinor, - 0, callback + 0, callback, 0 // unknown QObject instance type + }; + + return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); +} + +template <typename T> +inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, + QObject *(*callback)(QQmlEngine *, QJSEngine *)) +{ + QQmlPrivate::RegisterModuleApi api = { + 1, + + uri, versionMajor, versionMinor, + + 0, callback, &T::staticMetaObject }; return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index f7d0c00a5c..3a3bf403e6 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -55,6 +55,8 @@ #include <QtCore/qstringbuilder.h> #include <QtCore/qdebug.h> +Q_DECLARE_METATYPE(QJSValue) + QT_BEGIN_NAMESPACE class QQmlBoundSignalParameters : public QObject @@ -87,42 +89,45 @@ private: static int evaluateIdx = -1; -QQmlAbstractBoundSignal::QQmlAbstractBoundSignal(QObject *parent) -: QObject(parent) +QQmlAbstractBoundSignal::QQmlAbstractBoundSignal() +: m_prevSignal(0), m_nextSignal(0) { } QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal() { + if (m_prevSignal) { + *m_prevSignal = m_nextSignal; + if (m_nextSignal) m_nextSignal->m_prevSignal = m_prevSignal; + m_prevSignal = 0; + m_nextSignal = 0; + } } -QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, - QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +void QQmlAbstractBoundSignal::addToObject() { - // This is thread safe. Although it may be updated by two threads, they - // will both set it to the same value - so the worst thing that can happen - // is that they both do the work to figure it out. Boo hoo. - if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); + Q_ASSERT(!m_prevSignal); + QObject *obj = object(); + Q_ASSERT(obj); - QQml_setParent_noEvent(this, parent); - QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); + QQmlData *data = QQmlData::get(obj, true); + + m_nextSignal = data->signalHandlers; + if (m_nextSignal) m_nextSignal->m_prevSignal = &m_nextSignal; + m_prevSignal = &data->signalHandlers; + data->signalHandlers = this; } -QQmlBoundSignal::QQmlBoundSignal(QQmlContext *ctxt, const QString &val, - QObject *scope, const QMetaMethod &signal, - QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) +QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, + QObject *owner) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0), m_owner(owner) { // This is thread safe. Although it may be updated by two threads, they // will both set it to the same value - so the worst thing that can happen // is that they both do the work to figure it out. Boo hoo. if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount(); - QQml_setParent_noEvent(this, parent); QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx); - - m_expression = new QQmlExpression(ctxt, scope, val); } QQmlBoundSignal::~QQmlBoundSignal() @@ -159,12 +164,6 @@ QQmlExpression *QQmlBoundSignal::setExpression(QQmlExpression *e) return rv; } -QQmlBoundSignal *QQmlBoundSignal::cast(QObject *o) -{ - QQmlAbstractBoundSignal *s = qobject_cast<QQmlAbstractBoundSignal*>(o); - return static_cast<QQmlBoundSignal *>(s); -} - int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { @@ -227,10 +226,14 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method, prop.setWritable(false); } else { QByteArray propType = type; - if ((QMetaType::typeFlags(t) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) { + QMetaType::TypeFlags flags = QMetaType::typeFlags(t); + if (flags & QMetaType::IsEnumeration) { t = QVariant::Int; propType = "int"; - } else if (t == QMetaType::UnknownType) { + } else if (t == QMetaType::UnknownType || + (t >= int(QMetaType::User) && !(flags & QMetaType::PointerToQObject) && + t != qMetaTypeId<QJSValue>())) { + //the UserType clause is to catch registered QFlags QByteArray scope; QByteArray name; int scopeIdx = propType.lastIndexOf("::"); @@ -244,7 +247,7 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method, if (scope == "Qt") meta = &QObject::staticQtMetaObject; else - meta = parent->parent()->metaObject(); //### assumes parent->parent() + meta = static_cast<QQmlBoundSignal*>(parent)->object()->metaObject(); for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { QMetaEnum m = meta->enumerator(i); if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) { @@ -297,6 +300,71 @@ int QQmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a) } } +//////////////////////////////////////////////////////////////////////// + +QQmlBoundSignalNoParams::QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal, + QObject *owner) +: m_expression(0), m_owner(owner), m_index(signal.methodIndex()), m_isEvaluating(false) +{ + callback = &subscriptionCallback; + QQmlNotifierEndpoint::connect(scope, m_index); +} + +QQmlBoundSignalNoParams::~QQmlBoundSignalNoParams() +{ + delete m_expression; + m_expression = 0; +} + +int QQmlBoundSignalNoParams::index() const +{ + return m_index; +} + +/*! + Returns the signal expression. +*/ +QQmlExpression *QQmlBoundSignalNoParams::expression() const +{ + return m_expression; +} + +/*! + Sets the signal expression to \a e. Returns the current signal expression, + or null if there is no signal expression. + + The QQmlBoundSignalNoParams instance takes ownership of \a e. The caller is + assumes ownership of the returned QQmlExpression. +*/ +QQmlExpression *QQmlBoundSignalNoParams::setExpression(QQmlExpression *e) +{ + QQmlExpression *rv = m_expression; + m_expression = e; + if (m_expression) m_expression->setNotifyOnValueChanged(false); + return rv; +} + +void QQmlBoundSignalNoParams::subscriptionCallback(QQmlNotifierEndpoint *e) +{ + QQmlBoundSignalNoParams *s = static_cast<QQmlBoundSignalNoParams*>(e); + if (!s->m_expression) + return; + + if (QQmlDebugService::isDebuggingEnabled()) + QV8DebugService::instance()->signalEmitted(QString::fromAscii(s->m_owner->metaObject()->method(s->m_index).methodSignature())); + + QQmlHandlingSignalProfiler prof(s->m_owner, s->m_index, s->m_expression); + + s->m_isEvaluating = true; + + if (s->m_expression && s->m_expression->engine()) { + QQmlExpressionPrivate::get(s->m_expression)->value(); + if (s->m_expression && s->m_expression->hasError()) + QQmlEnginePrivate::warning(s->m_expression->engine(), s->m_expression->error()); + } + s->m_isEvaluating = false; +} + QT_END_NAMESPACE #include <qqmlboundsignal.moc> diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h index 11386159cb..5fc8c3522f 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -57,36 +57,48 @@ #include <QtCore/qmetaobject.h> +#include <private/qqmlnotifier_p.h> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE -class Q_QML_EXPORT QQmlAbstractBoundSignal : public QObject +class Q_QML_EXPORT QQmlAbstractBoundSignal { - Q_OBJECT public: - QQmlAbstractBoundSignal(QObject *parent = 0); - virtual ~QQmlAbstractBoundSignal() = 0; + QQmlAbstractBoundSignal(); + virtual ~QQmlAbstractBoundSignal(); + + virtual int index() const = 0; + virtual QQmlExpression *expression() const = 0; + virtual QQmlExpression *setExpression(QQmlExpression *) = 0; + virtual QObject *object() = 0; + + void addToObject(); + +private: + friend class QQmlData; + friend class QQmlPropertyPrivate; + friend class QQmlEngineDebugService; + QQmlAbstractBoundSignal **m_prevSignal; + QQmlAbstractBoundSignal *m_nextSignal; }; class QQmlBoundSignalParameters; -class Q_QML_EXPORT QQmlBoundSignal : public QQmlAbstractBoundSignal +class Q_QML_EXPORT QQmlBoundSignal : public QObject, + public QQmlAbstractBoundSignal { public: - QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *parent); - QQmlBoundSignal(QQmlContext *ctxt, const QString &val, QObject *scope, - const QMetaMethod &signal, QObject *parent); + QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *owner); virtual ~QQmlBoundSignal(); int index() const; QQmlExpression *expression() const; QQmlExpression *setExpression(QQmlExpression *); + QObject *object() { return m_owner; } bool isEvaluating() const { return m_isEvaluating; } - static QQmlBoundSignal *cast(QObject *); - protected: virtual int qt_metacall(QMetaObject::Call c, int id, void **a); @@ -96,8 +108,34 @@ private: bool m_paramsValid : 1; bool m_isEvaluating : 1; QQmlBoundSignalParameters *m_params; + QObject *m_owner; }; +class Q_QML_EXPORT QQmlBoundSignalNoParams : public QQmlAbstractBoundSignal, + public QQmlNotifierEndpoint +{ +public: + QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal, QObject *owner); + virtual ~QQmlBoundSignalNoParams(); + + int index() const; + + QQmlExpression *expression() const; + QQmlExpression *setExpression(QQmlExpression *); + QObject *object() { return m_owner; } + + static void subscriptionCallback(QQmlNotifierEndpoint *e); + + bool isEvaluating() const { return m_isEvaluating; } + +private: + QQmlExpression *m_expression; + QObject *m_owner; + int m_index; + bool m_isEvaluating; +}; + + QT_END_NAMESPACE #endif // QQMLBOUNDSIGNAL_P_H diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 416178e3e1..7bddaadcd0 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -110,8 +110,9 @@ static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) /*! \class QQmlComponent - \since 4.7 + \since 5.0 \brief The QQmlComponent class encapsulates a QML component definition. + \inmodule QtQml \mainclass Components are reusable, encapsulated QML elements with well-defined interfaces. @@ -179,6 +180,8 @@ static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) } \endcode + Note that the QtQuick 1 version is named QDeclarativeComponent. + \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code} */ diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h index f6d8aa1d3a..4b11095ec2 100644 --- a/src/qml/qml/qqmlcontext.h +++ b/src/qml/qml/qqmlcontext.h @@ -98,7 +98,6 @@ private: friend class QQmlComponent; friend class QQmlComponentPrivate; friend class QQmlScriptPrivate; - friend class QQmlBoundSignalProxy; friend class QQmlContextData; QQmlContext(QQmlContextData *); QQmlContext(QQmlEngine *, bool); diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index 09d1a23510..e7e001c4f2 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -63,6 +63,7 @@ template <class Key, class T> class QHash; class QQmlGuardImpl; class QQmlCompiledData; class QQmlAbstractBinding; +class QQmlAbstractBoundSignal; class QQmlContext; class QQmlPropertyCache; class QQmlContextData; @@ -79,7 +80,7 @@ public: QQmlData() : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), hasTaintedV8Object(false), isQueuedForDeletion(false), notifyList(0), context(0), outerContext(0), - bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), + bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), v8objectid(0), propertyCache(0), guards(0), extendedData(0) { init(); @@ -136,6 +137,7 @@ public: QQmlContextData *outerContext; QQmlAbstractBinding *bindings; + QQmlAbstractBoundSignal *signalHandlers; // Linked list for QQmlContext::contextObjects QQmlData *nextContextObject; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 672996085f..955c8ce414 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -69,6 +69,7 @@ #include <private/qdebugmessageservice_p.h> #include "qqmlincubator.h" #include <private/qv8profilerservice_p.h> +#include <private/qqmlboundsignal_p.h> #include <QtCore/qstandardpaths.h> #include <QtCore/qsettings.h> @@ -507,7 +508,8 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine() /*! \class QQmlEngine - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlEngine class provides an environment for instantiating QML components. \mainclass @@ -533,6 +535,8 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine() In this case, the Text item will be created in the engine's \l {QQmlEngine::rootContext()}{root context}. + Note that the QtQuick 1 version is called QDeclarativeEngine. + \sa QQmlComponent QQmlContext */ @@ -1020,10 +1024,11 @@ QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object, return qmlAttachedPropertiesObjectById(*idCache, object, create); } -QQmlDebuggingEnabler::QQmlDebuggingEnabler() +QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning) { #ifndef QQML_NO_DEBUG_PROTOCOL - if (!QQmlEnginePrivate::qml_debugging_enabled) { + if (!QQmlEnginePrivate::qml_debugging_enabled + && printWarning) { qDebug("QML debugging is enabled. Only use this in a safe environment."); } QQmlEnginePrivate::qml_debugging_enabled = true; @@ -1153,6 +1158,15 @@ void QQmlData::destroyed(QObject *object) binding = next; } + QQmlAbstractBoundSignal *signalHandler = signalHandlers; + while (signalHandler) { + QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal; + signalHandler->m_prevSignal = 0; + signalHandler->m_nextSignal = 0; + delete signalHandler; + signalHandler = next; + } + if (bindingBits) free(bindingBits); @@ -1690,6 +1704,7 @@ QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module) a = new QQmlMetaType::ModuleApiInstance; a->scriptCallback = module.script; a->qobjectCallback = module.qobject; + a->instanceMetaObject = module.instanceMetaObject; moduleApiInstances.insert(module, a); } diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 79424913f8..ce7fd01fdf 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -49,7 +49,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlError - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlError class encapsulates a QML error. QQmlError includes a textual description of the error, as well @@ -69,6 +70,8 @@ QT_BEGIN_NAMESPACE ^ \endcode + Note that the QtQuick 1 version is named QDeclarativeError + \sa QQuickView::errors(), QQmlComponent::errors() */ class QQmlErrorPrivate diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 60a0fe1c89..d760486605 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -137,7 +137,8 @@ QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, /*! \class QQmlExpression - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlExpression class evaluates JavaScript in a QML context. For example, given a file \c main.qml like this: @@ -161,6 +162,8 @@ QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, QQmlExpression *expr = new QQmlExpression(engine->rootContext(), myObject, "width * 2"); int result = expr->evaluate().toInt(); // result = 400 \endcode + + Note that the QtQuick 1 version is called QDeclarativeExpression. */ /*! diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index 86d9f9588d..73d74f9e21 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -44,7 +44,8 @@ QT_BEGIN_NAMESPACE /*! - \since 4.7 + \since 5.0 + \inmodule QtQml \class QQmlExtensionPlugin \brief The QQmlExtensionPlugin class provides an abstract base for custom QML extension plugins. @@ -75,7 +76,7 @@ QT_BEGIN_NAMESPACE as a new QML element. It provides the current time through \c hour and \c minute properties, like this: - \snippet examples/declarative/cppextensions/plugins/plugin.cpp 0 + \snippet examples/qml/cppextensions/plugins/plugin.cpp 0 \dots To make this class available as a QML type, create a plugin that registers @@ -83,9 +84,9 @@ QT_BEGIN_NAMESPACE module will be named \c com.nokia.TimeExample (as defined in the project file further below). - \snippet examples/declarative/cppextensions/plugins/plugin.cpp plugin + \snippet examples/qml/cppextensions/plugins/plugin.cpp plugin \codeline - \snippet examples/declarative/cppextensions/plugins/plugin.cpp export + \snippet examples/qml/cppextensions/plugins/plugin.cpp export This registers the \c TimeModel class with the 1.0 version of this plugin library, as a QML type called \c Time. The Q_ASSERT statement @@ -121,6 +122,8 @@ QT_BEGIN_NAMESPACE The \l {Tutorial: Writing QML extensions with C++} also contains a chapter on creating QML plugins. + Note that the QtQuick 1 version is called QDeclarativeExtensionPlugin. + \sa QQmlEngine::importPlugin(), {How to Create Qt Plugins} */ diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index 00fd805ee0..ad28e38a64 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -87,7 +87,7 @@ void QQmlListReferencePrivate::release() /*! \class QQmlListReference -\since 4.7 +\since 5.0 \module QtQml \brief The QQmlListReference class allows the manipulation of QQmlListProperty properties. @@ -111,6 +111,8 @@ Attempting to add objects of the incorrect type to a list property will fail. Like with normal lists, when accessing a list element by index, it is the callers responsibility to ensure that it does not request an out of range element using the count() method before calling at(). + +The QtQuick 1 version of this class is named QDeclarativeListReference. */ /*! @@ -306,7 +308,8 @@ int QQmlListReference::count() const /*! \class QQmlListProperty -\since 4.7 +\since 5.0 +\inmodule QtQml \brief The QQmlListProperty class allows applications to expose list-like properties to QML. @@ -340,6 +343,8 @@ Q_PROPERTY(QQmlListProperty<Fruit> fruit READ fruit); QML list properties are typesafe - in this case \c {Fruit} is a QObject type that \c {Apple}, \c {Orange} and \c {Banana} all derive from. +The QtQuick 1 version of this class is named QDeclarativeListProperty. + \note QQmlListProperty can only be used for lists of QObject-derived object pointers. \sa {Object and List Property Types} diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 4af08c28bf..856f75fc16 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -908,6 +908,10 @@ int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api) import.minor = api.versionMinor; import.script = api.scriptApi; import.qobject = api.qobjectApi; + import.instanceMetaObject = (api.qobjectApi && api.version >= 1) ? api.instanceMetaObject : 0; // BC with version 0. + + if (import.qobject && !import.instanceMetaObject) // BC - check import.iMO rather than api.iMO. + qWarning() << "qmlRegisterModuleApi(): sub-optimal: use the templated version of this function instead!"; int index = data->moduleApiCount++; diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index b715d0c8f2..03017cafab 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -115,20 +115,23 @@ public: struct ModuleApiInstance { ModuleApiInstance() - : scriptCallback(0), qobjectCallback(0), qobjectApi(0) {} + : scriptCallback(0), qobjectCallback(0), qobjectApi(0), instanceMetaObject(0) {} QJSValue (*scriptCallback)(QQmlEngine *, QJSEngine *); QObject *(*qobjectCallback)(QQmlEngine *, QJSEngine *); - QJSValue scriptApi; QObject *qobjectApi; + const QMetaObject *instanceMetaObject; + QJSValue scriptApi; + }; struct ModuleApi { inline ModuleApi(); inline bool operator==(const ModuleApi &) const; int major; int minor; - QJSValue (*script)(QQmlEngine *, QJSEngine *); QObject *(*qobject)(QQmlEngine *, QJSEngine *); + const QMetaObject *instanceMetaObject; + QJSValue (*script)(QQmlEngine *, QJSEngine *); }; static ModuleApi moduleApi(const QString &, int, int); static QHash<QString, QList<ModuleApi> > moduleApis(); @@ -247,8 +250,9 @@ QQmlMetaType::ModuleApi::ModuleApi() { major = 0; minor = 0; - script = 0; qobject = 0; + instanceMetaObject = 0; + script = 0; } bool QQmlMetaType::ModuleApi::operator==(const ModuleApi &other) const diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp index e5d0d708e2..4c31e557bc 100644 --- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp +++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlNetworkAccessManagerFactory - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlNetworkAccessManagerFactory class creates QNetworkAccessManager instances for a QML engine. A QML engine uses QNetworkAccessManager for all network access. @@ -79,7 +80,9 @@ QT_BEGIN_NAMESPACE For more information about signals and threads, see \l {Threads and QObjects} and \l {Signals and Slots Across Threads}. - \sa {declarative/cppextensions/networkaccessmanagerfactory}{NetworkAccessManagerFactory example} + The QtQuick 1 version of this class is named QDeclarativeNetworkAccessManagerFactory. + + \sa {qml/cppextensions/networkaccessmanagerfactory}{NetworkAccessManagerFactory example} */ /*! diff --git a/src/qml/qml/qqmlparserstatus.cpp b/src/qml/qml/qqmlparserstatus.cpp index d4e415a069..8468a1da00 100644 --- a/src/qml/qml/qqmlparserstatus.cpp +++ b/src/qml/qml/qqmlparserstatus.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlParserStatus - \since 4.7 + \since 5.0 + \inmodule QtQml \brief The QQmlParserStatus class provides updates on the QML parser state. QQmlParserStatus provides a mechanism for classes instantiated by @@ -75,6 +76,8 @@ QT_BEGIN_NAMESPACE void componentComplete(); } \endcode + + The QtQuick 1.0 version of this class is named QDeclarativeParserStatus. */ /*! \internal */ diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index b4c6fc3a12..82da62ff45 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -246,6 +246,7 @@ namespace QQmlPrivate QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *); + const QMetaObject *instanceMetaObject; }; enum RegistrationType { diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index d3778fa5c5..f68c345f3a 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -72,7 +72,8 @@ QT_BEGIN_NAMESPACE /*! \class QQmlProperty -\since 4.7 +\since 5.0 +\inmodule QtQml \brief The QQmlProperty class abstracts accessing properties on objects created from QML. As QML uses Qt's meta-type system all of the existing QMetaObject classes can be used to introspect @@ -108,6 +109,8 @@ qWarning() << "Current pixel size:" << property.read().toInt(); property.write(24); qWarning() << "Pixel size should now be 24:" << property.read().toInt(); \endcode + +The QtQuick 1 version of this class was named QDeclarativeProperty. */ /*! @@ -923,15 +926,17 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that) if (!(that.type() & QQmlProperty::SignalProperty)) return 0; - const QObjectList &children = that.d->object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QObject *child = children.at(ii); + QQmlData *data = QQmlData::get(that.d->object); + if (!data) + return 0; - QQmlBoundSignal *signal = QQmlBoundSignal::cast(child); - if (signal && signal->index() == that.index()) - return signal->expression(); - } + QQmlAbstractBoundSignal *signalHandler = data->signalHandlers; + + while (signalHandler && signalHandler->index() != that.index()) + signalHandler = signalHandler->m_nextSignal; + + if (signalHandler) + return signalHandler->expression(); return 0; } @@ -952,19 +957,27 @@ QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that, return 0; } - const QObjectList &children = that.d->object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QObject *child = children.at(ii); + QQmlData *data = QQmlData::get(that.d->object, 0 != expr); + if (!data) + return 0; - QQmlBoundSignal *signal = QQmlBoundSignal::cast(child); - if (signal && signal->index() == that.index()) - return signal->setExpression(expr); - } + QQmlAbstractBoundSignal *signalHandler = data->signalHandlers; + + while (signalHandler && signalHandler->index() != that.index()) + signalHandler = signalHandler->m_nextSignal; + + if (signalHandler) + return signalHandler->setExpression(expr); if (expr) { - QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object); - return signal->setExpression(expr); + QQmlAbstractBoundSignal *signal = 0; + if (that.method().parameterTypes().count()) + signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object); + else + signal = new QQmlBoundSignalNoParams(that.d->object, that.method(), that.d->object); + QQmlExpression *oldExpr = signal->setExpression(expr); + signal->addToObject(); + return oldExpr; } else { return 0; } diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 4a1eb79213..1e8cfb6c20 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -680,7 +680,7 @@ struct StaticQtMetaObject : public QObject { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; } }; -static int EnumType(const QMetaObject *metaobj, const QByteArray &str) +static int EnumType(const QMetaObject *metaobj, const QByteArray &str, int type) { QByteArray scope; QByteArray name; @@ -701,7 +701,7 @@ static int EnumType(const QMetaObject *metaobj, const QByteArray &str) if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) return QVariant::Int; } - return QVariant::Invalid; + return type; } // Returns an array of the arguments for method \a index. The first entry in the array @@ -738,12 +738,16 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) + QMetaType::TypeFlags flags = QMetaType::typeFlags(type); + if (flags & QMetaType::IsEnumeration) type = QVariant::Int; - else if (type == QMetaType::UnknownType) { + else if (type == QMetaType::UnknownType || + (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) && + type != qMetaTypeId<QJSValue>())) { + //the UserType clause is to catch registered QFlags if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); - type = EnumType(object->metaObject(), argTypeNames.at(ii)); + type = EnumType(object->metaObject(), argTypeNames.at(ii), type); } if (type == QMetaType::UnknownType) { if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); @@ -767,12 +771,16 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) + QMetaType::TypeFlags flags = QMetaType::typeFlags(type); + if (flags & QMetaType::IsEnumeration) type = QVariant::Int; - else if (type == QMetaType::UnknownType) { + else if (type == QMetaType::UnknownType || + (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) && + type != qMetaTypeId<QJSValue>())) { + //the UserType clause is to catch registered QFlags) if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); - type = EnumType(object->metaObject(), argTypeNames.at(ii)); + type = EnumType(object->metaObject(), argTypeNames.at(ii), type); } if (type == QMetaType::UnknownType) { if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 352684ed5e..5412315d31 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -724,10 +724,15 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, QMetaMethod signal = target->metaObject()->method(instr.signalIndex); - QQmlBoundSignal *bs = new QQmlBoundSignal(target, signal, target); - QQmlExpression *expr = + QQmlAbstractBoundSignal *bs = 0; + if (signal.parameterTypes().count()) + bs = new QQmlBoundSignal(target, signal, target); + else + bs = new QQmlBoundSignalNoParams(target, signal, target); + QQmlExpression *expr = new QQmlExpression(CTXT, context, DATAS.at(instr.value), true, COMP->name, instr.line, instr.column, *new QQmlExpressionPrivate); bs->setExpression(expr); + bs->addToObject(); QML_END_INSTR(StoreSignal) QML_BEGIN_INSTR(StoreImportedScript) diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index ea4d1afbbc..453120c6c7 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -428,18 +428,18 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast) if (r.isValid()) { if (r.type) { _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); - } /*else if (r.importNamespace) { + } else if (r.importNamespace) { QQmlMetaType::ModuleApiInstance *moduleApi = m_expression->importCache->moduleApi(r.importNamespace); - if (moduleApi) { - if (moduleApi->qobjectCallback) { - moduleApi->qobjectApi = moduleApi->qobjectCallback(QQmlEnginePrivate::get(m_engine), QQmlEnginePrivate::get(m_engine)); - moduleApi->qobjectCallback = 0; - moduleApi->scriptCallback = 0; - } - if (moduleApi->qobjectApi) - _expr.code = _block->MODULE_OBJECT(name, moduleApi->qobjectApi->metaObject(), IR::Name::MemberStorage, line, column); + if (moduleApi && moduleApi->instanceMetaObject) { + // Note: we don't need to check moduleApi->qobjectCallback here, since + // we did that check in registerModuleApi() in qqmlmetatype.cpp. + // We cannot create the QObject Module Api Instance here, + // as we might be running in a loader thread. + // Thus, V4 can only handle bindings which use Module APIs which + // were registered with the templated registration function. + _expr.code = _block->MODULE_OBJECT(name, moduleApi->instanceMetaObject, IR::Name::MemberStorage, line, column); } - }*/ //### we can't create the actual QObject here, as we may be running in a thread (can be reenabled once QTBUG-24894 is handled) + } // We don't support anything else } else { bool found = false; diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index a11f68f709..2e2c8725aa 100644 --- a/src/quick/items/qquickcanvas.cpp +++ b/src/quick/items/qquickcanvas.cpp @@ -389,7 +389,17 @@ void QQuickCanvasPrivate::translateTouchToMouse(QTouchEvent *event) bool doubleClick = event->timestamp() - touchMousePressTimestamp < static_cast<ulong>(qApp->styleHints()->mouseDoubleClickInterval()); touchMousePressTimestamp = event->timestamp(); + QQuickMouseEventEx me = touchToMouseEvent(QEvent::MouseButtonPress, p); + me.setTimestamp(event->timestamp()); + me.setAccepted(false); + me.setCapabilities(event->device()->capabilities()); + deliverMouseEvent(&me); + if (me.isAccepted()) { + touchMouseId = p.id(); + event->setAccepted(true); + } if (doubleClick) { + touchMousePressTimestamp = 0; QQuickMouseEventEx me = touchToMouseEvent(QEvent::MouseButtonDblClick, p); me.setTimestamp(event->timestamp()); me.setAccepted(false); @@ -407,15 +417,6 @@ void QQuickCanvasPrivate::translateTouchToMouse(QTouchEvent *event) } } } - QQuickMouseEventEx me = touchToMouseEvent(QEvent::MouseButtonPress, p); - me.setTimestamp(event->timestamp()); - me.setAccepted(false); - me.setCapabilities(event->device()->capabilities()); - deliverMouseEvent(&me); - if (me.isAccepted()) { - touchMouseId = p.id(); - event->setAccepted(true); - } if (touchMouseId != -1) break; } else if (p.id() == touchMouseId) { @@ -531,7 +532,7 @@ void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F if (oldActiveFocusItem) { #ifndef QT_NO_IM - qApp->inputMethod()->reset(); + qApp->inputMethod()->commit(); #endif activeFocusItem = 0; @@ -627,7 +628,7 @@ void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, Q_ASSERT(oldActiveFocusItem); #ifndef QT_NO_IM - qApp->inputMethod()->reset(); + qApp->inputMethod()->commit(); #endif activeFocusItem = 0; @@ -993,6 +994,10 @@ bool QQuickCanvas::event(QEvent *e) case QEvent::WindowDeactivate: rootItem()->windowDeactivateEvent(); break; + case QEvent::FocusAboutToChange: + if (d->activeFocusItem) + qGuiApp->inputMethod()->commit(); + break; default: break; } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 2a744c0559..1cf10df2f7 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3067,10 +3067,6 @@ void QQuickItem::updatePolish() { } -void QQuickItem::sendAccessibilityUpdate() -{ -} - void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types) { changeListeners.append(ChangeListener(listener, types)); @@ -3316,6 +3312,10 @@ void QQuickItem::setBaselineOffset(qreal offset) anchor->updateVerticalAnchors(); } } + + if (d->_anchors && (d->_anchors->usedAnchors() & QQuickAnchors::BaselineAnchor)) + QQuickAnchorsPrivate::get(d->_anchors)->updateVerticalAnchors(); + emit baselineOffsetChanged(offset); } diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 70a8ebc932..16dee80380 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -399,9 +399,6 @@ protected: virtual void releaseResources(); virtual void updatePolish(); -protected Q_SLOTS: - void sendAccessibilityUpdate(); - protected: QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent = 0); diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 0d95500860..209d30aa74 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -186,6 +186,18 @@ void QQuickItemViewChangeSet::applyChanges(const QQuickChangeSet &changeSet) } } +void QQuickItemViewChangeSet::applyBufferedChanges(const QQuickItemViewChangeSet &other) +{ + if (!other.hasPendingChanges()) + return; + + pendingChanges.apply(other.pendingChanges); + itemCount = other.itemCount; + newCurrentIndex = other.newCurrentIndex; + currentChanged = other.currentChanged; + currentRemoved = other.currentRemoved; +} + void QQuickItemViewChangeSet::prepare(int currentIndex, int count) { if (active) @@ -1044,8 +1056,17 @@ void QQuickItemView::modelUpdated(const QQuickChangeSet &changeSet, bool reset) polish(); } } else { - d->currentChanges.prepare(d->currentIndex, d->itemCount); - d->currentChanges.applyChanges(changeSet); + if (d->disableLayout) { + d->bufferedChanges.prepare(d->currentIndex, d->itemCount); + d->bufferedChanges.applyChanges(changeSet); + } else { + if (d->bufferedChanges.hasPendingChanges()) { + d->currentChanges.applyBufferedChanges(d->bufferedChanges); + d->bufferedChanges.reset(); + } + d->currentChanges.prepare(d->currentIndex, d->itemCount); + d->currentChanges.applyChanges(changeSet); + } polish(); } } @@ -1756,11 +1777,16 @@ void QQuickItemViewPrivate::layout() bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult, ChangeResult *totalRemovalResult) { Q_Q(QQuickItemView); - if (!q->isComponentComplete() || (!currentChanges.hasPendingChanges() && !runDelayedRemoveTransition) || disableLayout) + if (!q->isComponentComplete() || (!currentChanges.hasPendingChanges() && !bufferedChanges.hasPendingChanges() && !runDelayedRemoveTransition) || disableLayout) return false; disableLayout = true; + if (bufferedChanges.hasPendingChanges()) { + currentChanges.applyBufferedChanges(bufferedChanges); + bufferedChanges.reset(); + } + updateUnrequestedIndexes(); moveReason = QQuickItemViewPrivate::Other; diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index 7516761ee8..e352c461d6 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -107,6 +107,8 @@ public: void applyChanges(const QQuickChangeSet &changeSet); + void applyBufferedChanges(const QQuickItemViewChangeSet &other); + int itemCount; int newCurrentIndex; QQuickChangeSet pendingChanges; @@ -245,6 +247,7 @@ public: int requestedIndex; FxViewItem *requestedItem; QQuickItemViewChangeSet currentChanges; + QQuickItemViewChangeSet bufferedChanges; QQmlComponent *highlightComponent; FxViewItem *highlight; diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index b85a449c51..962dddafc9 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -67,8 +67,16 @@ #define QML_FLICK_DISCARDSAMPLES 1 #endif +// The default maximum velocity of a flick. +#ifndef QML_FLICK_DEFAULTMAXVELOCITY +#define QML_FLICK_DEFAULTMAXVELOCITY 2500 +#endif + + QT_BEGIN_NAMESPACE +const qreal MinimumFlickVelocity = 75.0; + inline qreal qmlMod(qreal x, qreal y) { #ifdef QT_USE_MATH_H_FLOATS @@ -105,6 +113,23 @@ void QQuickPathViewAttached::setValue(const QByteArray &name, const QVariant &va m_metaobject->setValue(name, val); } +QQuickPathViewPrivate::QQuickPathViewPrivate() + : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0), lastDist(0) + , lastElapsed(0), offset(0.0), offsetAdj(0.0), mappedRange(1.0) + , stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true) + , autoHighlight(true), highlightUp(false), layoutScheduled(false) + , moving(false), flicking(false), requestedOnPath(false), inRequest(false) + , dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY) + , moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0) + , firstIndex(-1), pathItems(-1), requestedIndex(-1), requestedZ(0) + , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0) + , moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition) + , highlightPosition(0) + , highlightRangeStart(0), highlightRangeEnd(0) + , highlightRangeMode(QQuickPathView::StrictlyEnforceRange) + , highlightMoveDuration(300), modelCount(0) +{ +} void QQuickPathViewPrivate::init() { @@ -975,6 +1000,28 @@ void QQuickPathView::setFlickDeceleration(qreal dec) } /*! + \qmlproperty real QtQuick2::PathView::maximumFlickVelocity + This property holds the approximate maximum velocity that the user can flick the view in pixels/second. + + The default value is platform dependent. +*/ +qreal QQuickPathView::maximumFlickVelocity() const +{ + Q_D(const QQuickPathView); + return d->maximumFlickVelocity; +} + +void QQuickPathView::setMaximumFlickVelocity(qreal vel) +{ + Q_D(QQuickPathView); + if (vel == d->maximumFlickVelocity) + return; + d->maximumFlickVelocity = vel; + emit maximumFlickVelocityChanged(); +} + + +/*! \qmlproperty bool QtQuick2::PathView::interactive A user cannot drag or flick a PathView that is not interactive. @@ -1203,7 +1250,7 @@ void QQuickPathView::mousePressEvent(QMouseEvent *event) void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event) { Q_Q(QQuickPathView); - if (!interactive || !items.count()) + if (!interactive || !items.count() || !model || !modelCount) return; velocityBuffer.clear(); QPointF scenePoint = q->mapToScene(event->localPos()); @@ -1252,7 +1299,7 @@ void QQuickPathView::mouseMoveEvent(QMouseEvent *event) void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event) { Q_Q(QQuickPathView); - if (!interactive || !lastPosTime.isValid()) + if (!interactive || !lastPosTime.isValid() || !model || !modelCount) return; qreal newPc; @@ -1306,14 +1353,22 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *) Q_Q(QQuickPathView); stealMouse = false; q->setKeepMouseGrab(false); - if (!interactive || !lastPosTime.isValid()) + if (!interactive || !lastPosTime.isValid() || !model || !modelCount) { + lastPosTime.invalidate(); + if (!tl.isActive()) + q->movementEnding(); return; + } qreal velocity = calcVelocity(); - if (model && modelCount && qAbs(velocity) > 0.5) { - qreal count = pathItems == -1 ? modelCount : pathItems; - if (qAbs(velocity) > count * 2) // limit velocity - velocity = (velocity > 0 ? count : -count) * 2; + qreal count = modelCount*mappedRange; + qreal pixelVelocity = (path->path().length()/count) * velocity; + if (qAbs(pixelVelocity) > MinimumFlickVelocity) { + if (qAbs(pixelVelocity) > maximumFlickVelocity) { + // limit velocity + qreal maxVel = velocity < 0 ? -maximumFlickVelocity : maximumFlickVelocity; + velocity = maxVel / (path->path().length()/count); + } // Calculate the distance to be travelled qreal v2 = velocity*velocity; qreal accel = deceleration/10; diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h index 8f1ecd6caf..8b15e85b8a 100644 --- a/src/quick/items/qquickpathview_p.h +++ b/src/quick/items/qquickpathview_p.h @@ -73,6 +73,7 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged) Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin NOTIFY dragMarginChanged) + Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged) @@ -126,6 +127,9 @@ public: qreal flickDeceleration() const; void setFlickDeceleration(qreal dec); + qreal maximumFlickVelocity() const; + void setMaximumFlickVelocity(qreal); + bool isInteractive() const; void setInteractive(bool); @@ -160,6 +164,7 @@ Q_SIGNALS: void snapPositionChanged(); void delegateChanged(); void pathItemCountChanged(); + void maximumFlickVelocityChanged(); void flickDecelerationChanged(); void interactiveChanged(); void movingChanged(); diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 412caa6d2b..ac74e9a568 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -74,23 +74,7 @@ class QQuickPathViewPrivate : public QQuickItemPrivate, public QQuickItemChangeL Q_DECLARE_PUBLIC(QQuickPathView) public: - QQuickPathViewPrivate() - : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0), lastDist(0) - , lastElapsed(0), offset(0.0), offsetAdj(0.0), mappedRange(1.0) - , stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true) - , autoHighlight(true), highlightUp(false), layoutScheduled(false) - , moving(false), flicking(false), requestedOnPath(false), inRequest(false) - , dragMargin(0), deceleration(100) - , moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0) - , firstIndex(-1), pathItems(-1), requestedIndex(-1), requestedZ(0) - , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0) - , moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition) - , highlightPosition(0) - , highlightRangeStart(0), highlightRangeEnd(0) - , highlightRangeMode(QQuickPathView::StrictlyEnforceRange) - , highlightMoveDuration(300), modelCount(0) - { - } + QQuickPathViewPrivate(); void init(); @@ -169,6 +153,7 @@ public: QPointF lastPos; qreal dragMargin; qreal deceleration; + qreal maximumFlickVelocity; QQuickTimeLine tl; QQuickTimeLineValueProxy<QQuickPathViewPrivate> moveOffset; int flickDuration; diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index c55b1ca7f5..fffa4d9521 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -210,6 +210,14 @@ void QQuickShaderEffectTexture::setItem(QSGNode *item) if (item == m_item) return; m_item = item; + + if (m_live && !m_item) { + delete m_fbo; + delete m_secondaryFbo; + m_fbo = m_secondaryFbo = 0; + m_depthStencilBuffer.clear(); + } + markDirtyTexture(); } @@ -226,6 +234,14 @@ void QQuickShaderEffectTexture::setSize(const QSize &size) if (size == m_size) return; m_size = size; + + if (m_live && m_size.isNull()) { + delete m_fbo; + delete m_secondaryFbo; + m_fbo = m_secondaryFbo = 0; + m_depthStencilBuffer.clear(); + } + markDirtyTexture(); } @@ -242,6 +258,14 @@ void QQuickShaderEffectTexture::setLive(bool live) if (live == m_live) return; m_live = live; + + if (m_live && (!m_item || m_size.isNull())) { + delete m_fbo; + delete m_secondaryFbo; + m_fbo = m_secondaryFbo = 0; + m_depthStencilBuffer.clear(); + } + markDirtyTexture(); } @@ -613,6 +637,8 @@ void QQuickShaderEffectSource::setWrapMode(WrapMode mode) \qmlproperty Item ShaderEffectSource::sourceItem This property holds the element to be rendered into the texture. + Setting this to null while \l live is true, will release the texture + resources. */ QQuickItem *QQuickShaderEffectSource::sourceItem() const @@ -750,8 +776,8 @@ void QQuickShaderEffectSource::setFormat(QQuickShaderEffectSource::Format format \qmlproperty bool ShaderEffectSource::live If this property is true, the texture is updated whenever the - \l sourceItem changes. Otherwise, it will be a frozen image of the - \l sourceItem. The property is true by default. + \l sourceItem updates. Otherwise, it will be a frozen image, even if + \l sourceItem is assigned a new element. The property is true by default. */ bool QQuickShaderEffectSource::live() const diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index d7303352c5..e1a28a466a 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -402,7 +402,7 @@ void QQuickTextPrivate::updateSize() if (text.isEmpty()) { qreal fontHeight = fm.height(); q->setImplicitSize(0, fontHeight); - layedOutTextRect = QRect(0, 0, 0, fontHeight); + layedOutTextRect = QRectF(0, 0, 0, fontHeight); emit q->contentSizeChanged(); updateType = UpdatePaintNode; q->update(); @@ -2001,7 +2001,20 @@ QRectF QQuickText::boundingRect() const // Could include font max left/right bearings to either side of rectangle. - int h = height(); + qreal w = width(); + switch (d->hAlign) { + case AlignLeft: + case AlignJustify: + break; + case AlignRight: + rect.moveLeft(w - rect.width()); + break; + case AlignHCenter: + rect.moveLeft((w - rect.width()) / 2); + break; + } + + qreal h = height(); switch (d->vAlign) { case AlignTop: break; diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 1846d03b9b..eefe938467 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -1459,7 +1459,6 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } } layout->setAdditionalFormats(overrides); - tentativeCommit = e->tentativeCommitString(); cursor.endEditBlock(); @@ -1503,7 +1502,6 @@ void QQuickTextControlPrivate::focusEvent(QFocusEvent *e) if (e->gotFocus()) { setBlinkingCursorEnabled(interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard)); } else { - commitPreedit(); setBlinkingCursorEnabled(false); if (cursorIsFocusIndicator @@ -1732,14 +1730,12 @@ void QQuickTextControlPrivate::commitPreedit() if (!isPreediting()) return; - cursor.beginEditBlock(); - qApp->inputMethod()->reset(); + qApp->inputMethod()->commit(); - if (!tentativeCommit.isEmpty()) { - cursor.insertText(tentativeCommit); - tentativeCommit.clear(); - } + if (!isPreediting()) + return; + cursor.beginEditBlock(); preeditCursor = 0; QTextBlock block = cursor.block(); QTextLayout *layout = block.layout(); @@ -1767,17 +1763,12 @@ Qt::TextInteractionFlags QQuickTextControl::textInteractionFlags() const QString QQuickTextControl::toPlainText() const { - Q_D(const QQuickTextControl); - QString plainText = document()->toPlainText(); - if (!d->tentativeCommit.isEmpty()) - plainText.insert(textCursor().position(), d->tentativeCommit); - return plainText; + return document()->toPlainText(); } #ifndef QT_NO_TEXTHTMLPARSER QString QQuickTextControl::toHtml() const { - // note: currently not including tentative commit return document()->toHtml(); } #endif diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h index 9d776ce46b..c5a39cc759 100644 --- a/src/quick/items/qquicktextcontrol_p_p.h +++ b/src/quick/items/qquicktextcontrol_p_p.h @@ -137,7 +137,6 @@ public: QTextCursor cursor; QTextCursor selectedWordOnDoubleClick; QTextCursor selectedBlockOnTrippleClick; - QString tentativeCommit; QString highlightedAnchor; // Anchor below cursor QString anchorOnMousePress; QString linkToCopy; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 94856b63ab..f2da67bae7 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -119,8 +119,6 @@ QString QQuickTextInput::text() const Q_D(const QQuickTextInput); QString content = d->m_text; - if (!d->m_tentativeCommit.isEmpty()) - content.insert(d->m_cursor, d->m_tentativeCommit); QString res = d->m_maskData ? d->stripString(content) : content; return (res.isNull() ? QString::fromLatin1("") : res); } @@ -132,7 +130,6 @@ void QQuickTextInput::setText(const QString &s) return; if (d->composeMode()) qApp->inputMethod()->reset(); - d->m_tentativeCommit.clear(); d->internalSetText(s, -1, false); } @@ -2496,7 +2493,6 @@ void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value) } if (!hasFocus) { - d->commitPreedit(); if (!d->persistentSelection) d->deselect(); disconnect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)), @@ -2831,21 +2827,16 @@ void QQuickTextInputPrivate::paste(QClipboard::Mode clipboardMode) /*! \internal - - Exits preedit mode and commits parts marked as tentative commit */ void QQuickTextInputPrivate::commitPreedit() { if (!composeMode()) return; - qApp->inputMethod()->reset(); + qApp->inputMethod()->commit(); - if (!m_tentativeCommit.isEmpty()) { - internalInsert(m_tentativeCommit); - m_tentativeCommit.clear(); - finishChange(-1, true/*not used, not documented*/, false); - } + if (!composeMode()) + return; m_preeditCursor = 0; m_textLayout.setPreeditArea(-1, QString()); @@ -3160,14 +3151,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event) q->updateCursorRectangle(); } - bool tentativeCommitChanged = m_tentativeCommit != event->tentativeCommitString(); - - if (tentativeCommitChanged) { - m_textDirty = true; - m_tentativeCommit = event->tentativeCommitString(); - } - - if (isGettingInput || tentativeCommitChanged) + if (isGettingInput) finishChange(priorState); if (selectionChange) { @@ -3237,15 +3221,6 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo return true; } m_cursor = cursorCopy; - - if (!m_tentativeCommit.isEmpty()) { - textCopy.insert(m_cursor, m_tentativeCommit); - bool validInput = m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid; - if (!validInput) - m_tentativeCommit.clear(); - } - } else { - m_tentativeCommit.clear(); } } #endif diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 165155acd0..3bd34b2661 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -188,7 +188,6 @@ public: QString m_text; QString m_inputMask; QString m_cancelText; - QString m_tentativeCommit; QFont font; QFont sourceFont; diff --git a/src/quick/items/qquickwindowmanager.cpp b/src/quick/items/qquickwindowmanager.cpp index 61c2ef24b4..bac5cc7582 100644 --- a/src/quick/items/qquickwindowmanager.cpp +++ b/src/quick/items/qquickwindowmanager.cpp @@ -1120,7 +1120,8 @@ void QQuickRenderThreadSingleContextWindowManager::maybeUpdate(QQuickCanvas *) void QQuickRenderThreadSingleContextWindowManager::wakeup() { lockInGui(); - if (isRenderBlocked) + isExternalUpdatePending = true; + if (isRenderBlocked || isPostingSyncEvent) wake(); unlockInGui(); } diff --git a/src/quick/util/qquickconnections.cpp b/src/quick/util/qquickconnections.cpp index 533c7013ef..acc9738f2c 100644 --- a/src/quick/util/qquickconnections.cpp +++ b/src/quick/util/qquickconnections.cpp @@ -283,6 +283,7 @@ void QQuickConnections::connectSignals() QQmlExpression *expression = ctxtdata ? QQmlExpressionPrivate::create(ctxtdata, 0, script, true, location, line, column) : 0; signal->setExpression(expression); + signal->addToObject(); d->boundsignals += signal; } else { if (!d->ignoreUnknownSignals) diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index 1d838cac32..b306ab3419 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -53,6 +53,7 @@ public: \class QQuickTextureFactory \since 5.0 \brief The QQuickTextureFactory class provides an interface for loading custom textures from QML. + \inmodule QtQml The purpose of the texture factory is to provide a placeholder for a image data that can be converted into an OpenGL texture. @@ -110,7 +111,8 @@ QImage QQuickTextureFactory::image() const /*! \class QQuickImageProvider - \since 4.7 + \since 5.0 + \inmodule QtQuick \brief The QQuickImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML. QQuickImageProvider is used to provide advanced image loading features @@ -218,6 +220,8 @@ QImage QQuickTextureFactory::image() const \c cache property to \c false for the relevant \l Image, \l BorderImage or \l AnimatedImage object. + The QtQuick 1 version of this class is named QDeclarativeImageProvider. + \sa QQmlEngine::addImageProvider() */ |