1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qfiledialog.h"
44 #ifndef QT_NO_FILEDIALOG
46 /*****************************************************************************
47 QFileDialog debug facilities
48 *****************************************************************************/
49 //#define DEBUG_FILEDIALOG_FILTERS
51 #include <qapplication.h>
52 #include <private/qapplication_p.h>
53 #include <private/qfiledialog_p.h>
54 #include <private/qt_mac_p.h>
55 #include <private/qt_cocoa_helpers_mac_p.h>
59 #include <qstringlist.h>
61 #include <qtextcodec.h>
62 #include <qvarlengtharray.h>
63 #include <qdesktopwidget.h>
65 #include <qabstracteventdispatcher.h>
66 #import <AppKit/NSSavePanel.h>
67 #include "ui_qfiledialog.h"
71 extern QStringList qt_make_filter_list(const QString &filter); // qfiledialog.cpp
72 extern QStringList qt_clean_filter_list(const QString &filter); // qfiledialog.cpp
73 extern const char *qt_file_dialog_filter_reg_exp; // qfiledialog.cpp
74 extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
78 QT_FORWARD_DECLARE_CLASS(QFileDialogPrivate)
79 QT_FORWARD_DECLARE_CLASS(QString)
80 QT_FORWARD_DECLARE_CLASS(QStringList)
81 QT_FORWARD_DECLARE_CLASS(QWidget)
82 QT_FORWARD_DECLARE_CLASS(QAction)
83 QT_FORWARD_DECLARE_CLASS(QFileInfo)
86 @class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate);
88 @interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
89 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
90 : NSObject<NSOpenSavePanelDelegate>
96 NSOpenPanel *mOpenPanel;
97 NSSavePanel *mSavePanel;
98 NSView *mAccessoryView;
99 NSPopUpButton *mPopUpButton;
100 NSTextField *mTextField;
101 QFileDialogPrivate *mPriv;
102 NSString *mCurrentDir;
103 bool mConfirmOverwrite;
106 QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode) mAcceptMode;
107 QT_PREPEND_NAMESPACE(QDir::Filters) *mQDirFilter;
108 QT_PREPEND_NAMESPACE(QFileDialog::FileMode) mFileMode;
109 QT_PREPEND_NAMESPACE(QFileDialog::Options) *mFileOptions;
111 QString *mLastFilterCheckPath;
112 QString *mCurrentSelection;
113 QStringList *mQDirFilterEntryList;
114 QStringList *mNameFilterDropDownList;
115 QStringList *mSelectedNameFilter;
118 - (NSString *)strip:(const QString &)label;
119 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
120 - (void)filterChanged:(id)sender;
121 - (void)showModelessPanel;
122 - (BOOL)runApplicationModalPanel;
123 - (void)showWindowModalSheet:(QWidget *)docWidget;
124 - (void)updateProperties;
125 - (QStringList)acceptableExtensionsForSave;
126 - (QString)removeExtensions:(const QString &)filter;
127 - (void)createTextField;
128 - (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails;
129 - (QStringList)findStrippedFilterWithVisualFilterName:(QString)name;
130 - (void)createAccessory;
134 @implementation QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
136 - (id)initWithAcceptMode:(QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode))acceptMode
137 title:(const QString &)title
138 hideNameFilterDetails:(bool)hideNameFilterDetails
139 qDirFilter:(QT_PREPEND_NAMESPACE(QDir::Filters))qDirFilter
140 fileOptions:(QT_PREPEND_NAMESPACE(QFileDialog::Options))fileOptions
141 fileMode:(QT_PREPEND_NAMESPACE(QFileDialog::FileMode))fileMode
142 selectFile:(const QString &)selectFile
143 confirmOverwrite:(bool)confirm
144 priv:(QFileDialogPrivate *)priv
148 mAcceptMode = acceptMode;
149 if (mAcceptMode == QT_PREPEND_NAMESPACE(QFileDialog::AcceptOpen)){
150 mOpenPanel = [NSOpenPanel openPanel];
151 mSavePanel = mOpenPanel;
153 mSavePanel = [NSSavePanel savePanel];
157 [mSavePanel setLevel:NSModalPanelWindowLevel];
158 [mSavePanel setDelegate:self];
159 mQDirFilter = new QT_PREPEND_NAMESPACE(QDir::Filters)(qDirFilter);
160 mFileOptions = new QT_PREPEND_NAMESPACE(QFileDialog::Options)(fileOptions);
161 mFileMode = fileMode;
162 mConfirmOverwrite = confirm;
165 mLastFilterCheckPath = new QString;
166 mQDirFilterEntryList = new QStringList;
167 mNameFilterDropDownList = new QStringList(priv->nameFilters);
168 QString selectedVisualNameFilter = priv->qFileDialogUi->fileTypeCombo->currentText();
169 mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]);
171 QFileInfo sel(selectFile);
173 mCurrentDir = [qt_mac_QStringToNSString(sel.absoluteFilePath()) retain];
174 mCurrentSelection = new QString;
176 mCurrentDir = [qt_mac_QStringToNSString(sel.absolutePath()) retain];
177 mCurrentSelection = new QString(sel.absoluteFilePath());
180 [mSavePanel setTitle:qt_mac_QStringToNSString(title)];
181 [self createPopUpButton:selectedVisualNameFilter hideDetails:hideNameFilterDetails];
182 [self createTextField];
183 [self createAccessory];
184 [mSavePanel setAccessoryView:mNameFilterDropDownList->size() > 1 ? mAccessoryView : nil];
187 [mSavePanel setPrompt:[self strip:mPriv->acceptLabel]];
188 if (mPriv->fileNameLabelExplicitlySat)
189 [mSavePanel setNameFieldLabel:[self strip:mPriv->qFileDialogUi->fileNameLabel->text()]];
192 [self updateProperties];
201 delete mLastFilterCheckPath;
202 delete mQDirFilterEntryList;
203 delete mNameFilterDropDownList;
204 delete mSelectedNameFilter;
205 delete mCurrentSelection;
207 [mSavePanel orderOut:mSavePanel];
208 [mSavePanel setAccessoryView:nil];
209 [mPopUpButton release];
210 [mTextField release];
211 [mAccessoryView release];
212 [mSavePanel setDelegate:nil];
213 [mSavePanel release];
214 [mCurrentDir release];
218 - (NSString *)strip:(const QString &)label
221 return qt_mac_QStringToNSString(a.iconText());
226 *mCurrentSelection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
230 - (void)showModelessPanel
233 QFileInfo info(*mCurrentSelection);
234 NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
235 NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
236 bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
237 || [self panel:nil shouldShowFilename:filepath];
239 beginForDirectory:mCurrentDir
240 file:selectable ? filename : nil
242 modelessDelegate:self
243 didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
248 - (BOOL)runApplicationModalPanel
250 QFileInfo info(*mCurrentSelection);
251 NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
252 NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
253 bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
254 || [self panel:nil shouldShowFilename:filepath];
255 mReturnCode = [mSavePanel
256 runModalForDirectory:mCurrentDir
257 file:selectable ? filename : @"untitled"];
259 QAbstractEventDispatcher::instance()->interrupt();
260 return (mReturnCode == NSOKButton);
263 - (QT_PREPEND_NAMESPACE(QDialog::DialogCode))dialogResultCode
265 return (mReturnCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QDialog::Accepted) : QT_PREPEND_NAMESPACE(QDialog::Rejected);
268 - (void)showWindowModalSheet:(QWidget *)docWidget
271 QFileInfo info(*mCurrentSelection);
272 NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
273 NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
274 bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
275 || [self panel:nil shouldShowFilename:filepath];
277 beginSheetForDirectory:mCurrentDir
278 file:selectable ? filename : nil
279 modalForWindow:QT_PREPEND_NAMESPACE(qt_mac_window_for)(docWidget)
281 didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
285 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
289 if ([filename length] == 0)
292 // Always accept directories regardless of their names (unless it is a bundle):
294 if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir) {
295 if ([mSavePanel treatsFilePackagesAsDirectories] == NO) {
296 if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
301 QString qtFileName = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(filename);
302 QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C)));
303 QString path = info.absolutePath();
304 if (path != *mLastFilterCheckPath){
305 *mLastFilterCheckPath = path;
306 *mQDirFilterEntryList = info.dir().entryList(*mQDirFilter);
308 // Check if the QDir filter accepts the file:
309 if (!mQDirFilterEntryList->contains(info.fileName()))
312 // No filter means accept everything
313 if (mSelectedNameFilter->isEmpty())
315 // Check if the current file name filter accepts the file:
316 for (int i=0; i<mSelectedNameFilter->size(); ++i) {
317 if (QDir::match(mSelectedNameFilter->at(i), qtFileName))
323 - (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
328 if (mConfirmOverwrite)
331 // User has clicked save, and no overwrite confirmation should occur.
332 // To get the latter, we need to change the name we return (hence the prefix):
333 return [@"___qt_very_unlikely_prefix_" stringByAppendingString:filename];
336 - (void)setNameFilters:(const QStringList &)filters hideDetails:(BOOL)hideDetails
338 [mPopUpButton removeAllItems];
339 *mNameFilterDropDownList = filters;
340 if (filters.size() > 0){
341 for (int i=0; i<filters.size(); ++i) {
342 QString filter = hideDetails ? [self removeExtensions:filters.at(i)] : filters.at(i);
343 [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
345 [mPopUpButton selectItemAtIndex:0];
346 [mSavePanel setAccessoryView:mAccessoryView];
348 [mSavePanel setAccessoryView:nil];
350 [self filterChanged:self];
353 - (void)filterChanged:(id)sender
355 // This mDelegate function is called when the _name_ filter changes.
357 QString selection = mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
358 *mSelectedNameFilter = [self findStrippedFilterWithVisualFilterName:selection];
359 [mSavePanel validateVisibleColumns];
360 [self updateProperties];
362 mPriv->QNSOpenSavePanelDelegate_filterSelected([mPopUpButton indexOfSelectedItem]);
365 - (QString)currentNameFilter
367 return mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
370 - (QStringList)selectedFiles
373 return QT_PREPEND_NAMESPACE(qt_mac_NSArrayToQStringList)([mOpenPanel filenames]);
376 QString filename = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
377 result << filename.remove(QLatin1String("___qt_very_unlikely_prefix_"));
382 - (void)updateProperties
384 // Call this functions if mFileMode, mFileOptions,
385 // mNameFilterDropDownList or mQDirFilter changes.
386 // The savepanel does not contain the neccessary functions for this.
387 bool chooseFilesOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFile)
388 || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles);
389 bool chooseDirsOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::Directory)
390 || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::DirectoryOnly)
391 || *mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ShowDirsOnly);
393 [mOpenPanel setCanChooseFiles:!chooseDirsOnly];
394 [mOpenPanel setCanChooseDirectories:!chooseFilesOnly];
395 [mSavePanel setCanCreateDirectories:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ReadOnly))];
396 [mOpenPanel setAllowsMultipleSelection:(mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles))];
397 [mOpenPanel setResolvesAliases:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::DontResolveSymlinks))];
399 QStringList ext = [self acceptableExtensionsForSave];
400 if (mPriv && !ext.isEmpty() && !mPriv->defaultSuffix.isEmpty())
401 ext.prepend(mPriv->defaultSuffix);
402 [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : QT_PREPEND_NAMESPACE(qt_mac_QStringListToNSMutableArray(ext))];
404 if ([mSavePanel isVisible])
405 [mOpenPanel validateVisibleColumns];
408 - (void)panelSelectionDidChange:(id)sender
412 QString selection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString([mSavePanel filename]));
413 if (selection != mCurrentSelection) {
414 *mCurrentSelection = selection;
415 mPriv->QNSOpenSavePanelDelegate_selectionChanged(selection);
420 - (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
423 Q_UNUSED(contextInfo);
424 mReturnCode = returnCode;
426 mPriv->QNSOpenSavePanelDelegate_panelClosed(returnCode == NSOKButton);
429 - (void)panel:(id)sender directoryDidChange:(NSString *)path
434 if ([path isEqualToString:mCurrentDir])
437 [mCurrentDir release];
438 mCurrentDir = [path retain];
439 mPriv->QNSOpenSavePanelDelegate_directoryEntered(QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString(mCurrentDir)));
443 Returns a list of extensions (e.g. "png", "jpg", "gif")
444 for the current name filter. If a filter do not conform
445 to the format *.xyz or * or *.*, an empty list
446 is returned meaning accept everything.
448 - (QStringList)acceptableExtensionsForSave
451 for (int i=0; i<mSelectedNameFilter->count(); ++i) {
452 const QString &filter = mSelectedNameFilter->at(i);
453 if (filter.startsWith(QLatin1String("*."))
454 && !filter.contains(QLatin1Char('?'))
455 && filter.count(QLatin1Char('*')) == 1) {
456 result += filter.mid(2);
458 return QStringList(); // Accept everything
464 - (QString)removeExtensions:(const QString &)filter
466 QRegExp regExp(QT_PREPEND_NAMESPACE(QString::fromLatin1)(QT_PREPEND_NAMESPACE(qt_file_dialog_filter_reg_exp)));
467 if (regExp.indexIn(filter) != -1)
468 return regExp.cap(1).trimmed();
472 - (void)createTextField
474 NSRect textRect = { { 0.0, 3.0 }, { 100.0, 25.0 } };
475 mTextField = [[NSTextField alloc] initWithFrame:textRect];
476 [[mTextField cell] setFont:[NSFont systemFontOfSize:
477 [NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
478 [mTextField setAlignment:NSRightTextAlignment];
479 [mTextField setEditable:false];
480 [mTextField setSelectable:false];
481 [mTextField setBordered:false];
482 [mTextField setDrawsBackground:false];
484 [mTextField setStringValue:[self strip:mPriv->qFileDialogUi->fileTypeLabel->text()]];
486 [mTextField setStringValue:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(QT_PREPEND_NAMESPACE(QFileDialog::tr)("Files of type:"))];
489 - (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails
491 NSRect popUpRect = { { 100.0, 5.0 }, { 250.0, 25.0 } };
492 mPopUpButton = [[NSPopUpButton alloc] initWithFrame:popUpRect pullsDown:NO];
493 [mPopUpButton setTarget:self];
494 [mPopUpButton setAction:@selector(filterChanged:)];
496 QStringList *filters = mNameFilterDropDownList;
497 if (filters->size() > 0){
498 for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
499 QString filter = hideDetails ? [self removeExtensions:filters->at(i)] : filters->at(i);
500 [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
501 if (filters->at(i).startsWith(selectedFilter))
502 [mPopUpButton selectItemAtIndex:i];
507 - (QStringList) findStrippedFilterWithVisualFilterName:(QString)name
509 for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
510 if (mNameFilterDropDownList->at(i).startsWith(name))
511 return qt_clean_filter_list(mNameFilterDropDownList->at(i));
513 return QStringList();
516 - (void)createAccessory
518 NSRect accessoryRect = { { 0.0, 0.0 }, { 450.0, 33.0 } };
519 mAccessoryView = [[NSView alloc] initWithFrame:accessoryRect];
520 [mAccessoryView addSubview:mTextField];
521 [mAccessoryView addSubview:mPopUpButton];
528 void QFileDialogPrivate::QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath)
530 emit q_func()->currentChanged(newPath);
533 void QFileDialogPrivate::QNSOpenSavePanelDelegate_panelClosed(bool accepted)
541 void QFileDialogPrivate::QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir)
543 setLastVisitedDirectory(newDir);
544 emit q_func()->directoryEntered(newDir);
547 void QFileDialogPrivate::QNSOpenSavePanelDelegate_filterSelected(int menuIndex)
549 emit q_func()->filterSelected(nameFilters.at(menuIndex));
552 extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp
553 extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp
555 void QFileDialogPrivate::setDirectory_sys(const QString &directory)
557 QMacCocoaAutoReleasePool pool;
558 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
559 [delegate->mSavePanel setDirectory:qt_mac_QStringToNSString(directory)];
562 QString QFileDialogPrivate::directory_sys() const
564 QMacCocoaAutoReleasePool pool;
565 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
566 return qt_mac_NSStringToQString([delegate->mSavePanel directory]);
569 void QFileDialogPrivate::selectFile_sys(const QString &filename)
571 QString filePath = filename;
572 if (QDir::isRelativePath(filePath))
573 filePath = QFileInfo(directory_sys(), filePath).filePath();
575 // There seems to no way to select a file once the dialog is running.
576 // So do the next best thing, set the file's directory:
577 setDirectory_sys(QFileInfo(filePath).absolutePath());
580 QStringList QFileDialogPrivate::selectedFiles_sys() const
582 QMacCocoaAutoReleasePool pool;
583 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
584 return [delegate selectedFiles];
587 void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters)
589 QMacCocoaAutoReleasePool pool;
590 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
591 bool hideDetails = q_func()->testOption(QFileDialog::HideNameFilterDetails);
592 [delegate setNameFilters:filters hideDetails:hideDetails];
595 void QFileDialogPrivate::setFilter_sys()
598 QMacCocoaAutoReleasePool pool;
599 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
600 *(delegate->mQDirFilter) = model->filter();
601 delegate->mFileMode = fileMode;
602 [delegate->mSavePanel setTitle:qt_mac_QStringToNSString(q->windowTitle())];
603 [delegate->mSavePanel setPrompt:[delegate strip:acceptLabel]];
604 if (fileNameLabelExplicitlySat)
605 [delegate->mSavePanel setNameFieldLabel:[delegate strip:qFileDialogUi->fileNameLabel->text()]];
607 [delegate updateProperties];
610 void QFileDialogPrivate::selectNameFilter_sys(const QString &filter)
612 int index = nameFilters.indexOf(filter);
614 QMacCocoaAutoReleasePool pool;
615 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
616 [delegate->mPopUpButton selectItemAtIndex:index];
617 [delegate filterChanged:nil];
621 QString QFileDialogPrivate::selectedNameFilter_sys() const
623 QMacCocoaAutoReleasePool pool;
624 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
625 int index = [delegate->mPopUpButton indexOfSelectedItem];
626 return index != -1 ? nameFilters.at(index) : QString();
629 void QFileDialogPrivate::deleteNativeDialog_sys()
631 QMacCocoaAutoReleasePool pool;
632 [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate) release];
634 nativeDialogInUse = false;
637 bool QFileDialogPrivate::setVisible_sys(bool visible)
640 if (!visible == q->isHidden())
643 if (q->windowFlags() & Qt::WindowStaysOnTopHint) {
644 // The native file dialog tries all it can to stay
645 // on the NSModalPanel level. And it might also show
646 // its own "create directory" dialog that we cannot control.
647 // So we need to use the non-native version in this case...
651 return visible ? showCocoaFilePanel() : hideCocoaFilePanel();
654 void QFileDialogPrivate::createNSOpenSavePanelDelegate()
660 bool selectDir = q->selectedFiles().isEmpty();
661 QString selection(selectDir ? q->directory().absolutePath() : q->selectedFiles().value(0));
662 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) alloc]
663 initWithAcceptMode:acceptMode
664 title:q->windowTitle()
665 hideNameFilterDetails:q->testOption(QFileDialog::HideNameFilterDetails)
666 qDirFilter:model->filter()
670 confirmOverwrite:!q->testOption(QFileDialog::DontConfirmOverwrite)
673 mDelegate = delegate;
676 bool QFileDialogPrivate::showCocoaFilePanel()
679 QMacCocoaAutoReleasePool pool;
680 createNSOpenSavePanelDelegate();
681 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
682 if (qt_mac_is_macsheet(q))
683 [delegate showWindowModalSheet:q->parentWidget()];
685 [delegate showModelessPanel];
689 bool QFileDialogPrivate::hideCocoaFilePanel()
692 // Nothing to do. We return false to leave the question
693 // open regarding whether or not to go native:
696 QMacCocoaAutoReleasePool pool;
697 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
698 [delegate closePanel];
699 // Even when we hide it, we are still using a
700 // native dialog, so return true:
706 void QFileDialogPrivate::platformNativeDialogModalHelp()
708 // Do a queued meta-call to open the native modal dialog so it opens after the new
709 // event loop has started to execute (in QDialog::exec). Using a timer rather than
710 // a queued meta call is intentional to ensure that the call is only delivered when
711 // [NSApp run] runs (timers are handeled special in cocoa). If NSApp is not
712 // running (which is the case if e.g a top-most QEventLoop has been
713 // interrupted, and the second-most event loop has not yet been reactivated (regardless
714 // if [NSApp run] is still on the stack)), showing a native modal dialog will fail.
715 if (nativeDialogInUse){
717 QTimer::singleShot(1, q, SLOT(_q_macRunNativeAppModalPanel()));
721 void QFileDialogPrivate::_q_macRunNativeAppModalPanel()
723 QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
725 QMacCocoaAutoReleasePool pool;
726 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
727 [delegate runApplicationModalPanel];
728 dialogResultCode_sys() == QDialog::Accepted ? q->accept() : q->reject();
731 QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys()
733 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
734 return [delegate dialogResultCode];
740 #endif // QT_NO_FILEDIALOG