Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmessagebox.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtWidgets/qmessagebox.h>
6
7#include <QtWidgets/qdialogbuttonbox.h>
8#include "private/qlabel_p.h"
9#include "private/qapplication_p.h"
10#include <QtCore/qlist.h>
11#include <QtCore/qdebug.h>
12#include <QtWidgets/qstyle.h>
13#include <QtWidgets/qstyleoption.h>
14#include <QtWidgets/qgridlayout.h>
15#include <QtWidgets/qpushbutton.h>
16#include <QtWidgets/qcheckbox.h>
17#include <QtGui/qaccessible.h>
18#include <QtGui/qicon.h>
19#include <QtGui/qtextdocument.h>
20#include <QtWidgets/qapplication.h>
21#if QT_CONFIG(textedit)
22#include <QtWidgets/qtextedit.h>
23#endif
24#if QT_CONFIG(menu)
25#include <QtWidgets/qmenu.h>
26#endif
27#include "qdialog_p.h"
28#include <QtGui/qfont.h>
29#include <QtGui/qfontmetrics.h>
30#include <QtGui/qclipboard.h>
31#include "private/qabstractbutton_p.h"
32#include <QtGui/qpa/qplatformtheme.h>
33
34#include <QtCore/qanystringview.h>
35#include <QtCore/qdebug.h>
36#include <QtCore/qpointer.h>
37#include <QtCore/qversionnumber.h>
38
39#ifdef Q_OS_WIN
40# include <QtCore/qt_windows.h>
41#include <qpa/qplatformnativeinterface.h>
42#endif
43
44#include <optional>
45
46QT_BEGIN_NAMESPACE
47
48using namespace Qt::StringLiterals;
49
50#if defined(Q_OS_WIN)
51HMENU qt_getWindowsSystemMenu(const QWidget *w)
52{
53 if (QWindow *window = QApplicationPrivate::windowForWidget(w))
54 if (void *handle = QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", window))
55 return GetSystemMenu(reinterpret_cast<HWND>(handle), false);
56 return 0;
57}
58#endif
59
60static_assert(qToUnderlying(QMessageBox::ButtonRole::NRoles) ==
61 qToUnderlying(QDialogButtonBox::ButtonRole::NRoles),
62 "QMessageBox::ButtonRole and QDialogButtonBox::ButtonRole out of sync!");
63
64static_assert(std::is_same_v<std::underlying_type_t<QMessageBox::ButtonRole>,
65 std::underlying_type_t<QDialogButtonBox::ButtonRole>>);
66
67// StandardButton enums have different underlying types
68// => qToUnderlying and std::is_same_v won't work
69// ### Qt 7: make them have the same underlying type
70static_assert(static_cast<int>(QMessageBox::StandardButton::LastButton) ==
71 static_cast<int>(QDialogButtonBox::StandardButton::LastButton),
72 "QMessageBox::StandardButton and QDialogButtonBox::StandardButton out of sync!");
73
74enum Button { Old_Ok = 1, Old_Cancel = 2, Old_Yes = 3, Old_No = 4, Old_Abort = 5, Old_Retry = 6,
76 NewButtonMask = 0xFFFFFC00 };
77
79#if QT_CONFIG(textedit)
80class QMessageBoxDetailsText : public QWidget
81{
82 Q_OBJECT
83public:
84 class TextEdit : public QTextEdit
85 {
86 public:
87 TextEdit(QWidget *parent=nullptr) : QTextEdit(parent) { }
88#ifndef QT_NO_CONTEXTMENU
89 void contextMenuEvent(QContextMenuEvent * e) override
90 {
91 if (QMenu *menu = createStandardContextMenu()) {
92 menu->setAttribute(Qt::WA_DeleteOnClose);
93 menu->popup(e->globalPos());
94 }
95 }
96#endif // QT_NO_CONTEXTMENU
97 };
98
99 QMessageBoxDetailsText(QWidget *parent=nullptr)
100 : QWidget(parent)
101 , copyAvailable(false)
102 {
103 QVBoxLayout *layout = new QVBoxLayout;
104 layout->setContentsMargins(QMargins());
105 QFrame *line = new QFrame(this);
106 line->setFrameShape(QFrame::HLine);
107 line->setFrameShadow(QFrame::Sunken);
108 layout->addWidget(line);
109 textEdit = new TextEdit();
110 textEdit->setFixedHeight(100);
111 textEdit->setFocusPolicy(Qt::NoFocus);
112 textEdit->setReadOnly(true);
113 layout->addWidget(textEdit);
114 setLayout(layout);
115
116 connect(textEdit, &TextEdit::copyAvailable,
117 this, &QMessageBoxDetailsText::textCopyAvailable);
118 }
119 void setText(const QString &text) { textEdit->setPlainText(text); }
120 QString text() const { return textEdit->toPlainText(); }
121
122 bool copy()
123 {
124#ifdef QT_NO_CLIPBOARD
125 return false;
126#else
127 if (!copyAvailable)
128 return false;
129 textEdit->copy();
130 return true;
131#endif
132 }
133
134 void selectAll()
135 {
136 textEdit->selectAll();
137 }
138
139private slots:
140 void textCopyAvailable(bool available)
141 {
142 copyAvailable = available;
143 }
144
145private:
146 bool copyAvailable;
147 TextEdit *textEdit;
148};
149#endif // QT_CONFIG(textedit)
150
152{
153public:
155// see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123985
156#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU_ONLY >= 1600 && Q_CC_GNU_ONLY < 1700 && !defined(__OPTIMIZE__)
157QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
158#endif
163QT_WARNING_POP
164
166 { return label == ShowLabel ? QMessageBox::tr("Show Details...") : QMessageBox::tr("Hide Details..."); }
167
170
185};
186
188{
189 Q_DECLARE_PUBLIC(QMessageBox)
190
191public:
192 QMessageBoxPrivate() : escapeButton(nullptr), defaultButton(nullptr), checkbox(nullptr), clickedButton(nullptr), detailsButton(nullptr),
193#if QT_CONFIG(textedit)
194 detailsText(nullptr),
195#endif
196 compatMode(false), autoAddOkButton(true),
197 detectedEscapeButton(nullptr), informativeLabel(nullptr),
199
200 void init(const QString &title = QString(), const QString &text = QString());
202 void buttonClicked(QAbstractButton *);
203 void helperClicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role);
204 void setClickedButton(QAbstractButton *button);
205
206 QAbstractButton *findButton(int button0, int button1, int button2, int flags);
207 void addOldButtons(int button0, int button1, int button2);
208
210 int execReturnCode(QAbstractButton *button);
211
216
217 void setVisible(bool visible) override;
219
220 static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,
221 const QString &title, const QString &text,
222 int button0, int button1, int button2);
223 static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,
224 const QString &title, const QString &text,
225 const QString &button0Text,
226 const QString &button1Text,
227 const QString &button2Text,
228 int defaultButtonNumber,
229 int escapeButtonNumber);
230
232 QMessageBox::Icon icon, const QString& title, const QString& text,
234
235 static QPixmap standardIcon(QMessageBox::Icon icon, QMessageBox *mb);
237
248#if QT_CONFIG(textedit)
250#endif
259private:
260 void initHelper(QPlatformDialogHelper *) override;
261 void helperPrepareShow(QPlatformDialogHelper *) override;
262 int dialogCode() const override;
263};
264
265void QMessageBoxPrivate::init(const QString &title, const QString &text)
266{
267 Q_Q(QMessageBox);
268
269 label = new QLabel;
270 label->setObjectName("qt_msgbox_label"_L1);
271 label->setTextInteractionFlags(Qt::TextInteractionFlags(q->style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, q)));
272 label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
273 label->setOpenExternalLinks(true);
274 iconLabel = new QLabel(q);
275 iconLabel->setObjectName("qt_msgboxex_icon_label"_L1);
276 iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
277
278 buttonBox = new QDialogButtonBox;
279 buttonBox->setObjectName("qt_msgbox_buttonbox"_L1);
280 buttonBox->setCenterButtons(q->style()->styleHint(QStyle::SH_MessageBox_CenterButtons, nullptr, q));
281 QObjectPrivate::connect(buttonBox, &QDialogButtonBox::clicked,
282 this, &QMessageBoxPrivate::buttonClicked);
284 if (!title.isEmpty() || !text.isEmpty()) {
285 q->setWindowTitle(title);
286 q->setText(text);
287 }
288 q->setModal(true);
289#ifdef Q_OS_MAC
290 QFont f = q->font();
291 f.setBold(true);
292 label->setFont(f);
293#endif
294 icon = QMessageBox::NoIcon;
295}
296
298{
299 Q_Q(QMessageBox);
300 delete q->layout();
301 QGridLayout *grid = new QGridLayout;
302 const bool hasIcon = !iconLabel->pixmap().isNull();
303
304 if (hasIcon)
305 grid->addWidget(iconLabel, 0, 0, 2, 1, Qt::AlignTop);
306 iconLabel->setVisible(hasIcon);
307#ifdef Q_OS_MAC
308 QSpacerItem *indentSpacer = new QSpacerItem(14, 1, QSizePolicy::Fixed, QSizePolicy::Fixed);
309#else
310 QSpacerItem *indentSpacer = new QSpacerItem(hasIcon ? 7 : 15, 1, QSizePolicy::Fixed, QSizePolicy::Fixed);
311#endif
312 grid->addItem(indentSpacer, 0, hasIcon ? 1 : 0, 2, 1);
313 grid->addWidget(label, 0, hasIcon ? 2 : 1, 1, 1);
314 if (informativeLabel) {
315#ifndef Q_OS_MAC
316 informativeLabel->setContentsMargins(0, 7, 0, 7);
317#endif
318 grid->addWidget(informativeLabel, 1, hasIcon ? 2 : 1, 1, 1);
319 }
320 if (checkbox) {
321 grid->addWidget(checkbox, informativeLabel ? 2 : 1, hasIcon ? 2 : 1, 1, 1, Qt::AlignLeft);
322#ifdef Q_OS_MAC
323 grid->addItem(new QSpacerItem(1, 15, QSizePolicy::Fixed, QSizePolicy::Fixed), grid->rowCount(), 0);
324#else
325 grid->addItem(new QSpacerItem(1, 7, QSizePolicy::Fixed, QSizePolicy::Fixed), grid->rowCount(), 0);
326#endif
327 }
328#ifdef Q_OS_MAC
329 grid->addWidget(buttonBox, grid->rowCount(), hasIcon ? 2 : 1, 1, 1);
330 grid->setContentsMargins(0, 0, 0, 0);
331 grid->setVerticalSpacing(8);
332 grid->setHorizontalSpacing(0);
333 q->setContentsMargins(24, 15, 24, 20);
334 grid->setRowStretch(1, 100);
335 grid->setRowMinimumHeight(2, 6);
336#else
337 grid->addWidget(buttonBox, grid->rowCount(), 0, 1, grid->columnCount());
338#endif
339#if QT_CONFIG(textedit)
340 if (detailsText)
341 grid->addWidget(detailsText, grid->rowCount(), 0, 1, grid->columnCount());
342#endif
343 grid->setSizeConstraint(QLayout::SetNoConstraint);
344 q->setLayout(grid);
345
348}
349
351{
352 layout->activate();
353 return layout->totalMinimumSize().width();
354}
355
357{
358 Q_Q(QMessageBox);
359
360 if (!q->isVisible())
361 return;
362
363 const QSize screenSize = q->screen()->availableGeometry().size();
364 int hardLimit = qMin(screenSize.width() - 480, 1000); // can never get bigger than this
365 // on small screens allows the messagebox be the same size as the screen
366 if (screenSize.width() <= 1024)
367 hardLimit = screenSize.width();
368#ifdef Q_OS_MAC
369 int softLimit = qMin(screenSize.width()/2, 420);
370#else
371 // note: ideally on windows, hard and soft limits but it breaks compat
372 int softLimit = qMin(screenSize.width()/2, 500);
373#endif
374
375 if (informativeLabel)
376 informativeLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
377
378 label->setWordWrap(false); // makes the label return min size
379 int width = layoutMinimumWidth();
380
381 if (width > softLimit) {
382 label->setWordWrap(true);
383 width = qMax(softLimit, layoutMinimumWidth());
384
385 if (width > hardLimit) {
386 label->d_func()->ensureTextControl();
387 if (QWidgetTextControl *control = label->d_func()->control) {
388 QTextOption opt = control->document()->defaultTextOption();
389 opt.setWrapMode(QTextOption::WrapAnywhere);
390 control->document()->setDefaultTextOption(opt);
391 }
392 width = hardLimit;
393 }
394 }
395
396 if (informativeLabel) {
397 label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
398 QSizePolicy policy(QSizePolicy::Minimum, QSizePolicy::Preferred);
399 policy.setHeightForWidth(true);
400 informativeLabel->setSizePolicy(policy);
401 width = qMax(width, layoutMinimumWidth());
402 if (width > hardLimit) { // longest word is really big, so wrap anywhere
403 informativeLabel->d_func()->ensureTextControl();
404 if (QWidgetTextControl *control = informativeLabel->d_func()->control) {
405 QTextOption opt = control->document()->defaultTextOption();
406 opt.setWrapMode(QTextOption::WrapAnywhere);
407 control->document()->setDefaultTextOption(opt);
408 }
409 width = hardLimit;
410 }
411 policy.setHeightForWidth(label->wordWrap());
412 label->setSizePolicy(policy);
413 }
414
415 QFontMetrics fm(QApplication::font("QMdiSubWindowTitleBar"));
416 int windowTitleWidth = qMin(fm.horizontalAdvance(q->windowTitle()) + 50, hardLimit);
417 if (windowTitleWidth > width)
418 width = windowTitleWidth;
419
420 layout->activate();
421 int height = (layout->hasHeightForWidth())
422 ? layout->totalHeightForWidth(width)
423 : layout->totalMinimumSize().height();
424
425 q->setFixedSize(width, height);
426 QCoreApplication::removePostedEvents(q, QEvent::LayoutRequest);
427}
428
429static int oldButton(int button)
430{
431 switch (button & QMessageBox::ButtonMask) {
432 case QMessageBox::Ok:
433 return Old_Ok;
434 case QMessageBox::Cancel:
435 return Old_Cancel;
436 case QMessageBox::Yes:
437 return Old_Yes;
438 case QMessageBox::No:
439 return Old_No;
440 case QMessageBox::Abort:
441 return Old_Abort;
442 case QMessageBox::Retry:
443 return Old_Retry;
444 case QMessageBox::Ignore:
445 return Old_Ignore;
446 case QMessageBox::YesToAll:
447 return Old_YesAll;
448 case QMessageBox::NoToAll:
449 return Old_NoAll;
450 default:
451 return 0;
452 }
453}
454
455int QMessageBoxPrivate::execReturnCode(QAbstractButton *button)
456{
457 if (int standardButton = buttonBox->standardButton(button)) {
458 // When using a QMessageBox with standard buttons, the return
459 // code is a StandardButton value indicating the standard button
460 // that was clicked.
461 if (compatMode)
462 return oldButton(standardButton);
463 else
464 return standardButton;
465 } else {
466 // When using QMessageBox with custom buttons, the return code
467 // is an opaque value, and the user is expected to use clickedButton()
468 // to determine which button was clicked. We make sure to keep the opaque
469 // value out of the QDialog::DialogCode range, so we can distinguish them.
470 auto customButtonIndex = customButtonList.indexOf(button);
471 if (customButtonIndex >= 0)
472 return QDialog::DialogCode::Accepted + customButtonIndex + 1;
473 else
474 return customButtonIndex; // Not found, return -1
475 }
476}
477
479{
480 Q_Q(const QMessageBox);
481
482 if (rescode <= QDialog::Accepted) {
483 return rescode;
484 } else if (clickedButton) {
485 switch (q->buttonRole(clickedButton)) {
486 case QMessageBox::AcceptRole:
487 case QMessageBox::YesRole:
488 return QDialog::Accepted;
489 case QMessageBox::RejectRole:
490 case QMessageBox::NoRole:
491 return QDialog::Rejected;
492 default:
493 ;
494 }
495 }
496
497 return QDialogPrivate::dialogCode();
498}
499
500void QMessageBoxPrivate::buttonClicked(QAbstractButton *button)
501{
502 Q_Q(QMessageBox);
503#if QT_CONFIG(textedit)
504 if (detailsButton && detailsText && button == detailsButton) {
505 detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel);
506 detailsText->setHidden(!detailsText->isHidden());
507 updateSize();
508 } else
509#endif
510 {
511 setClickedButton(button);
512
513 if (receiverToDisconnectOnClose) {
514 QObject::disconnect(q, signalToDisconnectOnClose, receiverToDisconnectOnClose,
515 memberToDisconnectOnClose);
516 receiverToDisconnectOnClose = nullptr;
517 }
518 signalToDisconnectOnClose.clear();
519 memberToDisconnectOnClose.clear();
520 }
521}
522
523void QMessageBoxPrivate::setClickedButton(QAbstractButton *button)
524{
525 Q_Q(QMessageBox);
526
527 clickedButton = button;
528 emit q->buttonClicked(clickedButton);
529
530 auto resultCode = execReturnCode(button);
531 q->done(resultCode);
532}
533
534void QMessageBoxPrivate::helperClicked(QPlatformDialogHelper::StandardButton helperButton, QPlatformDialogHelper::ButtonRole role)
535{
536 Q_UNUSED(role);
537 Q_Q(QMessageBox);
538
539 // Map back to QAbstractButton, so that the message box behaves the same from
540 // the outside, regardless of whether it's backed by a native helper or not.
541 QAbstractButton *dialogButton = helperButton > QPlatformDialogHelper::LastButton ?
542 static_cast<QAbstractButton *>(options->customButton(helperButton)->button) :
543 q->button(QMessageBox::StandardButton(helperButton));
544
545 Q_ASSERT(dialogButton);
546
547 // Simulate click by explicitly clicking the button. This will ensure that
548 // any logic of the button that responds to the click is respected, including
549 // plumbing back to buttonClicked above based on the clicked() signal.
550 dialogButton->click();
551}
552
553/*!
554 \class QMessageBox
555
556 \brief The QMessageBox class provides a modal dialog for informing
557 the user or for asking the user a question and receiving an answer.
558
559 \ingroup standard-dialogs
560 \inmodule QtWidgets
561
562 A message box displays a primary \l{QMessageBox::text}{text} to
563 alert the user to a situation, an \l{QMessageBox::informativeText}
564 {informative text} to further explain the situation, and an optional
565 \l{QMessageBox::detailedText} {detailed text} to provide even more data
566 if the user requests it.
567
568 A message box can also display an \l{QMessageBox::icon} {icon}
569 and \l{QMessageBox::standardButtons} {standard buttons} for
570 accepting a user response.
571
572 While the parent parameter is optional, specifying it gives a hint
573 to the window manager, which can then take care of positioning, and
574 maintain a proper stacking order of the dialog window.
575
576 Two APIs for using QMessageBox are provided, the property-based
577 API, and the static functions. Calling one of the static functions
578 is the simpler approach, but it is less flexible than using the
579 property-based API, and the result is less informative. Using the
580 property-based API is recommended.
581
582 \section1 The Property-based API
583
584 To use the property-based API, construct an instance of
585 QMessageBox, set the desired properties, and call exec() to show
586 the message. The simplest configuration is to set only the
587 \l{QMessageBox::text} {message text} property.
588
589 \snippet code/src_gui_dialogs_qmessagebox.cpp 5
590
591 The user must click the \uicontrol{OK} button to dismiss the message
592 box. The rest of the GUI is blocked until the message box is
593 dismissed.
594
595 \image msgbox1.png {Message box with a simple message and an OK button}
596
597 A better approach than just alerting the user to an event is to
598 also ask the user what to do about it.
599
600 Set the \l{QMessageBox::standardButtons} {standard buttons}
601 property to the set of buttons you want as the set of user
602 responses. The buttons are specified by combining values from
603 StandardButtons using the bitwise OR operator. The display order
604 for the buttons is platform-dependent. For example, on Windows,
605 \uicontrol{Save} is displayed to the left of \uicontrol{Cancel}, whereas on
606 \macos, the order is reversed. Mark one of your standard buttons to be your
607 \l{QMessageBox::defaultButton()} {default button}.
608
609 The \l{QMessageBox::informativeText} {informative text} property can
610 be used to add additional context to help the user choose the appropriate action.
611
612 \snippet code/src_gui_dialogs_qmessagebox.cpp 6
613
614 \image msgbox2.png
615 {Message box with a "Save", "Don't Save", and "Cancel" buttons}
616
617 The exec() slot returns the StandardButtons value of the button
618 that was clicked.
619
620 \snippet code/src_gui_dialogs_qmessagebox.cpp 7
621
622 To give the user more information to help them choose the appropriate,
623 action, set the \l{QMessageBox::detailedText} {detailed text} property.
624 Depending on the platform the \l{QMessageBox::detailedText} {detailed text},
625 may require the user to click a \uicontrol{Show Details...} button to be shown.
626
627 \image msgbox3.png {Save message box with a "Show Details..." button}
628
629 Clicking the \uicontrol{Show Details...} button displays the detailed text.
630
631 \image msgbox4.png
632 {Save message box showing the detailed text}
633
634 \section2 Rich Text and the Text Format Property
635
636 The \l{QMessageBox::detailedText} {detailed text} property is
637 always interpreted as plain text. The \l{QMessageBox::text} {main
638 text} and \l{QMessageBox::informativeText} {informative text}
639 properties can be either plain text or rich text. These strings
640 are interpreted according to the setting of the
641 \l{QMessageBox::textFormat} {text format} property. The default
642 setting is \l{Qt::AutoText} {auto-text}.
643
644 Note that for some plain text strings containing XML
645 meta-characters, the auto-text \l{Qt::mightBeRichText()} {rich
646 text detection test} may fail causing your plain text string to be
647 interpreted incorrectly as rich text. In these rare cases, use
648 Qt::convertFromPlainText() to convert your plain text string to a
649 visually equivalent rich text string, or set the
650 \l{QMessageBox::textFormat} {text format} property explicitly with
651 setTextFormat().
652
653 \section2 Severity Levels and the Icon and Pixmap Properties
654
655 QMessageBox supports four predefined message severity levels, or message
656 types, which really only differ in the predefined icon they each show.
657 Specify one of the four predefined message types by setting the
658 \l{QMessageBox::icon}{icon} property to one of the
659 \l{QMessageBox::Icon}{predefined icons}. The following rules are
660 guidelines:
661
662 \table
663 \row
664 \li \image qmessagebox-quest.png {Question mark icon}
665 \li \l Question
666 \li For asking a question during normal operations.
667 \row
668 \li \image qmessagebox-info.png {Information icon}
669 \li \l Information
670 \li For reporting information about normal operations.
671 \row
672 \li \image qmessagebox-warn.png {Warning icon}
673 \li \l Warning
674 \li For reporting non-critical errors.
675 \row
676 \li \image qmessagebox-crit.png {Critical problem icon}
677 \li \l Critical
678 \li For reporting critical errors.
679 \endtable
680
681 \l{QMessageBox::Icon}{Predefined icons} are not defined by QMessageBox, but
682 provided by the style. The default value is \l{QMessageBox::NoIcon}
683 {No Icon}. The message boxes are otherwise the same for all cases. When
684 using a standard icon, use the one recommended in the table, or use the
685 one recommended by the style guidelines for your platform. If none of the
686 standard icons is right for your message box, you can use a custom icon by
687 setting the \l{QMessageBox::iconPixmap}{icon pixmap} property instead of
688 setting the \l{QMessageBox::icon}{icon} property.
689
690 In summary, to set an icon, use \e{either} setIcon() for one of the
691 standard icons, \e{or} setIconPixmap() for a custom icon.
692
693 \section1 The Static Functions API
694
695 Building message boxes with the static functions API, although
696 convenient, is less flexible than using the property-based API,
697 because the static function signatures lack parameters for setting
698 the \l{QMessageBox::informativeText} {informative text} and
699 \l{QMessageBox::detailedText} {detailed text} properties. One
700 work-around for this has been to use the \c{title} parameter as
701 the message box main text and the \c{text} parameter as the
702 message box informative text. Because this has the obvious
703 drawback of making a less readable message box, platform
704 guidelines do not recommend it. The \e{Microsoft Windows User
705 Interface Guidelines} recommend using the
706 \l{QCoreApplication::applicationName} {application name} as the
707 \l{QMessageBox::setWindowTitle()} {window's title}, which means
708 that if you have an informative text in addition to your main
709 text, you must concatenate it to the \c{text} parameter.
710
711 Note that the static function signatures have changed with respect
712 to their button parameters, which are now used to set the
713 \l{QMessageBox::standardButtons} {standard buttons} and the
714 \l{QMessageBox::defaultButton()} {default button}.
715
716 Static functions are available for creating information(),
717 question(), warning(), and critical() message boxes.
718
719 \snippet code/src_gui_dialogs_qmessagebox.cpp 0
720
721 The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
722 how to use QMessageBox and the other built-in Qt dialogs.
723
724 \section1 Advanced Usage
725
726 If the \l{QMessageBox::StandardButtons} {standard buttons} are not
727 flexible enough for your message box, you can use the addButton()
728 overload that takes a text and a ButtonRole to add custom
729 buttons. The ButtonRole is used by QMessageBox to determine the
730 ordering of the buttons on screen (which varies according to the
731 platform). You can test the value of clickedButton() after calling
732 exec(). For example,
733
734 \snippet code/src_gui_dialogs_qmessagebox.cpp 2
735
736 \section1 Default and Escape Keys
737
738 The default button (i.e., the button activated when \uicontrol Enter is
739 pressed) can be specified using setDefaultButton(). If a default
740 button is not specified, QMessageBox tries to find one based on
741 the \l{ButtonRole} {button roles} of the buttons used in the
742 message box.
743
744 The escape button (the button activated when \uicontrol Esc is pressed)
745 can be specified using setEscapeButton(). If an escape button is
746 not specified, QMessageBox tries to find one using these rules:
747
748 \list 1
749
750 \li If there is only one button, it is the button activated when
751 \uicontrol Esc is pressed.
752
753 \li If there is a \l Cancel button, it is the button activated when
754 \uicontrol Esc is pressed.
755
756 \li If there is exactly one button having either
757 \l{QMessageBox::RejectRole} {the Reject role} or the
758 \l{QMessageBox::NoRole} {the No role}, it is the button
759 activated when \uicontrol Esc is pressed.
760
761 \endlist
762
763 When an escape button can't be determined using these rules,
764 pressing \uicontrol Esc has no effect.
765
766 \sa QDialogButtonBox, {Standard Dialogs Example}
767*/
768
769/*!
770 \enum QMessageBox::ButtonRole
771
772 \include qdialogbuttonbox.cpp buttonrole-enum
773*/
774
775/*!
776 \enum QMessageBox::StandardButton
777
778 These enums describe flags for standard buttons. Each button has a
779 defined \l ButtonRole.
780
781 \value Ok An "OK" button defined with the \l AcceptRole.
782 \value Open An "Open" button defined with the \l AcceptRole.
783 \value Save A "Save" button defined with the \l AcceptRole.
784 \value Cancel A "Cancel" button defined with the \l RejectRole.
785 \value Close A "Close" button defined with the \l RejectRole.
786 \value Discard A "Discard" or "Don't Save" button, depending on the platform,
787 defined with the \l DestructiveRole.
788 \value Apply An "Apply" button defined with the \l ApplyRole.
789 \value Reset A "Reset" button defined with the \l ResetRole.
790 \value RestoreDefaults A "Restore Defaults" button defined with the \l ResetRole.
791 \value Help A "Help" button defined with the \l HelpRole.
792 \value SaveAll A "Save All" button defined with the \l AcceptRole.
793 \value Yes A "Yes" button defined with the \l YesRole.
794 \value YesToAll A "Yes to All" button defined with the \l YesRole.
795 \value No A "No" button defined with the \l NoRole.
796 \value NoToAll A "No to All" button defined with the \l NoRole.
797 \value Abort An "Abort" button defined with the \l RejectRole.
798 \value Retry A "Retry" button defined with the \l AcceptRole.
799 \value Ignore An "Ignore" button defined with the \l AcceptRole.
800
801 \value NoButton An invalid button.
802
803 \omitvalue FirstButton
804 \omitvalue LastButton
805
806 The following values are obsolete:
807
808 \value YesAll Use YesToAll instead.
809 \value NoAll Use NoToAll instead.
810 \value Default Use the \c defaultButton argument of
811 information(), warning(), etc. instead, or call
812 setDefaultButton().
813 \value Escape Call setEscapeButton() instead.
814 \value FlagMask
815 \value ButtonMask
816
817 \sa ButtonRole, standardButtons
818*/
819
820/*!
821 \enum QMessageBox::Option
822 \since 6.6
823 \value DontUseNativeDialog Don't use the native message dialog.
824*/
825
826/*!
827 \fn void QMessageBox::buttonClicked(QAbstractButton *button)
828
829 This signal is emitted whenever a button is clicked inside the QMessageBox.
830 The button that was clicked in returned in \a button.
831*/
832
833/*!
834 Constructs an \l{Qt::ApplicationModal} {application modal} message box with no text and no buttons.
835 \a parent is passed to the QDialog constructor.
836
837 The window modality can be overridden via setWindowModality() before calling show().
838
839 \note Using open() or exec() to show the message box affects the window modality.
840 Please see the detailed documentation for each function for more information.
841
842 On \macos, if you want your message box to appear
843 as a Qt::Sheet of its \a parent, set the message box's
844 \l{setWindowModality()} {window modality} to Qt::WindowModal or use open().
845 Otherwise, the message box will be a standard dialog.
846
847 \sa setWindowTitle(), setText(), setIcon(), setStandardButtons(), setWindowModality()
848
849*/
850QMessageBox::QMessageBox(QWidget *parent)
851 : QDialog(*new QMessageBoxPrivate, parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
852{
853 Q_D(QMessageBox);
854 d->init();
855}
856
857/*!
858 Constructs an \l{Qt::ApplicationModal} {application modal} message box with the given \a icon,
859 \a title, \a text, and standard \a buttons. Standard or custom buttons can be
860 added at any time using addButton(). The \a parent and \a f
861 arguments are passed to the QDialog constructor.
862
863 The window modality can be overridden via setWindowModality() before calling show().
864
865 \note Using open() or exec() to show the message box affects the window modality.
866 Please see the detailed documentation for each function for more information.
867
868 On \macos, if \a parent is not \nullptr and you want your message box
869 to appear as a Qt::Sheet of that parent, set the message box's
870 \l{setWindowModality()} {window modality} to Qt::WindowModal
871 (default). Otherwise, the message box will be a standard dialog.
872
873 \sa setWindowTitle(), setText(), setIcon(), setStandardButtons(), setWindowModality()
874*/
875QMessageBox::QMessageBox(Icon icon, const QString &title, const QString &text,
876 StandardButtons buttons, QWidget *parent,
877 Qt::WindowFlags f)
878: QDialog(*new QMessageBoxPrivate, parent, f | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
879{
880 Q_D(QMessageBox);
881 d->init(title, text);
882 setIcon(icon);
883 if (buttons != NoButton)
884 setStandardButtons(buttons);
885}
886
887/*!
888 Destroys the message box.
889*/
890QMessageBox::~QMessageBox()
891{
892}
893
894/*!
895 Adds the given \a button to the message box with the specified \a
896 role.
897
898 \sa removeButton(), button(), setStandardButtons()
899*/
900void QMessageBox::addButton(QAbstractButton *button, ButtonRole role)
901{
902 Q_D(QMessageBox);
903 if (!button)
904 return;
905 removeButton(button);
906
907 if (button->text().isEmpty()) {
908 if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {
909 if (auto standardButton = QMessageBoxPrivate::standardButtonForRole(role))
910 button->setText(platformTheme->standardButtonText(standardButton));
911 }
912
913 if (button->text().isEmpty()) {
914 qWarning() << "Cannot add" << button << "without title";
915 return;
916 }
917 }
918
919 d->buttonBox->addButton(button, (QDialogButtonBox::ButtonRole)role);
920 d->customButtonList.append(button);
921 d->autoAddOkButton = false;
922}
923
924QMessageBox::StandardButton QMessageBoxPrivate::standardButtonForRole(QMessageBox::ButtonRole role)
925{
926 switch (role) {
927 case QMessageBox::AcceptRole: return QMessageBox::Ok;
928 case QMessageBox::RejectRole: return QMessageBox::Cancel;
929 case QMessageBox::DestructiveRole: return QMessageBox::Discard;
930 case QMessageBox::HelpRole: return QMessageBox::Help;
931 case QMessageBox::ApplyRole: return QMessageBox::Apply;
932 case QMessageBox::YesRole: return QMessageBox::Yes;
933 case QMessageBox::NoRole: return QMessageBox::No;
934 case QMessageBox::ResetRole: return QMessageBox::Reset;
935 default: return QMessageBox::NoButton;
936 }
937}
938
939/*!
940 \overload
941
942 Creates a button with the given \a text, adds it to the message box for the
943 specified \a role, and returns it.
944*/
945QPushButton *QMessageBox::addButton(const QString& text, ButtonRole role)
946{
947 Q_D(QMessageBox);
948 QPushButton *pushButton = new QPushButton(text);
949 addButton(pushButton, role);
950 d->updateSize();
951 return pushButton;
952}
953
954/*!
955 \overload
956
957 Adds a standard \a button to the message box if it is valid to do so, and
958 returns the push button.
959
960 \sa setStandardButtons()
961*/
962QPushButton *QMessageBox::addButton(StandardButton button)
963{
964 Q_D(QMessageBox);
965 QPushButton *pushButton = d->buttonBox->addButton((QDialogButtonBox::StandardButton)button);
966 if (pushButton)
967 d->autoAddOkButton = false;
968 return pushButton;
969}
970
971/*!
972 Removes \a button from the button box without deleting it.
973
974 \sa addButton(), setStandardButtons()
975*/
976void QMessageBox::removeButton(QAbstractButton *button)
977{
978 Q_D(QMessageBox);
979 d->customButtonList.removeAll(button);
980 if (d->escapeButton == button)
981 d->escapeButton = nullptr;
982 if (d->defaultButton == button)
983 d->defaultButton = nullptr;
984 d->buttonBox->removeButton(button);
985 d->updateSize();
986}
987
988/*!
989 \property QMessageBox::standardButtons
990 \brief collection of standard buttons in the message box
991
992 This property controls which standard buttons are used by the message box.
993
994 By default, this property contains no standard buttons.
995
996 \sa addButton()
997*/
998void QMessageBox::setStandardButtons(StandardButtons buttons)
999{
1000 Q_D(QMessageBox);
1001 d->buttonBox->setStandardButtons(QDialogButtonBox::StandardButtons(int(buttons)));
1002
1003 QList<QAbstractButton *> buttonList = d->buttonBox->buttons();
1004 if (!buttonList.contains(d->escapeButton))
1005 d->escapeButton = nullptr;
1006 if (!buttonList.contains(d->defaultButton))
1007 d->defaultButton = nullptr;
1008 d->autoAddOkButton = false;
1009 d->updateSize();
1010}
1011
1012QMessageBox::StandardButtons QMessageBox::standardButtons() const
1013{
1014 Q_D(const QMessageBox);
1015 return QMessageBox::StandardButtons(int(d->buttonBox->standardButtons()));
1016}
1017
1018/*!
1019 Returns the standard button enum value corresponding to the given \a button,
1020 or NoButton if the given \a button isn't a standard button.
1021
1022 \sa button(), standardButtons()
1023*/
1024QMessageBox::StandardButton QMessageBox::standardButton(QAbstractButton *button) const
1025{
1026 Q_D(const QMessageBox);
1027 return (QMessageBox::StandardButton)d->buttonBox->standardButton(button);
1028}
1029
1030/*!
1031 Returns a pointer corresponding to the standard button \a which,
1032 or \nullptr if the standard button doesn't exist in this message box.
1033
1034 \note Modifying the properties of the returned button may not be reflected
1035 in native implementations of the message dialog. To customize dialog
1036 buttons add a \l{addButton(QAbstractButton *button, QMessageBox::ButtonRole role)}
1037 {custom button} or \l{addButton(const QString &text, QMessageBox::ButtonRole role)}
1038 {button title} instead, or set the \l Option::DontUseNativeDialog option.
1039
1040 \sa standardButtons, standardButton()
1041*/
1042QAbstractButton *QMessageBox::button(StandardButton which) const
1043{
1044 Q_D(const QMessageBox);
1045 return d->buttonBox->button(QDialogButtonBox::StandardButton(which));
1046}
1047
1048/*!
1049 Returns the button that is activated when escape is pressed.
1050
1051 By default, QMessageBox attempts to automatically detect an
1052 escape button as follows:
1053
1054 \list 1
1055 \li If there is only one button, it is made the escape button.
1056 \li If there is a \l Cancel button, it is made the escape button.
1057 \li On \macos only, if there is exactly one button with the role
1058 QMessageBox::RejectRole, it is made the escape button.
1059 \endlist
1060
1061 When an escape button could not be automatically detected, pressing
1062 \uicontrol Esc has no effect.
1063
1064 \sa addButton()
1065*/
1066QAbstractButton *QMessageBox::escapeButton() const
1067{
1068 Q_D(const QMessageBox);
1069 return d->escapeButton;
1070}
1071
1072/*!
1073 Sets the button that gets activated when the \uicontrol Escape key is
1074 pressed to \a button.
1075
1076 \sa addButton(), clickedButton()
1077*/
1078void QMessageBox::setEscapeButton(QAbstractButton *button)
1079{
1080 Q_D(QMessageBox);
1081 if (d->buttonBox->buttons().contains(button))
1082 d->escapeButton = button;
1083}
1084
1085/*!
1086 Sets the buttons that gets activated when the \uicontrol Escape key is
1087 pressed to \a button.
1088
1089 \sa addButton(), clickedButton()
1090*/
1091void QMessageBox::setEscapeButton(QMessageBox::StandardButton button)
1092{
1093 Q_D(QMessageBox);
1094 setEscapeButton(d->buttonBox->button(QDialogButtonBox::StandardButton(button)));
1095}
1096
1098{
1099 if (escapeButton) { // escape button explicitly set
1100 detectedEscapeButton = escapeButton;
1101 return;
1102 }
1103
1104 // Cancel button automatically becomes escape button
1105 detectedEscapeButton = buttonBox->button(QDialogButtonBox::Cancel);
1106 if (detectedEscapeButton)
1107 return;
1108
1109 // If there is only one button, make it the escape button
1110 const QList<QAbstractButton *> buttons = buttonBox->buttons();
1111 if (buttons.size() == 1) {
1112 detectedEscapeButton = buttons.first();
1113 return;
1114 }
1115
1116 // If there are two buttons and one of them is the "Show Details..."
1117 // button, then make the other one the escape button
1118 if (buttons.size() == 2 && detailsButton) {
1119 auto idx = buttons.indexOf(detailsButton);
1120 if (idx != -1) {
1121 detectedEscapeButton = buttons.at(1 - idx);
1122 return;
1123 }
1124 }
1125
1126 // if the message box has one RejectRole button, make it the escape button
1127 for (auto *button : buttons) {
1128 if (buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) {
1129 if (detectedEscapeButton) { // already detected!
1130 detectedEscapeButton = nullptr;
1131 break;
1132 }
1133 detectedEscapeButton = button;
1134 }
1135 }
1136 if (detectedEscapeButton)
1137 return;
1138
1139 // if the message box has one NoRole button, make it the escape button
1140 for (auto *button : buttons) {
1141 if (buttonBox->buttonRole(button) == QDialogButtonBox::NoRole) {
1142 if (detectedEscapeButton) { // already detected!
1143 detectedEscapeButton = nullptr;
1144 break;
1145 }
1146 detectedEscapeButton = button;
1147 }
1148 }
1149}
1150
1151/*!
1152 Returns the button that was clicked by the user,
1153 or \nullptr if the user hit the \uicontrol Esc key and
1154 no \l{setEscapeButton()}{escape button} was set.
1155
1156 If exec() hasn't been called yet, returns nullptr.
1157
1158 Example:
1159
1160 \snippet code/src_gui_dialogs_qmessagebox.cpp 3
1161
1162 \sa standardButton(), button()
1163*/
1164QAbstractButton *QMessageBox::clickedButton() const
1165{
1166 Q_D(const QMessageBox);
1167 return d->clickedButton;
1168}
1169
1170/*!
1171 Returns the button that should be the message box's
1172 \l{QPushButton::setDefault()}{default button}. Returns nullptr
1173 if no default button was set.
1174
1175 \sa addButton(), QPushButton::setDefault()
1176*/
1177QPushButton *QMessageBox::defaultButton() const
1178{
1179 Q_D(const QMessageBox);
1180 return d->defaultButton;
1181}
1182
1183/*!
1184 Sets the message box's \l{QPushButton::setDefault()}{default button}
1185 to \a button.
1186
1187 \sa addButton(), QPushButton::setDefault()
1188*/
1189void QMessageBox::setDefaultButton(QPushButton *button)
1190{
1191 Q_D(QMessageBox);
1192 if (!d->buttonBox->buttons().contains(button))
1193 return;
1194 d->defaultButton = button;
1195 button->setDefault(true);
1196 button->setFocus();
1197}
1198
1199/*!
1200 Sets the message box's \l{QPushButton::setDefault()}{default button}
1201 to \a button.
1202
1203 \sa addButton(), QPushButton::setDefault()
1204*/
1205void QMessageBox::setDefaultButton(QMessageBox::StandardButton button)
1206{
1207 Q_D(QMessageBox);
1208 setDefaultButton(d->buttonBox->button(QDialogButtonBox::StandardButton(button)));
1209}
1210
1211/*! \since 5.2
1212
1213 Sets the checkbox \a cb on the message dialog. The message box takes ownership of the checkbox.
1214 The argument \a cb can be \nullptr to remove an existing checkbox from the message box.
1215
1216 \sa checkBox()
1217*/
1218
1219void QMessageBox::setCheckBox(QCheckBox *cb)
1220{
1221 Q_D(QMessageBox);
1222
1223 if (cb == d->checkbox)
1224 return;
1225
1226 if (d->checkbox) {
1227 d->checkbox->hide();
1228 layout()->removeWidget(d->checkbox);
1229 if (d->checkbox->parentWidget() == this) {
1230 d->checkbox->setParent(nullptr);
1231 d->checkbox->deleteLater();
1232 }
1233 }
1234 d->checkbox = cb;
1235 if (d->checkbox) {
1236 QSizePolicy sp = d->checkbox->sizePolicy();
1237 sp.setHorizontalPolicy(QSizePolicy::MinimumExpanding);
1238 d->checkbox->setSizePolicy(sp);
1239 }
1240 d->setupLayout();
1241}
1242
1243
1244/*! \since 5.2
1245
1246 Returns the checkbox shown on the dialog. This is \nullptr if no checkbox is set.
1247 \sa setCheckBox()
1248*/
1249
1250QCheckBox* QMessageBox::checkBox() const
1251{
1252 Q_D(const QMessageBox);
1253 return d->checkbox;
1254}
1255
1256/*!
1257 \since 6.6
1258 Sets the given \a option to be enabled if \a on is true; otherwise,
1259 clears the given \a option.
1260
1261 Options (particularly the \l Option::DontUseNativeDialog option) should be set
1262 before showing the dialog.
1263
1264 Setting options while the dialog is visible is not guaranteed to have
1265 an immediate effect on the dialog.
1266
1267 Setting options after changing other properties may cause these
1268 values to have no effect.
1269
1270 \sa options, testOption()
1271*/
1272void QMessageBox::setOption(QMessageBox::Option option, bool on)
1273{
1274 const QMessageBox::Options previousOptions = options();
1275 if (!(previousOptions & option) != !on)
1276 setOptions(previousOptions ^ option);
1277}
1278
1279/*!
1280 \since 6.6
1281
1282 Returns \c true if the given \a option is enabled; otherwise, returns
1283 false.
1284
1285 \sa options, setOption()
1286*/
1287bool QMessageBox::testOption(QMessageBox::Option option) const
1288{
1289 Q_D(const QMessageBox);
1290 return d->options->testOption(static_cast<QMessageDialogOptions::Option>(option));
1291}
1292
1293void QMessageBox::setOptions(QMessageBox::Options options)
1294{
1295 Q_D(QMessageBox);
1296
1297 if (QMessageBox::options() == options)
1298 return;
1299
1300 d->options->setOptions(QMessageDialogOptions::Option(int(options)));
1301}
1302
1303QMessageBox::Options QMessageBox::options() const
1304{
1305 Q_D(const QMessageBox);
1306 return QMessageBox::Options(int(d->options->options()));
1307}
1308
1309/*!
1310 \property QMessageBox::options
1311 \brief Options that affect the look and feel of the dialog.
1312 \since 6.6
1313
1314 By default, these options are disabled.
1315
1316 The option \l Option::DontUseNativeDialog should be set
1317 before changing dialog properties or showing the dialog.
1318
1319 Setting options while the dialog is visible is not guaranteed to have
1320 an immediate effect on the dialog.
1321
1322 Setting options after changing other properties may cause these
1323 values to have no effect.
1324
1325 \sa setOption(), testOption()
1326*/
1327
1328/*!
1329 \property QMessageBox::text
1330 \brief the message box text to be displayed.
1331
1332 The text should be a brief sentence or phrase that describes the situation,
1333 ideally formulated as a neutral statement, or a call-to-action question.
1334
1335 The text will be interpreted either as a plain text or as rich text,
1336 depending on the text format setting (\l QMessageBox::textFormat).
1337 The default setting is Qt::AutoText, i.e., the message box will try
1338 to auto-detect the format of the text.
1339
1340 The default value of this property is an empty string.
1341
1342 \sa textFormat, QMessageBox::informativeText, QMessageBox::detailedText
1343*/
1344QString QMessageBox::text() const
1345{
1346 Q_D(const QMessageBox);
1347 return d->label->text();
1348}
1349
1350void QMessageBox::setText(const QString &text)
1351{
1352 Q_D(QMessageBox);
1353 d->label->setText(text);
1354 d->label->setWordWrap(d->label->textFormat() == Qt::RichText
1355 || (d->label->textFormat() == Qt::AutoText && Qt::mightBeRichText(text)));
1356 d->updateSize();
1357}
1358
1359/*!
1360 \enum QMessageBox::Icon
1361
1362 This enum has the following values:
1363
1364 \value NoIcon the message box does not have any icon.
1365
1366 \value Question an icon indicating that
1367 the message is asking a question.
1368
1369 \value Information an icon indicating that
1370 the message is nothing out of the ordinary.
1371
1372 \value Warning an icon indicating that the
1373 message is a warning, but can be dealt with.
1374
1375 \value Critical an icon indicating that
1376 the message represents a critical problem.
1377
1378*/
1379
1380/*!
1381 \property QMessageBox::icon
1382 \brief the message box's icon
1383
1384 The icon of the message box can be specified with one of the
1385 values:
1386
1387 \list
1388 \li QMessageBox::NoIcon
1389 \li QMessageBox::Question
1390 \li QMessageBox::Information
1391 \li QMessageBox::Warning
1392 \li QMessageBox::Critical
1393 \endlist
1394
1395 The default is QMessageBox::NoIcon.
1396
1397 The pixmap used to display the actual icon depends on the current
1398 \l{QWidget::style()} {GUI style}. You can also set a custom pixmap
1399 for the icon by setting the \l{QMessageBox::iconPixmap} {icon
1400 pixmap} property.
1401
1402 \sa iconPixmap
1403*/
1404QMessageBox::Icon QMessageBox::icon() const
1405{
1406 Q_D(const QMessageBox);
1407 return d->icon;
1408}
1409
1410void QMessageBox::setIcon(Icon icon)
1411{
1412 Q_D(QMessageBox);
1413 setIconPixmap(QMessageBoxPrivate::standardIcon((QMessageBox::Icon)icon,
1414 this));
1415 d->icon = icon;
1416}
1417
1418/*!
1419 \property QMessageBox::iconPixmap
1420 \brief the current icon
1421
1422 The icon currently used by the message box. Note that it's often
1423 hard to draw one pixmap that looks appropriate in all GUI styles;
1424 you may want to supply a different pixmap for each platform.
1425
1426 By default, this property is undefined.
1427
1428 \sa icon
1429*/
1430QPixmap QMessageBox::iconPixmap() const
1431{
1432 Q_D(const QMessageBox);
1433 return d->iconLabel->pixmap();
1434}
1435
1436void QMessageBox::setIconPixmap(const QPixmap &pixmap)
1437{
1438 Q_D(QMessageBox);
1439 d->iconLabel->setPixmap(pixmap);
1440 d->icon = NoIcon;
1441 d->setupLayout();
1442}
1443
1444/*!
1445 \property QMessageBox::textFormat
1446 \brief the format of the text displayed by the message box
1447
1448 The current text format used by the message box. See the \l
1449 Qt::TextFormat enum for an explanation of the possible options.
1450
1451 The default format is Qt::AutoText.
1452
1453 \sa setText()
1454*/
1455Qt::TextFormat QMessageBox::textFormat() const
1456{
1457 Q_D(const QMessageBox);
1458 return d->label->textFormat();
1459}
1460
1461void QMessageBox::setTextFormat(Qt::TextFormat format)
1462{
1463 Q_D(QMessageBox);
1464 d->label->setTextFormat(format);
1465 d->label->setWordWrap(format == Qt::RichText
1466 || (format == Qt::AutoText && Qt::mightBeRichText(d->label->text())));
1467 if (d->informativeLabel)
1468 d->informativeLabel->setTextFormat(format);
1469 d->updateSize();
1470}
1471
1472/*!
1473 \property QMessageBox::textInteractionFlags
1474 \since 5.1
1475
1476 Specifies how the label of the message box should interact with user
1477 input.
1478
1479 The default value depends on the style.
1480
1481 \sa QStyle::SH_MessageBox_TextInteractionFlags
1482*/
1483
1484Qt::TextInteractionFlags QMessageBox::textInteractionFlags() const
1485{
1486 Q_D(const QMessageBox);
1487 return d->label->textInteractionFlags();
1488}
1489
1490void QMessageBox::setTextInteractionFlags(Qt::TextInteractionFlags flags)
1491{
1492 Q_D(QMessageBox);
1493 d->label->setTextInteractionFlags(flags);
1494}
1495
1496/*!
1497 \reimp
1498*/
1499bool QMessageBox::event(QEvent *e)
1500{
1501 bool result =QDialog::event(e);
1502 switch (e->type()) {
1503 case QEvent::LayoutRequest:
1504 d_func()->updateSize();
1505 break;
1506 case QEvent::LanguageChange:
1507 d_func()->retranslateStrings();
1508 break;
1509 default:
1510 break;
1511 }
1512 return result;
1513}
1514
1515/*!
1516 \reimp
1517*/
1518void QMessageBox::resizeEvent(QResizeEvent *event)
1519{
1520 QDialog::resizeEvent(event);
1521}
1522
1523/*!
1524 \reimp
1525*/
1526void QMessageBox::closeEvent(QCloseEvent *e)
1527{
1528 Q_D(QMessageBox);
1529 if (!d->detectedEscapeButton) {
1530 e->ignore();
1531 return;
1532 }
1533 QDialog::closeEvent(e);
1534 if (!d->clickedButton) {
1535 d->clickedButton = d->detectedEscapeButton;
1536 setResult(d->execReturnCode(d->detectedEscapeButton));
1537 }
1538}
1539
1540/*!
1541 \reimp
1542*/
1543void QMessageBox::changeEvent(QEvent *ev)
1544{
1545 Q_D(QMessageBox);
1546 switch (ev->type()) {
1547 case QEvent::StyleChange:
1548 {
1549 if (d->icon != NoIcon)
1550 setIcon(d->icon);
1551 Qt::TextInteractionFlags flags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, this));
1552 d->label->setTextInteractionFlags(flags);
1553 d->buttonBox->setCenterButtons(style()->styleHint(QStyle::SH_MessageBox_CenterButtons, nullptr, this));
1554 if (d->informativeLabel)
1555 d->informativeLabel->setTextInteractionFlags(flags);
1556 Q_FALLTHROUGH();
1557 }
1558 case QEvent::FontChange:
1559 case QEvent::ApplicationFontChange:
1560#ifdef Q_OS_MAC
1561 {
1562 QFont f = font();
1563 f.setBold(true);
1564 d->label->setFont(f);
1565 }
1566#endif
1567 Q_FALLTHROUGH();
1568 default:
1569 break;
1570 }
1571 QDialog::changeEvent(ev);
1572}
1573
1574/*!
1575 \reimp
1576*/
1577void QMessageBox::keyPressEvent(QKeyEvent *e)
1578{
1579#if QT_CONFIG(shortcut)
1580 Q_D(QMessageBox);
1581 if (e->matches(QKeySequence::Cancel)) {
1582 if (d->detectedEscapeButton) {
1583#ifdef Q_OS_MAC
1584 d->detectedEscapeButton->animateClick();
1585#else
1586 d->detectedEscapeButton->click();
1587#endif
1588 }
1589 return;
1590 }
1591#endif // QT_CONFIG(shortcut)
1592
1593#if !defined(QT_NO_CLIPBOARD) && !defined(QT_NO_SHORTCUT)
1594
1595#if QT_CONFIG(textedit)
1596 if (e == QKeySequence::Copy) {
1597 if (d->detailsText && d->detailsText->isVisible() && d->detailsText->copy()) {
1598 e->setAccepted(true);
1599 return;
1600 }
1601 } else if (e == QKeySequence::SelectAll && d->detailsText && d->detailsText->isVisible()) {
1602 d->detailsText->selectAll();
1603 e->setAccepted(true);
1604 return;
1605 }
1606#endif // QT_CONFIG(textedit)
1607
1608#if defined(Q_OS_WIN)
1609 if (e == QKeySequence::Copy) {
1610 const auto separator = "---------------------------\n"_L1;
1611 QString textToCopy;
1612 textToCopy += separator + windowTitle() + u'\n' + separator // title
1613 + d->label->text() + u'\n' + separator; // text
1614
1615 if (d->informativeLabel)
1616 textToCopy += d->informativeLabel->text() + u'\n' + separator;
1617
1618 const QList<QAbstractButton *> buttons = d->buttonBox->buttons();
1619 for (const auto *button : buttons)
1620 textToCopy += button->text() + " "_L1;
1621 textToCopy += u'\n' + separator;
1622#if QT_CONFIG(textedit)
1623 if (d->detailsText)
1624 textToCopy += d->detailsText->text() + u'\n' + separator;
1625#endif
1626 QGuiApplication::clipboard()->setText(textToCopy);
1627 return;
1628 }
1629#endif // Q_OS_WIN
1630
1631#endif // !QT_NO_CLIPBOARD && !QT_NO_SHORTCUT
1632
1633#ifndef QT_NO_SHORTCUT
1634 if (!(e->modifiers() & (Qt::AltModifier | Qt::ControlModifier | Qt::MetaModifier))) {
1635 int key = e->key() & ~Qt::MODIFIER_MASK;
1636 if (key) {
1637 const QList<QAbstractButton *> buttons = d->buttonBox->buttons();
1638 for (auto *pb : buttons) {
1639 QKeySequence shortcut = pb->shortcut();
1640 if (!shortcut.isEmpty() && key == shortcut[0].key()) {
1641 pb->animateClick();
1642 return;
1643 }
1644 }
1645 }
1646 }
1647#endif
1648 QDialog::keyPressEvent(e);
1649}
1650
1651/*!
1652 Opens the dialog and connects its finished() or buttonClicked() signal to
1653 the slot specified by \a receiver and \a member. If the slot in \a member
1654 has a pointer for its first parameter the connection is to buttonClicked(),
1655 otherwise the connection is to finished().
1656
1657 The signal will be disconnected from the slot when the dialog is closed.
1658*/
1659void QMessageBox::open(QObject *receiver, const char *member)
1660{
1661 Q_D(QMessageBox);
1662 const char *signal = member && strchr(member, '*') ? SIGNAL(buttonClicked(QAbstractButton*))
1663 : SIGNAL(finished(int));
1664 connect(this, signal, receiver, member);
1665 d->signalToDisconnectOnClose = signal;
1666 d->receiverToDisconnectOnClose = receiver;
1667 d->memberToDisconnectOnClose = member;
1668 QDialog::open();
1669}
1670
1672{
1673 // Last minute setup
1674 if (visible) {
1675 Q_Q(QMessageBox);
1676 if (autoAddOkButton)
1677 q->addButton(QMessageBox::Ok);
1679 }
1680 // On hide, we may be called from ~QDialog(), so prevent accessing
1681 // q_ptr as a QMessageBox!
1682
1684 setNativeDialogVisible(visible);
1685
1686 // Update WA_DontShowOnScreen based on whether the native dialog was shown,
1687 // so that QDialog::setVisible(visible) below updates the QWidget state correctly,
1688 // but skips showing the non-native version.
1689 static_cast<QWidget*>(q_ptr)->setAttribute(Qt::WA_DontShowOnScreen, nativeDialogInUse);
1690
1691 QDialogPrivate::setVisible(visible);
1692}
1693
1694/*!
1695 Returns a list of all the buttons that have been added to the message box.
1696
1697 \sa buttonRole(), addButton(), removeButton()
1698*/
1699QList<QAbstractButton *> QMessageBox::buttons() const
1700{
1701 Q_D(const QMessageBox);
1702 return d->buttonBox->buttons();
1703}
1704
1705/*!
1706 Returns the button role for the specified \a button. This function returns
1707 \l InvalidRole if \a button is \nullptr or has not been added to the message box.
1708
1709 \sa buttons(), addButton()
1710*/
1711QMessageBox::ButtonRole QMessageBox::buttonRole(QAbstractButton *button) const
1712{
1713 Q_D(const QMessageBox);
1714 return QMessageBox::ButtonRole(d->buttonBox->buttonRole(button));
1715}
1716
1717/*!
1718 \reimp
1719*/
1720void QMessageBox::showEvent(QShowEvent *e)
1721{
1722 Q_D(QMessageBox);
1723 d->clickedButton = nullptr;
1724 d->updateSize();
1725
1726#if QT_CONFIG(accessibility)
1727 QAccessibleEvent event(this, QAccessible::Alert);
1728 QAccessible::updateAccessibility(&event);
1729#endif
1730#if defined(Q_OS_WIN)
1731 if (const HMENU systemMenu = qt_getWindowsSystemMenu(this)) {
1732 EnableMenuItem(systemMenu, SC_CLOSE, d->detectedEscapeButton ?
1733 MF_BYCOMMAND|MF_ENABLED : MF_BYCOMMAND|MF_GRAYED);
1734 }
1735#endif
1736 QDialog::showEvent(e);
1737}
1738
1739
1741 QMessageBox::Icon icon,
1742 const QString& title, const QString& text,
1743 QMessageBox::StandardButtons buttons,
1744 QMessageBox::StandardButton defaultButton)
1745{
1746 // necessary for source compatibility with Qt 4.0 and 4.1
1747 // handles (Yes, No) and (Yes|Default, No)
1748 if (defaultButton && !(buttons & defaultButton)) {
1749 const int defaultButtons = defaultButton | QMessageBox::Default;
1750 const int otherButtons = buttons.toInt();
1751 const int ret = QMessageBoxPrivate::showOldMessageBox(parent, icon, title,
1752 text, otherButtons,
1753 defaultButtons, 0);
1754 return static_cast<QMessageBox::StandardButton>(ret);
1755 }
1756
1757 QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent);
1758 QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox*>();
1759 Q_ASSERT(buttonBox != nullptr);
1760
1761 uint mask = QMessageBox::FirstButton;
1762 while (mask <= QMessageBox::LastButton) {
1763 uint sb = buttons & mask;
1764 mask <<= 1;
1765 if (!sb)
1766 continue;
1767 QPushButton *button = msgBox.addButton((QMessageBox::StandardButton)sb);
1768 // Choose the first accept role as the default
1769 if (msgBox.defaultButton())
1770 continue;
1771 if ((defaultButton == QMessageBox::NoButton && buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
1772 || (defaultButton != QMessageBox::NoButton && sb == uint(defaultButton)))
1773 msgBox.setDefaultButton(button);
1774 }
1775 if (msgBox.exec() == -1)
1776 return QMessageBox::Cancel;
1777 return msgBox.standardButton(msgBox.clickedButton());
1778}
1779
1780/*!
1781 Opens an information message box with the given \a title and
1782 \a text in front of the specified \a parent widget.
1783
1784 The standard \a buttons are added to the message box.
1785 \a defaultButton specifies the button used when \uicontrol Enter is pressed.
1786 \a defaultButton must refer to a button that was given in \a buttons.
1787 If \a defaultButton is QMessageBox::NoButton, QMessageBox
1788 chooses a suitable default automatically.
1789
1790 Returns the identity of the standard button that was clicked. If
1791 \uicontrol Esc was pressed instead, the \l{Default and Escape Keys}
1792 {escape button} is returned.
1793
1794 The message box is an \l{Qt::ApplicationModal}{application modal}
1795 dialog box.
1796
1797 \warning Do not delete \a parent during the execution of the dialog.
1798 If you want to do this, you should create the dialog
1799 yourself using one of the QMessageBox constructors.
1800
1801 \sa question(), warning(), critical()
1802*/
1803QMessageBox::StandardButton QMessageBox::information(QWidget *parent, const QString &title,
1804 const QString& text, StandardButtons buttons,
1805 StandardButton defaultButton)
1806{
1807 return showNewMessageBox(parent, Information, title, text, buttons,
1808 defaultButton);
1809}
1810
1811
1812/*!
1813 Opens a question message box with the given \a title and \a
1814 text in front of the specified \a parent widget.
1815
1816 The standard \a buttons are added to the message box. \a
1817 defaultButton specifies the button used when \uicontrol Enter is
1818 pressed. \a defaultButton must refer to a button that was given in \a buttons.
1819 If \a defaultButton is QMessageBox::NoButton, QMessageBox
1820 chooses a suitable default automatically.
1821
1822 Returns the identity of the standard button that was clicked. If
1823 \uicontrol Esc was pressed instead, the \l{Default and Escape Keys}
1824 {escape button} is returned.
1825
1826 The message box is an \l{Qt::ApplicationModal} {application modal}
1827 dialog box.
1828
1829 \warning Do not delete \a parent during the execution of the dialog.
1830 If you want to do this, you should create the dialog
1831 yourself using one of the QMessageBox constructors.
1832
1833 \sa information(), warning(), critical()
1834*/
1835QMessageBox::StandardButton QMessageBox::question(QWidget *parent, const QString &title,
1836 const QString& text, StandardButtons buttons,
1837 StandardButton defaultButton)
1838{
1839 return showNewMessageBox(parent, Question, title, text, buttons, defaultButton);
1840}
1841
1842/*!
1843 Opens a warning message box with the given \a title and \a
1844 text in front of the specified \a parent widget.
1845
1846 The standard \a buttons are added to the message box. \a
1847 defaultButton specifies the button used when \uicontrol Enter is
1848 pressed. \a defaultButton must refer to a button that was given in \a buttons.
1849 If \a defaultButton is QMessageBox::NoButton, QMessageBox
1850 chooses a suitable default automatically.
1851
1852 Returns the identity of the standard button that was clicked. If
1853 \uicontrol Esc was pressed instead, the \l{Default and Escape Keys}
1854 {escape button} is returned.
1855
1856 The message box is an \l{Qt::ApplicationModal} {application modal}
1857 dialog box.
1858
1859 \warning Do not delete \a parent during the execution of the dialog.
1860 If you want to do this, you should create the dialog
1861 yourself using one of the QMessageBox constructors.
1862
1863 \sa question(), information(), critical()
1864*/
1865QMessageBox::StandardButton QMessageBox::warning(QWidget *parent, const QString &title,
1866 const QString& text, StandardButtons buttons,
1867 StandardButton defaultButton)
1868{
1869 return showNewMessageBox(parent, Warning, title, text, buttons, defaultButton);
1870}
1871
1872/*!
1873 Opens a critical message box with the given \a title and \a
1874 text in front of the specified \a parent widget.
1875
1876 The standard \a buttons are added to the message box. \a
1877 defaultButton specifies the button used when \uicontrol Enter is
1878 pressed. \a defaultButton must refer to a button that was given in \a buttons.
1879 If \a defaultButton is QMessageBox::NoButton, QMessageBox
1880 chooses a suitable default automatically.
1881
1882 Returns the identity of the standard button that was clicked. If
1883 \uicontrol Esc was pressed instead, the \l{Default and Escape Keys}
1884 {escape button} is returned.
1885
1886 The message box is an \l{Qt::ApplicationModal} {application modal}
1887 dialog box.
1888
1889 \warning Do not delete \a parent during the execution of the dialog.
1890 If you want to do this, you should create the dialog
1891 yourself using one of the QMessageBox constructors.
1892
1893 \sa question(), warning(), information()
1894*/
1895QMessageBox::StandardButton QMessageBox::critical(QWidget *parent, const QString &title,
1896 const QString& text, StandardButtons buttons,
1897 StandardButton defaultButton)
1898{
1899 return showNewMessageBox(parent, Critical, title, text, buttons, defaultButton);
1900}
1901
1902/*!
1903 Displays a simple about box with title \a title and text \a
1904 text. The about box's parent is \a parent.
1905
1906 about() looks for a suitable icon in four locations:
1907
1908 \list 1
1909 \li It prefers \l{QWidget::windowIcon()}{parent->icon()}
1910 if that exists.
1911 \li If not, it tries the top-level widget containing \a parent.
1912 \li If that fails, it tries the \l{QApplication::activeWindow()}{active window.}
1913 \li As a last resort it uses the Information icon.
1914 \endlist
1915
1916 The about box has a single button labelled "OK".
1917
1918 On \macos, the about box is popped up as a modeless window; on
1919 other platforms, it is currently application modal.
1920
1921 \sa QWidget::windowIcon(), QApplication::activeWindow()
1922*/
1923void QMessageBox::about(QWidget *parent, const QString &title, const QString &text)
1924{
1925#ifdef Q_OS_MAC
1926 static QPointer<QMessageBox> oldMsgBox;
1927
1928 if (oldMsgBox && oldMsgBox->text() == text) {
1929 oldMsgBox->show();
1930 oldMsgBox->raise();
1931 oldMsgBox->activateWindow();
1932 return;
1933 }
1934#endif
1935
1936 QMessageBox *msgBox = new QMessageBox(Information, title, text, NoButton, parent
1937#ifdef Q_OS_MAC
1938 , Qt::WindowTitleHint | Qt::WindowSystemMenuHint
1939#endif
1940 );
1941 msgBox->setAttribute(Qt::WA_DeleteOnClose);
1942 QIcon icon = msgBox->windowIcon();
1943 msgBox->setIconPixmap(icon.pixmap(QSize(64, 64), msgBox->devicePixelRatio()));
1944
1945 // should perhaps be a style hint
1946#ifdef Q_OS_MAC
1947 oldMsgBox = msgBox;
1948 auto *d = msgBox->d_func();
1949 d->buttonBox->setCenterButtons(true);
1950#ifdef Q_OS_IOS
1951 msgBox->setModal(true);
1952#else
1953 msgBox->setModal(false);
1954#endif
1955 msgBox->show();
1956#else
1957 msgBox->exec();
1958#endif
1959}
1960
1961/*!
1962 Displays a simple message box about Qt, with the given \a title
1963 and centered over \a parent (if \a parent is not \nullptr). The message
1964 includes the version number of Qt being used by the application.
1965
1966 This is useful for inclusion in the \uicontrol Help menu of an application,
1967 as shown in the \l{mainwindows/menus}{Menus} example.
1968
1969 QApplication provides this functionality as a slot.
1970
1971 On \macos, the aboutQt box is popped up as a modeless window; on
1972 other platforms, it is currently application modal.
1973
1974 \sa QApplication::aboutQt()
1975*/
1976void QMessageBox::aboutQt(QWidget *parent, const QString &title)
1977{
1978#ifdef Q_OS_MAC
1979 static QPointer<QMessageBox> oldMsgBox;
1980
1981 if (oldMsgBox) {
1982 oldMsgBox->show();
1983 oldMsgBox->raise();
1984 oldMsgBox->activateWindow();
1985 return;
1986 }
1987#endif
1988
1989 QString translatedTextAboutQtCaption;
1990 translatedTextAboutQtCaption = QMessageBox::tr(
1991 "<h3>About Qt</h3>"
1992 "<p>This program uses Qt version %1.</p>"
1993 ).arg(QT_VERSION_STR ""_L1);
1994 //: Leave this text untranslated or include a verbatim copy of it below
1995 //: and note that it is the authoritative version in case of doubt.
1996 const QString translatedTextAboutQtText = QMessageBox::tr(
1997 "<p>Qt is a C++ toolkit for cross-platform application "
1998 "development.</p>"
1999 "<p>Qt provides single-source portability across all major desktop "
2000 "operating systems. It is also available for embedded Linux and other "
2001 "embedded and mobile operating systems.</p>"
2002 "<p>Qt is available under multiple licensing options designed "
2003 "to accommodate the needs of our various users.</p>"
2004 "<p>Qt licensed under our commercial license agreement is appropriate "
2005 "for development of proprietary/commercial software where you do not "
2006 "want to share any source code with third parties or otherwise cannot "
2007 "comply with the terms of GNU (L)GPL.</p>"
2008 "<p>Qt licensed under GNU (L)GPL is appropriate for the "
2009 "development of Qt&nbsp;applications provided you can comply with the terms "
2010 "and conditions of the respective licenses.</p>"
2011 "<p>Please see <a href=\"https://%2/\">%2</a> "
2012 "for an overview of Qt licensing.</p>"
2013 "<p>Copyright (C) The Qt Company Ltd. and other "
2014 "contributors.</p>"
2015 "<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>"
2016 "<p>Qt is The Qt Company Ltd. product developed as an open source "
2017 "project. See <a href=\"https://%3/\">%3</a> for more information.</p>"
2018 ).arg(QStringLiteral("qt.io/licensing"),
2019 QStringLiteral("qt.io"));
2020 QMessageBox *msgBox = new QMessageBox(parent);
2021 msgBox->setAttribute(Qt::WA_DeleteOnClose);
2022 msgBox->setWindowTitle(title.isEmpty() ? tr("About Qt") : title);
2023 msgBox->setText(translatedTextAboutQtCaption);
2024 msgBox->setInformativeText(translatedTextAboutQtText);
2025
2026 QPixmap pm(":/qt-project.org/qmessagebox/images/qtlogo-64.png"_L1);
2027 if (!pm.isNull())
2028 msgBox->setIconPixmap(pm);
2029
2030 // should perhaps be a style hint
2031#ifdef Q_OS_MAC
2032 oldMsgBox = msgBox;
2033 auto *d = msgBox->d_func();
2034 d->buttonBox->setCenterButtons(true);
2035#ifdef Q_OS_IOS
2036 msgBox->setModal(true);
2037#else
2038 msgBox->setModal(false);
2039#endif
2040 msgBox->show();
2041#else
2042 msgBox->exec();
2043#endif
2044}
2045
2046/////////////////////////////////////////////////////////////////////////////////////////
2047// Source and binary compatibility routines for 4.0 and 4.1
2048
2050{
2051 // this is needed for source compatibility with Qt 4.0 and 4.1
2052 if (button == QMessageBox::NoButton || (button & NewButtonMask))
2053 return QMessageBox::StandardButton(button & QMessageBox::ButtonMask);
2054
2055 return QMessageBox::NoButton;
2056}
2057
2058static bool detectedCompat(int button0, int button1, int button2)
2059{
2060 if (button0 != 0 && !(button0 & NewButtonMask))
2061 return true;
2062 if (button1 != 0 && !(button1 & NewButtonMask))
2063 return true;
2064 if (button2 != 0 && !(button2 & NewButtonMask))
2065 return true;
2066 return false;
2067}
2068
2069QAbstractButton *QMessageBoxPrivate::findButton(int button0, int button1, int button2, int flags)
2070{
2071 Q_Q(QMessageBox);
2072 int button = 0;
2073
2074 if (button0 & flags) {
2075 button = button0;
2076 } else if (button1 & flags) {
2077 button = button1;
2078 } else if (button2 & flags) {
2079 button = button2;
2080 }
2081 return q->button(newButton(button));
2082}
2083
2084void QMessageBoxPrivate::addOldButtons(int button0, int button1, int button2)
2085{
2086 Q_Q(QMessageBox);
2087 q->addButton(newButton(button0));
2088 q->addButton(newButton(button1));
2089 q->addButton(newButton(button2));
2090 q->setDefaultButton(
2091 static_cast<QPushButton *>(findButton(button0, button1, button2, QMessageBox::Default)));
2092 q->setEscapeButton(findButton(button0, button1, button2, QMessageBox::Escape));
2093 compatMode = detectedCompat(button0, button1, button2);
2094}
2095
2097{
2098 Q_Q(const QMessageBox);
2099 QAbstractButton *result = customButtonList.value(id);
2100 if (result)
2101 return result;
2102 if (id & QMessageBox::FlagMask) // for compatibility with Qt 4.0/4.1 (even if it is silly)
2103 return nullptr;
2104 return q->button(newButton(id));
2105}
2106
2107int QMessageBoxPrivate::showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,
2108 const QString &title, const QString &text,
2109 int button0, int button1, int button2)
2110{
2111 QMessageBox messageBox(icon, title, text, QMessageBox::NoButton, parent);
2112 messageBox.d_func()->addOldButtons(button0, button1, button2);
2113 return messageBox.exec();
2114}
2115
2116int QMessageBoxPrivate::showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,
2117 const QString &title, const QString &text,
2118 const QString &button0Text,
2119 const QString &button1Text,
2120 const QString &button2Text,
2121 int defaultButtonNumber,
2122 int escapeButtonNumber)
2123{
2124 QMessageBox messageBox(icon, title, text, QMessageBox::NoButton, parent);
2125 QString myButton0Text = button0Text;
2126 if (myButton0Text.isEmpty())
2127 myButton0Text = QDialogButtonBox::tr("OK");
2128 messageBox.addButton(myButton0Text, QMessageBox::ActionRole);
2129 if (!button1Text.isEmpty())
2130 messageBox.addButton(button1Text, QMessageBox::ActionRole);
2131 if (!button2Text.isEmpty())
2132 messageBox.addButton(button2Text, QMessageBox::ActionRole);
2133
2134 const QList<QAbstractButton *> &buttonList = messageBox.d_func()->customButtonList;
2135 messageBox.setDefaultButton(static_cast<QPushButton *>(buttonList.value(defaultButtonNumber)));
2136 messageBox.setEscapeButton(buttonList.value(escapeButtonNumber));
2137
2138 messageBox.exec();
2139
2140 // Ignore exec return value and use button index instead,
2141 // as that's what the documentation promises.
2142 return buttonList.indexOf(messageBox.clickedButton());
2143}
2144
2146{
2147#if QT_CONFIG(textedit)
2148 if (detailsButton && detailsText)
2149 detailsButton->setLabel(detailsText->isHidden() ? ShowLabel : HideLabel);
2150#endif
2151}
2152
2153#if QT_DEPRECATED_SINCE(6,2)
2154/*!
2155 \deprecated
2156
2157 Constructs a message box with a \a title, a \a text, an \a icon,
2158 and up to three buttons.
2159
2160 The \a icon must be one of the following:
2161 \list
2162 \li QMessageBox::NoIcon
2163 \li QMessageBox::Question
2164 \li QMessageBox::Information
2165 \li QMessageBox::Warning
2166 \li QMessageBox::Critical
2167 \endlist
2168
2169 Each button, \a button0, \a button1 and \a button2, can have one
2170 of the following values:
2171 \list
2172 \li QMessageBox::NoButton
2173 \li QMessageBox::Ok
2174 \li QMessageBox::Cancel
2175 \li QMessageBox::Yes
2176 \li QMessageBox::No
2177 \li QMessageBox::Abort
2178 \li QMessageBox::Retry
2179 \li QMessageBox::Ignore
2180 \li QMessageBox::YesAll
2181 \li QMessageBox::NoAll
2182 \endlist
2183
2184 Use QMessageBox::NoButton for the later parameters to have fewer
2185 than three buttons in your message box. If you don't specify any
2186 buttons at all, QMessageBox will provide an Ok button.
2187
2188 One of the buttons can be OR-ed with the QMessageBox::Default
2189 flag to make it the default button (clicked when Enter is
2190 pressed).
2191
2192 One of the buttons can be OR-ed with the QMessageBox::Escape flag
2193 to make it the cancel or close button (clicked when \uicontrol Esc is
2194 pressed).
2195
2196 \snippet dialogs/dialogs.cpp 2
2197
2198 The message box is an \l{Qt::ApplicationModal} {application modal}
2199 dialog box.
2200
2201 The \a parent and \a f arguments are passed to
2202 the QDialog constructor.
2203
2204 \sa setWindowTitle(), setText(), setIcon()
2205*/
2206QMessageBox::QMessageBox(const QString &title, const QString &text, Icon icon,
2207 int button0, int button1, int button2, QWidget *parent,
2208 Qt::WindowFlags f)
2209 : QDialog(*new QMessageBoxPrivate, parent,
2210 f /*| Qt::MSWindowsFixedSizeDialogHint #### */| Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
2211{
2212 Q_D(QMessageBox);
2213 d->init(title, text);
2214 setIcon(icon);
2215 d->addOldButtons(button0, button1, button2);
2216}
2217
2218/*!
2219 \deprecated [6.2]. Use the overload taking StandardButtons instead.
2220
2221 Opens an information message box with the given \a title and the
2222 \a text. The dialog may have up to three buttons. Each of the
2223 buttons, \a button0, \a button1 and \a button2 may be set to one
2224 of the following values:
2225
2226 \list
2227 \li QMessageBox::NoButton
2228 \li QMessageBox::Ok
2229 \li QMessageBox::Cancel
2230 \li QMessageBox::Yes
2231 \li QMessageBox::No
2232 \li QMessageBox::Abort
2233 \li QMessageBox::Retry
2234 \li QMessageBox::Ignore
2235 \li QMessageBox::YesAll
2236 \li QMessageBox::NoAll
2237 \endlist
2238
2239 If you don't want all three buttons, set the last button, or last
2240 two buttons to QMessageBox::NoButton.
2241
2242 One button can be OR-ed with QMessageBox::Default, and one
2243 button can be OR-ed with QMessageBox::Escape.
2244
2245 Returns the identity (QMessageBox::Ok, or QMessageBox::No, etc.)
2246 of the button that was clicked.
2247
2248 The message box is an \l{Qt::ApplicationModal} {application modal}
2249 dialog box.
2250
2251 \warning Do not delete \a parent during the execution of the dialog.
2252 If you want to do this, you should create the dialog
2253 yourself using one of the QMessageBox constructors.
2254
2255 \sa question(), warning(), critical()
2256*/
2257int QMessageBox::information(QWidget *parent, const QString &title, const QString& text,
2258 int button0, int button1, int button2)
2259{
2260 return QMessageBoxPrivate::showOldMessageBox(parent, Information, title, text,
2261 button0, button1, button2);
2262}
2263
2264/*!
2265 \deprecated [6.2] Use the overload taking StandardButtons instead.
2266 \overload
2267
2268 Displays an information message box with the given \a title and
2269 \a text, as well as one, two or three buttons. Returns the index
2270 of the button that was clicked (0, 1 or 2).
2271
2272 \a button0Text is the text of the first button, and is optional.
2273 If \a button0Text is not supplied, "OK" (translated) will be
2274 used. \a button1Text is the text of the second button, and is
2275 optional. \a button2Text is the text of the third button, and is
2276 optional. \a defaultButtonNumber (0, 1 or 2) is the index of the
2277 default button; pressing Return or Enter is the same as clicking
2278 the default button. It defaults to 0 (the first button). \a
2279 escapeButtonNumber is the index of the escape button; pressing
2280 \uicontrol Esc is the same as clicking this button. It defaults to -1;
2281 supply 0, 1 or 2 to make pressing \uicontrol Esc equivalent to clicking
2282 the relevant button.
2283
2284 The message box is an \l{Qt::ApplicationModal} {application modal}
2285 dialog box.
2286
2287 \warning Do not delete \a parent during the execution of the dialog.
2288 If you want to do this, you should create the dialog
2289 yourself using one of the QMessageBox constructors.
2290
2291 \sa question(), warning(), critical()
2292*/
2293
2294int QMessageBox::information(QWidget *parent, const QString &title, const QString& text,
2295 const QString& button0Text, const QString& button1Text,
2296 const QString& button2Text, int defaultButtonNumber,
2297 int escapeButtonNumber)
2298{
2299 return QMessageBoxPrivate::showOldMessageBox(parent, Information, title, text,
2300 button0Text, button1Text, button2Text,
2301 defaultButtonNumber, escapeButtonNumber);
2302}
2303
2304/*!
2305 \deprecated [6.2]. Use the overload taking StandardButtons
2306 instead.
2307
2308 Opens a question message box with the given \a title and \a text.
2309 The dialog may have up to three buttons. Each of the buttons, \a
2310 button0, \a button1 and \a button2 may be set to one of the
2311 following values:
2312
2313 \list
2314 \li QMessageBox::NoButton
2315 \li QMessageBox::Ok
2316 \li QMessageBox::Cancel
2317 \li QMessageBox::Yes
2318 \li QMessageBox::No
2319 \li QMessageBox::Abort
2320 \li QMessageBox::Retry
2321 \li QMessageBox::Ignore
2322 \li QMessageBox::YesAll
2323 \li QMessageBox::NoAll
2324 \endlist
2325
2326 If you don't want all three buttons, set the last button, or last
2327 two buttons to QMessageBox::NoButton.
2328
2329 One button can be OR-ed with QMessageBox::Default, and one
2330 button can be OR-ed with QMessageBox::Escape.
2331
2332 Returns the identity (QMessageBox::Yes, or QMessageBox::No, etc.)
2333 of the button that was clicked.
2334
2335 The message box is an \l{Qt::ApplicationModal} {application modal}
2336 dialog box.
2337
2338 \warning Do not delete \a parent during the execution of the dialog.
2339 If you want to do this, you should create the dialog
2340 yourself using one of the QMessageBox constructors.
2341
2342 \sa information(), warning(), critical()
2343*/
2344int QMessageBox::question(QWidget *parent, const QString &title, const QString& text,
2345 int button0, int button1, int button2)
2346{
2347 return QMessageBoxPrivate::showOldMessageBox(parent, Question, title, text,
2348 button0, button1, button2);
2349}
2350
2351/*!
2352 \deprecated [6.2]. Use the overload taking StandardButtons instead.
2353 \overload
2354
2355 Displays a question message box with the given \a title and \a
2356 text, as well as one, two or three buttons. Returns the index of
2357 the button that was clicked (0, 1 or 2).
2358
2359 \a button0Text is the text of the first button, and is optional.
2360 If \a button0Text is not supplied, "OK" (translated) will be used.
2361 \a button1Text is the text of the second button, and is optional.
2362 \a button2Text is the text of the third button, and is optional.
2363 \a defaultButtonNumber (0, 1 or 2) is the index of the default
2364 button; pressing Return or Enter is the same as clicking the
2365 default button. It defaults to 0 (the first button). \a
2366 escapeButtonNumber is the index of the Escape button; pressing
2367 Escape is the same as clicking this button. It defaults to -1;
2368 supply 0, 1 or 2 to make pressing Escape equivalent to clicking
2369 the relevant button.
2370
2371 The message box is an \l{Qt::ApplicationModal} {application modal}
2372 dialog box.
2373
2374 \warning Do not delete \a parent during the execution of the dialog.
2375 If you want to do this, you should create the dialog
2376 yourself using one of the QMessageBox constructors.
2377
2378 \sa information(), warning(), critical()
2379*/
2380int QMessageBox::question(QWidget *parent, const QString &title, const QString& text,
2381 const QString& button0Text, const QString& button1Text,
2382 const QString& button2Text, int defaultButtonNumber,
2383 int escapeButtonNumber)
2384{
2385 return QMessageBoxPrivate::showOldMessageBox(parent, Question, title, text,
2386 button0Text, button1Text, button2Text,
2387 defaultButtonNumber, escapeButtonNumber);
2388}
2389
2390
2391/*!
2392 \deprecated [6.2]. Use the overload taking StandardButtons instead.
2393
2394 Opens a warning message box with the given \a title and \a text.
2395 The dialog may have up to three buttons. Each of the button
2396 parameters, \a button0, \a button1 and \a button2 may be set to
2397 one of the following values:
2398
2399 \list
2400 \li QMessageBox::NoButton
2401 \li QMessageBox::Ok
2402 \li QMessageBox::Cancel
2403 \li QMessageBox::Yes
2404 \li QMessageBox::No
2405 \li QMessageBox::Abort
2406 \li QMessageBox::Retry
2407 \li QMessageBox::Ignore
2408 \li QMessageBox::YesAll
2409 \li QMessageBox::NoAll
2410 \endlist
2411
2412 If you don't want all three buttons, set the last button, or last
2413 two buttons to QMessageBox::NoButton.
2414
2415 One button can be OR-ed with QMessageBox::Default, and one
2416 button can be OR-ed with QMessageBox::Escape.
2417
2418 Returns the identity (QMessageBox::Ok or QMessageBox::No or ...)
2419 of the button that was clicked.
2420
2421 The message box is an \l{Qt::ApplicationModal} {application modal}
2422 dialog box.
2423
2424 \warning Do not delete \a parent during the execution of the dialog.
2425 If you want to do this, you should create the dialog
2426 yourself using one of the QMessageBox constructors.
2427
2428 \sa information(), question(), critical()
2429*/
2430int QMessageBox::warning(QWidget *parent, const QString &title, const QString& text,
2431 int button0, int button1, int button2)
2432{
2433 return QMessageBoxPrivate::showOldMessageBox(parent, Warning, title, text,
2434 button0, button1, button2);
2435}
2436
2437/*!
2438 \deprecated [6.2]. Use the overload taking StandardButtons instead.
2439 \overload
2440
2441 Displays a warning message box with the given \a title and \a
2442 text, as well as one, two, or three buttons. Returns the number
2443 of the button that was clicked (0, 1, or 2).
2444
2445 \a button0Text is the text of the first button, and is optional.
2446 If \a button0Text is not supplied, "OK" (translated) will be used.
2447 \a button1Text is the text of the second button, and is optional,
2448 and \a button2Text is the text of the third button, and is
2449 optional. \a defaultButtonNumber (0, 1 or 2) is the index of the
2450 default button; pressing Return or Enter is the same as clicking
2451 the default button. It defaults to 0 (the first button). \a
2452 escapeButtonNumber is the index of the Escape button; pressing
2453 Escape is the same as clicking this button. It defaults to -1;
2454 supply 0, 1, or 2 to make pressing Escape equivalent to clicking
2455 the relevant button.
2456
2457 The message box is an \l{Qt::ApplicationModal} {application modal}
2458 dialog box.
2459
2460 \warning Do not delete \a parent during the execution of the dialog.
2461 If you want to do this, you should create the dialog
2462 yourself using one of the QMessageBox constructors.
2463
2464 \sa information(), question(), critical()
2465*/
2466int QMessageBox::warning(QWidget *parent, const QString &title, const QString& text,
2467 const QString& button0Text, const QString& button1Text,
2468 const QString& button2Text, int defaultButtonNumber,
2469 int escapeButtonNumber)
2470{
2471 return QMessageBoxPrivate::showOldMessageBox(parent, Warning, title, text,
2472 button0Text, button1Text, button2Text,
2473 defaultButtonNumber, escapeButtonNumber);
2474}
2475
2476/*!
2477 \deprecated [6.2]. Use the overload taking StandardButtons instead.
2478
2479 Opens a critical message box with the given \a title and \a text.
2480 The dialog may have up to three buttons. Each of the button
2481 parameters, \a button0, \a button1 and \a button2 may be set to
2482 one of the following values:
2483
2484 \list
2485 \li QMessageBox::NoButton
2486 \li QMessageBox::Ok
2487 \li QMessageBox::Cancel
2488 \li QMessageBox::Yes
2489 \li QMessageBox::No
2490 \li QMessageBox::Abort
2491 \li QMessageBox::Retry
2492 \li QMessageBox::Ignore
2493 \li QMessageBox::YesAll
2494 \li QMessageBox::NoAll
2495 \endlist
2496
2497 If you don't want all three buttons, set the last button, or last
2498 two buttons to QMessageBox::NoButton.
2499
2500 One button can be OR-ed with QMessageBox::Default, and one
2501 button can be OR-ed with QMessageBox::Escape.
2502
2503 Returns the identity (QMessageBox::Ok, or QMessageBox::No, etc.)
2504 of the button that was clicked.
2505
2506 The message box is an \l{Qt::ApplicationModal} {application modal}
2507 dialog box.
2508
2509 \warning Do not delete \a parent during the execution of the dialog.
2510 If you want to do this, you should create the dialog
2511 yourself using one of the QMessageBox constructors.
2512
2513 \sa information(), question(), warning()
2514*/
2515
2516int QMessageBox::critical(QWidget *parent, const QString &title, const QString& text,
2517 int button0, int button1, int button2)
2518{
2519 return QMessageBoxPrivate::showOldMessageBox(parent, Critical, title, text,
2520 button0, button1, button2);
2521}
2522
2523/*!
2524 \deprecated [6.2]. Use the overload taking StandardButtons instead.
2525 \overload
2526
2527 Displays a critical error message box with the given \a title and
2528 \a text, as well as one, two, or three buttons. Returns the
2529 number of the button that was clicked (0, 1 or 2).
2530
2531 \a button0Text is the text of the first button, and is optional.
2532 If \a button0Text is not supplied, "OK" (translated) will be used.
2533 \a button1Text is the text of the second button, and is optional,
2534 and \a button2Text is the text of the third button, and is
2535 optional. \a defaultButtonNumber (0, 1 or 2) is the index of the
2536 default button; pressing Return or Enter is the same as clicking
2537 the default button. It defaults to 0 (the first button). \a
2538 escapeButtonNumber is the index of the Escape button; pressing
2539 Escape is the same as clicking this button. It defaults to -1;
2540 supply 0, 1, or 2 to make pressing Escape equivalent to clicking
2541 the relevant button.
2542
2543 The message box is an \l{Qt::ApplicationModal} {application modal}
2544 dialog box.
2545
2546 \warning Do not delete \a parent during the execution of the dialog.
2547 If you want to do this, you should create the dialog
2548 yourself using one of the QMessageBox constructors.
2549
2550 \sa information(), question(), warning()
2551*/
2552int QMessageBox::critical(QWidget *parent, const QString &title, const QString& text,
2553 const QString& button0Text, const QString& button1Text,
2554 const QString& button2Text, int defaultButtonNumber,
2555 int escapeButtonNumber)
2556{
2557 return QMessageBoxPrivate::showOldMessageBox(parent, Critical, title, text,
2558 button0Text, button1Text, button2Text,
2559 defaultButtonNumber, escapeButtonNumber);
2560}
2561
2562
2563/*!
2564 \deprecated [6.2]
2565
2566 Returns the text of the message box button \a button, or
2567 an empty string if the message box does not contain the button.
2568
2569 Use button() and QPushButton::text() instead.
2570*/
2571QString QMessageBox::buttonText(int button) const
2572{
2573 Q_D(const QMessageBox);
2574
2575 if (QAbstractButton *abstractButton = d->abstractButtonForId(button)) {
2576 return abstractButton->text();
2577 } else if (d->buttonBox->buttons().isEmpty() && (button == Ok || button == Old_Ok)) {
2578 // for compatibility with Qt 4.0/4.1
2579 return QDialogButtonBox::tr("OK");
2580 }
2581 return QString();
2582}
2583
2584/*!
2585 \deprecated [6.2]
2586
2587 Sets the text of the message box button \a button to \a text.
2588 Setting the text of a button that is not in the message box is
2589 silently ignored.
2590
2591 Use addButton() instead.
2592*/
2593void QMessageBox::setButtonText(int button, const QString &text)
2594{
2595 Q_D(QMessageBox);
2596 if (QAbstractButton *abstractButton = d->abstractButtonForId(button)) {
2597 abstractButton->setText(text);
2598 } else if (d->buttonBox->buttons().isEmpty() && (button == Ok || button == Old_Ok)) {
2599 // for compatibility with Qt 4.0/4.1
2600 addButton(QMessageBox::Ok)->setText(text);
2601 }
2602}
2603#endif // QT_DEPRECATED_SINCE(6,2)
2604
2605
2606#if QT_CONFIG(textedit)
2607/*!
2608 \property QMessageBox::detailedText
2609 \brief the text to be displayed in the details area.
2610
2611 The text will be interpreted as a plain text.
2612
2613 By default, this property contains an empty string.
2614
2615 \sa QMessageBox::text, QMessageBox::informativeText
2616*/
2617QString QMessageBox::detailedText() const
2618{
2619 Q_D(const QMessageBox);
2620 return d->detailsText ? d->detailsText->text() : QString();
2621}
2622
2623void QMessageBox::setDetailedText(const QString &text)
2624{
2625 Q_D(QMessageBox);
2626 if (text.isEmpty()) {
2627 if (d->detailsText) {
2628 d->detailsText->hide();
2629 d->detailsText->deleteLater();
2630 }
2631 d->detailsText = nullptr;
2632 removeButton(d->detailsButton);
2633 if (d->detailsButton) {
2634 d->detailsButton->hide();
2635 d->detailsButton->deleteLater();
2636 }
2637 d->detailsButton = nullptr;
2638 } else {
2639 if (!d->detailsText) {
2640 d->detailsText = new QMessageBoxDetailsText(this);
2641 d->detailsText->hide();
2642 }
2643 if (!d->detailsButton) {
2644 const bool autoAddOkButton = d->autoAddOkButton; // QTBUG-39334, addButton() clears the flag.
2645 d->detailsButton = new DetailButton(this);
2646 addButton(d->detailsButton, QMessageBox::ActionRole);
2647 d->autoAddOkButton = autoAddOkButton;
2648 }
2649 d->detailsText->setText(text);
2650 }
2651 d->setupLayout();
2652}
2653#endif // QT_CONFIG(textedit)
2654
2655/*!
2656 \property QMessageBox::informativeText
2657
2658 \brief the informative text that provides a fuller description for
2659 the message
2660
2661 Informative text can be used to expand upon the text() to give more
2662 information to the user, for example describing the consequences of
2663 the situation, or suggestion alternative solutions.
2664
2665 The text will be interpreted either as a plain text or as rich text,
2666 depending on the text format setting (\l QMessageBox::textFormat).
2667 The default setting is Qt::AutoText, i.e., the message box will try
2668 to auto-detect the format of the text.
2669
2670 By default, this property contains an empty string.
2671
2672 \sa textFormat, QMessageBox::text, QMessageBox::detailedText
2673*/
2674QString QMessageBox::informativeText() const
2675{
2676 Q_D(const QMessageBox);
2677 return d->informativeLabel ? d->informativeLabel->text() : QString();
2678}
2679
2680void QMessageBox::setInformativeText(const QString &text)
2681{
2682 Q_D(QMessageBox);
2683 if (text.isEmpty()) {
2684 if (d->informativeLabel) {
2685 d->informativeLabel->hide();
2686 d->informativeLabel->deleteLater();
2687 }
2688 d->informativeLabel = nullptr;
2689 } else {
2690 if (!d->informativeLabel) {
2691 QLabel *label = new QLabel;
2692 label->setObjectName("qt_msgbox_informativelabel"_L1);
2693 label->setTextInteractionFlags(Qt::TextInteractionFlags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, this)));
2694 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
2695 label->setOpenExternalLinks(true);
2696#ifdef Q_OS_MAC
2697 // apply a smaller font the information label on the mac
2698 label->setFont(qt_app_fonts_hash()->value("QTipLabel"));
2699#endif
2700 label->setWordWrap(true);
2701 label->setTextFormat(d->label->textFormat());
2702 d->informativeLabel = label;
2703 }
2704 d->informativeLabel->setText(text);
2705 }
2706 d->setupLayout();
2707}
2708
2709/*!
2710 This function shadows QWidget::setWindowTitle().
2711
2712 Sets the title of the message box to \a title. On \macos,
2713 the window title is ignored (as required by the \macos
2714 Guidelines).
2715*/
2716void QMessageBox::setWindowTitle(const QString &title)
2717{
2718 // Message boxes on the mac do not have a title
2719#ifndef Q_OS_MAC
2720 QDialog::setWindowTitle(title);
2721#else
2722 Q_UNUSED(title);
2723#endif
2724}
2725
2726
2727/*!
2728 This function shadows QWidget::setWindowModality().
2729
2730 Sets the modality of the message box to \a windowModality.
2731
2732 On \macos, if the modality is set to Qt::WindowModal and the message box
2733 has a parent, then the message box will be a Qt::Sheet, otherwise the
2734 message box will be a standard dialog.
2735*/
2736void QMessageBox::setWindowModality(Qt::WindowModality windowModality)
2737{
2738 QDialog::setWindowModality(windowModality);
2739
2740 if (parentWidget() && windowModality == Qt::WindowModal)
2741 setParent(parentWidget(), Qt::Sheet);
2742 else
2743 setParent(parentWidget(), Qt::Dialog);
2744 setDefaultButton(d_func()->defaultButton);
2745}
2746
2747
2748QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb)
2749{
2750 QStyle *style = mb ? mb->style() : QApplication::style();
2751 int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, mb);
2752 QIcon tmpIcon;
2753 switch (icon) {
2754 case QMessageBox::Information:
2755 tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, mb);
2756 break;
2757 case QMessageBox::Warning:
2758 tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, mb);
2759 break;
2760 case QMessageBox::Critical:
2761 tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, mb);
2762 break;
2763 case QMessageBox::Question:
2764 tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, mb);
2765 break;
2766 default:
2767 break;
2768 }
2769 if (!tmpIcon.isNull()) {
2770 qreal dpr = mb ? mb->devicePixelRatio() : qApp->devicePixelRatio();
2771 return tmpIcon.pixmap(QSize(iconSize, iconSize), dpr);
2772 }
2773 return QPixmap();
2774}
2775
2776void QMessageBoxPrivate::initHelper(QPlatformDialogHelper *h)
2777{
2778 auto *messageDialogHelper = static_cast<QPlatformMessageDialogHelper *>(h);
2779 QObjectPrivate::connect(messageDialogHelper, &QPlatformMessageDialogHelper::clicked,
2780 this, &QMessageBoxPrivate::helperClicked);
2781 // Forward state via lambda, so that we can handle addition and removal
2782 // of checkbox via setCheckBox() after initializing helper.
2783 QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::checkBoxStateChanged,
2784 q_ptr, [this](Qt::CheckState state) {
2785 if (checkbox)
2786 checkbox->setCheckState(state);
2787 }
2788 );
2789 messageDialogHelper->setOptions(options);
2790}
2791
2793{
2794 switch (i) {
2795 case QMessageBox::NoIcon:
2796 return QMessageDialogOptions::NoIcon;
2797 case QMessageBox::Information:
2798 return QMessageDialogOptions::Information;
2799 case QMessageBox::Warning:
2800 return QMessageDialogOptions::Warning;
2801 case QMessageBox::Critical:
2802 return QMessageDialogOptions::Critical;
2803 case QMessageBox::Question:
2804 return QMessageDialogOptions::Question;
2805 }
2806 return QMessageDialogOptions::NoIcon;
2807}
2808
2810{
2811 QPlatformDialogHelper::StandardButtons buttons(int(q->standardButtons()));
2812 return buttons;
2813}
2814
2816{
2817 // Don't use Q_Q here! This function is called from ~QDialog,
2818 // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
2819 const QDialog * const q = static_cast<const QDialog*>(q_ptr);
2820 if (nativeDialogInUse)
2821 return true;
2822 if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
2823 || q->testAttribute(Qt::WA_DontShowOnScreen)
2824 || q->testAttribute(Qt::WA_StyleSheet)
2825 || (options->options() & QMessageDialogOptions::Option::DontUseNativeDialog)) {
2826 return false;
2827 }
2828
2829 if (strcmp(QMessageBox::staticMetaObject.className(), q->metaObject()->className()) != 0)
2830 return false;
2831
2832#if QT_CONFIG(menu)
2833 for (auto *customButton : buttonBox->buttons()) {
2834 if (QPushButton *pushButton = qobject_cast<QPushButton *>(customButton)) {
2835 // We can't support buttons with menus in native dialogs (yet)
2836 if (pushButton->menu())
2837 return false;
2838 }
2839 }
2840#endif
2841
2842 return QDialogPrivate::canBeNativeDialog();
2843}
2844
2845void QMessageBoxPrivate::helperPrepareShow(QPlatformDialogHelper *)
2846{
2847 Q_Q(QMessageBox);
2848 options->setWindowTitle(q->windowTitle());
2849 options->setText(q->text());
2850 options->setInformativeText(q->informativeText());
2851#if QT_CONFIG(textedit)
2852 options->setDetailedText(q->detailedText());
2853#endif
2854 options->setStandardIcon(helperIcon(q->icon()));
2855 options->setIconPixmap(q->iconPixmap());
2856
2857 // Clear up front, since we might have prepared earlier
2858 options->clearCustomButtons();
2859
2860 // Add standard buttons and resolve default/escape button
2861 auto standardButtons = helperStandardButtons(q);
2862 for (int button = QDialogButtonBox::StandardButton::FirstButton;
2863 button <= QDialogButtonBox::StandardButton::LastButton; button <<= 1) {
2864 auto *standardButton = buttonBox->button(QDialogButtonBox::StandardButton(button));
2865 if (!standardButton)
2866 continue;
2867
2868 if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {
2869 if (standardButton->text() != platformTheme->standardButtonText(button)) {
2870 // The standard button has been customized, so add it as
2871 // a custom button instead.
2872 const auto buttonRole = buttonBox->buttonRole(standardButton);
2873 options->addButton(standardButton->text(),
2874 static_cast<QPlatformDialogHelper::ButtonRole>(buttonRole),
2875 standardButton, button);
2876 standardButtons &= ~QPlatformDialogHelper::StandardButton(button);
2877 }
2878 }
2879
2880 if (standardButton == defaultButton)
2881 options->setDefaultButton(button);
2882 else if (standardButton == detectedEscapeButton)
2883 options->setEscapeButton(button);
2884 }
2885 options->setStandardButtons(standardButtons);
2886
2887 // Add custom buttons and resolve default/escape button
2888 for (auto *customButton : customButtonList) {
2889 // Unless it's the details button, since we don't do any
2890 // plumbing for the button's action in that case.
2891 if (customButton == detailsButton)
2892 continue;
2893
2894 const auto buttonRole = buttonBox->buttonRole(customButton);
2895 const int buttonId = options->addButton(customButton->text(),
2896 static_cast<QPlatformDialogHelper::ButtonRole>(buttonRole),
2897 customButton);
2898
2899 if (customButton == defaultButton)
2900 options->setDefaultButton(buttonId);
2901 else if (customButton == detectedEscapeButton)
2902 options->setEscapeButton(buttonId);
2903 }
2904
2905 if (checkbox)
2906 options->setCheckBox(checkbox->text(), checkbox->checkState());
2907}
2908
2909void qRequireVersion(int argc, char *argv[], QAnyStringView req)
2910{
2911 const auto required = QVersionNumber::fromString(req).normalized();
2912 const auto current = QVersionNumber::fromString(qVersion()).normalized();
2913 if (current >= required)
2914 return;
2915 std::optional<QApplication> application;
2916 if (!qApp)
2917 application.emplace(argc, argv);
2918 const QString message = QApplication::tr("Application \"%1\" requires Qt %2, found Qt %3.")
2919 .arg(qAppName(), required.toString(), current.toString());
2920 QMessageBox::critical(nullptr, QApplication::tr("Incompatible Qt Library Error"),
2921 message, QMessageBox::Abort);
2922 qFatal("%ls", qUtf16Printable(message));
2923}
2924
2925#if QT_DEPRECATED_SINCE(6,2)
2926/*!
2927 \deprecated [6.2]
2928
2929 Returns the pixmap used for a standard icon. This allows the
2930 pixmaps to be used in more complex message boxes. \a icon
2931 specifies the required icon, e.g. QMessageBox::Question,
2932 QMessageBox::Information, QMessageBox::Warning or
2933 QMessageBox::Critical.
2934
2935 Call QStyle::standardIcon() with QStyle::SP_MessageBoxInformation etc.
2936 instead.
2937*/
2938
2939QPixmap QMessageBox::standardIcon(Icon icon)
2940{
2941 return QMessageBoxPrivate::standardIcon(icon, nullptr);
2942}
2943#endif
2944
2945/*!
2946 \typedef QMessageBox::Button
2947 \deprecated
2948
2949 Use QMessageBox::StandardButton instead.
2950*/
2951
2952/*!
2953 \fn int QMessageBox::information(QWidget *parent, const QString &title,
2954 const QString& text, StandardButton button0,
2955 StandardButton button1)
2956 \fn int QMessageBox::warning(QWidget *parent, const QString &title,
2957 const QString& text, StandardButton button0,
2958 StandardButton button1)
2959 \fn int QMessageBox::critical(QWidget *parent, const QString &title,
2960 const QString& text, StandardButton button0,
2961 StandardButton button1)
2962 \fn int QMessageBox::question(QWidget *parent, const QString &title,
2963 const QString& text, StandardButton button0,
2964 StandardButton button1)
2965 \internal
2966
2967 ### Needed for Qt 4 source compatibility
2968*/
2969
2970/*!
2971 \fn int QMessageBox::exec()
2972
2973 Shows the message box as a \l{QDialog#Modal Dialogs}{modal dialog},
2974 blocking until the user closes it.
2975
2976 When using a QMessageBox with standard buttons, this function returns a
2977 \l StandardButton value indicating the standard button that was clicked.
2978 When using QMessageBox with custom buttons, this function returns an
2979 opaque value; use clickedButton() to determine which button was clicked.
2980
2981 \note The result() function returns also \l StandardButton value instead
2982 of \l QDialog::DialogCode.
2983
2984 Users cannot interact with any other window in the same
2985 application until they close the dialog, either by clicking a
2986 button or by using a mechanism provided by the window system.
2987
2988 \sa show(), result()
2989*/
2990
2991/*!
2992 \macro QT_REQUIRE_VERSION(int argc, char **argv, const char *version)
2993 \relates QMessageBox
2994
2995 This macro can be used to ensure that the application is run
2996 with a recent enough version of Qt. This is especially useful
2997 if your application depends on a specific bug fix introduced in a
2998 bug-fix release (for example, 6.1.2).
2999
3000 The \a argc and \a argv parameters are the \c main() function's
3001 \c argc and \c argv parameters. The \a version parameter is a
3002 string literal that specifies which version of Qt the application
3003 requires (for example, "6.1.2").
3004
3005 Example:
3006
3007 \snippet code/src_gui_dialogs_qmessagebox.cpp 4
3008*/
3009
3010QT_END_NAMESPACE
3011
3012#include "moc_qmessagebox.cpp"
3013#include "qmessagebox.moc"
DetailButton * detailsButton
QAbstractButton * abstractButtonForId(int id) const
void initHelper(QPlatformDialogHelper *) override
QPushButton * defaultButton
int execReturnCode(QAbstractButton *button)
QList< QAbstractButton * > customButtonList
QAbstractButton * clickedButton
bool canBeNativeDialog() const override
void addOldButtons(int button0, int button1, int button2)
QAbstractButton * detectedEscapeButton
void buttonClicked(QAbstractButton *)
QDialogButtonBox * buttonBox
static QPixmap standardIcon(QMessageBox::Icon icon, QMessageBox *mb)
QPointer< QObject > receiverToDisconnectOnClose
QAbstractButton * escapeButton
int dialogCode() const override
void setVisible(bool visible) override
static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon, const QString &title, const QString &text, const QString &button0Text, const QString &button1Text, const QString &button2Text, int defaultButtonNumber, int escapeButtonNumber)
static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon, const QString &title, const QString &text, int button0, int button1, int button2)
QByteArray memberToDisconnectOnClose
void helperPrepareShow(QPlatformDialogHelper *) override
QAbstractButton * findButton(int button0, int button1, int button2, int flags)
void setClickedButton(QAbstractButton *button)
QSharedPointer< QMessageDialogOptions > options
void helperClicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role)
QByteArray signalToDisconnectOnClose
Button
@ Old_Cancel
@ Old_ButtonMask
@ Old_YesAll
@ Old_Abort
@ Old_NoAll
@ Old_Ok
@ Old_Yes
@ Old_Ignore
@ Old_No
@ NewButtonMask
@ Old_Retry
static int oldButton(int button)
static QMessageDialogOptions::StandardIcon helperIcon(QMessageBox::Icon i)
static QMessageBox::StandardButton showNewMessageBox(QWidget *parent, QMessageBox::Icon icon, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
static QMessageBox::StandardButton newButton(int button)
static bool detectedCompat(int button0, int button1, int button2)
void qRequireVersion(int argc, char *argv[], QAnyStringView req)
DetailButtonLabel
@ ShowLabel
@ HideLabel
static QPlatformDialogHelper::StandardButtons helperStandardButtons(QMessageBox *q)