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