/**************************************************************************** | |
** | |
** 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$ | |
** GNU Lesser General Public License Usage | |
** 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. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $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> | |
#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) : NSObject { | |
@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 | |