void QObject::setParent(QObject *newParent) { // QWidget overrides this methods if (newParent == m_parent) { return; } if (m_parent) { // remove the current object from the old m_parent m_children list if (m_parent->m_wasDeleted && m_wasDeleted && m_parent->m_currentChildBeingDeleted == this) { // QObject::deleteChildren() cleared our entry for m_parent->m_children } else { const int index = m_parent->m_children.indexOf(this); if (m_parent->m_wasDeleted) { m_parent->m_children[index] = 0; } else { m_parent->m_children.removeAt(index); if (m_sendChildEvents && m_parent->m_receiveChildEvents && ! m_sentChildRemoved) { QChildEvent e(QEvent::ChildRemoved, this); QCoreApplication::sendEvent(m_parent, &e); } } } } m_parent = newParent; if (m_parent) { // object hierarchies are constrained to a single thread if (m_threadData != m_parent->m_threadData) { qWarning("QObject::setParent() Can not set parent, new parent is in a different thread"); m_parent = 0; return; } m_parent->m_children.append(this); if (m_sendChildEvents && m_parent->m_receiveChildEvents) { if (! isWidgetType()) { QChildEvent e(QEvent::ChildAdded, this); QCoreApplication::sendEvent(m_parent, &e); } } } if (! m_wasDeleted && m_declarativeData) { CSAbstractDeclarativeData::parentChanged(m_declarativeData, this, newParent); } }
void QObject::moveToThread(QThread *targetThread) { if (m_threadData.load()->thread == targetThread) { // object is already in this thread return; } if (m_parent != 0) { qWarning("QObject::moveToThread() Can not move an object with a parent"); return; } if (isWidgetType()) { qWarning("QObject::moveToThread() Widgets can not be moved to a new thread"); return; } QThreadData *currentData = QThreadData::current(); QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : new QThreadData(0); QThreadData *threadData = m_threadData.load(); if (threadData->thread == 0 && currentData == targetData) { // exception: allow moving objects with no thread affinity to the current thread currentData = threadData; } else if (threadData != currentData) { qWarning("QObject::moveToThread() Current thread (%p) is not the current object's thread (%p).\n" "Can not move to target thread (%p)\n", currentData->thread, threadData->thread, targetData->thread); #ifdef Q_WS_MAC qWarning("Multiple libraries might be loaded in the same process. Verify all plugins are " "linked with the correct binaries. Export DYLD_PRINT_LIBRARIES=1 and verify only one set of " "binaries are being loaded."); #endif return; } // prepare to move this->moveToThread_helper(); QOrderedMutexLocker locker(¤tData->postEventList.mutex, &targetData->postEventList.mutex); // keep currentData alive currentData->ref(); // move the object this->setThreadData_helper(currentData, targetData); locker.unlock(); currentData->deref(); }
/** depth first search of widgets hierarchy, from application topLevelWidgets */ static QWidget *search_widget(std::function<bool(QWidget* w)> match) { foreach (auto widget, QApplication::topLevelWidgets()) { QStack<QObject*> s; s.push(widget); while (!s.isEmpty()) { auto p = qobject_cast<QWidget*>(s.pop()); if (match(p)) return p; foreach (auto c, p->children()) if (c->isWidgetType()) s.push(c); } }