Various documentation fixes ported from Qt 4.8
[profile/ivi/qtbase.git] / src / widgets / dialogs / qdialog.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qcolordialog.h"
43 #include "qfontdialog.h"
44 #include "qfiledialog.h"
45
46 #include "qevent.h"
47 #include "qdesktopwidget.h"
48 #include "qpushbutton.h"
49 #include "qapplication.h"
50 #include "qlayout.h"
51 #include "qsizegrip.h"
52 #include "qwhatsthis.h"
53 #include "qmenu.h"
54 #include "qcursor.h"
55 #include "private/qdialog_p.h"
56 #include "private/qguiapplication_p.h"
57 #ifndef QT_NO_ACCESSIBILITY
58 #include "qaccessible.h"
59 #endif
60
61 QT_BEGIN_NAMESPACE
62
63 static inline int themeDialogType(const QDialog *dialog)
64 {
65     if (qobject_cast<const QFileDialog *>(dialog))
66         return QPlatformTheme::FileDialog;
67     if (qobject_cast<const QColorDialog *>(dialog))
68         return QPlatformTheme::ColorDialog;
69     if (qobject_cast<const QFontDialog *>(dialog))
70         return QPlatformTheme::FontDialog;
71     return -1;
72 }
73
74 QPlatformDialogHelper *QDialogPrivate::platformHelper() const
75 {
76     // Delayed creation of the platform, ensuring that
77     // that qobject_cast<> on the dialog works in the plugin.
78     if (!m_platformHelperCreated) {
79         m_platformHelperCreated = true;
80         QDialogPrivate *ncThis = const_cast<QDialogPrivate *>(this);
81         QDialog *dialog = ncThis->q_func();
82         const int type = themeDialogType(dialog);
83         if (type >= 0) {
84             m_platformHelper = QGuiApplicationPrivate::platformTheme()
85                     ->createPlatformDialogHelper(static_cast<QPlatformTheme::DialogType>(type));
86             if (m_platformHelper) {
87                 QObject::connect(m_platformHelper, SIGNAL(accept()), dialog, SLOT(accept()));
88                 QObject::connect(m_platformHelper, SIGNAL(reject()), dialog, SLOT(reject()));
89                 QObject::connect(m_platformHelper, SIGNAL(launchNativeAppModalPanel()),
90                                  dialog, SLOT(_q_platformRunNativeAppModalPanel()));
91                 ncThis->initHelper(m_platformHelper);
92             }
93         }
94     }
95     return m_platformHelper;
96 }
97
98 QWindow *QDialogPrivate::parentWindow() const
99 {
100     if (const QWidget *parent = q_func()->nativeParentWidget())
101         return parent->windowHandle();
102     return 0;
103 }
104
105 bool QDialogPrivate::setNativeDialogVisible(bool visible)
106 {
107     if (QPlatformDialogHelper *helper = platformHelper()) {
108         if (visible) {
109             helperPrepareShow(helper);
110             QPlatformDialogHelper::ShowFlags flags(0);
111             if (q_func()->isModal())
112                 flags |= QPlatformDialogHelper::ShowModal;
113             nativeDialogInUse = helper->show_sys(flags, q_func()->windowFlags(), parentWindow());
114         } else {
115             helper->hide_sys();
116         }
117     }
118     return nativeDialogInUse;
119 }
120
121 void QDialogPrivate::_q_platformRunNativeAppModalPanel()
122 {
123     if (nativeDialogInUse)
124         platformHelper()->_q_platformRunNativeAppModalPanel();
125 }
126
127
128 QVariant QDialogPrivate::styleHint(QPlatformDialogHelper::StyleHint hint) const
129 {
130     if (const QPlatformDialogHelper *helper = platformHelper())
131         return helper->styleHint(hint);
132     return QPlatformDialogHelper::defaultStyleHint(hint);
133 }
134
135 /*!
136     \class QDialog
137     \brief The QDialog class is the base class of dialog windows.
138
139     \ingroup dialog-classes
140     \ingroup abstractwidgets
141     \inmodule QtWidgets
142
143     A dialog window is a top-level window mostly used for short-term
144     tasks and brief communications with the user. QDialogs may be
145     modal or modeless. QDialogs can
146     provide a \link #return return
147     value\endlink, and they can have \link #default default
148     buttons\endlink. QDialogs can also have a QSizeGrip in their
149     lower-right corner, using setSizeGripEnabled().
150
151     Note that QDialog (an any other widget that has type Qt::Dialog) uses
152     the parent widget slightly differently from other classes in Qt. A
153     dialog is always a top-level widget, but if it has a parent, its
154     default location is centered on top of the parent's top-level widget
155     (if it is not top-level itself). It will also share the parent's
156     taskbar entry.
157
158     Use the overload of the QWidget::setParent() function to change
159     the ownership of a QDialog widget. This function allows you to
160     explicitly set the window flags of the reparented widget; using
161     the overloaded function will clear the window flags specifying the
162     window-system properties for the widget (in particular it will
163     reset the Qt::Dialog flag).
164
165     \section1 Modal Dialogs
166
167     A \bold{modal} dialog is a dialog that blocks input to other
168     visible windows in the same application. Dialogs that are used to
169     request a file name from the user or that are used to set
170     application preferences are usually modal. Dialogs can be
171     \l{Qt::ApplicationModal}{application modal} (the default) or
172     \l{Qt::WindowModal}{window modal}.
173
174     When an application modal dialog is opened, the user must finish
175     interacting with the dialog and close it before they can access
176     any other window in the application. Window modal dialogs only
177     block access to the window associated with the dialog, allowing
178     the user to continue to use other windows in an application.
179
180     The most common way to display a modal dialog is to call its
181     exec() function. When the user closes the dialog, exec() will
182     provide a useful \link #return return value\endlink. Typically,
183     to get the dialog to close and return the appropriate value, we
184     connect a default button, e.g. \gui OK, to the accept() slot and a
185     \gui Cancel button to the reject() slot.
186     Alternatively you can call the done() slot with \c Accepted or
187     \c Rejected.
188
189     An alternative is to call setModal(true) or setWindowModality(),
190     then show(). Unlike exec(), show() returns control to the caller
191     immediately. Calling setModal(true) is especially useful for
192     progress dialogs, where the user must have the ability to interact
193     with the dialog, e.g.  to cancel a long running operation. If you
194     use show() and setModal(true) together to perform a long operation,
195     you must call QApplication::processEvents() periodically during
196     processing to enable the user to interact with the dialog. (See
197     QProgressDialog.)
198
199     \section1 Modeless Dialogs
200
201     A \bold{modeless} dialog is a dialog that operates
202     independently of other windows in the same application. Find and
203     replace dialogs in word-processors are often modeless to allow the
204     user to interact with both the application's main window and with
205     the dialog.
206
207     Modeless dialogs are displayed using show(), which returns control
208     to the caller immediately.
209
210     If you invoke the \l{QWidget::show()}{show()} function after hiding
211     a dialog, the dialog will be displayed in its original position. This is
212     because the window manager decides the position for windows that
213     have not been explicitly placed by the programmer. To preserve the
214     position of a dialog that has been moved by the user, save its position
215     in your \l{QWidget::closeEvent()}{closeEvent()}  handler and then
216     move the dialog to that position, before showing it again.
217
218     \target default
219     \section1 Default Button
220
221     A dialog's \e default button is the button that's pressed when the
222     user presses Enter (Return). This button is used to signify that
223     the user accepts the dialog's settings and wants to close the
224     dialog. Use QPushButton::setDefault(), QPushButton::isDefault()
225     and QPushButton::autoDefault() to set and control the dialog's
226     default button.
227
228     \target escapekey
229     \section1 Escape Key
230
231     If the user presses the Esc key in a dialog, QDialog::reject()
232     will be called. This will cause the window to close: The \link
233     QCloseEvent close event \endlink cannot be \link
234     QCloseEvent::ignore() ignored \endlink.
235
236     \section1 Extensibility
237
238     Extensibility is the ability to show the dialog in two ways: a
239     partial dialog that shows the most commonly used options, and a
240     full dialog that shows all the options. Typically an extensible
241     dialog will initially appear as a partial dialog, but with a
242     \gui More toggle button. If the user presses the \gui More button down,
243     the dialog is expanded. The \l{Extension Example} shows how to achieve
244     extensible dialogs using Qt.
245
246     \target return
247     \section1 Return Value (Modal Dialogs)
248
249     Modal dialogs are often used in situations where a return value is
250     required, e.g. to indicate whether the user pressed \gui OK or
251     \gui Cancel. A dialog can be closed by calling the accept() or the
252     reject() slots, and exec() will return \c Accepted or \c Rejected
253     as appropriate. The exec() call returns the result of the dialog.
254     The result is also available from result() if the dialog has not
255     been destroyed.
256
257     In order to modify your dialog's close behavior, you can reimplement
258     the functions accept(), reject() or done(). The
259     \l{QWidget::closeEvent()}{closeEvent()} function should only be
260     reimplemented to preserve the dialog's position or to override the
261     standard close or reject behavior.
262
263     \target examples
264     \section1 Code Examples
265
266     A modal dialog:
267
268     \snippet doc/src/snippets/dialogs/dialogs.cpp 1
269
270     A modeless dialog:
271
272     \snippet doc/src/snippets/dialogs/dialogs.cpp 0
273
274     \sa QDialogButtonBox, QTabWidget, QWidget, QProgressDialog,
275         {fowler}{GUI Design Handbook: Dialogs, Standard}, {Extension Example},
276         {Standard Dialogs Example}
277 */
278
279 /*! \enum QDialog::DialogCode
280
281     The value returned by a modal dialog.
282
283     \value Accepted
284     \value Rejected
285 */
286
287 /*!
288   \property QDialog::sizeGripEnabled
289   \brief whether the size grip is enabled
290
291   A QSizeGrip is placed in the bottom-right corner of the dialog when this
292   property is enabled. By default, the size grip is disabled.
293 */
294
295
296 /*!
297   Constructs a dialog with parent \a parent.
298
299   A dialog is always a top-level widget, but if it has a parent, its
300   default location is centered on top of the parent. It will also
301   share the parent's taskbar entry.
302
303   The widget flags \a f are passed on to the QWidget constructor.
304   If, for example, you don't want a What's This button in the title bar
305   of the dialog, pass Qt::WindowTitleHint | Qt::WindowSystemMenuHint in \a f.
306
307   \sa QWidget::setWindowFlags()
308 */
309
310 QDialog::QDialog(QWidget *parent, Qt::WindowFlags f)
311     : QWidget(*new QDialogPrivate, parent,
312               f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
313 {
314 }
315
316 /*!
317   \overload
318   \internal
319 */
320 QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
321     : QWidget(dd, parent, f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
322 {
323 }
324
325 /*!
326   Destroys the QDialog, deleting all its children.
327 */
328
329 QDialog::~QDialog()
330 {
331     QT_TRY {
332         // Need to hide() here, as our (to-be) overridden hide()
333         // will not be called in ~QWidget.
334         hide();
335     } QT_CATCH(...) {
336         // we're in the destructor - just swallow the exception
337     }
338 }
339
340 /*!
341   \internal
342   This function is called by the push button \a pushButton when it
343   becomes the default button. If \a pushButton is 0, the dialogs
344   default default button becomes the default button. This is what a
345   push button calls when it loses focus.
346 */
347 void QDialogPrivate::setDefault(QPushButton *pushButton)
348 {
349     Q_Q(QDialog);
350     bool hasMain = false;
351     QList<QPushButton*> list = q->findChildren<QPushButton*>();
352     for (int i=0; i<list.size(); ++i) {
353         QPushButton *pb = list.at(i);
354         if (pb->window() == q) {
355             if (pb == mainDef)
356                 hasMain = true;
357             if (pb != pushButton)
358                 pb->setDefault(false);
359         }
360     }
361     if (!pushButton && hasMain)
362         mainDef->setDefault(true);
363     if (!hasMain)
364         mainDef = pushButton;
365 }
366
367 /*!
368   \internal
369   This function sets the default default push button to \a pushButton.
370   This function is called by QPushButton::setDefault().
371 */
372 void QDialogPrivate::setMainDefault(QPushButton *pushButton)
373 {
374     mainDef = 0;
375     setDefault(pushButton);
376 }
377
378 /*!
379   \internal
380   Hides the default button indicator. Called when non auto-default
381   push button get focus.
382  */
383 void QDialogPrivate::hideDefault()
384 {
385     Q_Q(QDialog);
386     QList<QPushButton*> list = q->findChildren<QPushButton*>();
387     for (int i=0; i<list.size(); ++i) {
388         list.at(i)->setDefault(false);
389     }
390 }
391
392 void QDialogPrivate::resetModalitySetByOpen()
393 {
394     Q_Q(QDialog);
395     if (resetModalityTo != -1 && !q->testAttribute(Qt::WA_SetWindowModality)) {
396         // open() changed the window modality and the user didn't touch it afterwards; restore it
397         q->setWindowModality(Qt::WindowModality(resetModalityTo));
398         q->setAttribute(Qt::WA_SetWindowModality, wasModalitySet);
399 #ifdef Q_OS_MAC
400         Q_ASSERT(resetModalityTo != Qt::WindowModal);
401         q->setParent(q->parentWidget(), Qt::Dialog);
402 #endif
403     }
404     resetModalityTo = -1;
405 }
406
407 #if defined(Q_OS_WINCE)
408 #ifdef Q_OS_WINCE_WM
409 void QDialogPrivate::_q_doneAction()
410 {
411     //Done...
412     QApplication::postEvent(q_func(), new QEvent(QEvent::OkRequest));
413 }
414 #endif
415
416 /*!
417     \reimp
418 */
419 bool QDialog::event(QEvent *e)
420 {
421     bool result = QWidget::event(e);
422 #ifdef Q_OS_WINCE
423     if (e->type() == QEvent::OkRequest) {
424         accept();
425         result = true;
426      }
427 #endif
428     return result;
429 }
430 #endif
431
432 /*!
433   In general returns the modal dialog's result code, \c Accepted or
434   \c Rejected.
435
436   \note When called on a QMessageBox instance, the returned value is a
437   value of the \l QMessageBox::StandardButton enum.
438
439   Do not call this function if the dialog was constructed with the
440   Qt::WA_DeleteOnClose attribute.
441 */
442 int QDialog::result() const
443 {
444     Q_D(const QDialog);
445     return d->rescode;
446 }
447
448 /*!
449   \fn void QDialog::setResult(int i)
450
451   Sets the modal dialog's result code to \a i.
452
453   \note We recommend that you use one of the values defined by
454   QDialog::DialogCode.
455 */
456 void QDialog::setResult(int r)
457 {
458     Q_D(QDialog);
459     d->rescode = r;
460 }
461
462 /*!
463     \since 4.5
464
465     Shows the dialog as a \l{QDialog#Modal Dialogs}{window modal dialog},
466     returning immediately.
467
468     \sa exec(), show(), result(), setWindowModality()
469 */
470 void QDialog::open()
471 {
472     Q_D(QDialog);
473
474     Qt::WindowModality modality = windowModality();
475     if (modality != Qt::WindowModal) {
476         d->resetModalityTo = modality;
477         d->wasModalitySet = testAttribute(Qt::WA_SetWindowModality);
478         setWindowModality(Qt::WindowModal);
479         setAttribute(Qt::WA_SetWindowModality, false);
480 #ifdef Q_OS_MAC
481         setParent(parentWidget(), Qt::Sheet);
482 #endif
483     }
484
485     setResult(0);
486     show();
487 }
488
489 /*!
490     Shows the dialog as a \l{QDialog#Modal Dialogs}{modal dialog},
491     blocking until the user closes it. The function returns a \l
492     DialogCode result.
493
494     If the dialog is \l{Qt::ApplicationModal}{application modal}, users cannot
495     interact with any other window in the same application until they close
496     the dialog. If the dialog is \l{Qt::ApplicationModal}{window modal}, only
497     interaction with the parent window is blocked while the dialog is open.
498     By default, the dialog is application modal.
499
500     \sa open(), show(), result(), setWindowModality()
501 */
502
503 int QDialog::exec()
504 {
505     Q_D(QDialog);
506
507     if (d->eventLoop) {
508         qWarning("QDialog::exec: Recursive call detected");
509         return -1;
510     }
511
512     bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
513     setAttribute(Qt::WA_DeleteOnClose, false);
514
515     d->resetModalitySetByOpen();
516
517     bool wasShowModal = testAttribute(Qt::WA_ShowModal);
518     setAttribute(Qt::WA_ShowModal, true);
519     setResult(0);
520
521     bool showSystemDialogFullScreen = false;
522     if (showSystemDialogFullScreen) {
523         setWindowFlags(windowFlags() | Qt::WindowSoftkeysVisibleHint);
524         setWindowState(Qt::WindowFullScreen);
525     }
526     show();
527
528     if (d->nativeDialogInUse)
529         d->platformHelper()->platformNativeDialogModalHelp();
530
531     QEventLoop eventLoop;
532     d->eventLoop = &eventLoop;
533     QPointer<QDialog> guard = this;
534     (void) eventLoop.exec(QEventLoop::DialogExec);
535     if (guard.isNull())
536         return QDialog::Rejected;
537     d->eventLoop = 0;
538
539     setAttribute(Qt::WA_ShowModal, wasShowModal);
540
541     int res = result();
542     if (d->nativeDialogInUse)
543         d->helperDone(static_cast<QDialog::DialogCode>(res), d->platformHelper());
544     if (deleteOnClose)
545         delete this;
546     return res;
547 }
548
549 /*!
550   Closes the dialog and sets its result code to \a r. If this dialog
551   is shown with exec(), done() causes the local event loop to finish,
552   and exec() to return \a r.
553
554   As with QWidget::close(), done() deletes the dialog if the
555   Qt::WA_DeleteOnClose flag is set. If the dialog is the application's
556   main widget, the application terminates. If the dialog is the
557   last window closed, the QApplication::lastWindowClosed() signal is
558   emitted.
559
560   \sa accept(), reject(), QApplication::activeWindow(), QApplication::quit()
561 */
562
563 void QDialog::done(int r)
564 {
565     Q_D(QDialog);
566     hide();
567     setResult(r);
568
569     d->close_helper(QWidgetPrivate::CloseNoEvent);
570     d->resetModalitySetByOpen();
571
572     emit finished(r);
573     if (r == Accepted)
574         emit accepted();
575     else if (r == Rejected)
576         emit rejected();
577 }
578
579 /*!
580   Hides the modal dialog and sets the result code to \c Accepted.
581
582   \sa reject() done()
583 */
584
585 void QDialog::accept()
586 {
587     done(Accepted);
588 }
589
590 /*!
591   Hides the modal dialog and sets the result code to \c Rejected.
592
593   \sa accept() done()
594 */
595
596 void QDialog::reject()
597 {
598     done(Rejected);
599 }
600
601 /*! \reimp */
602 bool QDialog::eventFilter(QObject *o, QEvent *e)
603 {
604     return QWidget::eventFilter(o, e);
605 }
606
607 /*****************************************************************************
608   Event handlers
609  *****************************************************************************/
610
611 #ifndef QT_NO_CONTEXTMENU
612 /*! \reimp */
613 void QDialog::contextMenuEvent(QContextMenuEvent *e)
614 {
615 #if defined(QT_NO_WHATSTHIS) || defined(QT_NO_MENU)
616     Q_UNUSED(e);
617 #else
618     QWidget *w = childAt(e->pos());
619     if (!w) {
620         w = rect().contains(e->pos()) ? this : 0;
621         if (!w)
622             return;
623     }
624     while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))
625         w = w->isWindow() ? 0 : w->parentWidget();
626     if (w) {
627         QWeakPointer<QMenu> p = new QMenu(this);
628         QAction *wt = p.data()->addAction(tr("What's This?"));
629         if (p.data()->exec(e->globalPos()) == wt) {
630             QHelpEvent e(QEvent::WhatsThis, w->rect().center(),
631                          w->mapToGlobal(w->rect().center()));
632             QApplication::sendEvent(w, &e);
633         }
634         delete p.data();
635     }
636 #endif
637 }
638 #endif // QT_NO_CONTEXTMENU
639
640 /*! \reimp */
641 void QDialog::keyPressEvent(QKeyEvent *e)
642 {
643     //   Calls reject() if Escape is pressed. Simulates a button
644     //   click for the default button if Enter is pressed. Move focus
645     //   for the arrow keys. Ignore the rest.
646 #ifdef Q_OS_MAC
647     if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Period) {
648         reject();
649     } else
650 #endif
651     if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) {
652         switch (e->key()) {
653         case Qt::Key_Enter:
654         case Qt::Key_Return: {
655             QList<QPushButton*> list = findChildren<QPushButton*>();
656             for (int i=0; i<list.size(); ++i) {
657                 QPushButton *pb = list.at(i);
658                 if (pb->isDefault() && pb->isVisible()) {
659                     if (pb->isEnabled())
660                         pb->click();
661                     return;
662                 }
663             }
664         }
665         break;
666         case Qt::Key_Escape:
667             reject();
668             break;
669         default:
670             e->ignore();
671             return;
672         }
673     } else {
674         e->ignore();
675     }
676 }
677
678 /*! \reimp */
679 void QDialog::closeEvent(QCloseEvent *e)
680 {
681 #ifndef QT_NO_WHATSTHIS
682     if (isModal() && QWhatsThis::inWhatsThisMode())
683         QWhatsThis::leaveWhatsThisMode();
684 #endif
685     if (isVisible()) {
686         QPointer<QObject> that = this;
687         reject();
688         if (that && isVisible())
689             e->ignore();
690     } else {
691         e->accept();
692     }
693 }
694
695 /*****************************************************************************
696   Geometry management.
697  *****************************************************************************/
698
699 /*! \reimp
700 */
701
702 void QDialog::setVisible(bool visible)
703 {
704     Q_D(QDialog);
705     if (visible) {
706         if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
707             return;
708
709         if (!testAttribute(Qt::WA_Moved)) {
710             Qt::WindowStates state = windowState();
711             adjustPosition(parentWidget());
712             setAttribute(Qt::WA_Moved, false); // not really an explicit position
713             if (state != windowState())
714                 setWindowState(state);
715         }
716         QWidget::setVisible(visible);
717         showExtension(d->doShowExtension);
718         QWidget *fw = window()->focusWidget();
719         if (!fw)
720             fw = this;
721
722         /*
723           The following block is to handle a special case, and does not
724           really follow propper logic in concern of autoDefault and TAB
725           order. However, it's here to ease usage for the users. If a
726           dialog has a default QPushButton, and first widget in the TAB
727           order also is a QPushButton, then we give focus to the main
728           default QPushButton. This simplifies code for the developers,
729           and actually catches most cases... If not, then they simply
730           have to use [widget*]->setFocus() themselves...
731         */
732         if (d->mainDef && fw->focusPolicy() == Qt::NoFocus) {
733             QWidget *first = fw;
734             while ((first = first->nextInFocusChain()) != fw && first->focusPolicy() == Qt::NoFocus)
735                 ;
736             if (first != d->mainDef && qobject_cast<QPushButton*>(first))
737                 d->mainDef->setFocus();
738         }
739         if (!d->mainDef && isWindow()) {
740             QWidget *w = fw;
741             while ((w = w->nextInFocusChain()) != fw) {
742                 QPushButton *pb = qobject_cast<QPushButton *>(w);
743                 if (pb && pb->autoDefault() && pb->focusPolicy() != Qt::NoFocus) {
744                     pb->setDefault(true);
745                     break;
746                 }
747             }
748         }
749         if (fw && !fw->hasFocus()) {
750             QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);
751             QApplication::sendEvent(fw, &e);
752         }
753
754 #ifndef QT_NO_ACCESSIBILITY
755         QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::DialogStart, this, 0));
756 #endif
757
758     } else {
759         if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
760             return;
761
762 #ifndef QT_NO_ACCESSIBILITY
763         if (isVisible())
764             QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::DialogEnd, this, 0));
765 #endif
766
767         // Reimplemented to exit a modal event loop when the dialog is hidden.
768         QWidget::setVisible(visible);
769         if (d->eventLoop)
770             d->eventLoop->exit();
771     }
772     if (d->mainDef && isActiveWindow()
773         && d->styleHint(QPlatformDialogHelper::SnapToDefaultButton).toBool())
774         QCursor::setPos(d->mainDef->mapToGlobal(d->mainDef->rect().center()));
775 }
776
777 /*!\reimp */
778 void QDialog::showEvent(QShowEvent *event)
779 {
780     if (!event->spontaneous() && !testAttribute(Qt::WA_Moved)) {
781         Qt::WindowStates  state = windowState();
782         adjustPosition(parentWidget());
783         setAttribute(Qt::WA_Moved, false); // not really an explicit position
784         if (state != windowState())
785             setWindowState(state);
786     }
787 }
788
789 /*! \internal */
790 void QDialog::adjustPosition(QWidget* w)
791 {
792 #ifdef Q_WS_X11
793     // if the WM advertises that it will place the windows properly for us, let it do it :)
794     if (X11->isSupportedByWM(ATOM(_NET_WM_FULL_PLACEMENT)))
795         return;
796 #endif
797     QPoint p(0, 0);
798     int extraw = 0, extrah = 0, scrn = 0;
799     if (w)
800         w = w->window();
801     QRect desk;
802     if (w) {
803         scrn = QApplication::desktop()->screenNumber(w);
804     } else if (QApplication::desktop()->isVirtualDesktop()) {
805         scrn = QApplication::desktop()->screenNumber(QCursor::pos());
806     } else {
807         scrn = QApplication::desktop()->screenNumber(this);
808     }
809     desk = QApplication::desktop()->availableGeometry(scrn);
810
811     QWidgetList list = QApplication::topLevelWidgets();
812     for (int i = 0; (extraw == 0 || extrah == 0) && i < list.size(); ++i) {
813         QWidget * current = list.at(i);
814         if (current->isVisible()) {
815             int framew = current->geometry().x() - current->x();
816             int frameh = current->geometry().y() - current->y();
817
818             extraw = qMax(extraw, framew);
819             extrah = qMax(extrah, frameh);
820         }
821     }
822
823     // sanity check for decoration frames. With embedding, we
824     // might get extraordinary values
825     if (extraw == 0 || extrah == 0 || extraw >= 10 || extrah >= 40) {
826         extrah = 40;
827         extraw = 10;
828     }
829
830
831     if (w) {
832         // Use mapToGlobal rather than geometry() in case w might
833         // be embedded in another application
834         QPoint pp = w->mapToGlobal(QPoint(0,0));
835         p = QPoint(pp.x() + w->width()/2,
836                     pp.y() + w->height()/ 2);
837     } else {
838         // p = middle of the desktop
839         p = QPoint(desk.x() + desk.width()/2, desk.y() + desk.height()/2);
840     }
841
842     // p = origin of this
843     p = QPoint(p.x()-width()/2 - extraw,
844                 p.y()-height()/2 - extrah);
845
846
847     if (p.x() + extraw + width() > desk.x() + desk.width())
848         p.setX(desk.x() + desk.width() - width() - extraw);
849     if (p.x() < desk.x())
850         p.setX(desk.x());
851
852     if (p.y() + extrah + height() > desk.y() + desk.height())
853         p.setY(desk.y() + desk.height() - height() - extrah);
854     if (p.y() < desk.y())
855         p.setY(desk.y());
856
857     move(p);
858 }
859
860 /*!
861     \obsolete
862
863     If \a orientation is Qt::Horizontal, the extension will be displayed
864     to the right of the dialog's main area. If \a orientation is
865     Qt::Vertical, the extension will be displayed below the dialog's main
866     area.
867
868     Instead of using this functionality, we recommend that you simply call
869     show() or hide() on the part of the dialog that you want to use as an
870     extension. See the \l{Extension Example} for details.
871
872     \sa setExtension()
873 */
874 void QDialog::setOrientation(Qt::Orientation orientation)
875 {
876     Q_D(QDialog);
877     d->orientation = orientation;
878 }
879
880 /*!
881     \obsolete
882
883     Returns the dialog's extension orientation.
884
885     Instead of using this functionality, we recommend that you simply call
886     show() or hide() on the part of the dialog that you want to use as an
887     extension. See the \l{Extension Example} for details.
888
889     \sa extension()
890 */
891 Qt::Orientation QDialog::orientation() const
892 {
893     Q_D(const QDialog);
894     return d->orientation;
895 }
896
897 /*!
898     \obsolete
899
900     Sets the widget, \a extension, to be the dialog's extension,
901     deleting any previous extension. The dialog takes ownership of the
902     extension. Note that if 0 is passed any existing extension will be
903     deleted. This function must only be called while the dialog is hidden.
904
905     Instead of using this functionality, we recommend that you simply call
906     show() or hide() on the part of the dialog that you want to use as an
907     extension. See the \l{Extension Example} for details.
908
909     \sa showExtension(), setOrientation()
910 */
911 void QDialog::setExtension(QWidget* extension)
912 {
913     Q_D(QDialog);
914     delete d->extension;
915     d->extension = extension;
916
917     if (!extension)
918         return;
919
920     if (extension->parentWidget() != this)
921         extension->setParent(this);
922     extension->hide();
923 }
924
925 /*!
926     \obsolete
927
928     Returns the dialog's extension or 0 if no extension has been
929     defined.
930
931     Instead of using this functionality, we recommend that you simply call
932     show() or hide() on the part of the dialog that you want to use as an
933     extension. See the \l{Extension Example} for details.
934
935     \sa showExtension(), setOrientation()
936 */
937 QWidget* QDialog::extension() const
938 {
939     Q_D(const QDialog);
940     return d->extension;
941 }
942
943
944 /*!
945     \obsolete
946
947     If \a showIt is true, the dialog's extension is shown; otherwise the
948     extension is hidden.
949
950     Instead of using this functionality, we recommend that you simply call
951     show() or hide() on the part of the dialog that you want to use as an
952     extension. See the \l{Extension Example} for details.
953
954     \sa show(), setExtension(), setOrientation()
955 */
956 void QDialog::showExtension(bool showIt)
957 {
958     Q_D(QDialog);
959     d->doShowExtension = showIt;
960     if (!d->extension)
961         return;
962     if (!testAttribute(Qt::WA_WState_Visible))
963         return;
964     if (d->extension->isVisible() == showIt)
965         return;
966
967     if (showIt) {
968         d->size = size();
969         d->min = minimumSize();
970         d->max = maximumSize();
971         if (layout())
972             layout()->setEnabled(false);
973         QSize s(d->extension->sizeHint()
974                  .expandedTo(d->extension->minimumSize())
975                  .boundedTo(d->extension->maximumSize()));
976         if (d->orientation == Qt::Horizontal) {
977             int h = qMax(height(), s.height());
978             d->extension->setGeometry(width(), 0, s.width(), h);
979             setFixedSize(width() + s.width(), h);
980         } else {
981             int w = qMax(width(), s.width());
982             d->extension->setGeometry(0, height(), w, s.height());
983             setFixedSize(w, height() + s.height());
984         }
985         d->extension->show();
986 #ifndef QT_NO_SIZEGRIP
987         const bool sizeGripEnabled = isSizeGripEnabled();
988         setSizeGripEnabled(false);
989         d->sizeGripEnabled = sizeGripEnabled;
990 #endif
991     } else {
992         d->extension->hide();
993         // workaround for CDE window manager that won't shrink with (-1,-1)
994         setMinimumSize(d->min.expandedTo(QSize(1, 1)));
995         setMaximumSize(d->max);
996         resize(d->size);
997         if (layout())
998             layout()->setEnabled(true);
999 #ifndef QT_NO_SIZEGRIP
1000         setSizeGripEnabled(d->sizeGripEnabled);
1001 #endif
1002     }
1003 }
1004
1005
1006 /*! \reimp */
1007 QSize QDialog::sizeHint() const
1008 {
1009     Q_D(const QDialog);
1010     if (d->extension) {
1011         if (d->orientation == Qt::Horizontal)
1012             return QSize(QWidget::sizeHint().width(),
1013                         qMax(QWidget::sizeHint().height(),d->extension->sizeHint().height()));
1014         else
1015             return QSize(qMax(QWidget::sizeHint().width(), d->extension->sizeHint().width()),
1016                         QWidget::sizeHint().height());
1017     }
1018     return QWidget::sizeHint();
1019 }
1020
1021
1022 /*! \reimp */
1023 QSize QDialog::minimumSizeHint() const
1024 {
1025     Q_D(const QDialog);
1026     if (d->extension) {
1027         if (d->orientation == Qt::Horizontal)
1028             return QSize(QWidget::minimumSizeHint().width(),
1029                         qMax(QWidget::minimumSizeHint().height(), d->extension->minimumSizeHint().height()));
1030         else
1031             return QSize(qMax(QWidget::minimumSizeHint().width(), d->extension->minimumSizeHint().width()),
1032                         QWidget::minimumSizeHint().height());
1033     }
1034
1035     return QWidget::minimumSizeHint();
1036 }
1037
1038 /*!
1039     \property QDialog::modal
1040     \brief whether show() should pop up the dialog as modal or modeless
1041
1042     By default, this property is false and show() pops up the dialog
1043     as modeless. Setting his property to true is equivalent to setting
1044     QWidget::windowModality to Qt::ApplicationModal.
1045
1046     exec() ignores the value of this property and always pops up the
1047     dialog as modal.
1048
1049     \sa QWidget::windowModality, show(), exec()
1050 */
1051
1052 void QDialog::setModal(bool modal)
1053 {
1054     setAttribute(Qt::WA_ShowModal, modal);
1055 }
1056
1057
1058 bool QDialog::isSizeGripEnabled() const
1059 {
1060 #ifndef QT_NO_SIZEGRIP
1061     Q_D(const QDialog);
1062     return !!d->resizer;
1063 #else
1064     return false;
1065 #endif
1066 }
1067
1068
1069 void QDialog::setSizeGripEnabled(bool enabled)
1070 {
1071 #ifdef QT_NO_SIZEGRIP
1072     Q_UNUSED(enabled);
1073 #else
1074     Q_D(QDialog);
1075 #ifndef QT_NO_SIZEGRIP
1076     d->sizeGripEnabled = enabled;
1077     if (enabled && d->doShowExtension)
1078         return;
1079 #endif
1080     if (!enabled != !d->resizer) {
1081         if (enabled) {
1082             d->resizer = new QSizeGrip(this);
1083             // adjustSize() processes all events, which is suboptimal
1084             d->resizer->resize(d->resizer->sizeHint());
1085             if (isRightToLeft())
1086                 d->resizer->move(rect().bottomLeft() -d->resizer->rect().bottomLeft());
1087             else
1088                 d->resizer->move(rect().bottomRight() -d->resizer->rect().bottomRight());
1089             d->resizer->raise();
1090             d->resizer->show();
1091         } else {
1092             delete d->resizer;
1093             d->resizer = 0;
1094         }
1095     }
1096 #endif //QT_NO_SIZEGRIP
1097 }
1098
1099
1100
1101 /*! \reimp */
1102 void QDialog::resizeEvent(QResizeEvent *)
1103 {
1104 #ifndef QT_NO_SIZEGRIP
1105     Q_D(QDialog);
1106     if (d->resizer) {
1107         if (isRightToLeft())
1108             d->resizer->move(rect().bottomLeft() -d->resizer->rect().bottomLeft());
1109         else
1110             d->resizer->move(rect().bottomRight() -d->resizer->rect().bottomRight());
1111         d->resizer->raise();
1112     }
1113 #endif
1114 }
1115
1116 /*! \fn void QDialog::finished(int result)
1117     \since 4.1
1118
1119     This signal is emitted when the dialog's \a result code has been
1120     set, either by the user or by calling done(), accept(), or
1121     reject().
1122
1123     Note that this signal is \e not emitted when hiding the dialog
1124     with hide() or setVisible(false). This includes deleting the
1125     dialog while it is visible.
1126
1127     \sa accepted(), rejected()
1128 */
1129
1130 /*! \fn void QDialog::accepted()
1131     \since 4.1
1132
1133     This signal is emitted when the dialog has been accepted either by
1134     the user or by calling accept() or done() with the
1135     QDialog::Accepted argument.
1136
1137     Note that this signal is \e not emitted when hiding the dialog
1138     with hide() or setVisible(false). This includes deleting the
1139     dialog while it is visible.
1140
1141     \sa finished(), rejected()
1142 */
1143
1144 /*! \fn void QDialog::rejected()
1145     \since 4.1
1146
1147     This signal is emitted when the dialog has been rejected either by
1148     the user or by calling reject() or done() with the
1149     QDialog::Rejected argument.
1150
1151     Note that this signal is \e not emitted when hiding the dialog
1152     with hide() or setVisible(false). This includes deleting the
1153     dialog while it is visible.
1154
1155     \sa finished(), accepted()
1156 */
1157
1158 QT_END_NAMESPACE
1159 #include "moc_qdialog.cpp"