Allow QObjects to opt in to receiving ParentAboutToChange/ParentChange
QWidget already handles this, but it might be useful for non-Widget object hierarchies as well, such as in Qt Quick. The flag is opt in, and as QWidget already handles these events by itself (without checking any flags), we assert that we don't end up in this code path, instead of enabling it for QWidget. The latter would mean refactoring the QWidget code, with possible regressions. Docs and header comments have been updated to reflect that this event is not widget specific. (This is an issue with other events as well, that are documented to say "widget", since they came from a time when there was only QWidget, but nowadays apply to e.g. QWindow as well. That's something for another fix though). Change-Id: Ib71962131d6011c17dcce8c01bd8adcdaa58d798 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>bb10
parent
bb2f551b32
commit
4ba7a76985
|
|
@ -159,8 +159,10 @@ Q_TRACE_POINT(qtcore, QEvent_dtor, QEvent *event, QEvent::Type type);
|
|||
\value OrientationChange The screens orientation has changes (QScreenOrientationChangeEvent).
|
||||
\value Paint Screen update necessary (QPaintEvent).
|
||||
\value PaletteChange Palette of the widget changed.
|
||||
\value ParentAboutToChange The widget parent is about to change.
|
||||
\value ParentChange The widget parent has changed.
|
||||
\value ParentAboutToChange The object parent is about to change.
|
||||
Only sent to some object types, such as QWidget.
|
||||
\value ParentChange The object parent has changed.
|
||||
Only sent to some object types, such as QWidget.
|
||||
\value PlatformPanel A platform specific panel has been requested.
|
||||
\value PlatformSurface A native platform surface has been created or is about to be destroyed (QPlatformSurfaceEvent).
|
||||
\omitvalue Pointer
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
Hide = 18, // widget is hidden
|
||||
Close = 19, // request to close widget
|
||||
Quit = 20, // request to quit application
|
||||
ParentChange = 21, // widget has been reparented
|
||||
ParentChange = 21, // object has been reparented
|
||||
ParentAboutToChange = 131, // sent just before the parent change is done
|
||||
ThreadChange = 22, // object has changed threads
|
||||
WindowActivate = 24, // window was activated
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ QObjectPrivate::QObjectPrivate(int version)
|
|||
isQuickItem = false;
|
||||
willBeWidget = false;
|
||||
wasWidget = false;
|
||||
receiveParentEvents = false; // If object wants ParentAboutToChange and ParentChange
|
||||
}
|
||||
|
||||
QObjectPrivate::~QObjectPrivate()
|
||||
|
|
@ -2249,7 +2250,15 @@ void QObjectPrivate::setParent_helper(QObject *o)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (receiveParentEvents) {
|
||||
Q_ASSERT(!isWidget); // Handled in QWidget
|
||||
QEvent e(QEvent::ParentAboutToChange);
|
||||
QCoreApplication::sendEvent(q, &e);
|
||||
}
|
||||
|
||||
parent = o;
|
||||
|
||||
if (parent) {
|
||||
// object hierarchies are constrained to a single thread
|
||||
if (threadData.loadRelaxed() != parent->d_func()->threadData.loadRelaxed()) {
|
||||
|
|
@ -2265,6 +2274,12 @@ void QObjectPrivate::setParent_helper(QObject *o)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (receiveParentEvents) {
|
||||
Q_ASSERT(!isWidget); // Handled in QWidget
|
||||
QEvent e(QEvent::ParentChange);
|
||||
QCoreApplication::sendEvent(q, &e);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ public:
|
|||
uint isQuickItem : 1;
|
||||
uint willBeWidget : 1; // for handling widget-specific bits in QObject's ctor
|
||||
uint wasWidget : 1; // for properly cleaning up in QObject's dtor
|
||||
uint unused : 21;
|
||||
uint receiveParentEvents: 1;
|
||||
uint unused : 20;
|
||||
QAtomicInt postedEvents;
|
||||
QDynamicMetaObjectData *metaObject;
|
||||
QBindingStorage bindingStorage;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ private slots:
|
|||
void signalBlocking();
|
||||
void blockingQueuedConnection();
|
||||
void childEvents();
|
||||
void parentEvents();
|
||||
void installEventFilter();
|
||||
void deleteSelfInSlot();
|
||||
void disconnectSelfInSlotAndDeleteAfterEmit();
|
||||
|
|
@ -3200,6 +3201,78 @@ void tst_QObject::childEvents()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_QObject::parentEvents()
|
||||
{
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
EventSpy::EventList expected;
|
||||
|
||||
{
|
||||
// Parent events not enabled
|
||||
QObject parent;
|
||||
QObject child;
|
||||
|
||||
EventSpy spy;
|
||||
child.installEventFilter(&spy);
|
||||
|
||||
QCoreApplication::postEvent(&child, new QEvent(QEvent::Type(QEvent::User + 1)));
|
||||
|
||||
child.setParent(&parent);
|
||||
|
||||
QCoreApplication::postEvent(&child, new QEvent(QEvent::Type(QEvent::User + 2)));
|
||||
|
||||
expected =
|
||||
EventSpy::EventList();
|
||||
QCOMPARE(spy.eventList(), expected);
|
||||
spy.clear();
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
expected =
|
||||
EventSpy::EventList()
|
||||
<< qMakePair(&child, QEvent::Type(QEvent::User + 1))
|
||||
<< qMakePair(&child, QEvent::Type(QEvent::User + 2));
|
||||
QCOMPARE(spy.eventList(), expected);
|
||||
}
|
||||
|
||||
{
|
||||
// Parent events enabled
|
||||
QObject parent;
|
||||
QObject child;
|
||||
auto *childPrivate = QObjectPrivate::get(&child);
|
||||
childPrivate->receiveParentEvents = true;
|
||||
|
||||
EventSpy spy;
|
||||
child.installEventFilter(&spy);
|
||||
|
||||
QCoreApplication::postEvent(&child, new QEvent(QEvent::Type(QEvent::User + 1)));
|
||||
|
||||
child.setParent(&parent);
|
||||
child.setParent(nullptr);
|
||||
|
||||
QCoreApplication::postEvent(&child, new QEvent(QEvent::Type(QEvent::User + 2)));
|
||||
|
||||
expected =
|
||||
EventSpy::EventList()
|
||||
<< qMakePair(&child, QEvent::ParentAboutToChange)
|
||||
<< qMakePair(&child, QEvent::ParentChange)
|
||||
<< qMakePair(&child, QEvent::ParentAboutToChange)
|
||||
<< qMakePair(&child, QEvent::ParentChange);
|
||||
QCOMPARE(spy.eventList(), expected);
|
||||
spy.clear();
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
expected =
|
||||
EventSpy::EventList()
|
||||
<< qMakePair(&child, QEvent::Type(QEvent::User + 1))
|
||||
<< qMakePair(&child, QEvent::Type(QEvent::User + 2));
|
||||
QCOMPARE(spy.eventList(), expected);
|
||||
}
|
||||
#else
|
||||
QSKIP("Needs QT_BUILD_INTERNAL");
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QObject::installEventFilter()
|
||||
{
|
||||
QEvent event(QEvent::User);
|
||||
|
|
|
|||
Loading…
Reference in New Issue