source: trunk/src/gui/dialogs/qfiledialog_mac.mm

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 42.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qfiledialog.h"
43
44#ifndef QT_NO_FILEDIALOG
45
46/*****************************************************************************
47 QFileDialog debug facilities
48 *****************************************************************************/
49//#define DEBUG_FILEDIALOG_FILTERS
50
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>
56#include <qregexp.h>
57#include <qbuffer.h>
58#include <qdebug.h>
59#include <qstringlist.h>
60#include <qaction.h>
61#include <qtextcodec.h>
62#include <qvarlengtharray.h>
63#include <qdesktopwidget.h>
64#include <stdlib.h>
65#include <qabstracteventdispatcher.h>
66#include "ui_qfiledialog.h"
67
68QT_BEGIN_NAMESPACE
69
70extern QStringList qt_make_filter_list(const QString &filter); // qfiledialog.cpp
71extern QStringList qt_clean_filter_list(const QString &filter); // qfiledialog.cpp
72extern const char *qt_file_dialog_filter_reg_exp; // qfiledialog.cpp
73extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
74
75QT_END_NAMESPACE
76
77QT_FORWARD_DECLARE_CLASS(QFileDialogPrivate)
78QT_FORWARD_DECLARE_CLASS(QString)
79QT_FORWARD_DECLARE_CLASS(QStringList)
80QT_FORWARD_DECLARE_CLASS(QWidget)
81QT_FORWARD_DECLARE_CLASS(QAction)
82QT_FORWARD_DECLARE_CLASS(QFileInfo)
83QT_USE_NAMESPACE
84
85@class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate);
86
87@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) : NSObject {
88 @public
89 NSOpenPanel *mOpenPanel;
90 NSSavePanel *mSavePanel;
91 NSView *mAccessoryView;
92 NSPopUpButton *mPopUpButton;
93 NSTextField *mTextField;
94 QFileDialogPrivate *mPriv;
95 NSString *mCurrentDir;
96 bool mConfirmOverwrite;
97 int mReturnCode;
98
99 QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode) mAcceptMode;
100 QT_PREPEND_NAMESPACE(QDir::Filters) *mQDirFilter;
101 QT_PREPEND_NAMESPACE(QFileDialog::FileMode) mFileMode;
102 QT_PREPEND_NAMESPACE(QFileDialog::Options) *mFileOptions;
103
104 QString *mLastFilterCheckPath;
105 QString *mCurrentSelection;
106 QStringList *mQDirFilterEntryList;
107 QStringList *mNameFilterDropDownList;
108 QStringList *mSelectedNameFilter;
109}
110
111- (NSString *)strip:(const QString &)label;
112- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
113- (void)filterChanged:(id)sender;
114- (void)showModelessPanel;
115- (BOOL)runApplicationModalPanel;
116- (void)showWindowModalSheet:(QWidget *)docWidget;
117- (void)updateProperties;
118- (QStringList)acceptableExtensionsForSave;
119- (QString)removeExtensions:(const QString &)filter;
120- (void)createTextField;
121- (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails;
122- (QStringList)findStrippedFilterWithVisualFilterName:(QString)name;
123- (void)createAccessory;
124
125@end
126
127@implementation QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
128
129- (id)initWithAcceptMode:(QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode))acceptMode
130 title:(const QString &)title
131 hideNameFilterDetails:(bool)hideNameFilterDetails
132 qDirFilter:(QT_PREPEND_NAMESPACE(QDir::Filters))qDirFilter
133 fileOptions:(QT_PREPEND_NAMESPACE(QFileDialog::Options))fileOptions
134 fileMode:(QT_PREPEND_NAMESPACE(QFileDialog::FileMode))fileMode
135 selectFile:(const QString &)selectFile
136 confirmOverwrite:(bool)confirm
137 priv:(QFileDialogPrivate *)priv
138{
139 self = [super init];
140
141 mAcceptMode = acceptMode;
142 if (mAcceptMode == QT_PREPEND_NAMESPACE(QFileDialog::AcceptOpen)){
143 mOpenPanel = [NSOpenPanel openPanel];
144 mSavePanel = mOpenPanel;
145 } else {
146 mSavePanel = [NSSavePanel savePanel];
147 mOpenPanel = 0;
148 }
149
150 [mSavePanel setLevel:NSModalPanelWindowLevel];
151 [mSavePanel setDelegate:self];
152 mQDirFilter = new QT_PREPEND_NAMESPACE(QDir::Filters)(qDirFilter);
153 mFileOptions = new QT_PREPEND_NAMESPACE(QFileDialog::Options)(fileOptions);
154 mFileMode = fileMode;
155 mConfirmOverwrite = confirm;
156 mReturnCode = -1;
157 mPriv = priv;
158 mLastFilterCheckPath = new QString;
159 mQDirFilterEntryList = new QStringList;
160 mNameFilterDropDownList = new QStringList(priv->nameFilters);
161 QString selectedVisualNameFilter = priv->qFileDialogUi->fileTypeCombo->currentText();
162 mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]);
163
164 QFileInfo sel(selectFile);
165 if (sel.isDir()){
166 mCurrentDir = [qt_mac_QStringToNSString(sel.absoluteFilePath()) retain];
167 mCurrentSelection = new QString;
168 } else {
169 mCurrentDir = [qt_mac_QStringToNSString(sel.absolutePath()) retain];
170 mCurrentSelection = new QString(sel.absoluteFilePath());
171 }
172
173 [mSavePanel setTitle:qt_mac_QStringToNSString(title)];
174 [self createPopUpButton:selectedVisualNameFilter hideDetails:hideNameFilterDetails];
175 [self createTextField];
176 [self createAccessory];
177 [mSavePanel setAccessoryView:mNameFilterDropDownList->size() > 1 ? mAccessoryView : nil];
178
179 if (mPriv){
180 [mSavePanel setPrompt:[self strip:mPriv->acceptLabel]];
181 if (mPriv->fileNameLabelExplicitlySat)
182 [mSavePanel setNameFieldLabel:[self strip:mPriv->qFileDialogUi->fileNameLabel->text()]];
183 }
184
185 [self updateProperties];
186 [mSavePanel retain];
187 return self;
188}
189
190- (void)dealloc
191{
192 delete mQDirFilter;
193 delete mFileOptions;
194 delete mLastFilterCheckPath;
195 delete mQDirFilterEntryList;
196 delete mNameFilterDropDownList;
197 delete mSelectedNameFilter;
198 delete mCurrentSelection;
199
200 [mSavePanel orderOut:mSavePanel];
201 [mSavePanel setAccessoryView:nil];
202 [mPopUpButton release];
203 [mTextField release];
204 [mAccessoryView release];
205 [mSavePanel setDelegate:nil];
206 [mSavePanel release];
207 [mCurrentDir release];
208 [super dealloc];
209}
210
211- (NSString *)strip:(const QString &)label
212{
213 QAction a(label, 0);
214 return qt_mac_QStringToNSString(a.iconText());
215}
216
217- (void)closePanel
218{
219 *mCurrentSelection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
220 [mSavePanel close];
221}
222
223- (void)showModelessPanel
224{
225 if (mOpenPanel){
226 QFileInfo info(*mCurrentSelection);
227 NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
228 NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
229 bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
230 || [self panel:nil shouldShowFilename:filepath];
231 [mOpenPanel
232 beginForDirectory:mCurrentDir
233 file:selectable ? filename : nil
234 types:nil
235 modelessDelegate:self
236 didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
237 contextInfo:nil];
238 }
239}
240
241- (BOOL)runApplicationModalPanel
242{
243 QFileInfo info(*mCurrentSelection);
244 NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
245 NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
246 bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
247 || [self panel:nil shouldShowFilename:filepath];
248 mReturnCode = [mSavePanel
249 runModalForDirectory:mCurrentDir
250 file:selectable ? filename : @"untitled"];
251
252 QAbstractEventDispatcher::instance()->interrupt();
253 return (mReturnCode == NSOKButton);
254}
255
256- (QT_PREPEND_NAMESPACE(QDialog::DialogCode))dialogResultCode
257{
258 return (mReturnCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QDialog::Accepted) : QT_PREPEND_NAMESPACE(QDialog::Rejected);
259}
260
261- (void)showWindowModalSheet:(QWidget *)docWidget
262{
263 Q_UNUSED(docWidget);
264 QFileInfo info(*mCurrentSelection);
265 NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
266 NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
267 bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
268 || [self panel:nil shouldShowFilename:filepath];
269 [mSavePanel
270 beginSheetForDirectory:mCurrentDir
271 file:selectable ? filename : nil
272#ifdef QT_MAC_USE_COCOA
273 modalForWindow:QT_PREPEND_NAMESPACE(qt_mac_window_for)(docWidget)
274#else
275 modalForWindow:nil
276#endif
277 modalDelegate:self
278 didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
279 contextInfo:nil];
280}
281
282- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
283{
284 Q_UNUSED(sender);
285
286 if ([filename length] == 0)
287 return NO;
288
289 // Always accept directories regardless of their names (unless it is a bundle):
290 BOOL isDir;
291 if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir) {
292 if ([mSavePanel treatsFilePackagesAsDirectories] == NO) {
293 if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
294 return YES;
295 }
296 }
297
298 QString qtFileName = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(filename);
299 QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C)));
300 QString path = info.absolutePath();
301 if (path != *mLastFilterCheckPath){
302 *mLastFilterCheckPath = path;
303 *mQDirFilterEntryList = info.dir().entryList(*mQDirFilter);
304 }
305 // Check if the QDir filter accepts the file:
306 if (!mQDirFilterEntryList->contains(info.fileName()))
307 return NO;
308
309 // No filter means accept everything
310 if (mSelectedNameFilter->isEmpty())
311 return YES;
312 // Check if the current file name filter accepts the file:
313 for (int i=0; i<mSelectedNameFilter->size(); ++i) {
314 if (QDir::match(mSelectedNameFilter->at(i), qtFileName))
315 return YES;
316 }
317 return NO;
318}
319
320- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
321{
322 Q_UNUSED(sender);
323 if (!okFlag)
324 return filename;
325 if (mConfirmOverwrite)
326 return filename;
327
328 // User has clicked save, and no overwrite confirmation should occur.
329 // To get the latter, we need to change the name we return (hence the prefix):
330 return [@"___qt_very_unlikely_prefix_" stringByAppendingString:filename];
331}
332
333- (void)setNameFilters:(const QStringList &)filters hideDetails:(BOOL)hideDetails
334{
335 [mPopUpButton removeAllItems];
336 *mNameFilterDropDownList = filters;
337 if (filters.size() > 0){
338 for (int i=0; i<filters.size(); ++i) {
339 QString filter = hideDetails ? [self removeExtensions:filters.at(i)] : filters.at(i);
340 [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
341 }
342 [mPopUpButton selectItemAtIndex:0];
343 [mSavePanel setAccessoryView:mAccessoryView];
344 } else
345 [mSavePanel setAccessoryView:nil];
346
347 [self filterChanged:self];
348}
349
350- (void)filterChanged:(id)sender
351{
352 // This mDelegate function is called when the _name_ filter changes.
353 Q_UNUSED(sender);
354 QString selection = mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
355 *mSelectedNameFilter = [self findStrippedFilterWithVisualFilterName:selection];
356 [mSavePanel validateVisibleColumns];
357 [self updateProperties];
358 if (mPriv)
359 mPriv->QNSOpenSavePanelDelegate_filterSelected([mPopUpButton indexOfSelectedItem]);
360}
361
362- (QString)currentNameFilter
363{
364 return mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
365}
366
367- (QStringList)selectedFiles
368{
369 if (mOpenPanel)
370 return QT_PREPEND_NAMESPACE(qt_mac_NSArrayToQStringList)([mOpenPanel filenames]);
371 else{
372 QStringList result;
373 QString filename = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
374 result << filename.remove(QLatin1String("___qt_very_unlikely_prefix_"));
375 return result;
376 }
377}
378
379- (void)updateProperties
380{
381 // Call this functions if mFileMode, mFileOptions,
382 // mNameFilterDropDownList or mQDirFilter changes.
383 // The savepanel does not contain the neccessary functions for this.
384 bool chooseFilesOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFile)
385 || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles);
386 bool chooseDirsOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::Directory)
387 || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::DirectoryOnly)
388 || *mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ShowDirsOnly);
389
390 [mOpenPanel setCanChooseFiles:!chooseDirsOnly];
391 [mOpenPanel setCanChooseDirectories:!chooseFilesOnly];
392 [mSavePanel setCanCreateDirectories:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ReadOnly))];
393 [mOpenPanel setAllowsMultipleSelection:(mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles))];
394 [mOpenPanel setResolvesAliases:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::DontResolveSymlinks))];
395
396 QStringList ext = [self acceptableExtensionsForSave];
397 if (mPriv && !ext.isEmpty() && !mPriv->defaultSuffix.isEmpty())
398 ext.prepend(mPriv->defaultSuffix);
399 [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : QT_PREPEND_NAMESPACE(qt_mac_QStringListToNSMutableArray(ext))];
400
401 if ([mSavePanel isVisible])
402 [mOpenPanel validateVisibleColumns];
403}
404
405- (void)panelSelectionDidChange:(id)sender
406{
407 Q_UNUSED(sender);
408 if (mPriv) {
409 QString selection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString([mSavePanel filename]));
410 if (selection != mCurrentSelection) {
411 *mCurrentSelection = selection;
412 mPriv->QNSOpenSavePanelDelegate_selectionChanged(selection);
413 }
414 }
415}
416
417- (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
418{
419 Q_UNUSED(panel);
420 Q_UNUSED(contextInfo);
421 mReturnCode = returnCode;
422 if (mPriv)
423 mPriv->QNSOpenSavePanelDelegate_panelClosed(returnCode == NSOKButton);
424}
425
426- (void)panel:(id)sender directoryDidChange:(NSString *)path
427{
428 Q_UNUSED(sender);
429 if (!mPriv)
430 return;
431 if ([path isEqualToString:mCurrentDir])
432 return;
433
434 [mCurrentDir release];
435 mCurrentDir = [path retain];
436 mPriv->QNSOpenSavePanelDelegate_directoryEntered(QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString(mCurrentDir)));
437}
438
439/*
440 Returns a list of extensions (e.g. "png", "jpg", "gif")
441 for the current name filter. If a filter do not conform
442 to the format *.xyz or * or *.*, an empty list
443 is returned meaning accept everything.
444*/
445- (QStringList)acceptableExtensionsForSave
446{
447 QStringList result;
448 for (int i=0; i<mSelectedNameFilter->count(); ++i) {
449 const QString &filter = mSelectedNameFilter->at(i);
450 if (filter.startsWith(QLatin1String("*."))
451 && !filter.contains(QLatin1Char('?'))
452 && filter.count(QLatin1Char('*')) == 1) {
453 result += filter.mid(2);
454 } else {
455 return QStringList(); // Accept everything
456 }
457 }
458 return result;
459}
460
461- (QString)removeExtensions:(const QString &)filter
462{
463 QRegExp regExp(QT_PREPEND_NAMESPACE(QString::fromLatin1)(QT_PREPEND_NAMESPACE(qt_file_dialog_filter_reg_exp)));
464 if (regExp.indexIn(filter) != -1)
465 return regExp.cap(1).trimmed();
466 return filter;
467}
468
469- (void)createTextField
470{
471 NSRect textRect = { { 0.0, 3.0 }, { 100.0, 25.0 } };
472 mTextField = [[NSTextField alloc] initWithFrame:textRect];
473 [[mTextField cell] setFont:[NSFont systemFontOfSize:
474 [NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
475 [mTextField setAlignment:NSRightTextAlignment];
476 [mTextField setEditable:false];
477 [mTextField setSelectable:false];
478 [mTextField setBordered:false];
479 [mTextField setDrawsBackground:false];
480 if (mPriv){
481 [mTextField setStringValue:[self strip:mPriv->qFileDialogUi->fileTypeLabel->text()]];
482 } else
483 [mTextField setStringValue:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(QT_PREPEND_NAMESPACE(QFileDialog::tr)("Files of type:"))];
484}
485
486- (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails
487{
488 NSRect popUpRect = { { 100.0, 5.0 }, { 250.0, 25.0 } };
489 mPopUpButton = [[NSPopUpButton alloc] initWithFrame:popUpRect pullsDown:NO];
490 [mPopUpButton setTarget:self];
491 [mPopUpButton setAction:@selector(filterChanged:)];
492
493 QStringList *filters = mNameFilterDropDownList;
494 if (filters->size() > 0){
495 for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
496 QString filter = hideDetails ? [self removeExtensions:filters->at(i)] : filters->at(i);
497 [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
498 if (filters->at(i).startsWith(selectedFilter))
499 [mPopUpButton selectItemAtIndex:i];
500 }
501 }
502}
503
504- (QStringList) findStrippedFilterWithVisualFilterName:(QString)name
505{
506 for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
507 if (mNameFilterDropDownList->at(i).startsWith(name))
508 return qt_clean_filter_list(mNameFilterDropDownList->at(i));
509 }
510 return QStringList();
511}
512
513- (void)createAccessory
514{
515 NSRect accessoryRect = { { 0.0, 0.0 }, { 450.0, 33.0 } };
516 mAccessoryView = [[NSView alloc] initWithFrame:accessoryRect];
517 [mAccessoryView addSubview:mTextField];
518 [mAccessoryView addSubview:mPopUpButton];
519}
520
521@end
522
523QT_BEGIN_NAMESPACE
524
525void QFileDialogPrivate::QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath)
526{
527 emit q_func()->currentChanged(newPath);
528}
529
530void QFileDialogPrivate::QNSOpenSavePanelDelegate_panelClosed(bool accepted)
531{
532 if (accepted)
533 q_func()->accept();
534 else
535 q_func()->reject();
536}
537
538void QFileDialogPrivate::QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir)
539{
540 setLastVisitedDirectory(newDir);
541 emit q_func()->directoryEntered(newDir);
542}
543
544void QFileDialogPrivate::QNSOpenSavePanelDelegate_filterSelected(int menuIndex)
545{
546 emit q_func()->filterSelected(nameFilters.at(menuIndex));
547}
548
549extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp
550extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp
551
552void QFileDialogPrivate::setDirectory_sys(const QString &directory)
553{
554#ifndef QT_MAC_USE_COCOA
555 if (directory == mCurrentLocation)
556 return;
557 mCurrentLocation = directory;
558 emit q_func()->directoryEntered(mCurrentLocation);
559
560 FSRef fsRef;
561 if (qt_mac_create_fsref(directory, &fsRef) == noErr) {
562 AEDesc desc;
563 if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr)
564 NavCustomControl(mDialog, kNavCtlSetLocation, (void*)&desc);
565 }
566#else
567 QMacCocoaAutoReleasePool pool;
568 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
569 [delegate->mSavePanel setDirectory:qt_mac_QStringToNSString(directory)];
570#endif
571}
572
573QString QFileDialogPrivate::directory_sys() const
574{
575#ifndef QT_MAC_USE_COCOA
576 return mCurrentLocation;
577#else
578 QMacCocoaAutoReleasePool pool;
579 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
580 return qt_mac_NSStringToQString([delegate->mSavePanel directory]);
581#endif
582}
583
584void QFileDialogPrivate::selectFile_sys(const QString &filename)
585{
586 QString filePath = filename;
587 if (QDir::isRelativePath(filePath))
588 filePath = QFileInfo(directory_sys(), filePath).filePath();
589
590#ifndef QT_MAC_USE_COCOA
591 // Update the selection list immidiatly, so
592 // subsequent calls to selectedFiles() gets correct:
593 mCurrentSelectionList.clear();
594 mCurrentSelectionList << filename;
595 if (mCurrentSelection != filename){
596 mCurrentSelection = filename;
597 emit q_func()->currentChanged(mCurrentSelection);
598 }
599
600 AEDescList descList;
601 if (AECreateList(0, 0, false, &descList) != noErr)
602 return;
603
604 FSRef fsRef;
605 if (qt_mac_create_fsref(filePath, &fsRef) == noErr) {
606 AEDesc desc;
607 if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr){
608 if (AEPutDesc(&descList, 0, &desc) == noErr)
609 NavCustomControl(mDialog, kNavCtlSetSelection, (void*)&descList);
610 }
611 }
612
613 // Type the file name into the save dialog's text field:
614 UInt8 *strBuffer = (UInt8 *)malloc(1024);
615 qt_mac_to_pascal_string(QFileInfo(filename).fileName(), strBuffer);
616 NavCustomControl(mDialog, kNavCtlSetEditFileName, strBuffer);
617 free(strBuffer);
618#else
619 // There seems to no way to select a file once the dialog is running.
620 // So do the next best thing, set the file's directory:
621 setDirectory_sys(QFileInfo(filePath).absolutePath());
622#endif
623}
624
625QStringList QFileDialogPrivate::selectedFiles_sys() const
626{
627#ifndef QT_MAC_USE_COCOA
628 if (q_func()->acceptMode() == QFileDialog::AcceptOpen){
629 return mCurrentSelectionList;
630 } else {
631 return QStringList() << mCurrentLocation + QLatin1Char('/')
632 + QCFString::toQString(NavDialogGetSaveFileName(mDialog));
633 }
634#else
635 QMacCocoaAutoReleasePool pool;
636 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
637 return [delegate selectedFiles];
638#endif
639}
640
641void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters)
642{
643#ifndef QT_MAC_USE_COCOA
644 Q_UNUSED(filters);
645#else
646 QMacCocoaAutoReleasePool pool;
647 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
648 bool hideDetails = q_func()->testOption(QFileDialog::HideNameFilterDetails);
649 [delegate setNameFilters:filters hideDetails:hideDetails];
650#endif
651}
652
653void QFileDialogPrivate::setFilter_sys()
654{
655#ifndef QT_MAC_USE_COCOA
656#else
657 Q_Q(QFileDialog);
658 QMacCocoaAutoReleasePool pool;
659 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
660 *(delegate->mQDirFilter) = model->filter();
661 delegate->mFileMode = fileMode;
662 [delegate->mSavePanel setTitle:qt_mac_QStringToNSString(q->windowTitle())];
663 [delegate->mSavePanel setPrompt:[delegate strip:acceptLabel]];
664 if (fileNameLabelExplicitlySat)
665 [delegate->mSavePanel setNameFieldLabel:[delegate strip:qFileDialogUi->fileNameLabel->text()]];
666
667 [delegate updateProperties];
668#endif
669}
670
671void QFileDialogPrivate::selectNameFilter_sys(const QString &filter)
672{
673 int index = nameFilters.indexOf(filter);
674 if (index != -1) {
675#ifndef QT_MAC_USE_COCOA
676 NavMenuItemSpec navSpec;
677 bzero(&navSpec, sizeof(NavMenuItemSpec));
678 navSpec.menuType = index;
679 NavCustomControl(mDialog, kNavCtlSelectCustomType, &navSpec);
680#else
681 QMacCocoaAutoReleasePool pool;
682 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
683 [delegate->mPopUpButton selectItemAtIndex:index];
684 [delegate filterChanged:nil];
685#endif
686 }
687}
688
689QString QFileDialogPrivate::selectedNameFilter_sys() const
690{
691#ifndef QT_MAC_USE_COCOA
692 int index = filterInfo.currentSelection;
693#else
694 QMacCocoaAutoReleasePool pool;
695 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
696 int index = [delegate->mPopUpButton indexOfSelectedItem];
697#endif
698 return index != -1 ? nameFilters.at(index) : QString();
699}
700
701void QFileDialogPrivate::deleteNativeDialog_sys()
702{
703#ifndef QT_MAC_USE_COCOA
704 if (mDialog)
705 NavDialogDispose(mDialog);
706 mDialog = 0;
707 mDialogStarted = false;
708#else
709 QMacCocoaAutoReleasePool pool;
710 [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate) release];
711 mDelegate = 0;
712#endif
713 nativeDialogInUse = false;
714}
715
716bool QFileDialogPrivate::setVisible_sys(bool visible)
717{
718 Q_Q(QFileDialog);
719 if (!visible == q->isHidden())
720 return false;
721
722 if (q->windowFlags() & Qt::WindowStaysOnTopHint) {
723 // The native file dialog tries all it can to stay
724 // on the NSModalPanel level. And it might also show
725 // its own "create directory" dialog that we cannot control.
726 // So we need to use the non-native version in this case...
727 return false;
728 }
729
730#ifndef QT_MAC_USE_COCOA
731 return visible ? showCarbonNavServicesDialog() : hideCarbonNavServicesDialog();
732#else
733 return visible ? showCocoaFilePanel() : hideCocoaFilePanel();
734#endif
735}
736
737#ifndef QT_MAC_USE_COCOA
738Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void *info,
739 void *data, NavFilterModes)
740{
741 QFileDialogPrivate *fileDialogPrivate = static_cast<QFileDialogPrivate *>(data);
742
743 if (!fileDialogPrivate || fileDialogPrivate->filterInfo.filters.isEmpty()
744 || (fileDialogPrivate->filterInfo.currentSelection < 0
745 && fileDialogPrivate->filterInfo.currentSelection
746 >= fileDialogPrivate->filterInfo.filters.size()))
747 return true;
748
749 NavFileOrFolderInfo *theInfo = static_cast<NavFileOrFolderInfo *>(info);
750 QString file;
751 QString path;
752 const QtMacFilterName &fn
753 = fileDialogPrivate->filterInfo.filters.at(fileDialogPrivate->filterInfo.currentSelection);
754 if (theItem->descriptorType == typeFSRef) {
755 FSRef ref;
756 AEGetDescData(theItem, &ref, sizeof(ref));
757 UInt8 str_buffer[1024];
758 FSRefMakePath(&ref, str_buffer, 1024);
759 path = QString::fromUtf8(reinterpret_cast<const char *>(str_buffer));
760 int slsh = path.lastIndexOf(QLatin1Char('/'));
761 if (slsh != -1)
762 file = path.right(path.length() - slsh - 1);
763 else
764 file = path;
765 }
766 QStringList reg = fn.regexp.split(QLatin1String(";"));
767 for (QStringList::const_iterator it = reg.constBegin(); it != reg.constEnd(); ++it) {
768 QRegExp rg(*it, Qt::CaseInsensitive, QRegExp::Wildcard);
769#ifdef DEBUG_FILEDIALOG_FILTERS
770 qDebug("QFileDialogPrivate::qt_mac_filedialog_filter_proc:%d, asked to filter.. %s (%s)", __LINE__,
771 qPrintable(file), qPrintable(*it));
772#endif
773 if (rg.exactMatch(file))
774 return true;
775 }
776
777 if (theInfo->isFolder) {
778 if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:qt_mac_QStringToNSString(path)])
779 return false;
780 return true;
781 }
782 return false;
783}
784
785void QFileDialogPrivate::qt_mac_filedialog_event_proc(const NavEventCallbackMessage msg,
786 NavCBRecPtr p, NavCallBackUserData data)
787{
788 QFileDialogPrivate *fileDialogPrivate = static_cast<QFileDialogPrivate *>(data);
789
790 switch(msg) {
791 case kNavCBPopupMenuSelect: {
792 NavMenuItemSpec *s = static_cast<NavMenuItemSpec *>(p->eventData.eventDataParms.param);
793 if (int(s->menuType) != fileDialogPrivate->filterInfo.currentSelection) {
794 fileDialogPrivate->filterInfo.currentSelection = s->menuType;
795 emit fileDialogPrivate->q_func()->filterSelected(fileDialogPrivate->nameFilters.at(s->menuType));
796 }
797 if (fileDialogPrivate->acceptMode == QFileDialog::AcceptSave) {
798 QString base = QCFString::toQString(NavDialogGetSaveFileName(p->context));
799 QFileInfo fi(base);
800 base = fi.completeBaseName();
801 const QtMacFilterName &fn = fileDialogPrivate->filterInfo.filters.at(
802 fileDialogPrivate->filterInfo.currentSelection);
803 QStringList reg = fn.regexp.split(QLatin1String(";"), QString::SkipEmptyParts);
804 if (reg.count()) {
805 QString r = reg.first();
806 r = r.right(r.length()-1); // Strip the *
807 base += r; //"." + QString::number(s->menuType);
808 }
809 NavDialogSetSaveFileName(p->context, QCFString::toCFStringRef(base));
810 }
811#ifdef DEBUG_FILEDIALOG_FILTERS
812 qDebug("QFileDialogPrivate::qt_mac_filedialog_event_proc:%d - Selected a filter: %ld", __LINE__, s->menuType);
813#endif
814 break; }
815 case kNavCBStart:{
816 fileDialogPrivate->mDialogStarted = true;
817 // Set selected file:
818 QModelIndexList indexes = fileDialogPrivate->qFileDialogUi->listView->selectionModel()->selectedRows();
819 QString selected;
820 if (!indexes.isEmpty())
821 selected = indexes.at(0).data(QFileSystemModel::FilePathRole).toString();
822 else
823 selected = fileDialogPrivate->typedFiles().value(0);
824 fileDialogPrivate->selectFile_sys(selected);
825 fileDialogPrivate->selectNameFilter_sys(fileDialogPrivate->qFileDialogUi->fileTypeCombo->currentText());
826 break; }
827 case kNavCBSelectEntry:{
828 // Event: Current selection has changed.
829 QStringList prevSelectionList = fileDialogPrivate->mCurrentSelectionList;
830 fileDialogPrivate->mCurrentSelectionList.clear();
831 QString fileNameToEmit;
832
833 AEDescList *descList = (AEDescList *)p->eventData.eventDataParms.param;
834 // Get the number of files selected:
835 UInt8 strBuffer[1024];
836 long count;
837 OSErr err = AECountItems(descList, &count);
838 if (err != noErr || !count)
839 break;
840
841 for (long index=1; index<=count; ++index) {
842 FSRef ref;
843 err = AEGetNthPtr(descList, index, typeFSRef, 0, 0, &ref, sizeof(ref), 0);
844 if (err != noErr)
845 break;
846 FSRefMakePath(&ref, strBuffer, 1024);
847 QString selected = QString::fromUtf8((const char *)strBuffer);
848 fileDialogPrivate->mCurrentSelectionList << selected;
849 if (!prevSelectionList.contains(selected))
850 fileNameToEmit = selected;
851 }
852
853 if (!fileNameToEmit.isEmpty() && fileNameToEmit != fileDialogPrivate->mCurrentSelection)
854 emit fileDialogPrivate->q_func()->currentChanged(fileNameToEmit);
855 fileDialogPrivate->mCurrentSelection = fileNameToEmit;
856 break; }
857 case kNavCBShowDesktop:
858 case kNavCBNewLocation:{
859 // Event: Current directory has changed.
860 AEDesc *desc = (AEDesc *)p->eventData.eventDataParms.param;
861 FSRef ref;
862 AEGetDescData(desc, &ref, sizeof(ref));
863 UInt8 *strBuffer = (UInt8 *)malloc(1024);
864 FSRefMakePath(&ref, strBuffer, 1024);
865 QString newLocation = QString::fromUtf8((const char *)strBuffer);
866 free(strBuffer);
867 if (fileDialogPrivate->mCurrentLocation != newLocation){
868 fileDialogPrivate->mCurrentLocation = newLocation;
869 QFileDialog::FileMode mode = fileDialogPrivate->fileMode;
870 if (mode == QFileDialog::AnyFile || mode == QFileDialog::ExistingFile
871 || mode == QFileDialog::ExistingFiles){
872 // When changing directory, the current selection is cleared if
873 // we are supposed to be selecting files only:
874 if (!fileDialogPrivate->mCurrentSelection.isEmpty()){
875 fileDialogPrivate->mCurrentSelectionList.clear();
876 fileDialogPrivate->mCurrentSelection.clear();
877 emit fileDialogPrivate->q_func()->currentChanged(fileDialogPrivate->mCurrentSelection);
878 }
879 }
880 fileDialogPrivate->setLastVisitedDirectory(newLocation);
881 emit fileDialogPrivate->q_func()->directoryEntered(newLocation);
882 }
883 break; }
884 case kNavCBAccept:
885 fileDialogPrivate->mDialogClosed = true;
886 fileDialogPrivate->q_func()->accept();
887 break;
888 case kNavCBCancel:
889 fileDialogPrivate->mDialogClosed = true;
890 fileDialogPrivate->q_func()->reject();
891 break;
892 }
893}
894
895static QFileDialogPrivate::QtMacFilterName qt_mac_extract_filter(const QString &rawFilter, bool showDetails)
896{
897 QFileDialogPrivate::QtMacFilterName ret;
898 ret.filter = rawFilter;
899 QString result = rawFilter;
900 QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
901 int index = r.indexIn(result);
902 if (index >= 0)
903 result = r.cap(2);
904
905 if (showDetails) {
906 ret.description = rawFilter;
907 } else {
908 if (index >= 0)
909 ret.description = r.cap(1).trimmed();
910 if (ret.description.isEmpty())
911 ret.description = result;
912 }
913 ret.regexp = result.replace(QLatin1Char(' '), QLatin1Char(';'));
914 return ret;
915}
916
917static QList<QFileDialogPrivate::QtMacFilterName> qt_mac_make_filters_list(const QString &filter, bool showDetails)
918{
919#ifdef DEBUG_FILEDIALOG_FILTERS
920 qDebug("QFileDialog:%d - Got filter (%s)", __LINE__, filter.latin1());
921#endif
922
923 QList<QFileDialogPrivate::QtMacFilterName> ret;
924 QString f(filter);
925 if (f.isEmpty())
926 f = QFileDialog::tr("All Files (*)");
927 if (f.isEmpty())
928 return ret;
929 QStringList filts = qt_make_filter_list(f);
930 for (QStringList::const_iterator it = filts.constBegin(); it != filts.constEnd(); ++it) {
931 QFileDialogPrivate::QtMacFilterName filter = qt_mac_extract_filter(*it, showDetails);
932#ifdef DEBUG_FILEDIALOG_FILTERS
933 qDebug("QFileDialog:%d Split out filter (%d) '%s' '%s' [%s]", __LINE__, ret.count(),
934 filter->regxp.latin1(), filter->description.latin1(), (*it).latin1());
935#endif
936 ret.append(filter);
937 }
938 return ret;
939}
940
941void QFileDialogPrivate::createNavServicesDialog()
942{
943 Q_Q(QFileDialog);
944 if (mDialog)
945 deleteNativeDialog_sys();
946
947 NavDialogCreationOptions navOptions;
948 NavGetDefaultDialogCreationOptions(&navOptions);
949
950 // Translate QFileDialog settings into NavDialog options:
951 if (qt_mac_is_macsheet(q)) {
952 navOptions.modality = kWindowModalityWindowModal;
953 navOptions.parentWindow = qt_mac_window_for(q->parentWidget());
954 } else if (q->windowModality() == Qt::ApplicationModal)
955 navOptions.modality = kWindowModalityAppModal;
956 else
957 navOptions.modality = kWindowModalityNone;
958 navOptions.optionFlags |= kNavSupportPackages;
959 if (q->testOption(QFileDialog::DontConfirmOverwrite))
960 navOptions.optionFlags |= kNavDontConfirmReplacement;
961 if (fileMode != QFileDialog::ExistingFiles)
962 navOptions.optionFlags &= ~kNavAllowMultipleFiles;
963
964 navOptions.windowTitle = QCFString::toCFStringRef(q->windowTitle());
965
966 navOptions.location.h = -1;
967 navOptions.location.v = -1;
968
969 QWidget *parent = q->parentWidget();
970 if (parent && parent->isVisible()) {
971 WindowClass wclass;
972 GetWindowClass(qt_mac_window_for(parent), &wclass);
973 parent = parent->window();
974 QString s = parent->windowTitle();
975 navOptions.clientName = QCFString::toCFStringRef(s);
976 }
977
978 filterInfo.currentSelection = 0;
979 filterInfo.filters = qt_mac_make_filters_list(nameFilters.join(QLatin1String(";;")), q->isNameFilterDetailsVisible());
980 QCFType<CFArrayRef> filterArray;
981 if (filterInfo.filters.size() > 1) {
982 int i = 0;
983 CFStringRef *cfstringArray = static_cast<CFStringRef *>(malloc(sizeof(CFStringRef)
984 * filterInfo.filters.size()));
985 for (i = 0; i < filterInfo.filters.size(); ++i) {
986 cfstringArray[i] = QCFString::toCFStringRef(filterInfo.filters.at(i).description);
987 }
988 filterArray = CFArrayCreate(kCFAllocatorDefault,
989 reinterpret_cast<const void **>(cfstringArray), filterInfo.filters.size(),
990 &kCFTypeArrayCallBacks);
991 navOptions.popupExtension = filterArray;
992 free(cfstringArray);
993 }
994
995 if (q->acceptMode() == QFileDialog::AcceptSave) {
996 if (NavCreatePutFileDialog(&navOptions, 'cute', kNavGenericSignature,
997 QFileDialogPrivate::qt_mac_filedialog_event_proc, this, &mDialog)) {
998 qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
999 return;
1000 }
1001 } else if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory) {
1002 if (NavCreateChooseFolderDialog(&navOptions,
1003 QFileDialogPrivate::qt_mac_filedialog_event_proc, 0, this, &mDialog)) {
1004 qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
1005 return;
1006 }
1007 } else {
1008 if (NavCreateGetFileDialog(&navOptions, 0,
1009 QFileDialogPrivate::qt_mac_filedialog_event_proc, 0,
1010 QFileDialogPrivate::qt_mac_filedialog_filter_proc, this, &mDialog)) {
1011 qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
1012 return;
1013 }
1014 }
1015
1016 // Set start-up directory:
1017 if (mCurrentLocation.isEmpty())
1018 mCurrentLocation = rootPath();
1019 FSRef fsRef;
1020 if (qt_mac_create_fsref(mCurrentLocation, &fsRef) == noErr) {
1021 AEDesc desc;
1022 if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr)
1023 NavCustomControl(mDialog, kNavCtlSetLocation, (void*)&desc);
1024 }
1025}
1026
1027bool QFileDialogPrivate::showCarbonNavServicesDialog()
1028{
1029 Q_Q(QFileDialog);
1030 if (q->acceptMode() == QFileDialog::AcceptSave && q->windowModality() == Qt::NonModal)
1031 return false; // cannot do native no-modal save dialogs.
1032 createNavServicesDialog();
1033 mDialogClosed = false;
1034 if (q->windowModality() != Qt::ApplicationModal)
1035 NavDialogRun(mDialog);
1036 return true;
1037}
1038
1039bool QFileDialogPrivate::hideCarbonNavServicesDialog()
1040{
1041 if (!mDialogClosed){
1042 mDialogClosed = true;
1043 NavCustomControl(mDialog, kNavCtlCancel, 0);
1044 }
1045 return true;
1046}
1047
1048#else // Cocoa
1049
1050void QFileDialogPrivate::createNSOpenSavePanelDelegate()
1051{
1052 Q_Q(QFileDialog);
1053 if (mDelegate)
1054 return;
1055
1056 bool selectDir = q->selectedFiles().isEmpty();
1057 QString selection(selectDir ? q->directory().absolutePath() : q->selectedFiles().value(0));
1058 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) alloc]
1059 initWithAcceptMode:acceptMode
1060 title:q->windowTitle()
1061 hideNameFilterDetails:q->testOption(QFileDialog::HideNameFilterDetails)
1062 qDirFilter:model->filter()
1063 fileOptions:opts
1064 fileMode:fileMode
1065 selectFile:selection
1066 confirmOverwrite:!q->testOption(QFileDialog::DontConfirmOverwrite)
1067 priv:this];
1068
1069 mDelegate = delegate;
1070}
1071
1072bool QFileDialogPrivate::showCocoaFilePanel()
1073{
1074 Q_Q(QFileDialog);
1075 QMacCocoaAutoReleasePool pool;
1076 createNSOpenSavePanelDelegate();
1077 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
1078 if (qt_mac_is_macsheet(q))
1079 [delegate showWindowModalSheet:q->parentWidget()];
1080 else
1081 [delegate showModelessPanel];
1082 return true;
1083}
1084
1085bool QFileDialogPrivate::hideCocoaFilePanel()
1086{
1087 if (!mDelegate){
1088 // Nothing to do. We return false to leave the question
1089 // open regarding whether or not to go native:
1090 return false;
1091 } else {
1092 QMacCocoaAutoReleasePool pool;
1093 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
1094 [delegate closePanel];
1095 // Even when we hide it, we are still using a
1096 // native dialog, so return true:
1097 return true;
1098 }
1099}
1100
1101#endif
1102
1103void QFileDialogPrivate::mac_nativeDialogModalHelp()
1104{
1105 // Do a queued meta-call to open the native modal dialog so it opens after the new
1106 // event loop has started to execute (in QDialog::exec). Using a timer rather than
1107 // a queued meta call is intentional to ensure that the call is only delivered when
1108 // [NSApp run] runs (timers are handeled special in cocoa). If NSApp is not
1109 // running (which is the case if e.g a top-most QEventLoop has been
1110 // interrupted, and the second-most event loop has not yet been reactivated (regardless
1111 // if [NSApp run] is still on the stack)), showing a native modal dialog will fail.
1112 if (nativeDialogInUse){
1113 Q_Q(QFileDialog);
1114 QTimer::singleShot(1, q, SLOT(_q_macRunNativeAppModalPanel()));
1115 }
1116}
1117
1118void QFileDialogPrivate::_q_macRunNativeAppModalPanel()
1119{
1120 QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
1121#ifndef QT_MAC_USE_COCOA
1122 NavDialogRun(mDialog);
1123#else
1124 Q_Q(QFileDialog);
1125 QMacCocoaAutoReleasePool pool;
1126 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
1127 [delegate runApplicationModalPanel];
1128 dialogResultCode_sys() == QDialog::Accepted ? q->accept() : q->reject();
1129#endif
1130}
1131
1132QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys()
1133{
1134#ifndef QT_MAC_USE_COCOA
1135 NavUserAction result = NavDialogGetUserAction(mDialog);
1136 if (result == kNavUserActionCancel || result == kNavUserActionNone)
1137 return QDialog::Rejected;
1138 else
1139 return QDialog::Accepted;
1140#else
1141 QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
1142 return [delegate dialogResultCode];
1143#endif
1144}
1145
1146
1147QT_END_NAMESPACE
1148
1149#endif // QT_NO_FILEDIALOG
1150
Note: See TracBrowser for help on using the repository browser.