diff options
author | Morten Sorvig <morten.sorvig@nokia.com> | 2011-09-28 09:52:15 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-27 11:12:38 +0200 |
commit | 8f912c5c0f3f89e6f3042c0a948ccd155e57e216 (patch) | |
tree | 8b0ebe25160243e43ef1dc83bc669714779ffb68 /src/widgets/dialogs | |
parent | a94c960b75453ef2eb9dca0be1db426de7a1091d (diff) |
Native file dialog support for Mac
* New API: QPlatformDialogHelper to support native dialog on QPA.
(Currently, It supports only file dialog.)
* Modify QDialog* and QFileDialog* to support native dialog.
* Add native file dialog support to cocoa platform plugin.
Change-Id: I957f046748a27a33fd9f8af3c525feabd1b0f582
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
Diffstat (limited to 'src/widgets/dialogs')
-rw-r--r-- | src/widgets/dialogs/qdialog.cpp | 17 | ||||
-rw-r--r-- | src/widgets/dialogs/qdialog_p.h | 9 | ||||
-rw-r--r-- | src/widgets/dialogs/qfiledialog.cpp | 46 | ||||
-rw-r--r-- | src/widgets/dialogs/qfiledialog.h | 5 | ||||
-rw-r--r-- | src/widgets/dialogs/qfiledialog.ui | 10 | ||||
-rw-r--r-- | src/widgets/dialogs/qfiledialog_mac.mm | 2 | ||||
-rw-r--r-- | src/widgets/dialogs/qfiledialog_p.h | 118 | ||||
-rw-r--r-- | src/widgets/dialogs/qfiledialog_win.cpp | 5 |
8 files changed, 140 insertions, 72 deletions
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index de71e451a7..38609a97ed 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -52,6 +52,7 @@ #include "qmenu.h" #include "qcursor.h" #include "private/qdialog_p.h" +#include "private/qguiapplication_p.h" #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" #endif @@ -251,6 +252,10 @@ QDialog::QDialog(QWidget *parent, Qt::WindowFlags f) : QWidget(*new QDialogPrivate, parent, f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0))) { + Q_D(QDialog); + d->platformHelper = QGuiApplicationPrivate::platformIntegration()->createPlatformDialogHelper(this); + if (d->platformHelper) + d->platformHelper->d_ptr = d_func(); #ifdef Q_WS_WINCE if (!qt_wince_is_smartphone()) setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint)); @@ -265,7 +270,6 @@ QDialog::QDialog(QWidget *parent, Qt::WindowFlags f) #endif } - /*! \overload \internal @@ -361,7 +365,7 @@ void QDialogPrivate::resetModalitySetByOpen() // open() changed the window modality and the user didn't touch it afterwards; restore it q->setWindowModality(Qt::WindowModality(resetModalityTo)); q->setAttribute(Qt::WA_SetWindowModality, wasModalitySet); -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC Q_ASSERT(resetModalityTo != Qt::WindowModal); q->setParent(q->parentWidget(), Qt::Dialog); #endif @@ -449,7 +453,7 @@ void QDialog::open() d->wasModalitySet = testAttribute(Qt::WA_SetWindowModality); setWindowModality(Qt::WindowModal); setAttribute(Qt::WA_SetWindowModality, false); -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC setParent(parentWidget(), Qt::Sheet); #endif } @@ -511,9 +515,8 @@ int QDialog::exec() } show(); -#ifdef Q_WS_MAC - d->mac_nativeDialogModalHelp(); -#endif + if (d->platformHelper) + d->platformHelper->platformNativeDialogModalHelp(); QEventLoop eventLoop; d->eventLoop = &eventLoop; @@ -635,7 +638,7 @@ void QDialog::keyPressEvent(QKeyEvent *e) // Calls reject() if Escape is pressed. Simulates a button // click for the default button if Enter is pressed. Move focus // for the arrow keys. Ignore the rest. -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Period) { reject(); } else diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h index 3ee88f4703..04e0d7401c 100644 --- a/src/widgets/dialogs/qdialog_p.h +++ b/src/widgets/dialogs/qdialog_p.h @@ -58,6 +58,7 @@ #include "QtCore/qpointer.h" #include "QtWidgets/qdialog.h" #include "QtWidgets/qpushbutton.h" +#include "QtWidgets/qplatformdialoghelper_qpa.h" QT_BEGIN_NAMESPACE @@ -74,7 +75,7 @@ public: resizer(0), sizeGripEnabled(false), #endif - rescode(0), resetModalityTo(-1), wasModalitySet(true), eventLoop(0) + rescode(0), resetModalityTo(-1), wasModalitySet(true), eventLoop(0), platformHelper(0) {} QPointer<QPushButton> mainDef; @@ -97,15 +98,13 @@ public: void _q_doneAction(); #endif -#ifdef Q_WS_MAC - virtual void mac_nativeDialogModalHelp() {} -#endif - int rescode; int resetModalityTo; bool wasModalitySet; QPointer<QEventLoop> eventLoop; + + QPlatformDialogHelper *platformHelper; }; QT_END_NAMESPACE diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 22d334a1ec..4c0d50f55b 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -45,6 +45,7 @@ #ifndef QT_NO_FILEDIALOG #include "qfiledialog_p.h" +#include <private/qguiapplication_p.h> #include <qfontmetrics.h> #include <qaction.h> #include <qheaderview.h> @@ -70,6 +71,7 @@ extern bool qt_priv_ptr_valid; #include <pwd.h> #endif #endif +#include "qplatformdialoghelper_qpa.h" QT_BEGIN_NAMESPACE @@ -295,9 +297,9 @@ Q_WIDGETS_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_h This signal is emitted when the user selects a \a filter. */ -#if defined(Q_WS_WIN) || defined(Q_WS_MAC) -bool Q_WIDGETS_EXPORT qt_use_native_dialogs = true; // for the benefit of testing tools, until we have a proper API -#endif +//#if defined(Q_WS_WIN) || defined(Q_WS_MAC) +//bool Q_WIDGETS_EXPORT qt_use_native_dialogs = true; // for the benefit of testing tools, until we have a proper API +//#endif QT_BEGIN_INCLUDE_NAMESPACE #ifdef Q_WS_WIN @@ -400,7 +402,7 @@ QList<QUrl> QFileDialog::sidebarUrls() const static const qint32 QFileDialogMagic = 0xbe; -const char *qt_file_dialog_filter_reg_exp = +const char *QFileDialogPrivate::qt_file_dialog_filter_reg_exp = "^(.*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; /*! @@ -515,9 +517,6 @@ QFileDialogPrivate::QFileDialogPrivate() defaultFileTypes(true), fileNameLabelExplicitlySat(false), nativeDialogInUse(false), -#ifdef Q_WS_MAC - mDelegate(0), -#endif qFileDialogUi(0) { } @@ -1066,7 +1065,7 @@ bool QFileDialog::isNameFilterDetailsVisible() const QStringList qt_strip_filters(const QStringList &filters) { QStringList strippedFilters; - QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp)); + QRegExp r(QString::fromLatin1(QFileDialogPrivate::qt_file_dialog_filter_reg_exp)); for (int i = 0; i < filters.count(); ++i) { QString filterName; int index = r.indexIn(filters[i]); @@ -1361,7 +1360,7 @@ void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode) d->qFileDialogUi->lookInCombo->setEditable(false); } d->retranslateWindowTitle(); -#if defined(Q_WS_MAC) +#if defined(Q_OS_MAC) d->deleteNativeDialog_sys(); setAttribute(Qt::WA_DontShowOnScreen, false); #endif @@ -1761,7 +1760,7 @@ QString QFileDialog::getOpenFileName(QWidget *parent, args.mode = ExistingFile; args.options = options; #if defined(Q_WS_WIN) - if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) { + if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) { return qt_win_get_open_file_name(args, &(args.directory), selectedFilter); } #endif @@ -1854,7 +1853,7 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent, args.options = options; #if defined(Q_WS_WIN) - if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) { + if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) { return qt_win_get_open_file_names(args, &(args.directory), selectedFilter); } #endif @@ -1948,7 +1947,7 @@ QString QFileDialog::getSaveFileName(QWidget *parent, args.options = options; #if defined(Q_WS_WIN) - if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) { + if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog)) { return qt_win_get_save_file_name(args, &(args.directory), selectedFilter); } #endif @@ -2028,7 +2027,7 @@ QString QFileDialog::getExistingDirectory(QWidget *parent, args.options = options; #if defined(Q_WS_WIN) - if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly) + if (QGuiApplicationPrivate::platformIntegration()->usePlatformNativeDialog() && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly) #if defined(Q_WS_WINCE) && qt_priv_ptr_valid #endif @@ -2224,6 +2223,10 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte const QString &caption) { Q_Q(QFileDialog); + platformHelper = QGuiApplicationPrivate::platformIntegration()->createPlatformDialogHelper(q); + if (platformHelper) + platformHelper->d_ptr = this; + if (!caption.isEmpty()) { useDefaultCaption = false; setWindowTitle = caption; @@ -2270,11 +2273,10 @@ void QFileDialogPrivate::createWidgets() Q_Q(QFileDialog); model = new QFileSystemModel(q); model->setObjectName(QLatin1String("qt_filesystem_model")); -#ifdef Q_WS_MAC - model->setNameFilterDisables(true); -#else - model->setNameFilterDisables(false); -#endif + if (platformHelper) + model->setNameFilterDisables(platformHelper->defaultNameFilterDisables()); + else + model->setNameFilterDisables(false); model->d_func()->disableRecursiveSort = true; QFileDialog::connect(model, SIGNAL(fileRenamed(QString,QString,QString)), q, SLOT(_q_fileRenamed(QString,QString,QString))); QFileDialog::connect(model, SIGNAL(rootPathChanged(QString)), @@ -3013,7 +3015,7 @@ void QFileDialogPrivate::_q_goToDirectory(const QString &path) } // Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)" -QStringList qt_clean_filter_list(const QString &filter) +QStringList QFileDialogPrivate::qt_clean_filter_list(const QString &filter) { QRegExp regexp(QString::fromLatin1(qt_file_dialog_filter_reg_exp)); QString f = filter; @@ -3126,6 +3128,12 @@ void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldNa } } +void QFileDialogPrivate::_q_platformRunNativeAppModalPanel() +{ + if (platformHelper) + platformHelper->_q_platformRunNativeAppModalPanel(); +} + /*! \internal diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index e27b655ba1..df33fdb265 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -261,9 +261,8 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex & parent)) Q_PRIVATE_SLOT(d_func(), void _q_fileRenamed(const QString &path, const QString oldName, const QString newName)) -#if defined(Q_WS_MAC) - Q_PRIVATE_SLOT(d_func(), void _q_macRunNativeAppModalPanel()) -#endif + Q_PRIVATE_SLOT(d_func(), void _q_platformRunNativeAppModalPanel()) + friend class QPlatformDialogHelper; }; inline void QFileDialog::setDirectory(const QDir &adirectory) diff --git a/src/widgets/dialogs/qfiledialog.ui b/src/widgets/dialogs/qfiledialog.ui index 01a49f975e..9d61de351f 100644 --- a/src/widgets/dialogs/qfiledialog.ui +++ b/src/widgets/dialogs/qfiledialog.ui @@ -313,27 +313,27 @@ <customwidget> <class>QFileDialogTreeView</class> <extends>QTreeView</extends> - <header>qfiledialog_p.h</header> + <header>private/qfiledialog_p.h</header> </customwidget> <customwidget> <class>QFileDialogListView</class> <extends>QListView</extends> - <header>qfiledialog_p.h</header> + <header>private/qfiledialog_p.h</header> </customwidget> <customwidget> <class>QSidebar</class> <extends>QListWidget</extends> - <header>qsidebar_p.h</header> + <header>private/qsidebar_p.h</header> </customwidget> <customwidget> <class>QFileDialogLineEdit</class> <extends>QLineEdit</extends> - <header>qfiledialog_p.h</header> + <header>private/qfiledialog_p.h</header> </customwidget> <customwidget> <class>QFileDialogComboBox</class> <extends>QComboBox</extends> - <header>qfiledialog_p.h</header> + <header>private/qfiledialog_p.h</header> </customwidget> </customwidgets> <tabstops> diff --git a/src/widgets/dialogs/qfiledialog_mac.mm b/src/widgets/dialogs/qfiledialog_mac.mm index 62654f5a0e..1a9f36892d 100644 --- a/src/widgets/dialogs/qfiledialog_mac.mm +++ b/src/widgets/dialogs/qfiledialog_mac.mm @@ -703,7 +703,7 @@ bool QFileDialogPrivate::hideCocoaFilePanel() } -void QFileDialogPrivate::mac_nativeDialogModalHelp() +void QFileDialogPrivate::platformNativeDialogModalHelp() { // Do a queued meta-call to open the native modal dialog so it opens after the new // event loop has started to execute (in QDialog::exec). Using a timer rather than diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h index def25f9b14..4de970d4b2 100644 --- a/src/widgets/dialogs/qfiledialog_p.h +++ b/src/widgets/dialogs/qfiledialog_p.h @@ -92,7 +92,7 @@ class QGridLayout; class QCompleter; class QHBoxLayout; class Ui_QFileDialog; - +class QPlatformDialogHelper; struct QFileDialogArgs { @@ -109,7 +109,7 @@ struct QFileDialogArgs #define UrlRole (Qt::UserRole + 1) -class Q_AUTOTEST_EXPORT QFileDialogPrivate : public QDialogPrivate +class Q_WIDGETS_EXPORT QFileDialogPrivate : public QDialogPrivate { Q_DECLARE_PUBLIC(QFileDialog) @@ -223,6 +223,10 @@ public: void _q_autoCompleteFileName(const QString &); void _q_rowsInserted(const QModelIndex & parent); void _q_fileRenamed(const QString &path, const QString oldName, const QString newName); + void _q_platformRunNativeAppModalPanel(); + + static QStringList qt_clean_filter_list(const QString &filter); + static const char *qt_file_dialog_filter_reg_exp; // layout #ifndef QT_NO_PROXYMODEL @@ -276,19 +280,6 @@ public: QString selectedNameFilter_sys() const; ////////////////////////////////////////////// -#if defined(Q_WS_MAC) - void *mDelegate; - bool showCocoaFilePanel(); - bool hideCocoaFilePanel(); - void createNSOpenSavePanelDelegate(); - void QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath); - void QNSOpenSavePanelDelegate_panelClosed(bool accepted); - void QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir); - void QNSOpenSavePanelDelegate_filterSelected(int menuIndex); - void _q_macRunNativeAppModalPanel(); - void mac_nativeDialogModalHelp(); -#endif - QScopedPointer<Ui_QFileDialog> qFileDialogUi; QString acceptLabel; @@ -376,20 +367,89 @@ inline QString QFileDialogPrivate::rootPath() const { return model->rootPath(); } -#ifndef Q_WS_MAC - // Dummies for platforms that don't use native dialogs: - inline void QFileDialogPrivate::deleteNativeDialog_sys() { qt_guiPlatformPlugin()->fileDialogDelete(q_func()); } - inline bool QFileDialogPrivate::setVisible_sys(bool visible) { return qt_guiPlatformPlugin()->fileDialogSetVisible(q_func(), visible); } - inline QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys(){ return qt_guiPlatformPlugin()->fileDialogResultCode(q_func()); } - inline void QFileDialogPrivate::setDirectory_sys(const QString &directory) { qt_guiPlatformPlugin()->fileDialogSetDirectory(q_func(), directory); } - inline QString QFileDialogPrivate::directory_sys() const { return qt_guiPlatformPlugin()->fileDialogDirectory(q_func()); } - inline void QFileDialogPrivate::selectFile_sys(const QString &filename) { qt_guiPlatformPlugin()->fileDialogSelectFile(q_func(), filename); } - inline QStringList QFileDialogPrivate::selectedFiles_sys() const { return qt_guiPlatformPlugin()->fileDialogSelectedFiles(q_func()); } - inline void QFileDialogPrivate::setFilter_sys() { qt_guiPlatformPlugin()->fileDialogSetFilter(q_func()); } - inline void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters) { qt_guiPlatformPlugin()->fileDialogSetNameFilters(q_func(), filters); } - inline void QFileDialogPrivate::selectNameFilter_sys(const QString &filter) { qt_guiPlatformPlugin()->fileDialogSelectNameFilter(q_func(), filter); } - inline QString QFileDialogPrivate::selectedNameFilter_sys() const { return qt_guiPlatformPlugin()->fileDialogSelectedNameFilter(q_func()); } -#endif +// Dummies for platforms that don't use native dialogs: +inline void QFileDialogPrivate::deleteNativeDialog_sys() +{ + if (platformHelper) + platformHelper->deleteNativeDialog_sys(); + else + qt_guiPlatformPlugin()->fileDialogDelete(q_func()); +} + +inline bool QFileDialogPrivate::setVisible_sys(bool visible) +{ + if (platformHelper) + return platformHelper->setVisible_sys(visible); + return qt_guiPlatformPlugin()->fileDialogSetVisible(q_func(), visible); +} + +inline QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys() +{ + if (platformHelper) + return platformHelper->dialogResultCode_sys(); + return qt_guiPlatformPlugin()->fileDialogResultCode(q_func()); +} + +inline void QFileDialogPrivate::setDirectory_sys(const QString &directory) +{ + if (platformHelper) + platformHelper->setDirectory_sys(directory); + else + qt_guiPlatformPlugin()->fileDialogSetDirectory(q_func(), directory); +} + +inline QString QFileDialogPrivate::directory_sys() const +{ + if (platformHelper) + return platformHelper->directory_sys(); + return qt_guiPlatformPlugin()->fileDialogDirectory(q_func()); +} + +inline void QFileDialogPrivate::selectFile_sys(const QString &filename) +{ + if (platformHelper) + platformHelper->selectFile_sys(filename); + else + qt_guiPlatformPlugin()->fileDialogSelectFile(q_func(), filename); +} + +inline QStringList QFileDialogPrivate::selectedFiles_sys() const +{ + if (platformHelper) + return platformHelper->selectedFiles_sys(); + return qt_guiPlatformPlugin()->fileDialogSelectedFiles(q_func()); +} + +inline void QFileDialogPrivate::setFilter_sys() +{ + if (platformHelper) + platformHelper->setFilter_sys(); + else + qt_guiPlatformPlugin()->fileDialogSetFilter(q_func()); +} + +inline void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters) +{ + if (platformHelper) + platformHelper->setNameFilters_sys(filters); + else + qt_guiPlatformPlugin()->fileDialogSetNameFilters(q_func(), filters); +} + +inline void QFileDialogPrivate::selectNameFilter_sys(const QString &filter) +{ + if (platformHelper) + platformHelper->selectNameFilter_sys(filter); + else + qt_guiPlatformPlugin()->fileDialogSelectNameFilter(q_func(), filter); +} + +inline QString QFileDialogPrivate::selectedNameFilter_sys() const +{ + if (platformHelper) + return platformHelper->selectedNameFilter_sys(); + return qt_guiPlatformPlugin()->fileDialogSelectedNameFilter(q_func()); +} QT_END_NAMESPACE diff --git a/src/widgets/dialogs/qfiledialog_win.cpp b/src/widgets/dialogs/qfiledialog_win.cpp index 8c3b3cfda7..390e13183c 100644 --- a/src/widgets/dialogs/qfiledialog_win.cpp +++ b/src/widgets/dialogs/qfiledialog_win.cpp @@ -116,7 +116,6 @@ static void qt_win_resolve_libs() } } -extern const char* qt_file_dialog_filter_reg_exp; // defined in qfiledialog.cpp extern QStringList qt_make_filter_list(const QString &filter); const int maxNameLen = 1023; @@ -126,7 +125,7 @@ const int maxMultiLen = 65535; static QString qt_win_extract_filter(const QString &rawFilter) { QString result = rawFilter; - QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp)); + QRegExp r(QString::fromLatin1(QFileDialogPrivate::qt_file_dialog_filter_reg_exp)); int index = r.indexIn(result); if (index >= 0) result = r.cap(2); @@ -156,7 +155,7 @@ static QString qt_win_filter(const QString &filter, bool hideFiltersDetails) QStringList filterLst = qt_win_make_filters_list(filter); QStringList::Iterator it = filterLst.begin(); QString winfilters; - QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp)); + QRegExp r(QString::fromLatin1(QFileDialogPrivate::qt_file_dialog_filter_reg_exp)); for (; it != filterLst.end(); ++it) { QString subfilter = *it; if (!subfilter.isEmpty()) { |