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

source code of qtbase/src/widgets/dialogs/qmessagebox.cpp