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