From af914694d81317b4a7bf0804d9d34a1f3bf2cf48 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 10 Nov 2011 13:07:01 +0100 Subject: QPlatformDialogHelper: Split class hierarchy, decouple from Dialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduce hierarchy of QPlatformDialogHelper-derived classes for font, color and file dialogs. - Start reducing dependencies on QDialog: * Remove QDialog-specifics from interface, introduce enumeration for DialogCode * Make the helpers Q_OBJECTS to be able to add the signals passed on to the QDialogs * Remove QDialogPrivate pointer - Split setVisible_sys() in show_sys() (factory method for native dialogs) and hide_sys(). Pass parent window to show_sys(), removing the necessity to query the QDialog for it - Introduce a styleHint() similar to QGuiApplication's for platform-specific - Fix compile in cocoa/windows, reduce depency on QDialog (-private) classes. Change-Id: Ic1cb715e1edf767f2cb18b9780341d189339ef1d Reviewed-by: Morten Johan Sørvig --- src/widgets/dialogs/qcolordialog.cpp | 17 +++++++++---- src/widgets/dialogs/qcolordialog_p.h | 5 ++++ src/widgets/dialogs/qdialog.cpp | 44 +++++++++++++++++++++++--------- src/widgets/dialogs/qdialog_p.h | 6 +++++ src/widgets/dialogs/qfiledialog.cpp | 6 ++--- src/widgets/dialogs/qfiledialog_p.h | 49 ++++++++++++++++++++++-------------- src/widgets/dialogs/qfontdialog.cpp | 14 +++++++++-- src/widgets/dialogs/qfontdialog_p.h | 7 ++++++ 8 files changed, 106 insertions(+), 42 deletions(-) (limited to 'src/widgets/dialogs') diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 6b956b1277..1eaaf79bf5 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -1282,6 +1282,8 @@ inline bool QColorDialogPrivate::isAlphaVisible() const { return cs->isAlphaVisi QColor QColorDialogPrivate::currentQColor() const { + if (nativeDialogInUse) + return platformColorDialogHelper()->currentColor_sys(); return cs->currentQColor(); } @@ -1650,6 +1652,13 @@ void QColorDialogPrivate::init(const QColor &initial) q->setCurrentColor(initial); } +void QColorDialogPrivate::initHelper(QPlatformDialogHelper *h) +{ + QColorDialog *d = q_func(); + QObject::connect(h, SIGNAL(currentColorChanged(QColor)), d, SIGNAL(currentColorChanged(QColor))); + QObject::connect(h, SIGNAL(colorSelected(QColor)), d, SIGNAL(colorSelected(QColor))); +} + void QColorDialogPrivate::_q_addCustom() { cusrgb[nextCust] = cs->currentColor(); @@ -1758,8 +1767,8 @@ void QColorDialog::setCurrentColor(const QColor &color) d->setCocoaPanelColor(color); #endif // ### fixme: Call helper - // if (d->nativeDialogInUse) - // qt_guiPlatformPlugin()->colorDialogSetCurrentColor(this, color); + if (d->nativeDialogInUse) + d->platformColorDialogHelper()->setCurrentColor_sys(color); } QColor QColorDialog::currentColor() const @@ -1768,7 +1777,6 @@ QColor QColorDialog::currentColor() const return d->currentQColor(); } - /*! Returns the color that the user selected by clicking the \gui{OK} or equivalent button. @@ -1915,8 +1923,7 @@ void QColorDialog::setVisible(bool visible) #else if (!(d->opts & DontUseNativeDialog)) - if (QPlatformDialogHelper *helper = d->platformHelper()) - d->nativeDialogInUse = helper->setVisible_sys(visible); + d->setNativeDialogVisible(visible); if (d->nativeDialogInUse) { // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below diff --git a/src/widgets/dialogs/qcolordialog_p.h b/src/widgets/dialogs/qcolordialog_p.h index b2413f1418..39d7192b1d 100644 --- a/src/widgets/dialogs/qcolordialog_p.h +++ b/src/widgets/dialogs/qcolordialog_p.h @@ -75,6 +75,9 @@ class QColorDialogPrivate : public QDialogPrivate Q_DECLARE_PUBLIC(QColorDialog) public: + QPlatformColorDialogHelper *platformColorDialogHelper() const + { return static_cast(platformHelper()); } + void init(const QColor &initial); QRgb currentColor() const; QColor currentQColor() const; @@ -133,6 +136,8 @@ public: void _q_macRunNativeAppModalPanel(); void mac_nativeDialogModalHelp(); #endif +private: + virtual void initHelper(QPlatformDialogHelper *h); }; #endif // QT_NO_COLORDIALOG diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index 09c0127852..a0b0cdc564 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -64,16 +64,42 @@ QPlatformDialogHelper *QDialogPrivate::platformHelper() const // Delayed creation of the platform, ensuring that // that qobject_cast<> on the dialog works in the plugin. if (!m_platformHelperCreated) { + QDialogPrivate *ncThis = const_cast(this); m_platformHelperCreated = true; - QDialog *dialog = const_cast(q_func()); m_platformHelper = QGuiApplicationPrivate::platformIntegration() - ->createPlatformDialogHelper(dialog); + ->createPlatformDialogHelper(ncThis->q_func()); if (m_platformHelper) - m_platformHelper->d_ptr = const_cast(this); + ncThis->initHelper(m_platformHelper); } return m_platformHelper; } +QWindow *QDialogPrivate::parentWindow() const +{ + if (const QWidget *parent = q_func()->nativeParentWidget()) + return parent->windowHandle(); + return 0; +} + +bool QDialogPrivate::setNativeDialogVisible(bool visible) +{ + if (QPlatformDialogHelper *helper = platformHelper()) { + if (visible) { + nativeDialogInUse = helper->show_sys(parentWindow()); + } else { + helper->hide_sys(); + } + } + return nativeDialogInUse; +} + +QVariant QDialogPrivate::styleHint(QPlatformDialogHelper::StyleHint hint) const +{ + if (const QPlatformDialogHelper *helper = platformHelper()) + return helper->styleHint(hint); + return QPlatformDialogHelper::defaultStyleHint(hint); +} + /*! \class QDialog \brief The QDialog class is the base class of dialog windows. @@ -705,15 +731,9 @@ void QDialog::setVisible(bool visible) if (d->eventLoop) d->eventLoop->exit(); } -#ifdef Q_WS_WIN - if (d->mainDef && isActiveWindow()) { - BOOL snapToDefault = false; - if (SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0)) { - if (snapToDefault) - QCursor::setPos(d->mainDef->mapToGlobal(d->mainDef->rect().center())); - } - } -#endif + if (d->mainDef && isActiveWindow() + && d->styleHint(QPlatformDialogHelper::SnapToDefaultButton).toBool()) + QCursor::setPos(d->mainDef->mapToGlobal(d->mainDef->rect().center())); } /*!\reimp */ diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h index c88bda7b95..3d90686b6d 100644 --- a/src/widgets/dialogs/qdialog_p.h +++ b/src/widgets/dialogs/qdialog_p.h @@ -80,6 +80,10 @@ public: {} ~QDialogPrivate() { delete m_platformHelper; } + QWindow *parentWindow() const; + bool setNativeDialogVisible(bool visible); + QVariant styleHint(QPlatformDialogHelper::StyleHint hint) const; + QPointer mainDef; Qt::Orientation orientation; QWidget *extension; @@ -110,6 +114,8 @@ public: QPlatformDialogHelper *platformHelper() const; private: + virtual void initHelper(QPlatformDialogHelper *) {} + mutable QPlatformDialogHelper *m_platformHelper; mutable bool m_platformHelperCreated; }; diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 9b7c525c8b..75ba15af87 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -713,8 +713,7 @@ void QFileDialog::setVisible(bool visible) return; if (d->canBeNativeDialog()){ - if (d->setVisible_sys(visible)){ - d->nativeDialogInUse = true; + if (d->setNativeDialogVisible(visible)){ // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below // updates the state correctly, but skips showing the non-native version: setAttribute(Qt::WA_DontShowOnScreen); @@ -723,7 +722,6 @@ void QFileDialog::setVisible(bool visible) d->completer->setModel(0); #endif } else { - d->nativeDialogInUse = false; setAttribute(Qt::WA_DontShowOnScreen, false); #ifndef QT_NO_FSCOMPLETER if (d->proxyModel != 0) @@ -2268,7 +2266,7 @@ void QFileDialogPrivate::createWidgets() Q_Q(QFileDialog); model = new QFileSystemModel(q); model->setObjectName(QLatin1String("qt_filesystem_model")); - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) model->setNameFilterDisables(helper->defaultNameFilterDisables()); else model->setNameFilterDisables(false); diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index 6d4a00e681..383734950c 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -114,6 +114,9 @@ class Q_WIDGETS_EXPORT QFileDialogPrivate : public QDialogPrivate public: QFileDialogPrivate(); + QPlatformFileDialogHelper *platformFileDialogHelper() const + { return static_cast(platformHelper()); } + void createToolButtons(); void createMenuActions(); void createWidgets(); @@ -262,7 +265,6 @@ public: // dialog. Returning false means that a non-native dialog must be // used instead. bool canBeNativeDialog(); - bool setVisible_sys(bool visible); void deleteNativeDialog_sys(); QDialog::DialogCode dialogResultCode_sys(); @@ -289,6 +291,8 @@ public: ~QFileDialogPrivate(); private: + virtual void initHelper(QPlatformDialogHelper *); + Q_DISABLE_COPY(QFileDialogPrivate) }; @@ -344,6 +348,16 @@ private: QFileDialogPrivate *d_ptr; }; +void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h) +{ + QFileDialog *d = q_func(); + QObject::connect(h, SIGNAL(fileSelected(QString)), d, SIGNAL(fileSelected(QString))); + QObject::connect(h, SIGNAL(filesSelected(QStringList)), d, SIGNAL(filesSelected(QStringList))); + QObject::connect(h, SIGNAL(currentChanged(QString)), d, SIGNAL(currentChanged(QString))); + QObject::connect(h, SIGNAL(directoryEntered(QString)), d, SIGNAL(directoryEntered(QString))); + QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString))); +} + inline QModelIndex QFileDialogPrivate::mapToSource(const QModelIndex &index) const { #ifdef QT_NO_PROXYMODEL return index; @@ -366,71 +380,68 @@ inline QString QFileDialogPrivate::rootPath() const { // Dummies for platforms that don't use native dialogs: inline void QFileDialogPrivate::deleteNativeDialog_sys() { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) { helper->deleteNativeDialog_sys(); -} - -inline bool QFileDialogPrivate::setVisible_sys(bool visible) -{ - if (QPlatformDialogHelper *helper = platformHelper()) - return helper->setVisible_sys(visible); - return false; + nativeDialogInUse = false; + } } inline QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys() { + QDialog::DialogCode result = QDialog::Rejected; if (QPlatformDialogHelper *helper = platformHelper()) - return helper->dialogResultCode_sys(); - return QDialog::Rejected; + if (helper->dialogResultCode_sys() == QPlatformDialogHelper::Accepted) + result = QDialog::Accepted; + return result; } inline void QFileDialogPrivate::setDirectory_sys(const QString &directory) { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) helper->setDirectory_sys(directory); } inline QString QFileDialogPrivate::directory_sys() const { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) return helper->directory_sys(); return QString(); } inline void QFileDialogPrivate::selectFile_sys(const QString &filename) { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) helper->selectFile_sys(filename); } inline QStringList QFileDialogPrivate::selectedFiles_sys() const { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) return helper->selectedFiles_sys(); return QStringList(); } inline void QFileDialogPrivate::setFilter_sys() { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) helper->setFilter_sys(); } inline void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters) { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) helper->setNameFilters_sys(filters); } inline void QFileDialogPrivate::selectNameFilter_sys(const QString &filter) { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) helper->selectNameFilter_sys(filter); } inline QString QFileDialogPrivate::selectedNameFilter_sys() const { - if (QPlatformDialogHelper *helper = platformHelper()) + if (QPlatformFileDialogHelper *helper = platformFileDialogHelper()) return helper->selectedNameFilter_sys(); return QString(); } diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp index 1b8a9137ac..1935a5aa73 100644 --- a/src/widgets/dialogs/qfontdialog.cpp +++ b/src/widgets/dialogs/qfontdialog.cpp @@ -490,6 +490,13 @@ bool QFontDialog::eventFilter(QObject *o , QEvent *e) return QDialog::eventFilter(o, e); } +void QFontDialogPrivate::initHelper(QPlatformDialogHelper *h) +{ + QFontDialog *d = q_func(); + QObject::connect(h, SIGNAL(currentFontChanged(QFont)), d, SIGNAL(currentFontChanged(QFont))); + QObject::connect(h, SIGNAL(fontSelected(QFont)), d, SIGNAL(fontSelected(QFont))); +} + /* Updates the contents of the "font family" list box. This function can be reimplemented if you have special requirements. @@ -819,6 +826,8 @@ void QFontDialog::setCurrentFont(const QFont &font) d->strikeout->setChecked(font.strikeOut()); d->underline->setChecked(font.underline()); d->updateFamilies(); + if (QPlatformFontDialogHelper *helper = d->platformFontDialogHelper()) + helper->setCurrentFont_sys(font); #ifdef Q_WS_MAC if (d->delegate) @@ -836,6 +845,8 @@ void QFontDialog::setCurrentFont(const QFont &font) QFont QFontDialog::currentFont() const { Q_D(const QFontDialog); + if (const QPlatformFontDialogHelper *helper = d->platformFontDialogHelper()) + return helper->currentFont_sys(); return d->sampleEdit->font(); } @@ -985,8 +996,7 @@ void QFontDialog::setVisible(bool visible) return; Q_D(QFontDialog); if (d->canBeNativeDialog()) - if (QPlatformDialogHelper *helper = d->platformHelper()) - d->nativeDialogInUse = helper->setVisible_sys(visible); + d->setNativeDialogVisible(visible); if (d->nativeDialogInUse) { // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below // updates the state correctly, but skips showing the non-native version: diff --git a/src/widgets/dialogs/qfontdialog_p.h b/src/widgets/dialogs/qfontdialog_p.h index 8b423f92d8..ef4e933624 100644 --- a/src/widgets/dialogs/qfontdialog_p.h +++ b/src/widgets/dialogs/qfontdialog_p.h @@ -57,6 +57,7 @@ #include "private/qdialog_p.h" #include "qfontdatabase.h" #include "qfontdialog.h" +#include "qplatformdialoghelper_qpa.h" #ifndef QT_NO_FONTDIALOG @@ -80,6 +81,9 @@ public: : writingSystem(QFontDatabase::Any) { } + QPlatformFontDialogHelper *platformFontDialogHelper() const + { return static_cast(platformHelper()); } + void updateFamilies(); void updateStyles(); void updateSizes(); @@ -156,6 +160,9 @@ public: static bool sharedFontPanelAvailable; #endif + +private: + virtual void initHelper(QPlatformDialogHelper *); }; #endif // QT_NO_FONTDIALOG -- cgit v1.2.3