一路跟踪源码,关键就是这两句:
int QDialog::exec() { Q_D(QDialog); if (d->eventLoop) { qWarning("QDialog::exec: Recursive call detected"); return -1; } bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose, false); d->resetModalitySetByOpen(); bool wasShowModal = testAttribute(Qt::WA_ShowModal); setAttribute(Qt::WA_ShowModal, true); setResult(0); show(); QPointer<QDialog> guard = this; if (d->nativeDialogInUse) { d->platformHelper()->exec(); } else { QEventLoop eventLoop; d->eventLoop = &eventLoop; (void) eventLoop.exec(QEventLoop::DialogExec); } if (guard.isNull()) return QDialog::Rejected; d->eventLoop = 0; setAttribute(Qt::WA_ShowModal, wasShowModal); int res = result(); if (d->nativeDialogInUse) d->helperDone(static_cast<QDialog::DialogCode>(res), d->platformHelper()); if (deleteOnClose) delete this; return res; } void QWidget::hide() { setVisible(false); } void QDialog::setVisible(bool visible) { Q_D(QDialog); if (!testAttribute(Qt::WA_DontShowOnScreen) && d->canBeNativeDialog() && d->setNativeDialogVisible(visible)) return; if (visible) { if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) return; QWidget::setVisible(visible); showExtension(d->doShowExtension); QWidget *fw = window()->focusWidget(); if (!fw) fw = this; /* The following block is to handle a special case, and does not really follow propper logic in concern of autoDefault and TAB order. However, it's here to ease usage for the users. If a dialog has a default QPushButton, and first widget in the TAB order also is a QPushButton, then we give focus to the main default QPushButton. This simplifies code for the developers, and actually catches most cases... If not, then they simply have to use [widget*]->setFocus() themselves... */ if (d->mainDef && fw->focusPolicy() == Qt::NoFocus) { QWidget *first = fw; while ((first = first->nextInFocusChain()) != fw && first->focusPolicy() == Qt::NoFocus) ; if (first != d->mainDef && qobject_cast<QPushButton*>(first)) d->mainDef->setFocus(); } if (!d->mainDef && isWindow()) { QWidget *w = fw; while ((w = w->nextInFocusChain()) != fw) { QPushButton *pb = qobject_cast<QPushButton *>(w); if (pb && pb->autoDefault() && pb->focusPolicy() != Qt::NoFocus) { pb->setDefault(true); break; } } } if (fw && !fw->hasFocus()) { QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason); QApplication::sendEvent(fw, &e); } #ifndef QT_NO_ACCESSIBILITY QAccessibleEvent event(this, QAccessible::DialogStart); QAccessible::updateAccessibility(&event); #endif } else { if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) return; #ifndef QT_NO_ACCESSIBILITY if (isVisible()) { QAccessibleEvent event(this, QAccessible::DialogEnd); QAccessible::updateAccessibility(&event); } #endif // Reimplemented to exit a modal event loop when the dialog is hidden. QWidget::setVisible(visible); if (d->eventLoop) d->eventLoop->exit(); } const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); if (d->mainDef && isActiveWindow() && theme->themeHint(QPlatformTheme::DialogSnapToDefaultButton).toBool()) QCursor::setPos(d->mainDef->mapToGlobal(d->mainDef->rect().center())); }
最新评论