summaryrefslogtreecommitdiffstats
path: root/src/widgets/dialogs/qfiledialog_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/dialogs/qfiledialog_mac.mm')
-rw-r--r--src/widgets/dialogs/qfiledialog_mac.mm1157
1 files changed, 1157 insertions, 0 deletions
diff --git a/src/widgets/dialogs/qfiledialog_mac.mm b/src/widgets/dialogs/qfiledialog_mac.mm
new file mode 100644
index 0000000000..832f9bfaf8
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog_mac.mm
@@ -0,0 +1,1157 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfiledialog.h"
+
+#ifndef QT_NO_FILEDIALOG
+
+/*****************************************************************************
+ QFileDialog debug facilities
+ *****************************************************************************/
+//#define DEBUG_FILEDIALOG_FILTERS
+
+#include <qapplication.h>
+#include <private/qapplication_p.h>
+#include <private/qfiledialog_p.h>
+#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <qregexp.h>
+#include <qbuffer.h>
+#include <qdebug.h>
+#include <qstringlist.h>
+#include <qaction.h>
+#include <qtextcodec.h>
+#include <qvarlengtharray.h>
+#include <qdesktopwidget.h>
+#include <stdlib.h>
+#include <qabstracteventdispatcher.h>
+#import <AppKit/NSSavePanel.h>
+#include "ui_qfiledialog.h"
+
+QT_BEGIN_NAMESPACE
+
+extern QStringList qt_make_filter_list(const QString &filter); // qfiledialog.cpp
+extern QStringList qt_clean_filter_list(const QString &filter); // qfiledialog.cpp
+extern const char *qt_file_dialog_filter_reg_exp; // qfiledialog.cpp
+extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
+
+QT_END_NAMESPACE
+
+QT_FORWARD_DECLARE_CLASS(QFileDialogPrivate)
+QT_FORWARD_DECLARE_CLASS(QString)
+QT_FORWARD_DECLARE_CLASS(QStringList)
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_FORWARD_DECLARE_CLASS(QAction)
+QT_FORWARD_DECLARE_CLASS(QFileInfo)
+QT_USE_NAMESPACE
+
+@class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate);
+
+@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ : NSObject<NSOpenSavePanelDelegate>
+#else
+ : NSObject
+#endif
+{
+ @public
+ NSOpenPanel *mOpenPanel;
+ NSSavePanel *mSavePanel;
+ NSView *mAccessoryView;
+ NSPopUpButton *mPopUpButton;
+ NSTextField *mTextField;
+ QFileDialogPrivate *mPriv;
+ NSString *mCurrentDir;
+ bool mConfirmOverwrite;
+ int mReturnCode;
+
+ QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode) mAcceptMode;
+ QT_PREPEND_NAMESPACE(QDir::Filters) *mQDirFilter;
+ QT_PREPEND_NAMESPACE(QFileDialog::FileMode) mFileMode;
+ QT_PREPEND_NAMESPACE(QFileDialog::Options) *mFileOptions;
+
+ QString *mLastFilterCheckPath;
+ QString *mCurrentSelection;
+ QStringList *mQDirFilterEntryList;
+ QStringList *mNameFilterDropDownList;
+ QStringList *mSelectedNameFilter;
+}
+
+- (NSString *)strip:(const QString &)label;
+- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
+- (void)filterChanged:(id)sender;
+- (void)showModelessPanel;
+- (BOOL)runApplicationModalPanel;
+- (void)showWindowModalSheet:(QWidget *)docWidget;
+- (void)updateProperties;
+- (QStringList)acceptableExtensionsForSave;
+- (QString)removeExtensions:(const QString &)filter;
+- (void)createTextField;
+- (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails;
+- (QStringList)findStrippedFilterWithVisualFilterName:(QString)name;
+- (void)createAccessory;
+
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
+
+- (id)initWithAcceptMode:(QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode))acceptMode
+ title:(const QString &)title
+ hideNameFilterDetails:(bool)hideNameFilterDetails
+ qDirFilter:(QT_PREPEND_NAMESPACE(QDir::Filters))qDirFilter
+ fileOptions:(QT_PREPEND_NAMESPACE(QFileDialog::Options))fileOptions
+ fileMode:(QT_PREPEND_NAMESPACE(QFileDialog::FileMode))fileMode
+ selectFile:(const QString &)selectFile
+ confirmOverwrite:(bool)confirm
+ priv:(QFileDialogPrivate *)priv
+{
+ self = [super init];
+
+ mAcceptMode = acceptMode;
+ if (mAcceptMode == QT_PREPEND_NAMESPACE(QFileDialog::AcceptOpen)){
+ mOpenPanel = [NSOpenPanel openPanel];
+ mSavePanel = mOpenPanel;
+ } else {
+ mSavePanel = [NSSavePanel savePanel];
+ mOpenPanel = 0;
+ }
+
+ [mSavePanel setLevel:NSModalPanelWindowLevel];
+ [mSavePanel setDelegate:self];
+ mQDirFilter = new QT_PREPEND_NAMESPACE(QDir::Filters)(qDirFilter);
+ mFileOptions = new QT_PREPEND_NAMESPACE(QFileDialog::Options)(fileOptions);
+ mFileMode = fileMode;
+ mConfirmOverwrite = confirm;
+ mReturnCode = -1;
+ mPriv = priv;
+ mLastFilterCheckPath = new QString;
+ mQDirFilterEntryList = new QStringList;
+ mNameFilterDropDownList = new QStringList(priv->nameFilters);
+ QString selectedVisualNameFilter = priv->qFileDialogUi->fileTypeCombo->currentText();
+ mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]);
+
+ QFileInfo sel(selectFile);
+ if (sel.isDir()){
+ mCurrentDir = [qt_mac_QStringToNSString(sel.absoluteFilePath()) retain];
+ mCurrentSelection = new QString;
+ } else {
+ mCurrentDir = [qt_mac_QStringToNSString(sel.absolutePath()) retain];
+ mCurrentSelection = new QString(sel.absoluteFilePath());
+ }
+
+ [mSavePanel setTitle:qt_mac_QStringToNSString(title)];
+ [self createPopUpButton:selectedVisualNameFilter hideDetails:hideNameFilterDetails];
+ [self createTextField];
+ [self createAccessory];
+ [mSavePanel setAccessoryView:mNameFilterDropDownList->size() > 1 ? mAccessoryView : nil];
+
+ if (mPriv){
+ [mSavePanel setPrompt:[self strip:mPriv->acceptLabel]];
+ if (mPriv->fileNameLabelExplicitlySat)
+ [mSavePanel setNameFieldLabel:[self strip:mPriv->qFileDialogUi->fileNameLabel->text()]];
+ }
+
+ [self updateProperties];
+ [mSavePanel retain];
+ return self;
+}
+
+- (void)dealloc
+{
+ delete mQDirFilter;
+ delete mFileOptions;
+ delete mLastFilterCheckPath;
+ delete mQDirFilterEntryList;
+ delete mNameFilterDropDownList;
+ delete mSelectedNameFilter;
+ delete mCurrentSelection;
+
+ [mSavePanel orderOut:mSavePanel];
+ [mSavePanel setAccessoryView:nil];
+ [mPopUpButton release];
+ [mTextField release];
+ [mAccessoryView release];
+ [mSavePanel setDelegate:nil];
+ [mSavePanel release];
+ [mCurrentDir release];
+ [super dealloc];
+}
+
+- (NSString *)strip:(const QString &)label
+{
+ QAction a(label, 0);
+ return qt_mac_QStringToNSString(a.iconText());
+}
+
+- (void)closePanel
+{
+ *mCurrentSelection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
+ [mSavePanel close];
+}
+
+- (void)showModelessPanel
+{
+ if (mOpenPanel){
+ QFileInfo info(*mCurrentSelection);
+ NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
+ NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
+ bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
+ || [self panel:nil shouldShowFilename:filepath];
+ [mOpenPanel
+ beginForDirectory:mCurrentDir
+ file:selectable ? filename : nil
+ types:nil
+ modelessDelegate:self
+ didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
+ contextInfo:nil];
+ }
+}
+
+- (BOOL)runApplicationModalPanel
+{
+ QFileInfo info(*mCurrentSelection);
+ NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
+ NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
+ bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
+ || [self panel:nil shouldShowFilename:filepath];
+ mReturnCode = [mSavePanel
+ runModalForDirectory:mCurrentDir
+ file:selectable ? filename : @"untitled"];
+
+ QAbstractEventDispatcher::instance()->interrupt();
+ return (mReturnCode == NSOKButton);
+}
+
+- (QT_PREPEND_NAMESPACE(QDialog::DialogCode))dialogResultCode
+{
+ return (mReturnCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QDialog::Accepted) : QT_PREPEND_NAMESPACE(QDialog::Rejected);
+}
+
+- (void)showWindowModalSheet:(QWidget *)docWidget
+{
+ Q_UNUSED(docWidget);
+ QFileInfo info(*mCurrentSelection);
+ NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
+ NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
+ bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
+ || [self panel:nil shouldShowFilename:filepath];
+ [mSavePanel
+ beginSheetForDirectory:mCurrentDir
+ file:selectable ? filename : nil
+#ifdef QT_MAC_USE_COCOA
+ modalForWindow:QT_PREPEND_NAMESPACE(qt_mac_window_for)(docWidget)
+#else
+ modalForWindow:nil
+#endif
+ modalDelegate:self
+ didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
+ contextInfo:nil];
+}
+
+- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
+{
+ Q_UNUSED(sender);
+
+ if ([filename length] == 0)
+ return NO;
+
+ // Always accept directories regardless of their names (unless it is a bundle):
+ BOOL isDir;
+ if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir) {
+ if ([mSavePanel treatsFilePackagesAsDirectories] == NO) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
+ return YES;
+ }
+ }
+
+ QString qtFileName = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(filename);
+ QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C)));
+ QString path = info.absolutePath();
+ if (path != *mLastFilterCheckPath){
+ *mLastFilterCheckPath = path;
+ *mQDirFilterEntryList = info.dir().entryList(*mQDirFilter);
+ }
+ // Check if the QDir filter accepts the file:
+ if (!mQDirFilterEntryList->contains(info.fileName()))
+ return NO;
+
+ // No filter means accept everything
+ if (mSelectedNameFilter->isEmpty())
+ return YES;
+ // Check if the current file name filter accepts the file:
+ for (int i=0; i<mSelectedNameFilter->size(); ++i) {
+ if (QDir::match(mSelectedNameFilter->at(i), qtFileName))
+ return YES;
+ }
+ return NO;
+}
+
+- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
+{
+ Q_UNUSED(sender);
+ if (!okFlag)
+ return filename;
+ if (mConfirmOverwrite)
+ return filename;
+
+ // User has clicked save, and no overwrite confirmation should occur.
+ // To get the latter, we need to change the name we return (hence the prefix):
+ return [@"___qt_very_unlikely_prefix_" stringByAppendingString:filename];
+}
+
+- (void)setNameFilters:(const QStringList &)filters hideDetails:(BOOL)hideDetails
+{
+ [mPopUpButton removeAllItems];
+ *mNameFilterDropDownList = filters;
+ if (filters.size() > 0){
+ for (int i=0; i<filters.size(); ++i) {
+ QString filter = hideDetails ? [self removeExtensions:filters.at(i)] : filters.at(i);
+ [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
+ }
+ [mPopUpButton selectItemAtIndex:0];
+ [mSavePanel setAccessoryView:mAccessoryView];
+ } else
+ [mSavePanel setAccessoryView:nil];
+
+ [self filterChanged:self];
+}
+
+- (void)filterChanged:(id)sender
+{
+ // This mDelegate function is called when the _name_ filter changes.
+ Q_UNUSED(sender);
+ QString selection = mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
+ *mSelectedNameFilter = [self findStrippedFilterWithVisualFilterName:selection];
+ [mSavePanel validateVisibleColumns];
+ [self updateProperties];
+ if (mPriv)
+ mPriv->QNSOpenSavePanelDelegate_filterSelected([mPopUpButton indexOfSelectedItem]);
+}
+
+- (QString)currentNameFilter
+{
+ return mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
+}
+
+- (QStringList)selectedFiles
+{
+ if (mOpenPanel)
+ return QT_PREPEND_NAMESPACE(qt_mac_NSArrayToQStringList)([mOpenPanel filenames]);
+ else{
+ QStringList result;
+ QString filename = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
+ result << filename.remove(QLatin1String("___qt_very_unlikely_prefix_"));
+ return result;
+ }
+}
+
+- (void)updateProperties
+{
+ // Call this functions if mFileMode, mFileOptions,
+ // mNameFilterDropDownList or mQDirFilter changes.
+ // The savepanel does not contain the neccessary functions for this.
+ bool chooseFilesOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFile)
+ || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles);
+ bool chooseDirsOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::Directory)
+ || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::DirectoryOnly)
+ || *mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ShowDirsOnly);
+
+ [mOpenPanel setCanChooseFiles:!chooseDirsOnly];
+ [mOpenPanel setCanChooseDirectories:!chooseFilesOnly];
+ [mSavePanel setCanCreateDirectories:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ReadOnly))];
+ [mOpenPanel setAllowsMultipleSelection:(mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles))];
+ [mOpenPanel setResolvesAliases:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::DontResolveSymlinks))];
+
+ QStringList ext = [self acceptableExtensionsForSave];
+ if (mPriv && !ext.isEmpty() && !mPriv->defaultSuffix.isEmpty())
+ ext.prepend(mPriv->defaultSuffix);
+ [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : QT_PREPEND_NAMESPACE(qt_mac_QStringListToNSMutableArray(ext))];
+
+ if ([mSavePanel isVisible])
+ [mOpenPanel validateVisibleColumns];
+}
+
+- (void)panelSelectionDidChange:(id)sender
+{
+ Q_UNUSED(sender);
+ if (mPriv) {
+ QString selection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString([mSavePanel filename]));
+ if (selection != mCurrentSelection) {
+ *mCurrentSelection = selection;
+ mPriv->QNSOpenSavePanelDelegate_selectionChanged(selection);
+ }
+ }
+}
+
+- (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ Q_UNUSED(panel);
+ Q_UNUSED(contextInfo);
+ mReturnCode = returnCode;
+ if (mPriv)
+ mPriv->QNSOpenSavePanelDelegate_panelClosed(returnCode == NSOKButton);
+}
+
+- (void)panel:(id)sender directoryDidChange:(NSString *)path
+{
+ Q_UNUSED(sender);
+ if (!mPriv)
+ return;
+ if ([path isEqualToString:mCurrentDir])
+ return;
+
+ [mCurrentDir release];
+ mCurrentDir = [path retain];
+ mPriv->QNSOpenSavePanelDelegate_directoryEntered(QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString(mCurrentDir)));
+}
+
+/*
+ Returns a list of extensions (e.g. "png", "jpg", "gif")
+ for the current name filter. If a filter do not conform
+ to the format *.xyz or * or *.*, an empty list
+ is returned meaning accept everything.
+*/
+- (QStringList)acceptableExtensionsForSave
+{
+ QStringList result;
+ for (int i=0; i<mSelectedNameFilter->count(); ++i) {
+ const QString &filter = mSelectedNameFilter->at(i);
+ if (filter.startsWith(QLatin1String("*."))
+ && !filter.contains(QLatin1Char('?'))
+ && filter.count(QLatin1Char('*')) == 1) {
+ result += filter.mid(2);
+ } else {
+ return QStringList(); // Accept everything
+ }
+ }
+ return result;
+}
+
+- (QString)removeExtensions:(const QString &)filter
+{
+ QRegExp regExp(QT_PREPEND_NAMESPACE(QString::fromLatin1)(QT_PREPEND_NAMESPACE(qt_file_dialog_filter_reg_exp)));
+ if (regExp.indexIn(filter) != -1)
+ return regExp.cap(1).trimmed();
+ return filter;
+}
+
+- (void)createTextField
+{
+ NSRect textRect = { { 0.0, 3.0 }, { 100.0, 25.0 } };
+ mTextField = [[NSTextField alloc] initWithFrame:textRect];
+ [[mTextField cell] setFont:[NSFont systemFontOfSize:
+ [NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
+ [mTextField setAlignment:NSRightTextAlignment];
+ [mTextField setEditable:false];
+ [mTextField setSelectable:false];
+ [mTextField setBordered:false];
+ [mTextField setDrawsBackground:false];
+ if (mPriv){
+ [mTextField setStringValue:[self strip:mPriv->qFileDialogUi->fileTypeLabel->text()]];
+ } else
+ [mTextField setStringValue:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(QT_PREPEND_NAMESPACE(QFileDialog::tr)("Files of type:"))];
+}
+
+- (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails
+{
+ NSRect popUpRect = { { 100.0, 5.0 }, { 250.0, 25.0 } };
+ mPopUpButton = [[NSPopUpButton alloc] initWithFrame:popUpRect pullsDown:NO];
+ [mPopUpButton setTarget:self];
+ [mPopUpButton setAction:@selector(filterChanged:)];
+
+ QStringList *filters = mNameFilterDropDownList;
+ if (filters->size() > 0){
+ for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
+ QString filter = hideDetails ? [self removeExtensions:filters->at(i)] : filters->at(i);
+ [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
+ if (filters->at(i).startsWith(selectedFilter))
+ [mPopUpButton selectItemAtIndex:i];
+ }
+ }
+}
+
+- (QStringList) findStrippedFilterWithVisualFilterName:(QString)name
+{
+ for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
+ if (mNameFilterDropDownList->at(i).startsWith(name))
+ return qt_clean_filter_list(mNameFilterDropDownList->at(i));
+ }
+ return QStringList();
+}
+
+- (void)createAccessory
+{
+ NSRect accessoryRect = { { 0.0, 0.0 }, { 450.0, 33.0 } };
+ mAccessoryView = [[NSView alloc] initWithFrame:accessoryRect];
+ [mAccessoryView addSubview:mTextField];
+ [mAccessoryView addSubview:mPopUpButton];
+}
+
+@end
+
+QT_BEGIN_NAMESPACE
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath)
+{
+ emit q_func()->currentChanged(newPath);
+}
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_panelClosed(bool accepted)
+{
+ if (accepted)
+ q_func()->accept();
+ else
+ q_func()->reject();
+}
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir)
+{
+ setLastVisitedDirectory(newDir);
+ emit q_func()->directoryEntered(newDir);
+}
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_filterSelected(int menuIndex)
+{
+ emit q_func()->filterSelected(nameFilters.at(menuIndex));
+}
+
+extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp
+extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp
+
+void QFileDialogPrivate::setDirectory_sys(const QString &directory)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (directory == mCurrentLocation)
+ return;
+ mCurrentLocation = directory;
+ emit q_func()->directoryEntered(mCurrentLocation);
+
+ FSRef fsRef;
+ if (qt_mac_create_fsref(directory, &fsRef) == noErr) {
+ AEDesc desc;
+ if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr)
+ NavCustomControl(mDialog, kNavCtlSetLocation, (void*)&desc);
+ }
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate->mSavePanel setDirectory:qt_mac_QStringToNSString(directory)];
+#endif
+}
+
+QString QFileDialogPrivate::directory_sys() const
+{
+#ifndef QT_MAC_USE_COCOA
+ return mCurrentLocation;
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ return qt_mac_NSStringToQString([delegate->mSavePanel directory]);
+#endif
+}
+
+void QFileDialogPrivate::selectFile_sys(const QString &filename)
+{
+ QString filePath = filename;
+ if (QDir::isRelativePath(filePath))
+ filePath = QFileInfo(directory_sys(), filePath).filePath();
+
+#ifndef QT_MAC_USE_COCOA
+ // Update the selection list immidiatly, so
+ // subsequent calls to selectedFiles() gets correct:
+ mCurrentSelectionList.clear();
+ mCurrentSelectionList << filename;
+ if (mCurrentSelection != filename){
+ mCurrentSelection = filename;
+ emit q_func()->currentChanged(mCurrentSelection);
+ }
+
+ AEDescList descList;
+ if (AECreateList(0, 0, false, &descList) != noErr)
+ return;
+
+ FSRef fsRef;
+ if (qt_mac_create_fsref(filePath, &fsRef) == noErr) {
+ AEDesc desc;
+ if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr){
+ if (AEPutDesc(&descList, 0, &desc) == noErr)
+ NavCustomControl(mDialog, kNavCtlSetSelection, (void*)&descList);
+ }
+ }
+
+ // Type the file name into the save dialog's text field:
+ UInt8 *strBuffer = (UInt8 *)malloc(1024);
+ qt_mac_to_pascal_string(QFileInfo(filename).fileName(), strBuffer);
+ NavCustomControl(mDialog, kNavCtlSetEditFileName, strBuffer);
+ free(strBuffer);
+#else
+ // There seems to no way to select a file once the dialog is running.
+ // So do the next best thing, set the file's directory:
+ setDirectory_sys(QFileInfo(filePath).absolutePath());
+#endif
+}
+
+QStringList QFileDialogPrivate::selectedFiles_sys() const
+{
+#ifndef QT_MAC_USE_COCOA
+ if (q_func()->acceptMode() == QFileDialog::AcceptOpen){
+ return mCurrentSelectionList;
+ } else {
+ return QStringList() << mCurrentLocation + QLatin1Char('/')
+ + QCFString::toQString(NavDialogGetSaveFileName(mDialog));
+ }
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ return [delegate selectedFiles];
+#endif
+}
+
+void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(filters);
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ bool hideDetails = q_func()->testOption(QFileDialog::HideNameFilterDetails);
+ [delegate setNameFilters:filters hideDetails:hideDetails];
+#endif
+}
+
+void QFileDialogPrivate::setFilter_sys()
+{
+#ifndef QT_MAC_USE_COCOA
+#else
+ Q_Q(QFileDialog);
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ *(delegate->mQDirFilter) = model->filter();
+ delegate->mFileMode = fileMode;
+ [delegate->mSavePanel setTitle:qt_mac_QStringToNSString(q->windowTitle())];
+ [delegate->mSavePanel setPrompt:[delegate strip:acceptLabel]];
+ if (fileNameLabelExplicitlySat)
+ [delegate->mSavePanel setNameFieldLabel:[delegate strip:qFileDialogUi->fileNameLabel->text()]];
+
+ [delegate updateProperties];
+#endif
+}
+
+void QFileDialogPrivate::selectNameFilter_sys(const QString &filter)
+{
+ int index = nameFilters.indexOf(filter);
+ if (index != -1) {
+#ifndef QT_MAC_USE_COCOA
+ NavMenuItemSpec navSpec;
+ bzero(&navSpec, sizeof(NavMenuItemSpec));
+ navSpec.menuType = index;
+ NavCustomControl(mDialog, kNavCtlSelectCustomType, &navSpec);
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate->mPopUpButton selectItemAtIndex:index];
+ [delegate filterChanged:nil];
+#endif
+ }
+}
+
+QString QFileDialogPrivate::selectedNameFilter_sys() const
+{
+#ifndef QT_MAC_USE_COCOA
+ int index = filterInfo.currentSelection;
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ int index = [delegate->mPopUpButton indexOfSelectedItem];
+#endif
+ return index != -1 ? nameFilters.at(index) : QString();
+}
+
+void QFileDialogPrivate::deleteNativeDialog_sys()
+{
+#ifndef QT_MAC_USE_COCOA
+ if (mDialog)
+ NavDialogDispose(mDialog);
+ mDialog = 0;
+ mDialogStarted = false;
+#else
+ QMacCocoaAutoReleasePool pool;
+ [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate) release];
+ mDelegate = 0;
+#endif
+ nativeDialogInUse = false;
+}
+
+bool QFileDialogPrivate::setVisible_sys(bool visible)
+{
+ Q_Q(QFileDialog);
+ if (!visible == q->isHidden())
+ return false;
+
+ if (q->windowFlags() & Qt::WindowStaysOnTopHint) {
+ // The native file dialog tries all it can to stay
+ // on the NSModalPanel level. And it might also show
+ // its own "create directory" dialog that we cannot control.
+ // So we need to use the non-native version in this case...
+ return false;
+ }
+
+#ifndef QT_MAC_USE_COCOA
+ return visible ? showCarbonNavServicesDialog() : hideCarbonNavServicesDialog();
+#else
+ return visible ? showCocoaFilePanel() : hideCocoaFilePanel();
+#endif
+}
+
+#ifndef QT_MAC_USE_COCOA
+Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void *info,
+ void *data, NavFilterModes)
+{
+ QFileDialogPrivate *fileDialogPrivate = static_cast<QFileDialogPrivate *>(data);
+
+ if (!fileDialogPrivate || fileDialogPrivate->filterInfo.filters.isEmpty()
+ || (fileDialogPrivate->filterInfo.currentSelection < 0
+ && fileDialogPrivate->filterInfo.currentSelection
+ >= fileDialogPrivate->filterInfo.filters.size()))
+ return true;
+
+ NavFileOrFolderInfo *theInfo = static_cast<NavFileOrFolderInfo *>(info);
+ QString file;
+ QString path;
+ const QtMacFilterName &fn
+ = fileDialogPrivate->filterInfo.filters.at(fileDialogPrivate->filterInfo.currentSelection);
+ if (theItem->descriptorType == typeFSRef) {
+ FSRef ref;
+ AEGetDescData(theItem, &ref, sizeof(ref));
+ UInt8 str_buffer[1024];
+ FSRefMakePath(&ref, str_buffer, 1024);
+ path = QString::fromUtf8(reinterpret_cast<const char *>(str_buffer));
+ int slsh = path.lastIndexOf(QLatin1Char('/'));
+ if (slsh != -1)
+ file = path.right(path.length() - slsh - 1);
+ else
+ file = path;
+ }
+ QStringList reg = fn.regexp.split(QLatin1String(";"));
+ for (QStringList::const_iterator it = reg.constBegin(); it != reg.constEnd(); ++it) {
+ QRegExp rg(*it, Qt::CaseInsensitive, QRegExp::Wildcard);
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialogPrivate::qt_mac_filedialog_filter_proc:%d, asked to filter.. %s (%s)", __LINE__,
+ qPrintable(file), qPrintable(*it));
+#endif
+ if (rg.exactMatch(file))
+ return true;
+ }
+
+ if (theInfo->isFolder) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:qt_mac_QStringToNSString(path)])
+ return false;
+ return true;
+ }
+ return false;
+}
+
+void QFileDialogPrivate::qt_mac_filedialog_event_proc(const NavEventCallbackMessage msg,
+ NavCBRecPtr p, NavCallBackUserData data)
+{
+ QFileDialogPrivate *fileDialogPrivate = static_cast<QFileDialogPrivate *>(data);
+
+ switch(msg) {
+ case kNavCBPopupMenuSelect: {
+ NavMenuItemSpec *s = static_cast<NavMenuItemSpec *>(p->eventData.eventDataParms.param);
+ if (int(s->menuType) != fileDialogPrivate->filterInfo.currentSelection) {
+ fileDialogPrivate->filterInfo.currentSelection = s->menuType;
+ emit fileDialogPrivate->q_func()->filterSelected(fileDialogPrivate->nameFilters.at(s->menuType));
+ }
+ if (fileDialogPrivate->acceptMode == QFileDialog::AcceptSave) {
+ QString base = QCFString::toQString(NavDialogGetSaveFileName(p->context));
+ QFileInfo fi(base);
+ base = fi.completeBaseName();
+ const QtMacFilterName &fn = fileDialogPrivate->filterInfo.filters.at(
+ fileDialogPrivate->filterInfo.currentSelection);
+ QStringList reg = fn.regexp.split(QLatin1String(";"), QString::SkipEmptyParts);
+ if (reg.count()) {
+ QString r = reg.first();
+ r = r.right(r.length()-1); // Strip the *
+ base += r; //"." + QString::number(s->menuType);
+ }
+ NavDialogSetSaveFileName(p->context, QCFString::toCFStringRef(base));
+ }
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialogPrivate::qt_mac_filedialog_event_proc:%d - Selected a filter: %ld", __LINE__, s->menuType);
+#endif
+ break; }
+ case kNavCBStart:{
+ fileDialogPrivate->mDialogStarted = true;
+ // Set selected file:
+ QModelIndexList indexes = fileDialogPrivate->qFileDialogUi->listView->selectionModel()->selectedRows();
+ QString selected;
+ if (!indexes.isEmpty())
+ selected = indexes.at(0).data(QFileSystemModel::FilePathRole).toString();
+ else
+ selected = fileDialogPrivate->typedFiles().value(0);
+ fileDialogPrivate->selectFile_sys(selected);
+ fileDialogPrivate->selectNameFilter_sys(fileDialogPrivate->qFileDialogUi->fileTypeCombo->currentText());
+ break; }
+ case kNavCBSelectEntry:{
+ // Event: Current selection has changed.
+ QStringList prevSelectionList = fileDialogPrivate->mCurrentSelectionList;
+ fileDialogPrivate->mCurrentSelectionList.clear();
+ QString fileNameToEmit;
+
+ AEDescList *descList = (AEDescList *)p->eventData.eventDataParms.param;
+ // Get the number of files selected:
+ UInt8 strBuffer[1024];
+ long count;
+ OSErr err = AECountItems(descList, &count);
+ if (err != noErr || !count)
+ break;
+
+ for (long index=1; index<=count; ++index) {
+ FSRef ref;
+ err = AEGetNthPtr(descList, index, typeFSRef, 0, 0, &ref, sizeof(ref), 0);
+ if (err != noErr)
+ break;
+ FSRefMakePath(&ref, strBuffer, 1024);
+ QString selected = QString::fromUtf8((const char *)strBuffer);
+ fileDialogPrivate->mCurrentSelectionList << selected;
+ if (!prevSelectionList.contains(selected))
+ fileNameToEmit = selected;
+ }
+
+ if (!fileNameToEmit.isEmpty() && fileNameToEmit != fileDialogPrivate->mCurrentSelection)
+ emit fileDialogPrivate->q_func()->currentChanged(fileNameToEmit);
+ fileDialogPrivate->mCurrentSelection = fileNameToEmit;
+ break; }
+ case kNavCBShowDesktop:
+ case kNavCBNewLocation:{
+ // Event: Current directory has changed.
+ AEDesc *desc = (AEDesc *)p->eventData.eventDataParms.param;
+ FSRef ref;
+ AEGetDescData(desc, &ref, sizeof(ref));
+ UInt8 *strBuffer = (UInt8 *)malloc(1024);
+ FSRefMakePath(&ref, strBuffer, 1024);
+ QString newLocation = QString::fromUtf8((const char *)strBuffer);
+ free(strBuffer);
+ if (fileDialogPrivate->mCurrentLocation != newLocation){
+ fileDialogPrivate->mCurrentLocation = newLocation;
+ QFileDialog::FileMode mode = fileDialogPrivate->fileMode;
+ if (mode == QFileDialog::AnyFile || mode == QFileDialog::ExistingFile
+ || mode == QFileDialog::ExistingFiles){
+ // When changing directory, the current selection is cleared if
+ // we are supposed to be selecting files only:
+ if (!fileDialogPrivate->mCurrentSelection.isEmpty()){
+ fileDialogPrivate->mCurrentSelectionList.clear();
+ fileDialogPrivate->mCurrentSelection.clear();
+ emit fileDialogPrivate->q_func()->currentChanged(fileDialogPrivate->mCurrentSelection);
+ }
+ }
+ fileDialogPrivate->setLastVisitedDirectory(newLocation);
+ emit fileDialogPrivate->q_func()->directoryEntered(newLocation);
+ }
+ break; }
+ case kNavCBAccept:
+ fileDialogPrivate->mDialogClosed = true;
+ fileDialogPrivate->q_func()->accept();
+ break;
+ case kNavCBCancel:
+ fileDialogPrivate->mDialogClosed = true;
+ fileDialogPrivate->q_func()->reject();
+ break;
+ }
+}
+
+static QFileDialogPrivate::QtMacFilterName qt_mac_extract_filter(const QString &rawFilter, bool showDetails)
+{
+ QFileDialogPrivate::QtMacFilterName ret;
+ ret.filter = rawFilter;
+ QString result = rawFilter;
+ QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
+ int index = r.indexIn(result);
+ if (index >= 0)
+ result = r.cap(2);
+
+ if (showDetails) {
+ ret.description = rawFilter;
+ } else {
+ if (index >= 0)
+ ret.description = r.cap(1).trimmed();
+ if (ret.description.isEmpty())
+ ret.description = result;
+ }
+ ret.regexp = result.replace(QLatin1Char(' '), QLatin1Char(';'));
+ return ret;
+}
+
+static QList<QFileDialogPrivate::QtMacFilterName> qt_mac_make_filters_list(const QString &filter, bool showDetails)
+{
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialog:%d - Got filter (%s)", __LINE__, filter.latin1());
+#endif
+
+ QList<QFileDialogPrivate::QtMacFilterName> ret;
+ QString f(filter);
+ if (f.isEmpty())
+ f = QFileDialog::tr("All Files (*)");
+ if (f.isEmpty())
+ return ret;
+ QStringList filts = qt_make_filter_list(f);
+ for (QStringList::const_iterator it = filts.constBegin(); it != filts.constEnd(); ++it) {
+ QFileDialogPrivate::QtMacFilterName filter = qt_mac_extract_filter(*it, showDetails);
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialog:%d Split out filter (%d) '%s' '%s' [%s]", __LINE__, ret.count(),
+ filter->regxp.latin1(), filter->description.latin1(), (*it).latin1());
+#endif
+ ret.append(filter);
+ }
+ return ret;
+}
+
+void QFileDialogPrivate::createNavServicesDialog()
+{
+ Q_Q(QFileDialog);
+ if (mDialog)
+ deleteNativeDialog_sys();
+
+ NavDialogCreationOptions navOptions;
+ NavGetDefaultDialogCreationOptions(&navOptions);
+
+ // Translate QFileDialog settings into NavDialog options:
+ if (qt_mac_is_macsheet(q)) {
+ navOptions.modality = kWindowModalityWindowModal;
+ navOptions.parentWindow = qt_mac_window_for(q->parentWidget());
+ } else if (q->windowModality() == Qt::ApplicationModal)
+ navOptions.modality = kWindowModalityAppModal;
+ else
+ navOptions.modality = kWindowModalityNone;
+ navOptions.optionFlags |= kNavSupportPackages;
+ if (q->testOption(QFileDialog::DontConfirmOverwrite))
+ navOptions.optionFlags |= kNavDontConfirmReplacement;
+ if (fileMode != QFileDialog::ExistingFiles)
+ navOptions.optionFlags &= ~kNavAllowMultipleFiles;
+
+ navOptions.windowTitle = QCFString::toCFStringRef(q->windowTitle());
+
+ navOptions.location.h = -1;
+ navOptions.location.v = -1;
+
+ QWidget *parent = q->parentWidget();
+ if (parent && parent->isVisible()) {
+ WindowClass wclass;
+ GetWindowClass(qt_mac_window_for(parent), &wclass);
+ parent = parent->window();
+ QString s = parent->windowTitle();
+ navOptions.clientName = QCFString::toCFStringRef(s);
+ }
+
+ filterInfo.currentSelection = 0;
+ filterInfo.filters = qt_mac_make_filters_list(nameFilters.join(QLatin1String(";;")), q->isNameFilterDetailsVisible());
+ QCFType<CFArrayRef> filterArray;
+ if (filterInfo.filters.size() > 1) {
+ int i = 0;
+ CFStringRef *cfstringArray = static_cast<CFStringRef *>(malloc(sizeof(CFStringRef)
+ * filterInfo.filters.size()));
+ for (i = 0; i < filterInfo.filters.size(); ++i) {
+ cfstringArray[i] = QCFString::toCFStringRef(filterInfo.filters.at(i).description);
+ }
+ filterArray = CFArrayCreate(kCFAllocatorDefault,
+ reinterpret_cast<const void **>(cfstringArray), filterInfo.filters.size(),
+ &kCFTypeArrayCallBacks);
+ navOptions.popupExtension = filterArray;
+ free(cfstringArray);
+ }
+
+ if (q->acceptMode() == QFileDialog::AcceptSave) {
+ if (NavCreatePutFileDialog(&navOptions, 'cute', kNavGenericSignature,
+ QFileDialogPrivate::qt_mac_filedialog_event_proc, this, &mDialog)) {
+ qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
+ return;
+ }
+ } else if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory) {
+ if (NavCreateChooseFolderDialog(&navOptions,
+ QFileDialogPrivate::qt_mac_filedialog_event_proc, 0, this, &mDialog)) {
+ qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
+ return;
+ }
+ } else {
+ if (NavCreateGetFileDialog(&navOptions, 0,
+ QFileDialogPrivate::qt_mac_filedialog_event_proc, 0,
+ QFileDialogPrivate::qt_mac_filedialog_filter_proc, this, &mDialog)) {
+ qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
+ return;
+ }
+ }
+
+ // Set start-up directory:
+ if (mCurrentLocation.isEmpty())
+ mCurrentLocation = rootPath();
+ FSRef fsRef;
+ if (qt_mac_create_fsref(mCurrentLocation, &fsRef) == noErr) {
+ AEDesc desc;
+ if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr)
+ NavCustomControl(mDialog, kNavCtlSetLocation, (void*)&desc);
+ }
+}
+
+bool QFileDialogPrivate::showCarbonNavServicesDialog()
+{
+ Q_Q(QFileDialog);
+ if (q->acceptMode() == QFileDialog::AcceptSave && q->windowModality() == Qt::NonModal)
+ return false; // cannot do native no-modal save dialogs.
+ createNavServicesDialog();
+ mDialogClosed = false;
+ if (q->windowModality() != Qt::ApplicationModal)
+ NavDialogRun(mDialog);
+ return true;
+}
+
+bool QFileDialogPrivate::hideCarbonNavServicesDialog()
+{
+ if (!mDialogClosed){
+ mDialogClosed = true;
+ NavCustomControl(mDialog, kNavCtlCancel, 0);
+ }
+ return true;
+}
+
+#else // Cocoa
+
+void QFileDialogPrivate::createNSOpenSavePanelDelegate()
+{
+ Q_Q(QFileDialog);
+ if (mDelegate)
+ return;
+
+ bool selectDir = q->selectedFiles().isEmpty();
+ QString selection(selectDir ? q->directory().absolutePath() : q->selectedFiles().value(0));
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) alloc]
+ initWithAcceptMode:acceptMode
+ title:q->windowTitle()
+ hideNameFilterDetails:q->testOption(QFileDialog::HideNameFilterDetails)
+ qDirFilter:model->filter()
+ fileOptions:opts
+ fileMode:fileMode
+ selectFile:selection
+ confirmOverwrite:!q->testOption(QFileDialog::DontConfirmOverwrite)
+ priv:this];
+
+ mDelegate = delegate;
+}
+
+bool QFileDialogPrivate::showCocoaFilePanel()
+{
+ Q_Q(QFileDialog);
+ QMacCocoaAutoReleasePool pool;
+ createNSOpenSavePanelDelegate();
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ if (qt_mac_is_macsheet(q))
+ [delegate showWindowModalSheet:q->parentWidget()];
+ else
+ [delegate showModelessPanel];
+ return true;
+}
+
+bool QFileDialogPrivate::hideCocoaFilePanel()
+{
+ if (!mDelegate){
+ // Nothing to do. We return false to leave the question
+ // open regarding whether or not to go native:
+ return false;
+ } else {
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate closePanel];
+ // Even when we hide it, we are still using a
+ // native dialog, so return true:
+ return true;
+ }
+}
+
+#endif
+
+void QFileDialogPrivate::mac_nativeDialogModalHelp()
+{
+ // 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
+ // a queued meta call is intentional to ensure that the call is only delivered when
+ // [NSApp run] runs (timers are handeled special in cocoa). If NSApp is not
+ // running (which is the case if e.g a top-most QEventLoop has been
+ // interrupted, and the second-most event loop has not yet been reactivated (regardless
+ // if [NSApp run] is still on the stack)), showing a native modal dialog will fail.
+ if (nativeDialogInUse){
+ Q_Q(QFileDialog);
+ QTimer::singleShot(1, q, SLOT(_q_macRunNativeAppModalPanel()));
+ }
+}
+
+void QFileDialogPrivate::_q_macRunNativeAppModalPanel()
+{
+ QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
+#ifndef QT_MAC_USE_COCOA
+ NavDialogRun(mDialog);
+#else
+ Q_Q(QFileDialog);
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate runApplicationModalPanel];
+ dialogResultCode_sys() == QDialog::Accepted ? q->accept() : q->reject();
+#endif
+}
+
+QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys()
+{
+#ifndef QT_MAC_USE_COCOA
+ NavUserAction result = NavDialogGetUserAction(mDialog);
+ if (result == kNavUserActionCancel || result == kNavUserActionNone)
+ return QDialog::Rejected;
+ else
+ return QDialog::Accepted;
+#else
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ return [delegate dialogResultCode];
+#endif
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FILEDIALOG
+