137QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient)
138 : orientation(orient), buttonLayout(
nullptr), center(
false)
140 struct EventFilter :
public QObject
142 EventFilter(QDialogButtonBoxPrivate *d) : d(d) {};
144 bool eventFilter(QObject *obj, QEvent *event) override
146 QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
147 return button ? d->handleButtonShowAndHide(button, event) :
false;
151 QDialogButtonBoxPrivate *d;
155 filter.reset(
new EventFilter(
this));
158void QDialogButtonBoxPrivate::initLayout()
160 Q_Q(QDialogButtonBox);
161 layoutPolicy = QDialogButtonBox::ButtonLayout(q->style()->styleHint(QStyle::SH_DialogButtonLayout,
nullptr, q));
162 bool createNewLayout = buttonLayout ==
nullptr
163 || (orientation == Qt::Horizontal && qobject_cast<QVBoxLayout *>(buttonLayout) != 0)
164 || (orientation == Qt::Vertical && qobject_cast<QHBoxLayout *>(buttonLayout) != 0);
165 if (createNewLayout) {
167 if (orientation == Qt::Horizontal)
168 buttonLayout =
new QHBoxLayout(q);
170 buttonLayout =
new QVBoxLayout(q);
173 int left, top, right, bottom;
174 setLayoutItemMargins(QStyle::SE_PushButtonLayoutItem);
175 getLayoutItemMargins(&left, &top, &right, &bottom);
176 buttonLayout->setContentsMargins(-left, -top, -right, -bottom);
178 if (!q->testAttribute(Qt::WA_WState_OwnSizePolicy)) {
179 QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::ButtonBox);
180 if (orientation == Qt::Vertical)
182 q->setSizePolicy(sp);
183 q->setAttribute(Qt::WA_WState_OwnSizePolicy,
false);
207void QDialogButtonBoxPrivate::layoutButtons()
209 Q_Q(QDialogButtonBox);
210 const int MacGap = 36 - 8;
212 QScopedValueRollback blocker(ignoreShowAndHide,
true);
213 for (
int i = buttonLayout->count() - 1; i >= 0; --i) {
214 QLayoutItem *item = buttonLayout->takeAt(i);
215 if (QWidget *widget = item->widget())
220 int tmpPolicy = layoutPolicy;
222 static const int M = 5;
223 static const int ModalRoles[M] = { QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::RejectRole,
224 QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::YesRole, QPlatformDialogHelper::NoRole };
225 if (tmpPolicy == QDialogButtonBox::MacLayout) {
226 bool hasModalButton =
false;
227 for (
int i = 0; i < M; ++i) {
228 if (!buttonLists[ModalRoles[i]].isEmpty()) {
229 hasModalButton =
true;
237 const int *currentLayout = QPlatformDialogHelper::buttonLayout(
238 orientation,
static_cast<QPlatformDialogHelper::ButtonLayout>(tmpPolicy));
241 buttonLayout->addStretch();
243 const QList<QAbstractButton *> &acceptRoleList = buttonLists[QPlatformDialogHelper::AcceptRole];
245 while (*currentLayout != QPlatformDialogHelper::EOL) {
246 int role = (*currentLayout & ~QPlatformDialogHelper::Reverse);
247 bool reverse = (*currentLayout & QPlatformDialogHelper::Reverse);
250 case QPlatformDialogHelper::Stretch:
252 buttonLayout->addStretch();
254 case QPlatformDialogHelper::AcceptRole: {
255 if (acceptRoleList.isEmpty())
258 QAbstractButton *button = acceptRoleList.first();
259 buttonLayout->addWidget(button);
263 case QPlatformDialogHelper::AlternateRole:
264 if (acceptRoleList.size() > 1)
265 addButtonsToLayout(acceptRoleList.mid(1), reverse);
267 case QPlatformDialogHelper::DestructiveRole:
269 const QList<QAbstractButton *> &list = buttonLists[role];
272
273
274
275
276
277
278
279 if (tmpPolicy == QDialogButtonBox::MacLayout
280 && !list.isEmpty() && buttonLayout->count() > 1)
281 buttonLayout->addSpacing(MacGap);
283 addButtonsToLayout(list, reverse);
286
287
288
289 if (tmpPolicy == QDialogButtonBox::MacLayout && !list.isEmpty())
290 buttonLayout->addSpacing(MacGap);
293 case QPlatformDialogHelper::RejectRole:
294 case QPlatformDialogHelper::ActionRole:
295 case QPlatformDialogHelper::HelpRole:
296 case QPlatformDialogHelper::YesRole:
297 case QPlatformDialogHelper::NoRole:
298 case QPlatformDialogHelper::ApplyRole:
299 case QPlatformDialogHelper::ResetRole:
300 addButtonsToLayout(buttonLists[role], reverse);
305 QWidgetList layoutWidgets;
306 for (
int i = 0; i < buttonLayout->count(); ++i) {
307 if (
auto *widget = buttonLayout->itemAt(i)->widget())
308 layoutWidgets << widget;
311 q->setFocusProxy(
nullptr);
312 if (!layoutWidgets.isEmpty()) {
313 QWidget *prev = layoutWidgets.constLast();
314 for (QWidget *here : layoutWidgets) {
315 QWidget::setTabOrder(prev, here);
317 if (
auto *pushButton = qobject_cast<QPushButton *>(prev); pushButton && pushButton->isDefault())
318 q->setFocusProxy(pushButton);
323 buttonLayout->addStretch();
326QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardButton sbutton,
327 LayoutRule layoutRule)
329 Q_Q(QDialogButtonBox);
333 case QDialogButtonBox::Ok:
334 icon = QStyle::SP_DialogOkButton;
336 case QDialogButtonBox::Save:
337 icon = QStyle::SP_DialogSaveButton;
339 case QDialogButtonBox::Open:
340 icon = QStyle::SP_DialogOpenButton;
342 case QDialogButtonBox::Cancel:
343 icon = QStyle::SP_DialogCancelButton;
345 case QDialogButtonBox::Close:
346 icon = QStyle::SP_DialogCloseButton;
348 case QDialogButtonBox::Apply:
349 icon = QStyle::SP_DialogApplyButton;
351 case QDialogButtonBox::Reset:
352 icon = QStyle::SP_DialogResetButton;
354 case QDialogButtonBox::Help:
355 icon = QStyle::SP_DialogHelpButton;
357 case QDialogButtonBox::Discard:
358 icon = QStyle::SP_DialogDiscardButton;
360 case QDialogButtonBox::Yes:
361 icon = QStyle::SP_DialogYesButton;
363 case QDialogButtonBox::No:
364 icon = QStyle::SP_DialogNoButton;
366 case QDialogButtonBox::YesToAll:
367 icon = QStyle::SP_DialogYesToAllButton;
369 case QDialogButtonBox::NoToAll:
370 icon = QStyle::SP_DialogNoToAllButton;
372 case QDialogButtonBox::SaveAll:
373 icon = QStyle::SP_DialogSaveAllButton;
375 case QDialogButtonBox::Abort:
376 icon = QStyle::SP_DialogAbortButton;
378 case QDialogButtonBox::Retry:
379 icon = QStyle::SP_DialogRetryButton;
381 case QDialogButtonBox::Ignore:
382 icon = QStyle::SP_DialogIgnoreButton;
384 case QDialogButtonBox::RestoreDefaults:
385 icon = QStyle::SP_RestoreDefaultsButton;
387 case QDialogButtonBox::NoButton:
391 QPushButton *button =
new QPushButton(QGuiApplicationPrivate::platformTheme()->standardButtonText(sbutton), q);
392 QStyle *style = q->style();
393 if (style->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons,
nullptr, q) && icon != 0)
394 button->setIcon(style->standardIcon(QStyle::StandardPixmap(icon),
nullptr, q));
395 if (style != QApplication::style())
396 button->setStyle(style);
397 standardButtonMap.insert(button, sbutton);
398 QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(
static_cast<QPlatformDialogHelper::StandardButton>(sbutton));
399 if (Q_UNLIKELY(role == QPlatformDialogHelper::InvalidRole))
400 qWarning(
"QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
402 addButton(button,
static_cast<QDialogButtonBox::ButtonRole>(role), layoutRule);
403#if QT_CONFIG(shortcut)
404 const QKeySequence standardShortcut = QGuiApplicationPrivate::platformTheme()->standardButtonShortcut(sbutton);
405 if (!standardShortcut.isEmpty())
406 button->setShortcut(standardShortcut);
411void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role,
412 LayoutRule layoutRule, AddRule addRule)
414 buttonLists[role].append(button);
416 case AddRule::Connect:
417 QObjectPrivate::connect(button, &QAbstractButton::clicked,
418 this, &QDialogButtonBoxPrivate::handleButtonClicked);
419 QObjectPrivate::connect(button, &QAbstractButton::destroyed,
420 this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
421 button->installEventFilter(filter.get());
423 case AddRule::SkipConnect:
427 switch (layoutRule) {
428 case LayoutRule::DoLayout:
431 case LayoutRule::SkipLayout:
664void QDialogButtonBox::clear()
666 Q_D(QDialogButtonBox);
669 d->standardButtonMap.clear();
670 for (
int i = 0; i < NRoles; ++i) {
671 QList<QAbstractButton *> &list = d->buttonLists[i];
672 for (
auto button : std::as_const(list)) {
673 QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
674 d, &QDialogButtonBoxPrivate::handleButtonDestroyed);
753void QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveReason reason)
759 hiddenButtons.remove(button);
760 for (
int i = 0; i < QDialogButtonBox::NRoles; ++i)
761 buttonLists[i].removeOne(button);
764 case RemoveReason::ManualRemove:
765 button->setParent(
nullptr);
766 QObjectPrivate::disconnect(button, &QAbstractButton::clicked,
767 this, &QDialogButtonBoxPrivate::handleButtonClicked);
768 QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
769 this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
770 button->removeEventFilter(filter.get());
772 case RemoveReason::Destroyed:
773 standardButtonMap.remove(
reinterpret_cast<QPushButton *>(button));
775 case RemoveReason::HideEvent:
892void QDialogButtonBoxPrivate::handleButtonClicked()
894 Q_Q(QDialogButtonBox);
895 if (QAbstractButton *button = qobject_cast<QAbstractButton *>(q->sender())) {
900 const QDialogButtonBox::ButtonRole buttonRole = q->buttonRole(button);
901 QPointer<QDialogButtonBox> guard(q);
903 emit q->clicked(button);
908 switch (QPlatformDialogHelper::ButtonRole(buttonRole)) {
909 case QPlatformDialogHelper::AcceptRole:
910 case QPlatformDialogHelper::YesRole:
913 case QPlatformDialogHelper::RejectRole:
914 case QPlatformDialogHelper::NoRole:
917 case QPlatformDialogHelper::HelpRole:
918 emit q->helpRequested();
933bool QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton *button, QEvent *event)
935 Q_Q(QDialogButtonBox);
937 const QEvent::Type type = event->type();
939 if ((type != QEvent::HideToParent && type != QEvent::ShowToParent) || ignoreShowAndHide)
943 case QEvent::HideToParent: {
944 const QDialogButtonBox::ButtonRole role = q->buttonRole(button);
945 if (role != QDialogButtonBox::ButtonRole::InvalidRole) {
946 removeButton(button, RemoveReason::HideEvent);
947 hiddenButtons.insert(button, role);
952 case QEvent::ShowToParent:
953 if (hiddenButtons.contains(button)) {
954 const auto role = hiddenButtons.take(button);
955 addButton(button, role, LayoutRule::DoLayout, AddRule::SkipConnect);
956 if (role == QDialogButtonBox::AcceptRole)
957 ensureFirstAcceptIsDefault();
1018void QDialogButtonBoxPrivate::ensureFirstAcceptIsDefault()
1020 Q_Q(QDialogButtonBox);
1021 const QList<QAbstractButton *> &acceptRoleList = buttonLists[QDialogButtonBox::AcceptRole];
1022 QPushButton *firstAcceptButton = acceptRoleList.isEmpty()
1024 : qobject_cast<QPushButton *>(acceptRoleList.at(0));
1026 if (!firstAcceptButton)
1029 bool hasDefault =
false;
1030 QWidget *dialog =
nullptr;
1032 while (p && !p->isWindow()) {
1033 p = p->parentWidget();
1034 if ((dialog = qobject_cast<QDialog *>(p)))
1038 QWidget *parent = dialog ? dialog : q;
1041 const auto pushButtons = parent->findChildren<QPushButton *>();
1042 for (QPushButton *pushButton : pushButtons) {
1043 if (pushButton->isDefault() && pushButton != firstAcceptButton) {
1048 if (!hasDefault && firstAcceptButton) {
1049 firstAcceptButton->setDefault(
true);
1060 if (dialog && !(QWidgetPrivate::get(dialog)->hasChildWithFocusPolicy(Qt::StrongFocus, q)
1061 || dialog->focusWidget()))
1062 firstAcceptButton->setFocus();