OSDN Git Service

update link in QMessageBox
[kde/Katie.git] / src / gui / dialogs / qmessagebox.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Copyright (C) 2016-2021 Ivailo Monev
5 **
6 ** This file is part of the QtGui module of the Katie Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 **
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser
12 ** General Public License version 2.1 as published by the Free Software
13 ** Foundation and appearing in the file LICENSE.LGPL included in the
14 ** packaging of this file.  Please review the following information to
15 ** ensure the GNU Lesser General Public License version 2.1 requirements
16 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** As a special exception, The Qt Company gives you certain additional
19 ** rights. These rights are described in The Qt Company LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU
24 ** General Public License version 3.0 as published by the Free Software
25 ** Foundation and appearing in the file LICENSE.GPL included in the
26 ** packaging of this file.  Please review the following information to
27 ** ensure the GNU General Public License version 3.0 requirements will be
28 ** met: http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33
34 #include <QtGui/qmessagebox.h>
35
36 #ifndef QT_NO_MESSAGEBOX
37
38 #include <QtGui/qdialogbuttonbox.h>
39 #include "qlabel_p.h"
40 #include "qapplication_p.h"
41 #include <QtCore/qlist.h>
42 #include <QtCore/qdebug.h>
43 #include <QtGui/qstyle.h>
44 #include <QtGui/qstyleoption.h>
45 #include <QtGui/qgridlayout.h>
46 #include <QtGui/qdesktopwidget.h>
47 #include <QtGui/qpushbutton.h>
48 #ifndef QT_NO_ACCESSIBILITY
49 # include <QtGui/qaccessible.h>
50 #endif
51 #include <QtGui/qicon.h>
52 #include <QtGui/qtextdocument.h>
53 #include <QtGui/qapplication.h>
54 #include <QtGui/qtextedit.h>
55 #include <QtGui/qtextbrowser.h>
56 #include <QtGui/qmenu.h>
57 #include "qdialog_p.h"
58 #include <QtGui/qfont.h>
59 #include <QtGui/qfontmetrics.h>
60 #include <QtGui/qclipboard.h>
61
62 QT_BEGIN_NAMESPACE
63
64 enum DetailButtonLabel { ShowLabel = 0, HideLabel = 1 };
65 #ifndef QT_NO_TEXTEDIT
66 class QMessageBoxDetailsText : public QWidget
67 {
68 public:
69     class TextEdit : public QTextEdit
70     {
71     public:
72         TextEdit(QWidget *parent=0) : QTextEdit(parent) { }
73         void contextMenuEvent(QContextMenuEvent * e)
74         {
75 #ifndef QT_NO_CONTEXTMENU
76             QMenu *menu = createStandardContextMenu();
77             menu->setAttribute(Qt::WA_DeleteOnClose);
78             menu->popup(e->globalPos());
79 #else
80             Q_UNUSED(e);
81 #endif
82         }
83     };
84
85     QMessageBoxDetailsText(QWidget *parent=0)
86         : QWidget(parent)
87     {
88         QVBoxLayout *layout = new QVBoxLayout;
89         layout->setMargin(0);
90         QFrame *line = new QFrame(this);
91         line->setFrameShape(QFrame::HLine);
92         line->setFrameShadow(QFrame::Sunken);
93         layout->addWidget(line);
94         textEdit = new TextEdit();
95         textEdit->setFixedHeight(100);
96         textEdit->setFocusPolicy(Qt::NoFocus);
97         textEdit->setReadOnly(true);
98         layout->addWidget(textEdit);
99         setLayout(layout);
100     }
101     void setText(const QString &text) { textEdit->setPlainText(text); }
102     QString text() const { return textEdit->toPlainText(); }
103 private:
104     TextEdit *textEdit;
105 };
106 #endif // QT_NO_TEXTEDIT
107
108 class DetailButton : public QPushButton
109 {
110 public:
111     DetailButton(QWidget *parent) : QPushButton(label(ShowLabel), parent)
112     {
113         setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
114     }
115
116     QString label(DetailButtonLabel label) const
117     { return label == ShowLabel ? QMessageBox::tr("Show Details...") : QMessageBox::tr("Hide Details..."); }
118
119     void setLabel(DetailButtonLabel lbl)
120     { setText(label(lbl)); }
121
122     QSize sizeHint() const
123     {
124         ensurePolished();
125         QStyleOptionButton opt;
126         initStyleOption(&opt);
127         const QFontMetrics fm = fontMetrics();
128         opt.text = label(ShowLabel);
129         QSize sz = fm.size(Qt::TextShowMnemonic, opt.text);
130         QSize ret = style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this).
131                       expandedTo(QApplication::globalStrut());
132         opt.text = label(HideLabel);
133         sz = fm.size(Qt::TextShowMnemonic, opt.text);
134         ret = ret.expandedTo(style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this).
135                       expandedTo(QApplication::globalStrut()));
136         return ret;
137     }
138 };
139
140
141 class QMessageBoxPrivate : public QDialogPrivate
142 {
143     Q_DECLARE_PUBLIC(QMessageBox)
144
145 public:
146     QMessageBoxPrivate() : escapeButton(0), defaultButton(0), clickedButton(0), detailsButton(0),
147 #ifndef QT_NO_TEXTEDIT
148                            detailsText(0),
149 #endif
150                            autoAddOkButton(true),
151                            detectedEscapeButton(0), informativeLabel(0) { }
152
153     void init(const QString &title = QString(), const QString &text = QString());
154     void _q_buttonClicked(QAbstractButton *);
155
156     int execReturnCode(QAbstractButton *button);
157
158     void detectEscapeButton();
159     void updateSize();
160     int layoutMinimumWidth();
161     void retranslateStrings();
162
163     static QMessageBox::StandardButton showNewMessageBox(QWidget *parent,
164                 QMessageBox::Icon icon, const QString& title, const QString& text,
165                 QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
166
167     static QPixmap standardIcon(QMessageBox::Icon icon, QMessageBox *mb);
168
169     QLabel *label;
170     QMessageBox::Icon icon;
171     QLabel *iconLabel;
172     QDialogButtonBox *buttonBox;
173     QList<QAbstractButton *> customButtonList;
174     QAbstractButton *escapeButton;
175     QPushButton *defaultButton;
176     QAbstractButton *clickedButton;
177     DetailButton *detailsButton;
178 #ifndef QT_NO_TEXTEDIT
179     QMessageBoxDetailsText *detailsText;
180 #endif
181     bool autoAddOkButton;
182     QAbstractButton *detectedEscapeButton;
183     QLabel *informativeLabel;
184     QPointer<QObject> receiverToDisconnectOnClose;
185     QByteArray memberToDisconnectOnClose;
186     QByteArray signalToDisconnectOnClose;
187 };
188
189 void QMessageBoxPrivate::init(const QString &title, const QString &text)
190 {
191     Q_Q(QMessageBox);
192
193     label = new QLabel;
194     label->setObjectName(QLatin1String("qt_msgbox_label"));
195     label->setTextInteractionFlags(Qt::TextInteractionFlags(q->style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, 0, q)));
196     label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
197     label->setOpenExternalLinks(true);
198     label->setContentsMargins(2, 0, 0, 0);
199     label->setIndent(9);
200     icon = QMessageBox::NoIcon;
201     iconLabel = new QLabel;
202     iconLabel->setObjectName(QLatin1String("qt_msgboxex_icon_label"));
203     iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
204
205     buttonBox = new QDialogButtonBox;
206     buttonBox->setObjectName(QLatin1String("qt_msgbox_buttonbox"));
207     buttonBox->setCenterButtons(q->style()->styleHint(QStyle::SH_MessageBox_CenterButtons, 0, q));
208     QObject::connect(buttonBox, SIGNAL(clicked(QAbstractButton*)),
209                      q, SLOT(_q_buttonClicked(QAbstractButton*)));
210
211     QGridLayout *grid = new QGridLayout;
212     const int preferredIconColumn = 0;
213     const int preferredTextColumn = 1;
214     grid->addWidget(iconLabel, 0, preferredIconColumn, 2, 1, Qt::AlignTop);
215     grid->addWidget(label, 0, preferredTextColumn, 1, 1);
216     // -- leave space for information label --
217     grid->addWidget(buttonBox, 2, 0, 1, 2);
218
219     grid->setSizeConstraint(QLayout::SetNoConstraint);
220     q->setLayout(grid);
221
222     if (!title.isEmpty() || !text.isEmpty()) {
223         q->setWindowTitle(title);
224         q->setText(text);
225     }
226     q->setModal(true);
227
228     retranslateStrings();
229 }
230
231 int QMessageBoxPrivate::layoutMinimumWidth()
232 {
233     layout->activate();
234     return layout->totalMinimumSize().width();
235 }
236
237 void QMessageBoxPrivate::updateSize()
238 {
239     Q_Q(QMessageBox);
240
241     if (!q->isVisible())
242         return;
243
244     const QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
245     int hardLimit = qMin(screenSize.width() - 480, 1000); // can never get bigger than this
246     // on small screens allows the messagebox be the same size as the screen
247     if (screenSize.width() <= 1024)
248         hardLimit = screenSize.width();
249     const int softLimit = qMin(screenSize.width()/2, 500);
250
251     if (informativeLabel)
252         informativeLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
253
254     label->setWordWrap(false); // makes the label return min size
255     int width = layoutMinimumWidth();
256
257     if (width > softLimit) {
258         label->setWordWrap(true);
259         width = qMax(softLimit, layoutMinimumWidth());
260
261         if (width > hardLimit) {
262             label->d_func()->ensureTextControl();
263             if (QTextControl *control = label->d_func()->control) {
264                 QTextOption opt = control->document()->defaultTextOption();
265                 opt.setWrapMode(QTextOption::WrapAnywhere);
266                 control->document()->setDefaultTextOption(opt);
267             }
268             width = hardLimit;
269         }
270     }
271
272     if (informativeLabel) {
273         label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
274         QSizePolicy policy(QSizePolicy::Minimum, QSizePolicy::Preferred);
275         policy.setHeightForWidth(true);
276         informativeLabel->setSizePolicy(policy);
277         width = qMax(width, layoutMinimumWidth());
278         if (width > hardLimit) { // longest word is really big, so wrap anywhere
279             informativeLabel->d_func()->ensureTextControl();
280             if (QTextControl *control = informativeLabel->d_func()->control) {
281                 QTextOption opt = control->document()->defaultTextOption();
282                 opt.setWrapMode(QTextOption::WrapAnywhere);
283                 control->document()->setDefaultTextOption(opt);
284             }
285             width = hardLimit;
286         }
287         policy.setHeightForWidth(label->wordWrap());
288         label->setSizePolicy(policy);
289     }
290
291     QFontMetrics fm(QApplication::font("QWorkspaceTitleBar"));
292     int windowTitleWidth = qMin(fm.width(q->windowTitle()) + 50, hardLimit);
293     if (windowTitleWidth > width)
294         width = windowTitleWidth;
295
296     layout->activate();
297     int height = (layout->hasHeightForWidth())
298                      ? layout->totalHeightForWidth(width)
299                      : layout->totalMinimumSize().height();
300
301     q->setFixedSize(width, height);
302     QCoreApplication::removePostedEvents(q, QEvent::LayoutRequest);
303 }
304
305 int QMessageBoxPrivate::execReturnCode(QAbstractButton *button)
306 {
307     int ret = buttonBox->standardButton(button);
308     if (ret == QMessageBox::NoButton) {
309         ret = customButtonList.indexOf(button); // if button == 0, correctly sets ret = -1
310     }
311     return ret;
312 }
313
314 void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button)
315 {
316     Q_Q(QMessageBox);
317 #ifndef QT_NO_TEXTEDIT
318     if (detailsButton && detailsText && button == detailsButton) {
319         detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel);
320         detailsText->setHidden(!detailsText->isHidden());
321         updateSize();
322     } else
323 #endif
324     {
325         clickedButton = button;
326         q->done(execReturnCode(button)); // does not trigger closeEvent
327         emit q->buttonClicked(button);
328
329         if (receiverToDisconnectOnClose) {
330             QObject::disconnect(q, signalToDisconnectOnClose, receiverToDisconnectOnClose,
331                                 memberToDisconnectOnClose);
332             receiverToDisconnectOnClose = 0;
333         }
334         signalToDisconnectOnClose.clear();
335         memberToDisconnectOnClose.clear();
336     }
337 }
338
339 /*!
340     \class QMessageBox
341
342     \brief The QMessageBox class provides a modal dialog for informing
343     the user or for asking the user a question and receiving an answer.
344
345     \ingroup standard-dialogs
346
347
348     A message box displays a primary \l{QMessageBox::text}{text} to
349     alert the user to a situation, an \l{QMessageBox::informativeText}
350     {informative text} to further explain the alert or to ask the user
351     a question, and an optional \l{QMessageBox::detailedText}
352     {detailed text} to provide even more data if the user requests
353     it. A message box can also display an \l{QMessageBox::icon} {icon}
354     and \l{QMessageBox::standardButtons} {standard buttons} for
355     accepting a user response.
356
357     Two APIs for using QMessageBox are provided, the property-based
358     API, and the static functions. Calling one of the static functions
359     is the simpler approach, but it is less flexible than using the
360     property-based API, and the result is less informative. Using the
361     property-based API is recommended.
362
363     \section1 The Property-based API
364
365     To use the property-based API, construct an instance of
366     QMessageBox, set the desired properties, and call exec() to show
367     the message. The simplest configuration is to set only the
368     \l{QMessageBox::text} {message text} property.
369
370     \snippet doc/src/snippets/code/src_gui_dialogs_qmessagebox.cpp 5
371
372     The user must click the \gui{OK} button to dismiss the message
373     box. The rest of the GUI is blocked until the message box is
374     dismissed.
375
376     \image msgbox1.png
377
378     A better approach than just alerting the user to an event is to
379     also ask the user what to do about it. Store the question in the
380     \l{QMessageBox::informativeText} {informative text} property, and
381     set the \l{QMessageBox::standardButtons} {standard buttons}
382     property to the set of buttons you want as the set of user
383     responses. The buttons are specified by combining values from
384     StandardButtons using the bitwise OR operator. The display order
385     for the buttons is platform-dependent. For example, on Windows,
386     \gui{Save} is displayed to the left of \gui{Cancel}, whereas on
387     Mac OS, the order is reversed.
388
389     Mark one of your standard buttons to be your
390     \l{QMessageBox::defaultButton()} {default button}.
391
392     \snippet doc/src/snippets/code/src_gui_dialogs_qmessagebox.cpp 6
393
394     This is the approach recommended in the
395     \l{http://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AppleHIGuidelines/Windows/Windows.html#//apple_ref/doc/uid/20000961-BABCAJID}
396     {Mac OS X Guidelines}. Similar guidelines apply for the other
397     platforms, but note the different ways the
398     \l{QMessageBox::informativeText} {informative text} is handled for
399     different platforms.
400
401     \image msgbox2.png
402
403     The exec() slot returns the StandardButtons value of the button
404     that was clicked.
405
406     \snippet doc/src/snippets/code/src_gui_dialogs_qmessagebox.cpp 7
407
408     To give the user more information to help him answer the question,
409     set the \l{QMessageBox::detailedText} {detailed text} property. If
410     the \l{QMessageBox::detailedText} {detailed text} property is set,
411     the \gui{Show Details...} button will be shown.
412
413     \image msgbox3.png
414
415     Clicking the \gui{Show Details...} button displays the detailed text.
416
417     \image msgbox4.png
418
419     \section2 Rich Text and the Text Format Property
420
421     The \l{QMessageBox::detailedText} {detailed text} property is
422     always interpreted as plain text. The \l{QMessageBox::text} {main
423     text} and \l{QMessageBox::informativeText} {informative text}
424     properties can be either plain text or rich text. These strings
425     are interpreted according to the setting of the
426     \l{QMessageBox::textFormat} {text format} property. The default
427     setting is \l{Qt::AutoText} {auto-text}.
428
429     Note that for some plain text strings containing XML
430     meta-characters, the auto-text \l{Qt::mightBeRichText()} {rich
431     text detection test} may fail causing your plain text string to be
432     interpreted incorrectly as rich text. In these rare cases, use
433     Qt::convertFromPlainText() to convert your plain text string to a
434     visually equivalent rich text string, or set the
435     \l{QMessageBox::textFormat} {text format} property explicitly with
436     setTextFormat().
437
438     \section2 Severity Levels and the Icon and Pixmap Properties
439
440     QMessageBox supports four predefined message severity levels, or message
441     types, which really only differ in the predefined icon they each show.
442     Specify one of the four predefined message types by setting the
443     \l{QMessageBox::icon}{icon} property to one of the
444     \l{QMessageBox::Icon}{predefined icons}. The following rules are
445     guidelines:
446
447     \table
448     \row
449     \o \img qmessagebox-quest.png
450     \o \l Question
451     \o For asking a question during normal operations.
452     \row
453     \o \img qmessagebox-info.png
454     \o \l Information
455     \o For reporting information about normal operations.
456     \row
457     \o \img qmessagebox-warn.png
458     \o \l Warning
459     \o For reporting non-critical errors.
460     \row
461     \o \img qmessagebox-crit.png
462     \o \l Critical
463     \o For reporting critical errors.
464     \endtable
465
466     \l{QMessageBox::Icon}{Predefined icons} are not defined by QMessageBox, but
467     provided by the style. The default value is \l{QMessageBox::NoIcon}
468     {No Icon}. The message boxes are otherwise the same for all cases. When
469     using a standard icon, use the one recommended in the table, or use the
470     one recommended by the style guidelines for your platform. If none of the
471     standard icons is right for your message box, you can use a custom icon by
472     setting the \l{QMessageBox::iconPixmap}{icon pixmap} property instead of
473     setting the \l{QMessageBox::icon}{icon} property.
474
475     In summary, to set an icon, use \e{either} setIcon() for one of the
476     standard icons, \e{or} setIconPixmap() for a custom icon.
477
478     \section1 The Static Functions API
479
480     Building message boxes with the static functions API, although
481     convenient, is less flexible than using the property-based API,
482     because the static function signatures lack parameters for setting
483     the \l{QMessageBox::informativeText} {informative text} and
484     \l{QMessageBox::detailedText} {detailed text} properties. One
485     work-around for this has been to use the \c{title} parameter as
486     the message box main text and the \c{text} parameter as the
487     message box informative text. Because this has the obvious
488     drawback of making a less readable message box, platform
489     guidelines do not recommend it. The \e{Microsoft Windows User
490     Interface Guidelines} recommend using the
491     \l{QCoreApplication::applicationName} {application name} as the
492     \l{QMessageBox::setWindowTitle()} {window's title}, which means
493     that if you have an informative text in addition to your main
494     text, you must concatenate it to the \c{text} parameter.
495
496     Note that the static function signatures have changed with respect
497     to their button parameters, which are now used to set the
498     \l{QMessageBox::standardButtons} {standard buttons} and the
499     \l{QMessageBox::defaultButton()} {default button}.
500
501     Static functions are available for creating information(),
502     question(), warning(), and critical() message boxes.
503
504     \snippet doc/src/snippets/code/src_gui_dialogs_qmessagebox.cpp 0
505
506     The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
507     how to use QMessageBox and the other built-in Qt dialogs.
508
509     \section1 Advanced Usage
510
511     If the \l{QMessageBox::StandardButtons} {standard buttons} are not
512     flexible enough for your message box, you can use the addButton()
513     overload that takes a text and a ButtonRoleto to add custom
514     buttons. The ButtonRole is used by QMessageBox to determine the
515     ordering of the buttons on screen (which varies according to the
516     platform). You can test the value of clickedButton() after calling
517     exec(). For example,
518
519     \snippet doc/src/snippets/code/src_gui_dialogs_qmessagebox.cpp 2
520
521     \section1 Default and Escape Keys
522
523     The default button (i.e., the button activated when \key Enter is
524     pressed) can be specified using setDefaultButton(). If a default
525     button is not specified, QMessageBox tries to find one based on
526     the \l{ButtonRole} {button roles} of the buttons used in the
527     message box.
528
529     The escape button (the button activated when \key Esc is pressed)
530     can be specified using setEscapeButton().  If an escape button is
531     not specified, QMessageBox tries to find one using these rules:
532
533     \list 1
534
535     \o If there is only one button, it is the button activated when
536     \key Esc is pressed.
537
538     \o If there is a \l Cancel button, it is the button activated when
539     \key Esc is pressed.
540
541     \o If there is exactly one button having either
542        \l{QMessageBox::RejectRole} {the Reject role} or the
543        \l{QMessageBox::NoRole} {the No role}, it is the button
544        activated when \key Esc is pressed.
545
546     \endlist
547
548     When an escape button can't be determined using these rules,
549     pressing \key Esc has no effect.
550
551     \sa QDialogButtonBox, {fowler}{GUI Design Handbook: Message Box}, {Standard Dialogs Example}, {Application Example}
552 */
553
554 /*!
555     \enum QMessageBox::StandardButton
556     \since 4.2
557
558     These enums describe flags for standard buttons. Each button has a
559     defined \l ButtonRole.
560
561     \value Ok An "OK" button defined with the \l AcceptRole.
562     \value Open A "Open" button defined with the \l AcceptRole.
563     \value Save A "Save" button defined with the \l AcceptRole.
564     \value Cancel A "Cancel" button defined with the \l RejectRole.
565     \value Close A "Close" button defined with the \l RejectRole.
566     \value Discard A "Discard" or "Don't Save" button, depending on the platform,
567                     defined with the \l DestructiveRole.
568     \value Apply An "Apply" button defined with the \l ApplyRole.
569     \value Reset A "Reset" button defined with the \l ResetRole.
570     \value RestoreDefaults A "Restore Defaults" button defined with the \l ResetRole.
571     \value Help A "Help" button defined with the \l HelpRole.
572     \value SaveAll A "Save All" button defined with the \l AcceptRole.
573     \value Yes A "Yes" button defined with the \l YesRole.
574     \value YesToAll A "Yes to All" button defined with the \l YesRole.
575     \value No A "No" button defined with the \l NoRole.
576     \value NoToAll A "No to All" button defined with the \l NoRole.
577     \value Abort An "Abort" button defined with the \l RejectRole.
578     \value Retry A "Retry" button defined with the \l AcceptRole.
579     \value Ignore An "Ignore" button defined with the \l AcceptRole.
580
581     \value NoButton An invalid button.
582
583     \omitvalue FirstButton
584     \omitvalue LastButton
585
586     The following values are obsolete:
587
588     \value YesAll Use YesToAll instead.
589     \value NoAll Use NoToAll instead.
590     \value Default Use the \c defaultButton argument of
591            information(), warning(), etc. instead, or call
592            setDefaultButton().
593     \value Escape Call setEscapeButton() instead.
594     \value FlagMask
595     \value ButtonMask
596
597     \sa ButtonRole, standardButtons
598 */
599
600 /*!
601     \fn void QMessageBox::buttonClicked(QAbstractButton *button)
602
603     This signal is emitted whenever a button is clicked inside the QMessageBox.
604     The button that was clicked in returned in \a button.
605 */
606
607 /*!
608     Constructs a message box with no text and no buttons. \a parent is
609     passed to the QDialog constructor.
610
611     On Mac OS X, if you want your message box to appear
612     as a Qt::Sheet of its \a parent, set the message box's
613     \l{setWindowModality()} {window modality} to Qt::WindowModal or use open().
614     Otherwise, the message box will be a standard dialog.
615
616 */
617 QMessageBox::QMessageBox(QWidget *parent)
618     : QDialog(*new QMessageBoxPrivate, parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
619 {
620     Q_D(QMessageBox);
621     d->init();
622 }
623
624 /*!
625     Constructs a message box with the given \a icon, \a title, \a
626     text, and standard \a buttons. Standard or custom buttons can be
627     added at any time using addButton(). The \a parent and \a f
628     arguments are passed to the QDialog constructor.
629
630     The message box is an \l{Qt::ApplicationModal} {application modal}
631     dialog box.
632
633     On Mac OS X, if \a parent is not 0 and you want your message box
634     to appear as a Qt::Sheet of that parent, set the message box's
635     \l{setWindowModality()} {window modality} to Qt::WindowModal
636     (default). Otherwise, the message box will be a standard dialog.
637
638     \sa setWindowTitle(), setText(), setIcon(), setStandardButtons()
639 */
640 QMessageBox::QMessageBox(Icon icon, const QString &title, const QString &text,
641                          StandardButtons buttons, QWidget *parent,
642                          Qt::WindowFlags f)
643 : QDialog(*new QMessageBoxPrivate, parent, f | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
644 {
645     Q_D(QMessageBox);
646     d->init(title, text);
647     setIcon(icon);
648     if (buttons != NoButton)
649         setStandardButtons(buttons);
650 }
651
652 /*!
653     Destroys the message box.
654 */
655 QMessageBox::~QMessageBox()
656 {
657 }
658
659 /*!
660     \since 4.2
661
662     Adds the given \a button to the message box with the specified \a
663     role.
664
665     \sa removeButton(), button(), setStandardButtons()
666 */
667 void QMessageBox::addButton(QAbstractButton *button, ButtonRole role)
668 {
669     Q_D(QMessageBox);
670     if (!button)
671         return;
672     removeButton(button);
673     d->buttonBox->addButton(button, (QDialogButtonBox::ButtonRole)role);
674     d->customButtonList.append(button);
675     d->autoAddOkButton = false;
676 }
677
678 /*!
679     \since 4.2
680     \overload
681
682     Creates a button with the given \a text, adds it to the message box for the
683     specified \a role, and returns it.
684 */
685 QPushButton *QMessageBox::addButton(const QString& text, ButtonRole role)
686 {
687     Q_D(QMessageBox);
688     QPushButton *pushButton = new QPushButton(text);
689     addButton(pushButton, role);
690     d->updateSize();
691     return pushButton;
692 }
693
694 /*!
695     \since 4.2
696     \overload
697
698     Adds a standard \a button to the message box if it is valid to do so, and
699     returns the push button.
700
701     \sa setStandardButtons()
702 */
703 QPushButton *QMessageBox::addButton(StandardButton button)
704 {
705     Q_D(QMessageBox);
706     QPushButton *pushButton = d->buttonBox->addButton((QDialogButtonBox::StandardButton)button);
707     if (pushButton)
708         d->autoAddOkButton = false;
709     return pushButton;
710 }
711
712 /*!
713     \since 4.2
714
715     Removes \a button from the button box without deleting it.
716
717     \sa addButton(), setStandardButtons()
718 */
719 void QMessageBox::removeButton(QAbstractButton *button)
720 {
721     Q_D(QMessageBox);
722     d->customButtonList.removeAll(button);
723     if (d->escapeButton == button)
724         d->escapeButton = 0;
725     if (d->defaultButton == button)
726         d->defaultButton = 0;
727     d->buttonBox->removeButton(button);
728     d->updateSize();
729 }
730
731 /*!
732     \property QMessageBox::standardButtons
733     \brief collection of standard buttons in the message box
734     \since 4.2
735
736     This property controls which standard buttons are used by the message box.
737
738     By default, this property contains no standard buttons.
739
740     \sa addButton()
741 */
742 void QMessageBox::setStandardButtons(StandardButtons buttons)
743 {
744     Q_D(QMessageBox);
745     d->buttonBox->setStandardButtons(QDialogButtonBox::StandardButtons(int(buttons)));
746
747     QList<QAbstractButton *> buttonList = d->buttonBox->buttons();
748     if (!buttonList.contains(d->escapeButton))
749         d->escapeButton = 0;
750     if (!buttonList.contains(d->defaultButton))
751         d->defaultButton = 0;
752     d->autoAddOkButton = false;
753     d->updateSize();
754 }
755
756 QMessageBox::StandardButtons QMessageBox::standardButtons() const
757 {
758     Q_D(const QMessageBox);
759     return QMessageBox::StandardButtons(int(d->buttonBox->standardButtons()));
760 }
761
762 /*!
763     \since 4.2
764
765     Returns the standard button enum value corresponding to the given \a button,
766     or NoButton if the given \a button isn't a standard button.
767
768     \sa button(), standardButtons()
769 */
770 QMessageBox::StandardButton QMessageBox::standardButton(QAbstractButton *button) const
771 {
772     Q_D(const QMessageBox);
773     return (QMessageBox::StandardButton)d->buttonBox->standardButton(button);
774 }
775
776 /*!
777     \since 4.2
778
779     Returns a pointer corresponding to the standard button \a which,
780     or 0 if the standard button doesn't exist in this message box.
781
782     \sa standardButtons, standardButton()
783 */
784 QAbstractButton *QMessageBox::button(StandardButton which) const
785 {
786     Q_D(const QMessageBox);
787     return d->buttonBox->button(QDialogButtonBox::StandardButton(which));
788 }
789
790 /*!
791     \since 4.2
792
793     Returns the button that is activated when escape is pressed.
794
795     By default, QMessageBox attempts to automatically detect an
796     escape button as follows:
797
798     \list 1
799     \o If there is only one button, it is made the escape button.
800     \o If there is a \l Cancel button, it is made the escape button.
801     \o On Mac OS X only, if there is exactly one button with the role
802        QMessageBox::RejectRole, it is made the escape button.
803     \endlist
804
805     When an escape button could not be automatically detected, pressing
806     \key Esc has no effect.
807
808     \sa addButton()
809 */
810 QAbstractButton *QMessageBox::escapeButton() const
811 {
812     Q_D(const QMessageBox);
813     return d->escapeButton;
814 }
815
816 /*!
817     \since 4.2
818
819     Sets the button that gets activated when the \key Escape key is
820     pressed to \a button.
821
822     \sa addButton(), clickedButton()
823 */
824 void QMessageBox::setEscapeButton(QAbstractButton *button)
825 {
826     Q_D(QMessageBox);
827     if (d->buttonBox->buttons().contains(button))
828         d->escapeButton = button;
829 }
830
831 /*!
832     \since 4.3
833
834     Sets the buttons that gets activated when the \key Escape key is
835     pressed to \a button.
836
837     \sa addButton(), clickedButton()
838 */
839 void QMessageBox::setEscapeButton(QMessageBox::StandardButton button)
840 {
841     Q_D(QMessageBox);
842     setEscapeButton(d->buttonBox->button(QDialogButtonBox::StandardButton(button)));
843 }
844
845 void QMessageBoxPrivate::detectEscapeButton()
846 {
847     if (escapeButton) { // escape button explicitly set
848         detectedEscapeButton = escapeButton;
849         return;
850     }
851
852     // Cancel button automatically becomes escape button
853     detectedEscapeButton = buttonBox->button(QDialogButtonBox::Cancel);
854     if (detectedEscapeButton)
855         return;
856
857     // If there is only one button, make it the escape button
858     const QList<QAbstractButton *> buttons = buttonBox->buttons();
859     if (buttons.count() == 1) {
860         detectedEscapeButton = buttons.first();
861         return;
862     }
863
864     // if the message box has one RejectRole button, make it the escape button
865     for (int i = 0; i < buttons.count(); i++) {
866         if (buttonBox->buttonRole(buttons.at(i)) == QDialogButtonBox::RejectRole) {
867             if (detectedEscapeButton) { // already detected!
868                 detectedEscapeButton = 0;
869                 break;
870             }
871             detectedEscapeButton = buttons.at(i);
872         }
873     }
874     if (detectedEscapeButton)
875         return;
876
877     // if the message box has one NoRole button, make it the escape button
878     for (int i = 0; i < buttons.count(); i++) {
879         if (buttonBox->buttonRole(buttons.at(i)) == QDialogButtonBox::NoRole) {
880             if (detectedEscapeButton) { // already detected!
881                 detectedEscapeButton = 0;
882                 break;
883             }
884             detectedEscapeButton = buttons.at(i);
885         }
886     }
887 }
888
889 /*!
890     \since 4.2
891
892     Returns the button that was clicked by the user,
893     or 0 if the user hit the \key Esc key and
894     no \l{setEscapeButton()}{escape button} was set.
895
896     If exec() hasn't been called yet, returns 0.
897
898     Example:
899
900     \snippet doc/src/snippets/code/src_gui_dialogs_qmessagebox.cpp 3
901
902     \sa standardButton(), button()
903 */
904 QAbstractButton *QMessageBox::clickedButton() const
905 {
906     Q_D(const QMessageBox);
907     return d->clickedButton;
908 }
909
910 /*!
911     \since 4.2
912
913     Returns the button that should be the message box's
914     \l{QPushButton::setDefault()}{default button}. Returns 0
915     if no default button was set.
916
917     \sa addButton(), QPushButton::setDefault()
918 */
919 QPushButton *QMessageBox::defaultButton() const
920 {
921     Q_D(const QMessageBox);
922     return d->defaultButton;
923 }
924
925 /*!
926     \since 4.2
927
928     Sets the message box's \l{QPushButton::setDefault()}{default button}
929     to \a button.
930
931     \sa addButton(), QPushButton::setDefault()
932 */
933 void QMessageBox::setDefaultButton(QPushButton *button)
934 {
935     Q_D(QMessageBox);
936     if (!d->buttonBox->buttons().contains(button))
937         return;
938     d->defaultButton = button;
939     button->setDefault(true);
940     button->setFocus();
941 }
942
943 /*!
944     \since 4.3
945
946     Sets the message box's \l{QPushButton::setDefault()}{default button}
947     to \a button.
948
949     \sa addButton(), QPushButton::setDefault()
950 */
951 void QMessageBox::setDefaultButton(QMessageBox::StandardButton button)
952 {
953     Q_D(QMessageBox);
954     setDefaultButton(d->buttonBox->button(QDialogButtonBox::StandardButton(button)));
955 }
956
957 /*!
958   \property QMessageBox::text
959   \brief the message box text to be displayed.
960
961   The text will be interpreted either as a plain text or as rich text,
962   depending on the text format setting (\l QMessageBox::textFormat).
963   The default setting is Qt::AutoText, i.e., the message box will try
964   to auto-detect the format of the text.
965
966   The default value of this property is an empty string.
967
968   \sa textFormat, QMessageBox::informativeText, QMessageBox::detailedText
969 */
970 QString QMessageBox::text() const
971 {
972     Q_D(const QMessageBox);
973     return d->label->text();
974 }
975
976 void QMessageBox::setText(const QString &text)
977 {
978     Q_D(QMessageBox);
979     d->label->setText(text);
980     d->label->setWordWrap(d->label->textFormat() == Qt::RichText
981         || (d->label->textFormat() == Qt::AutoText && Qt::mightBeRichText(text)));
982     d->updateSize();
983 }
984
985 /*!
986     \enum QMessageBox::Icon
987
988     This enum has the following values:
989
990     \value NoIcon the message box does not have any icon.
991
992     \value Question an icon indicating that
993     the message is asking a question.
994
995     \value Information an icon indicating that
996     the message is nothing out of the ordinary.
997
998     \value Warning an icon indicating that the
999     message is a warning, but can be dealt with.
1000
1001     \value Critical an icon indicating that
1002     the message represents a critical problem.
1003
1004 */
1005
1006 /*!
1007     \property QMessageBox::icon
1008     \brief the message box's icon
1009
1010     The icon of the message box can be specified with one of the
1011     values:
1012
1013     \list
1014     \o QMessageBox::NoIcon
1015     \o QMessageBox::Question
1016     \o QMessageBox::Information
1017     \o QMessageBox::Warning
1018     \o QMessageBox::Critical
1019     \endlist
1020
1021     The default is QMessageBox::NoIcon.
1022
1023     The pixmap used to display the actual icon depends on the current
1024     \l{QWidget::style()} {GUI style}. You can also set a custom pixmap
1025     for the icon by setting the \l{QMessageBox::iconPixmap} {icon
1026     pixmap} property.
1027
1028     \sa iconPixmap
1029 */
1030 QMessageBox::Icon QMessageBox::icon() const
1031 {
1032     Q_D(const QMessageBox);
1033     return d->icon;
1034 }
1035
1036 void QMessageBox::setIcon(Icon icon)
1037 {
1038     Q_D(QMessageBox);
1039     setIconPixmap(QMessageBoxPrivate::standardIcon((QMessageBox::Icon)icon,
1040                                                    this));
1041     d->icon = icon;
1042 }
1043
1044 /*!
1045     \property QMessageBox::iconPixmap
1046     \brief the current icon
1047
1048     The icon currently used by the message box. Note that it's often
1049     hard to draw one pixmap that looks appropriate in all GUI styles;
1050     you may want to supply a different pixmap for each platform.
1051
1052     By default, this property is undefined.
1053
1054     \sa icon
1055 */
1056 QPixmap QMessageBox::iconPixmap() const
1057 {
1058     Q_D(const QMessageBox);
1059     if (d->iconLabel && d->iconLabel->pixmap())
1060         return *d->iconLabel->pixmap();
1061     return QPixmap();
1062 }
1063
1064 void QMessageBox::setIconPixmap(const QPixmap &pixmap)
1065 {
1066     Q_D(QMessageBox);
1067     d->iconLabel->setPixmap(pixmap);
1068     d->updateSize();
1069     d->icon = NoIcon;
1070 }
1071
1072 /*!
1073     \property QMessageBox::textFormat
1074     \brief the format of the text displayed by the message box
1075
1076     The current text format used by the message box. See the \l
1077     Qt::TextFormat enum for an explanation of the possible options.
1078
1079     The default format is Qt::AutoText.
1080
1081     \sa setText()
1082 */
1083 Qt::TextFormat QMessageBox::textFormat() const
1084 {
1085     Q_D(const QMessageBox);
1086     return d->label->textFormat();
1087 }
1088
1089 void QMessageBox::setTextFormat(Qt::TextFormat format)
1090 {
1091     Q_D(QMessageBox);
1092     d->label->setTextFormat(format);
1093     d->label->setWordWrap(format == Qt::RichText
1094                     || (format == Qt::AutoText && Qt::mightBeRichText(d->label->text())));
1095     d->updateSize();
1096 }
1097
1098 /*!
1099     \reimp
1100 */
1101 bool QMessageBox::event(QEvent *e)
1102 {
1103     bool result =QDialog::event(e);
1104     switch (e->type()) {
1105         case QEvent::LayoutRequest:
1106             d_func()->updateSize();
1107             break;
1108         case QEvent::LanguageChange:
1109             d_func()->retranslateStrings();
1110             break;
1111         default:
1112             break;
1113     }
1114     return result;
1115 }
1116
1117 /*!
1118     \reimp
1119 */
1120 void QMessageBox::closeEvent(QCloseEvent *e)
1121 {
1122     Q_D(QMessageBox);
1123     if (!d->detectedEscapeButton) {
1124         e->ignore();
1125         return;
1126     }
1127     QDialog::closeEvent(e);
1128     d->clickedButton = d->detectedEscapeButton;
1129     setResult(d->execReturnCode(d->detectedEscapeButton));
1130 }
1131
1132 /*!
1133     \reimp
1134 */
1135 void QMessageBox::changeEvent(QEvent *ev)
1136 {
1137     Q_D(QMessageBox);
1138     switch (ev->type()) {
1139     case QEvent::StyleChange:
1140     {
1141         if (d->icon != NoIcon)
1142             setIcon(d->icon);
1143         Qt::TextInteractionFlags flags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, 0, this));
1144         d->label->setTextInteractionFlags(flags);
1145         d->buttonBox->setCenterButtons(style()->styleHint(QStyle::SH_MessageBox_CenterButtons, 0, this));
1146         if (d->informativeLabel)
1147             d->informativeLabel->setTextInteractionFlags(flags);
1148         // intentional fall through
1149     }
1150     case QEvent::FontChange:
1151     case QEvent::ApplicationFontChange:
1152     default:
1153         break;
1154     }
1155     QDialog::changeEvent(ev);
1156 }
1157
1158 /*!
1159     \reimp
1160 */
1161 void QMessageBox::keyPressEvent(QKeyEvent *e)
1162 {
1163     Q_D(QMessageBox);
1164     if (e->key() == Qt::Key_Escape) {
1165         if (d->detectedEscapeButton) {
1166             d->detectedEscapeButton->click();
1167         }
1168         return;
1169     }
1170
1171 #ifndef QT_NO_SHORTCUT
1172     if (!(e->modifiers() & Qt::AltModifier)) {
1173         int key = e->key() & ~Qt::MODIFIER_MASK;
1174         if (key) {
1175             const QList<QAbstractButton *> buttons = d->buttonBox->buttons();
1176             for (int i = 0; i < buttons.count(); ++i) {
1177                 QAbstractButton *pb = buttons.at(i);
1178                 QKeySequence shortcut = pb->shortcut();
1179                 if (!shortcut.isEmpty() && key == (shortcut[0] & ~Qt::MODIFIER_MASK)) {
1180                     pb->animateClick();
1181                     return;
1182                 }
1183             }
1184         }
1185     }
1186 #endif
1187     QDialog::keyPressEvent(e);
1188 }
1189
1190 /*!
1191     \overload
1192
1193     Opens the dialog and connects its finished() or buttonClicked() signal to
1194     the slot specified by \a receiver and \a member. If the slot in \a member
1195     has a pointer for its first parameter the connection is to buttonClicked(),
1196     otherwise the connection is to finished().
1197
1198     The signal will be disconnected from the slot when the dialog is closed.
1199 */
1200 void QMessageBox::open(QObject *receiver, const char *member)
1201 {
1202     Q_D(QMessageBox);
1203     const char *signal = member && strchr(member, '*') ? SIGNAL(buttonClicked(QAbstractButton*))
1204                                                        : SIGNAL(finished(int));
1205     connect(this, signal, receiver, member);
1206     d->signalToDisconnectOnClose = signal;
1207     d->receiverToDisconnectOnClose = receiver;
1208     d->memberToDisconnectOnClose = member;
1209     QDialog::open();
1210 }
1211
1212 /*!
1213     \since 4.5
1214
1215     Returns a list of all the buttons that have been added to the message box.
1216
1217     \sa buttonRole(), addButton(), removeButton()
1218 */
1219 QList<QAbstractButton *> QMessageBox::buttons() const
1220 {
1221     Q_D(const QMessageBox);
1222     return d->buttonBox->buttons();
1223 }
1224
1225 /*!
1226     \since 4.5
1227
1228     Returns the button role for the specified \a button. This function returns
1229     \l InvalidRole if \a button is 0 or has not been added to the message box.
1230
1231     \sa buttons(), addButton()
1232 */
1233 QMessageBox::ButtonRole QMessageBox::buttonRole(QAbstractButton *button) const
1234 {
1235     Q_D(const QMessageBox);
1236     return QMessageBox::ButtonRole(d->buttonBox->buttonRole(button));
1237 }
1238
1239 /*!
1240     \reimp
1241 */
1242 void QMessageBox::showEvent(QShowEvent *e)
1243 {
1244     Q_D(QMessageBox);
1245     if (d->autoAddOkButton) {
1246         addButton(Ok);
1247     }
1248     if (d->detailsButton)
1249         addButton(d->detailsButton, QMessageBox::ActionRole);
1250     d->detectEscapeButton();
1251     d->updateSize();
1252
1253 #ifndef QT_NO_ACCESSIBILITY
1254     QAccessible::updateAccessibility(this, 0, QAccessible::Alert);
1255 #endif
1256     QDialog::showEvent(e);
1257 }
1258
1259
1260 static QMessageBox::StandardButton showNewMessageBox(QWidget *parent,
1261     QMessageBox::Icon icon,
1262     const QString& title, const QString& text,
1263     QMessageBox::StandardButtons buttons,
1264     QMessageBox::StandardButton defaultButton)
1265 {
1266     QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent);
1267     QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox*>();
1268     Q_ASSERT(buttonBox != 0);
1269
1270     uint mask = QMessageBox::FirstButton;
1271     while (mask <= QMessageBox::LastButton) {
1272         uint sb = buttons & mask;
1273         mask <<= 1;
1274         if (!sb)
1275             continue;
1276         QPushButton *button = msgBox.addButton((QMessageBox::StandardButton)sb);
1277         // Choose the first accept role as the default
1278         if (msgBox.defaultButton())
1279             continue;
1280         if ((defaultButton == QMessageBox::NoButton && buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
1281             || (defaultButton != QMessageBox::NoButton && sb == uint(defaultButton)))
1282             msgBox.setDefaultButton(button);
1283     }
1284     if (msgBox.exec() == -1)
1285         return QMessageBox::Cancel;
1286     return msgBox.standardButton(msgBox.clickedButton());
1287 }
1288
1289 /*!
1290     \since 4.2
1291
1292     Opens an information message box with the given \a title and
1293     \a text in front of the specified \a parent widget.
1294
1295     The standard \a buttons are added to the message box.
1296     \a defaultButton specifies the button used when \key Enter is pressed.
1297     \a defaultButton must refer to a button that was given in \a buttons.
1298     If \a defaultButton is QMessageBox::NoButton, QMessageBox
1299     chooses a suitable default automatically.
1300
1301     Returns the identity of the standard button that was clicked. If
1302     \key Esc was pressed instead, the \l{Default and Escape Keys}
1303     {escape button} is returned.
1304
1305     The message box is an \l{Qt::ApplicationModal}{application modal}
1306     dialog box.
1307
1308     \warning Do not delete \a parent during the execution of the dialog.
1309              If you want to do this, you should create the dialog
1310              yourself using one of the QMessageBox constructors.
1311
1312     \sa question(), warning(), critical()
1313 */
1314 QMessageBox::StandardButton QMessageBox::information(QWidget *parent, const QString &title,
1315                                const QString& text, StandardButtons buttons,
1316                                StandardButton defaultButton)
1317 {
1318     return showNewMessageBox(parent, Information, title, text, buttons,
1319                              defaultButton);
1320 }
1321
1322
1323 /*!
1324     \since 4.2
1325
1326     Opens a question message box with the given \a title and \a
1327     text in front of the specified \a parent widget.
1328
1329     The standard \a buttons are added to the message box. \a
1330     defaultButton specifies the button used when \key Enter is
1331     pressed. \a defaultButton must refer to a button that was given in \a buttons.
1332     If \a defaultButton is QMessageBox::NoButton, QMessageBox
1333     chooses a suitable default automatically.
1334
1335     Returns the identity of the standard button that was clicked. If
1336     \key Esc was pressed instead, the \l{Default and Escape Keys}
1337     {escape button} is returned.
1338
1339     The message box is an \l{Qt::ApplicationModal} {application modal}
1340     dialog box.
1341
1342     \warning Do not delete \a parent during the execution of the dialog.
1343              If you want to do this, you should create the dialog
1344              yourself using one of the QMessageBox constructors.
1345
1346     \sa information(), warning(), critical()
1347 */
1348 QMessageBox::StandardButton QMessageBox::question(QWidget *parent, const QString &title,
1349                             const QString& text, StandardButtons buttons,
1350                             StandardButton defaultButton)
1351 {
1352     return showNewMessageBox(parent, Question, title, text, buttons, defaultButton);
1353 }
1354
1355 /*!
1356     \since 4.2
1357
1358     Opens a warning message box with the given \a title and \a
1359     text in front of the specified \a parent widget.
1360
1361     The standard \a buttons are added to the message box. \a
1362     defaultButton specifies the button used when \key Enter is
1363     pressed. \a defaultButton must refer to a button that was given in \a buttons.
1364     If \a defaultButton is QMessageBox::NoButton, QMessageBox
1365     chooses a suitable default automatically.
1366
1367     Returns the identity of the standard button that was clicked. If
1368     \key Esc was pressed instead, the \l{Default and Escape Keys}
1369     {escape button} is returned.
1370
1371     The message box is an \l{Qt::ApplicationModal} {application modal}
1372     dialog box.
1373
1374     \warning Do not delete \a parent during the execution of the dialog.
1375              If you want to do this, you should create the dialog
1376              yourself using one of the QMessageBox constructors.
1377
1378     \sa question(), information(), critical()
1379 */
1380 QMessageBox::StandardButton QMessageBox::warning(QWidget *parent, const QString &title,
1381                         const QString& text, StandardButtons buttons,
1382                         StandardButton defaultButton)
1383 {
1384     return showNewMessageBox(parent, Warning, title, text, buttons, defaultButton);
1385 }
1386
1387 /*!
1388     \since 4.2
1389
1390     Opens a critical message box with the given \a title and \a
1391     text in front of the specified \a parent widget.
1392
1393     The standard \a buttons are added to the message box. \a
1394     defaultButton specifies the button used when \key Enter is
1395     pressed. \a defaultButton must refer to a button that was given in \a buttons.
1396     If \a defaultButton is QMessageBox::NoButton, QMessageBox
1397     chooses a suitable default automatically.
1398
1399     Returns the identity of the standard button that was clicked. If
1400     \key Esc was pressed instead, the \l{Default and Escape Keys}
1401     {escape button} is returned.
1402
1403     The message box is an \l{Qt::ApplicationModal} {application modal}
1404     dialog box.
1405
1406     \warning Do not delete \a parent during the execution of the dialog.
1407              If you want to do this, you should create the dialog
1408              yourself using one of the QMessageBox constructors.
1409
1410     \sa question(), warning(), information()
1411 */
1412 QMessageBox::StandardButton QMessageBox::critical(QWidget *parent, const QString &title,
1413                          const QString& text, StandardButtons buttons,
1414                          StandardButton defaultButton)
1415 {
1416     return showNewMessageBox(parent, Critical, title, text, buttons, defaultButton);
1417 }
1418
1419 /*!
1420     Displays a simple about box with title \a title and text \a
1421     text. The about box's parent is \a parent.
1422
1423     about() looks for a suitable icon in four locations:
1424
1425     \list 1
1426     \o It prefers \link QWidget::windowIcon() parent->icon() \endlink
1427     if that exists.
1428     \o If not, it tries the top-level widget containing \a parent.
1429     \o If that fails, it tries the \link
1430     QApplication::activeWindow() active window. \endlink
1431     \o As a last resort it uses the Information icon.
1432     \endlist
1433
1434     The about box has a single button labelled "OK". On Mac OS X, the
1435     about box is popped up as a modeless window; on other platforms,
1436     it is currently application modal.
1437
1438     \sa QWidget::windowIcon(), QApplication::activeWindow()
1439 */
1440 void QMessageBox::about(QWidget *parent, const QString &title, const QString &text)
1441 {
1442     QMessageBox *msgBox = new QMessageBox(Information, title, text, 0, parent);
1443     msgBox->setAttribute(Qt::WA_DeleteOnClose);
1444     QIcon icon = msgBox->windowIcon();
1445     QSize size = icon.actualSize(QSize(64, 64));
1446     msgBox->setIconPixmap(icon.pixmap(size));
1447
1448     msgBox->exec();
1449 }
1450
1451 /*!
1452     Displays a simple message box about Qt, with the given \a title
1453     and centered over \a parent (if \a parent is not 0). The message
1454     includes the version number of Qt being used by the application.
1455
1456     This is useful for inclusion in the \gui Help menu of an application,
1457     as shown in the \l{mainwindows/menus}{Menus} example.
1458
1459     QApplication provides this functionality as a slot.
1460
1461     \sa QApplication::aboutQt()
1462 */
1463 void QMessageBox::aboutQt(QWidget *parent, const QString &title)
1464 {
1465     QString translatedTextAboutQtCaption = QMessageBox::tr(
1466         "<h3>About Katie</h3>"
1467         "<p>This program uses Katie version %1.</p>"
1468         ).arg(QLatin1String(QT_VERSION_STR));
1469     QString translatedTextAboutQtText = QMessageBox::tr(
1470         "<p>Katie is a C++ toolkit derived from the Qt 4.8 framework.</p>"
1471         "<p>Katie is available under two different licensing options designed "
1472         "to accommodate the needs of our various users.</p>"
1473         "<p>Katie licensed under the GNU LGPL version 3 is appropriate for the "
1474         "development of Qt&nbsp;applications provided you can comply with the terms "
1475         "and conditions of the GNU LGPL version 3.</p>"
1476         "<p>Katie licensed under the GNU LGPL version 2.1 is appropriate for the "
1477         "development of applications provided you can comply with the terms "
1478         "and conditions of the GNU LGPL version 2.1.</p>"
1479         "<p>Copyright (C) 2015 The Qt Company Ltd and other contributors.</p>"
1480         "<p>Copyright (C) 2016-2021 Ivailo Monev</p>"
1481         "<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>"
1482         "<p>See <a href=\"https://github.com/fluxer/katie\">github.com/fluxer/katie</a> for more information.</p>"
1483         );
1484     QMessageBox *msgBox = new QMessageBox(parent);
1485     msgBox->setAttribute(Qt::WA_DeleteOnClose);
1486     msgBox->setWindowTitle(title.isEmpty() ? tr("About Katie") : title);
1487     msgBox->setText(translatedTextAboutQtCaption);
1488     msgBox->setInformativeText(translatedTextAboutQtText);
1489
1490     QPixmap pm(QLatin1String(":/trolltech/qmessagebox/images/katie.png"));
1491     if (!pm.isNull())
1492         msgBox->setIconPixmap(pm);
1493
1494     msgBox->exec();
1495 }
1496
1497 /////////////////////////////////////////////////////////////////////////////////////////
1498 // Source and binary compatibility routines for 4.0 and 4.1
1499
1500 void QMessageBoxPrivate::retranslateStrings()
1501 {
1502 #ifndef QT_NO_TEXTEDIT
1503     if (detailsButton)
1504         detailsButton->setLabel(detailsText->isHidden() ? ShowLabel : HideLabel);
1505 #endif
1506 }
1507
1508 #ifndef QT_NO_TEXTEDIT
1509 /*!
1510   \property QMessageBox::detailedText
1511   \brief the text to be displayed in the details area.
1512   \since 4.2
1513
1514   The text will be interpreted as a plain text.
1515
1516   By default, this property contains an empty string.
1517
1518   \sa QMessageBox::text, QMessageBox::informativeText
1519 */
1520 QString QMessageBox::detailedText() const
1521 {
1522     Q_D(const QMessageBox);
1523     return d->detailsText ? d->detailsText->text() : QString();
1524 }
1525
1526 void QMessageBox::setDetailedText(const QString &text)
1527 {
1528     Q_D(QMessageBox);
1529     if (text.isEmpty()) {
1530         delete d->detailsText;
1531         d->detailsText = 0;
1532         removeButton(d->detailsButton);
1533         delete d->detailsButton;
1534         d->detailsButton = 0;
1535         return;
1536     }
1537
1538     if (!d->detailsText) {
1539         d->detailsText = new QMessageBoxDetailsText(this);
1540         QGridLayout* grid = qobject_cast<QGridLayout*>(layout());
1541         if (grid)
1542             grid->addWidget(d->detailsText, grid->rowCount(), 0, 1, grid->columnCount());
1543         d->detailsText->hide();
1544     }
1545     if (!d->detailsButton)
1546         d->detailsButton = new DetailButton(this);
1547     d->detailsText->setText(text);
1548 }
1549 #endif // QT_NO_TEXTEDIT
1550
1551 /*!
1552   \property QMessageBox::informativeText
1553
1554   \brief the informative text that provides a fuller description for
1555   the message
1556
1557   \since 4.2
1558
1559   Infromative text can be used to expand upon the text() to give more
1560   information to the user. On the Mac, this text appears in small
1561   system font below the text().  On other platforms, it is simply
1562   appended to the existing text.
1563
1564   By default, this property contains an empty string.
1565
1566   \sa QMessageBox::text, QMessageBox::detailedText
1567 */
1568 QString QMessageBox::informativeText() const
1569 {
1570     Q_D(const QMessageBox);
1571     return d->informativeLabel ? d->informativeLabel->text() : QString();
1572 }
1573
1574 void QMessageBox::setInformativeText(const QString &text)
1575 {
1576     Q_D(QMessageBox);
1577     if (text.isEmpty()) {
1578         layout()->removeWidget(d->informativeLabel);
1579         delete d->informativeLabel;
1580         d->informativeLabel = 0;
1581         d->label->setContentsMargins(2, 0, 0, 0);
1582         d->updateSize();
1583         return;
1584     }
1585
1586     if (!d->informativeLabel) {
1587         QLabel *label = new QLabel(this);
1588         label->setObjectName(QLatin1String("qt_msgbox_informativelabel"));
1589         label->setTextInteractionFlags(Qt::TextInteractionFlags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, 0, this)));
1590         label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
1591         label->setOpenExternalLinks(true);
1592         label->setWordWrap(true);
1593         d->label->setContentsMargins(2, 0, 0, 0);
1594         label->setContentsMargins(2, 0, 0, 6);
1595         label->setIndent(9);
1596         label->setWordWrap(true);
1597         QGridLayout *grid = static_cast<QGridLayout *>(layout());
1598         grid->addWidget(label, 1, 1, 1, 1);
1599         d->informativeLabel = label;
1600     }
1601     d->informativeLabel->setText(text);
1602
1603     d->updateSize();
1604 }
1605
1606 /*!
1607     \since 4.2
1608
1609     This function shadows QWidget::setWindowModality().
1610
1611     Sets the modality of the message box to \a windowModality.
1612
1613     On Mac OS X, if the modality is set to Qt::WindowModal and the message box
1614     has a parent, then the message box will be a Qt::Sheet, otherwise the
1615     message box will be a standard dialog.
1616 */
1617 void QMessageBox::setWindowModality(Qt::WindowModality windowModality)
1618 {
1619     QDialog::setWindowModality(windowModality);
1620
1621     if (parentWidget() && windowModality == Qt::WindowModal)
1622         setParent(parentWidget(), Qt::Sheet);
1623     else
1624         setParent(parentWidget(), Qt::Dialog);
1625     setDefaultButton(d_func()->defaultButton);
1626 }
1627
1628
1629 QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb)
1630 {
1631     QStyle *style = mb ? mb->style() : QApplication::style();
1632     int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, mb);
1633     QIcon tmpIcon;
1634     switch (icon) {
1635     case QMessageBox::Information:
1636         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, 0, mb);
1637         break;
1638     case QMessageBox::Warning:
1639         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, 0, mb);
1640         break;
1641     case QMessageBox::Critical:
1642         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, 0, mb);
1643         break;
1644     case QMessageBox::Question:
1645         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mb);
1646     default:
1647         break;
1648     }
1649     if (!tmpIcon.isNull())
1650         return tmpIcon.pixmap(iconSize, iconSize);
1651     return QPixmap();
1652 }
1653
1654 /*!
1655     \obsolete
1656
1657     Returns the pixmap used for a standard icon. This allows the
1658     pixmaps to be used in more complex message boxes. \a icon
1659     specifies the required icon, e.g. QMessageBox::Question,
1660     QMessageBox::Information, QMessageBox::Warning or
1661     QMessageBox::Critical.
1662
1663     Call QStyle::standardIcon() with QStyle::SP_MessageBoxInformation etc.
1664     instead.
1665 */
1666
1667 QPixmap QMessageBox::standardIcon(Icon icon)
1668 {
1669     return QMessageBoxPrivate::standardIcon(icon, 0);
1670 }
1671
1672 /*!
1673     \typedef QMessageBox::Button
1674     \obsolete
1675
1676     Use QMessageBox::StandardButton instead.
1677 */
1678
1679 /*!
1680   \fn int QMessageBox::exec()
1681
1682   Shows the message box as a \l{QDialog#Modal Dialogs}{modal dialog},
1683   blocking until the user closes it.
1684
1685   When using a QMessageBox with standard buttons, this functions returns a
1686   \l StandardButton value indicating the standard button that was clicked.
1687   When using QMessageBox with custom buttons, this function returns an
1688   opaque value; use clickedButton() to determine which button was clicked.
1689
1690   \note The result() function returns also \l StandardButton value instead of \l QDialog::DialogCode
1691
1692   Users cannot interact with any other window in the same
1693   application until they close the dialog, either by clicking a
1694   button or by using a mechanism provided by the window system.
1695
1696   \sa show(), result()
1697 */
1698
1699 QT_END_NAMESPACE
1700
1701 #include "moc_qmessagebox.h"
1702 #include "qrc_qmessagebox.cpp"
1703
1704 #endif // QT_NO_MESSAGEBOX