From fc8adfea9f5e09e5f47ac4e592e5d9db471caede Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 29 Nov 2013 13:21:38 +0100 Subject: [PATCH] Introduce helper for QML to allow creating QWidget hierarchies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1259c5768e410361bcd8b5cf0c2057a2ebabda83 in qtdeclarative removed the ability to create QWidgets in QML by giving them the correct parent, which requires calling QWidget::setParent instead of QObject::setParent. This patch introduces a hook that will allow QtQml to give widgets a proper parent. Change-Id: I84c57ca5032582c43e405219343d55ac9cf2ffa0 Reviewed-by: Jørgen Lind --- src/corelib/kernel/qobject.cpp | 1 + src/corelib/kernel/qobject_p.h | 1 + src/widgets/kernel/qapplication.cpp | 3 +++ src/widgets/kernel/qwidget.cpp | 8 ++++++++ src/widgets/kernel/qwidget_p.h | 2 ++ .../auto/widgets/kernel/qwidget/tst_qwidget.cpp | 17 +++++++++++++++++ 6 files changed, 32 insertions(+) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 223de0c8e0..2f9ef9ca4a 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -177,6 +177,7 @@ void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObj void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = 0; int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = 0; bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = 0; +void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = 0; QObjectData::~QObjectData() {} diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index b663bc8d8c..dba5f0265f 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -87,6 +87,7 @@ public: static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **); static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int); static bool (*isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int); + static void (*setWidgetParent)(QObject *, QObject *); // Used by the QML engine to specify parents for widgets. Set by QtWidgets. }; // This is an implementation of QAbstractDeclarativeData that is identical with diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index bf05b2029b..392db60e2b 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -630,6 +630,9 @@ void QApplicationPrivate::initialize() // needed for a static build. qRegisterWidgetsVariant(); + // needed for widgets in QML + QAbstractDeclarativeData::setWidgetParent = QWidgetPrivate::setWidgetParentHelper; + if (application_type != QApplicationPrivate::Tty) (void) QApplication::style(); // trigger creation of application style #ifndef QT_NO_STATEMACHINE diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 7b7600fdc3..403e64d1ba 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -12779,6 +12779,14 @@ void QWidget::clearMask() setMask(QRegion()); } +void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent) +{ + Q_ASSERT(widgetAsObject->isWidgetType()); + Q_ASSERT(!newParent || newParent->isWidgetType()); + QWidget *widget = static_cast(widgetAsObject); + widget->setParent(static_cast(newParent)); +} + QT_END_NAMESPACE #include "moc_qwidget.cpp" diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 50a8066a41..afc2cfc06b 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -653,6 +653,8 @@ public: virtual void resolveSamples() { } #endif + static void setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent); + // Variables. // Regular pointers (keep them together to avoid gaps on 64 bit architectures). QWExtra *extra; diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 000cefb524..8f3f12e7ff 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -439,6 +439,8 @@ private slots: void resizeStaticContentsChildWidget_QTBUG35282(); + void qmlSetParentHelper(); + private: bool ensureScreenSize(int width, int height); QWidget *testWidget; @@ -10396,5 +10398,20 @@ void tst_QWidget::resizeStaticContentsChildWidget_QTBUG35282() QVERIFY(childWidget.numPaintEvents >= 1); } +void tst_QWidget::qmlSetParentHelper() +{ +#ifdef QT_BUILD_INTERNAL + QWidget parent; + QWidget child; + QVERIFY(QAbstractDeclarativeData::setWidgetParent); + QAbstractDeclarativeData::setWidgetParent(&child, &parent); + QVERIFY(child.parentWidget() == &parent); + QAbstractDeclarativeData::setWidgetParent(&child, 0); + QVERIFY(!child.parentWidget()); +#else + QSKIP("Needs QT_BUILD_INTERNAL"); +#endif +} + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc"