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