138QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient)
139 : orientation(orient), buttonLayout(
nullptr), center(
false)
141 struct EventFilter :
public QObject
143 EventFilter(QDialogButtonBoxPrivate *d) : d(d) {};
145 bool eventFilter(QObject *obj, QEvent *event) override
147 QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
148 return button ? d->handleButtonShowAndHide(button, event) :
false;
152 QDialogButtonBoxPrivate *d;
156 filter.reset(
new EventFilter(
this));
159void QDialogButtonBoxPrivate::initLayout()
161 Q_Q(QDialogButtonBox);
162 layoutPolicy = QDialogButtonBox::ButtonLayout(q->style()->styleHint(QStyle::SH_DialogButtonLayout,
nullptr, q));
163 bool createNewLayout = buttonLayout ==
nullptr
164 || (orientation == Qt::Horizontal && qobject_cast<QVBoxLayout *>(buttonLayout) != 0)
165 || (orientation == Qt::Vertical && qobject_cast<QHBoxLayout *>(buttonLayout) != 0);
166 if (createNewLayout) {
168 if (orientation == Qt::Horizontal)
169 buttonLayout =
new QHBoxLayout(q);
171 buttonLayout =
new QVBoxLayout(q);
174 int left, top, right, bottom;
175 setLayoutItemMargins(QStyle::SE_PushButtonLayoutItem);
176 getLayoutItemMargins(&left, &top, &right, &bottom);
177 buttonLayout->setContentsMargins(-left, -top, -right, -bottom);
179 if (!q->testAttribute(Qt::WA_WState_OwnSizePolicy)) {
180 QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::ButtonBox);
181 if (orientation == Qt::Vertical)
183 q->setSizePolicy(sp);
184 q->setAttribute(Qt::WA_WState_OwnSizePolicy,
false);
208void QDialogButtonBoxPrivate::layoutButtons()
210 Q_Q(QDialogButtonBox);
211 const int MacGap = 36 - 8;
213 QScopedValueRollback blocker(ignoreShowAndHide,
true);
214 for (
int i = buttonLayout->count() - 1; i >= 0; --i) {
215 QLayoutItem *item = buttonLayout->takeAt(i);
216 if (QWidget *widget = item->widget())
221 int tmpPolicy = layoutPolicy;
223 static const int M = 5;
224 static const int ModalRoles[M] = { QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::RejectRole,
225 QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::YesRole, QPlatformDialogHelper::NoRole };
226 if (tmpPolicy == QDialogButtonBox::MacLayout) {
227 bool hasModalButton =
false;
228 for (
int i = 0; i < M; ++i) {
229 if (!buttonLists[ModalRoles[i]].isEmpty()) {
230 hasModalButton =
true;
238 const int *currentLayout = QPlatformDialogHelper::buttonLayout(
239 orientation,
static_cast<QPlatformDialogHelper::ButtonLayout>(tmpPolicy));
242 buttonLayout->addStretch();
244 const QList<QAbstractButton *> &acceptRoleList = buttonLists[QPlatformDialogHelper::AcceptRole];
246 while (*currentLayout != QPlatformDialogHelper::EOL) {
247 int role = (*currentLayout & ~QPlatformDialogHelper::Reverse);
248 bool reverse = (*currentLayout & QPlatformDialogHelper::Reverse);
251 case QPlatformDialogHelper::Stretch:
253 buttonLayout->addStretch();
255 case QPlatformDialogHelper::AcceptRole: {
256 if (acceptRoleList.isEmpty())
259 QAbstractButton *button = acceptRoleList.first();
260 buttonLayout->addWidget(button);
264 case QPlatformDialogHelper::AlternateRole:
265 if (acceptRoleList.size() > 1)
266 addButtonsToLayout(acceptRoleList.mid(1), reverse);
268 case QPlatformDialogHelper::DestructiveRole:
270 const QList<QAbstractButton *> &list = buttonLists[role];
273
274
275
276
277
278
279
280 if (tmpPolicy == QDialogButtonBox::MacLayout
281 && !list.isEmpty() && buttonLayout->count() > 1)
282 buttonLayout->addSpacing(MacGap);
284 addButtonsToLayout(list, reverse);
287
288
289
290 if (tmpPolicy == QDialogButtonBox::MacLayout && !list.isEmpty())
291 buttonLayout->addSpacing(MacGap);
294 case QPlatformDialogHelper::RejectRole:
295 case QPlatformDialogHelper::ActionRole:
296 case QPlatformDialogHelper::HelpRole:
297 case QPlatformDialogHelper::YesRole:
298 case QPlatformDialogHelper::NoRole:
299 case QPlatformDialogHelper::ApplyRole:
300 case QPlatformDialogHelper::ResetRole:
301 addButtonsToLayout(buttonLists[role], reverse);
306 QWidgetList layoutWidgets;
307 for (
int i = 0; i < buttonLayout->count(); ++i) {
308 if (
auto *widget = buttonLayout->itemAt(i)->widget())
309 layoutWidgets << widget;
312 q->setFocusProxy(
nullptr);
313 if (!layoutWidgets.isEmpty()) {
314 QWidget *prev = layoutWidgets.constLast();
315 for (QWidget *here : layoutWidgets) {
316 QWidget::setTabOrder(prev, here);
318 if (
auto *pushButton = qobject_cast<QPushButton *>(prev); pushButton && pushButton->isDefault())
319 q->setFocusProxy(pushButton);
324 buttonLayout->addStretch();
327QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardButton sbutton,
328 LayoutRule layoutRule)
330 Q_Q(QDialogButtonBox);
334 case QDialogButtonBox::Ok:
335 icon = QStyle::SP_DialogOkButton;
337 case QDialogButtonBox::Save:
338 icon = QStyle::SP_DialogSaveButton;
340 case QDialogButtonBox::Open:
341 icon = QStyle::SP_DialogOpenButton;
343 case QDialogButtonBox::Cancel:
344 icon = QStyle::SP_DialogCancelButton;
346 case QDialogButtonBox::Close:
347 icon = QStyle::SP_DialogCloseButton;
349 case QDialogButtonBox::Apply:
350 icon = QStyle::SP_DialogApplyButton;
352 case QDialogButtonBox::Reset:
353 icon = QStyle::SP_DialogResetButton;
355 case QDialogButtonBox::Help:
356 icon = QStyle::SP_DialogHelpButton;
358 case QDialogButtonBox::Discard:
359 icon = QStyle::SP_DialogDiscardButton;
361 case QDialogButtonBox::Yes:
362 icon = QStyle::SP_DialogYesButton;
364 case QDialogButtonBox::No:
365 icon = QStyle::SP_DialogNoButton;
367 case QDialogButtonBox::YesToAll:
368 icon = QStyle::SP_DialogYesToAllButton;
370 case QDialogButtonBox::NoToAll:
371 icon = QStyle::SP_DialogNoToAllButton;
373 case QDialogButtonBox::SaveAll:
374 icon = QStyle::SP_DialogSaveAllButton;
376 case QDialogButtonBox::Abort:
377 icon = QStyle::SP_DialogAbortButton;
379 case QDialogButtonBox::Retry:
380 icon = QStyle::SP_DialogRetryButton;
382 case QDialogButtonBox::Ignore:
383 icon = QStyle::SP_DialogIgnoreButton;
385 case QDialogButtonBox::RestoreDefaults:
386 icon = QStyle::SP_RestoreDefaultsButton;
388 case QDialogButtonBox::NoButton:
392 QPushButton *button =
new QPushButton(QGuiApplicationPrivate::platformTheme()->standardButtonText(sbutton), q);
393 QStyle *style = q->style();
394 if (style->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons,
nullptr, q) && icon != 0)
395 button->setIcon(style->standardIcon(QStyle::StandardPixmap(icon),
nullptr, q));
396 if (style != QApplication::style())
397 button->setStyle(style);
398 standardButtonMap.insert(button, sbutton);
399 QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(
static_cast<QPlatformDialogHelper::StandardButton>(sbutton));
400 if (Q_UNLIKELY(role == QPlatformDialogHelper::InvalidRole))
401 qWarning(
"QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
403 addButton(button,
static_cast<QDialogButtonBox::ButtonRole>(role), layoutRule);
404#if QT_CONFIG(shortcut)
405 const QKeySequence standardShortcut = QGuiApplicationPrivate::platformTheme()->standardButtonShortcut(sbutton);
406 if (!standardShortcut.isEmpty())
407 button->setShortcut(standardShortcut);
412void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role,
413 LayoutRule layoutRule, AddRule addRule)
415 buttonLists[role].append(button);
417 case AddRule::Connect:
418 QObjectPrivate::connect(button, &QAbstractButton::clicked,
419 this, &QDialogButtonBoxPrivate::handleButtonClicked);
420 QObjectPrivate::connect(button, &QAbstractButton::destroyed,
421 this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
422 button->installEventFilter(filter.get());
424 case AddRule::SkipConnect:
428 switch (layoutRule) {
429 case LayoutRule::DoLayout:
432 case LayoutRule::SkipLayout:
665void QDialogButtonBox::clear()
667 Q_D(QDialogButtonBox);
670 d->standardButtonMap.clear();
671 for (
int i = 0; i < NRoles; ++i) {
672 QList<QAbstractButton *> &list = d->buttonLists[i];
673 for (
auto button : std::as_const(list)) {
674 QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
675 d, &QDialogButtonBoxPrivate::handleButtonDestroyed);
754void QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveReason reason)
760 hiddenButtons.remove(button);
761 for (
int i = 0; i < QDialogButtonBox::NRoles; ++i)
762 buttonLists[i].removeOne(button);
765 case RemoveReason::ManualRemove:
766 button->setParent(
nullptr);
767 QObjectPrivate::disconnect(button, &QAbstractButton::clicked,
768 this, &QDialogButtonBoxPrivate::handleButtonClicked);
769 QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
770 this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
771 button->removeEventFilter(filter.get());
773 case RemoveReason::Destroyed:
774 standardButtonMap.remove(
reinterpret_cast<QPushButton *>(button));
776 case RemoveReason::HideEvent:
893void QDialogButtonBoxPrivate::handleButtonClicked()
895 Q_Q(QDialogButtonBox);
896 if (QAbstractButton *button = qobject_cast<QAbstractButton *>(q->sender())) {
901 const QDialogButtonBox::ButtonRole buttonRole = q->buttonRole(button);
902 QPointer<QDialogButtonBox> guard(q);
904 emit q->clicked(button);
909 switch (QPlatformDialogHelper::ButtonRole(buttonRole)) {
910 case QPlatformDialogHelper::AcceptRole:
911 case QPlatformDialogHelper::YesRole:
914 case QPlatformDialogHelper::RejectRole:
915 case QPlatformDialogHelper::NoRole:
918 case QPlatformDialogHelper::HelpRole:
919 emit q->helpRequested();
934bool QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton *button, QEvent *event)
936 Q_Q(QDialogButtonBox);
938 const QEvent::Type type = event->type();
940 if ((type != QEvent::HideToParent && type != QEvent::ShowToParent) || ignoreShowAndHide)
944 case QEvent::HideToParent: {
945 const QDialogButtonBox::ButtonRole role = q->buttonRole(button);
946 if (role != QDialogButtonBox::ButtonRole::InvalidRole) {
947 removeButton(button, RemoveReason::HideEvent);
948 hiddenButtons.insert(button, role);
953 case QEvent::ShowToParent:
954 if (hiddenButtons.contains(button)) {
955 const auto role = hiddenButtons.take(button);
956 addButton(button, role, LayoutRule::DoLayout, AddRule::SkipConnect);
957 if (role == QDialogButtonBox::AcceptRole)
958 ensureFirstAcceptIsDefault();
1019void QDialogButtonBoxPrivate::ensureFirstAcceptIsDefault()
1021 Q_Q(QDialogButtonBox);
1022 const QList<QAbstractButton *> &acceptRoleList = buttonLists[QDialogButtonBox::AcceptRole];
1023 QPushButton *firstAcceptButton = acceptRoleList.isEmpty()
1025 : qobject_cast<QPushButton *>(acceptRoleList.at(0));
1027 if (!firstAcceptButton)
1030 bool hasDefault =
false;
1031 QWidget *dialog =
nullptr;
1033 while (p && !p->isWindow()) {
1034 p = p->parentWidget();
1035 if ((dialog = qobject_cast<QDialog *>(p)))
1039 QWidget *parent = dialog ? dialog : q;
1042 const auto pushButtons = parent->findChildren<QPushButton *>();
1043 for (QPushButton *pushButton : pushButtons) {
1044 if (pushButton->isDefault() && pushButton != firstAcceptButton) {
1049 if (!hasDefault && firstAcceptButton) {
1050 firstAcceptButton->setDefault(
true);
1061 if (dialog && !(QWidgetPrivate::get(dialog)->hasChildWithFocusPolicy(Qt::StrongFocus, q)
1062 || dialog->focusWidget()))
1063 firstAcceptButton->setFocus();