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