Support all modality types in QPlatformDialogHelper
authorBradley T. Hughes <bradley.hughes@nokia.com>
Thu, 26 Apr 2012 11:32:14 +0000 (13:32 +0200)
committerQt by Nokia <qt-info@nokia.com>
Mon, 30 Apr 2012 12:01:22 +0000 (14:01 +0200)
Modality is not a boolean property in Qt. There are 2 types: window
modality and application modality. Native dialogs can support both of
these types as well (e.g. on Cocoa, a window modal file dialog should be
displayed as a Sheet). Remove the QPlatformDialogHelper::ShowFlags enum
and instead pass a Qt::WindowModality parameter to
QPlatformDialogHelper::show_sys().

The Windows implementation has been updated to check for
Qt::ApplicationModal instead of the ShowModal flag (since only
Qt::ApplicationModal dialogs are blocking).

The Cocoa implementation has been updated to only use non-modal and
application modal native color and font dialogs (which restores Qt 4
behavior). These are shared Cocoa panels that cannot be shown as sheets,
however. If the programmer asks for window modal color/font dialogs, we
use the Qt versions, not the native ones. The file dialog can be shown
either as a Sheet (but we need to pass an NSWindow parent for it to work
properly) or as an application modal dialog.

This change has been tested on Mac OS X with
tests/manual/windowmodality.

Change-Id: I9064987433895c55f68aac979ef8e8207fb24bbe
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
src/gui/kernel/qplatformdialoghelper_qpa.h
src/plugins/platforms/cocoa/qcocoacolordialoghelper.h
src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
src/plugins/platforms/cocoa/qcocoafontdialoghelper.h
src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
src/plugins/platforms/windows/qwindowsdialoghelpers.h
src/widgets/dialogs/qdialog.cpp

index 80a9f0e..5cd3ab0 100644 (file)
@@ -84,11 +84,6 @@ public:
         SnapToDefaultButton
     };
     enum DialogCode { Rejected, Accepted };
-    enum ShowFlag {
-        ShowModal    = 0x00000001
-    };
-
-    Q_DECLARE_FLAGS(ShowFlags, ShowFlag)
 
     QPlatformDialogHelper();
     virtual ~QPlatformDialogHelper();
@@ -99,8 +94,8 @@ public:
     virtual void _q_platformRunNativeAppModalPanel() = 0;
 
     virtual void deleteNativeDialog_sys() = 0;
-    virtual bool show_sys(ShowFlags showFlags,
-                          Qt::WindowFlags windowFlags,
+    virtual bool show_sys(Qt::WindowFlags windowFlags,
+                          Qt::WindowModality windowModality,
                           QWindow *parent) = 0;
     virtual void hide_sys() = 0;
 
index 505fd4f..4b901f3 100644 (file)
@@ -56,7 +56,7 @@ public:
     void platformNativeDialogModalHelp();
     void _q_platformRunNativeAppModalPanel();
     void deleteNativeDialog_sys();
-    bool show_sys(QFlags<QPlatformDialogHelper::ShowFlag>, Qt::WindowFlags, QWindow*);
+    bool show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
     void hide_sys();
 
     DialogCode dialogResultCode_sys();
@@ -64,7 +64,7 @@ public:
     QColor currentColor_sys() const;
 
 public:
-    bool showCocoaColorPanel(QWindow *parent);
+    bool showCocoaColorPanel(Qt::WindowModality windowModality, QWindow *parent);
     bool hideCocoaColorPanel();
 
     void createNSColorPanelDelegate();
index 405cace..9f4446b 100644 (file)
@@ -381,9 +381,13 @@ void QCocoaColorDialogHelper::deleteNativeDialog_sys()
     mDelegate = 0;
 }
 
-bool QCocoaColorDialogHelper::show_sys(QFlags<QPlatformDialogHelper::ShowFlag>, Qt::WindowFlags, QWindow *parent)
+bool QCocoaColorDialogHelper::show_sys(Qt::WindowFlags, Qt::WindowModality windowModality, QWindow *parent)
 {
-    return showCocoaColorPanel(parent);
+    if (windowModality == Qt::WindowModal) {
+        // Cocoa's shared color panel cannot be shown as a sheet
+        return false;
+    }
+    return showCocoaColorPanel(windowModality, parent);
 }
 
 void QCocoaColorDialogHelper::hide_sys()
@@ -447,13 +451,15 @@ void QCocoaColorDialogHelper::createNSColorPanelDelegate()
     mDelegate = delegate;
 }
 
-bool QCocoaColorDialogHelper::showCocoaColorPanel(QWindow *parent)
+bool QCocoaColorDialogHelper::showCocoaColorPanel(Qt::WindowModality windowModality, QWindow *parent)
 {
     Q_UNUSED(parent);
     createNSColorPanelDelegate();
     QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) *>(mDelegate);
     [delegate->mColorPanel setShowsAlpha:options()->testOption(QColorDialogOptions::ShowAlphaChannel)];
-    [delegate showModelessPanel];
+    if (windowModality == Qt::NonModal)
+        [delegate showModelessPanel];
+    // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel()
     return true;
 }
 
index 7d4da01..9768d3e 100644 (file)
@@ -62,7 +62,7 @@ public:
     bool defaultNameFilterDisables() const;
 
     void deleteNativeDialog_sys();
-    bool show_sys(ShowFlags flags, Qt::WindowFlags windowFlags, QWindow *parent);
+    bool show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
     void hide_sys();
     QPlatformFileDialogHelper::DialogCode dialogResultCode_sys();
     void setDirectory_sys(const QString &directory);
@@ -74,7 +74,7 @@ public:
     QString selectedNameFilter_sys() const;
 
 public:
-    bool showCocoaFilePanel(QWindow *parent);
+    bool showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent);
     bool hideCocoaFilePanel();
 
     void createNSOpenSavePanelDelegate();
index c333e3a..9bc7df0 100644 (file)
@@ -244,18 +244,18 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
     return (mReturnCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Accepted) : QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Rejected);
 }
 
-- (void)showWindowModalSheet:(QWindow *)docWidget
+- (void)showWindowModalSheet:(QWindow *)parent
 {
-    Q_UNUSED(docWidget);
     QFileInfo info(*mCurrentSelection);
     NSString *filename = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName());
     NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath());
     bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave)
         || [self panel:nil shouldShowFilename:filepath];
+    NSWindow *nsparent = static_cast<NSWindow *>(qGuiApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parent));
     [mSavePanel
         beginSheetForDirectory:mCurrentDir
         file:selectable ? filename : nil
-        modalForWindow:nil
+        modalForWindow:nsparent
         modalDelegate:self
         didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
         contextInfo:nil];
@@ -613,7 +613,7 @@ void QCocoaFileDialogHelper::hide_sys()
     hideCocoaFilePanel();
 }
 
-bool QCocoaFileDialogHelper::show_sys(ShowFlags /* flags */, Qt::WindowFlags windowFlags, QWindow *parent)
+bool QCocoaFileDialogHelper::show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
 {
 //    Q_Q(QFileDialog);
     if (windowFlags & Qt::WindowStaysOnTopHint) {
@@ -624,7 +624,7 @@ bool QCocoaFileDialogHelper::show_sys(ShowFlags /* flags */, Qt::WindowFlags win
         return false;
     }
 
-    return showCocoaFilePanel(parent);
+    return showCocoaFilePanel(windowModality, parent);
 }
 
 void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
@@ -645,15 +645,15 @@ void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
     mDelegate = delegate;
 }
 
-bool QCocoaFileDialogHelper::showCocoaFilePanel(QWindow *parent)
+bool QCocoaFileDialogHelper::showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent)
 {
-//    Q_Q(QFileDialog);
     createNSOpenSavePanelDelegate();
     QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
-    if (0 /*qt_mac_is_macsheet(qtFileDialog)*/) // ### sheet support.
-        [delegate showWindowModalSheet:parent];
-    else
+    if (windowModality == Qt::NonModal)
         [delegate showModelessPanel];
+    else if (windowModality == Qt::WindowModal && parent)
+        [delegate showWindowModalSheet:parent];
+    // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel()
     return true;
 }
 
index 8a914bf..f9dd435 100644 (file)
@@ -60,7 +60,7 @@ public:
     void _q_platformRunNativeAppModalPanel();
     void deleteNativeDialog_sys();
 
-    bool show_sys(ShowFlags showFlags, Qt::WindowFlags windowFlags, QWindow *parent);
+    bool show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
     void hide_sys();
 
     QPlatformDialogHelper::DialogCode dialogResultCode_sys();
@@ -70,7 +70,7 @@ public:
 
 protected:
     void createNSFontPanelDelegate();
-    bool showCocoaFontPanel(QWindow *parent);
+    bool showCocoaFontPanel(Qt::WindowModality windowModality, QWindow *parent);
     bool hideCocoaFontPanel();
 
 private:
index 1e89270..515bc2a 100644 (file)
@@ -400,9 +400,13 @@ void QCocoaFontDialogHelper::deleteNativeDialog_sys()
     mDelegate = 0;
 }
 
-bool QCocoaFontDialogHelper::show_sys(QFlags<QPlatformDialogHelper::ShowFlag>, Qt::WindowFlags, QWindow *parent)
+bool QCocoaFontDialogHelper::show_sys(Qt::WindowFlags, Qt::WindowModality windowModality, QWindow *parent)
 {
-    return showCocoaFontPanel(parent);
+    if (windowModality == Qt::WindowModal) {
+        // Cocoa's shared font panel cannot be shown as a sheet
+        return false;
+    }
+    return showCocoaFontPanel(windowModality, parent);
 }
 
 void QCocoaFontDialogHelper::hide_sys()
@@ -466,12 +470,14 @@ void QCocoaFontDialogHelper::createNSFontPanelDelegate()
     mDelegate = delegate;
 }
 
-bool QCocoaFontDialogHelper::showCocoaFontPanel(QWindow *parent)
+bool QCocoaFontDialogHelper::showCocoaFontPanel(Qt::WindowModality windowModality, QWindow *parent)
 {
     Q_UNUSED(parent);
     createNSFontPanelDelegate();
     QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate);
-    [delegate showModelessPanel];
+    if (windowModality == Qt::NonModal)
+        [delegate showModelessPanel];
+    // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel()
     return true;
 }
 
index a6bde74..12ea880 100644 (file)
@@ -486,11 +486,11 @@ void QWindowsDialogThread::run()
 }
 
 template <class BaseClass>
-bool QWindowsDialogHelperBase<BaseClass>::show_sys(QPlatformDialogHelper::ShowFlags flags,
-                                                   Qt::WindowFlags,
+bool QWindowsDialogHelperBase<BaseClass>::show_sys(Qt::WindowFlags,
+                                                   Qt::WindowModality windowModality,
                                                    QWindow *parent)
 {
-    const bool modal = flags & QPlatformDialogHelper::ShowModal;
+    const bool modal = (windowModality == Qt::ApplicationModal);
     if (parent) {
         m_ownerWindow = QWindowsWindow::handleOf(parent);
     } else {
index 3ae22e6..909ce59 100644 (file)
@@ -69,8 +69,8 @@ public:
     virtual void platformNativeDialogModalHelp();
     virtual void _q_platformRunNativeAppModalPanel();
     virtual void deleteNativeDialog_sys();
-    virtual bool show_sys(QPlatformDialogHelper::ShowFlags flags,
-                          Qt::WindowFlags windowFlags,
+    virtual bool show_sys(Qt::WindowFlags windowFlags,
+                          Qt::WindowModality windowModality,
                           QWindow *parent);
     virtual void hide_sys();
     virtual QVariant styleHint(QPlatformDialogHelper::StyleHint) const;
index df76d0a..718d64b 100644 (file)
@@ -108,11 +108,9 @@ bool QDialogPrivate::setNativeDialogVisible(bool visible)
 {
     if (QPlatformDialogHelper *helper = platformHelper()) {
         if (visible) {
+            Q_Q(QDialog);
             helperPrepareShow(helper);
-            QPlatformDialogHelper::ShowFlags flags(0);
-            if (q_func()->isModal())
-                flags |= QPlatformDialogHelper::ShowModal;
-            nativeDialogInUse = helper->show_sys(flags, q_func()->windowFlags(), parentWindow());
+            nativeDialogInUse = helper->show_sys(q->windowFlags(), q->windowModality(), parentWindow());
         } else {
             helper->hide_sys();
         }