diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 95 |
1 files changed, 50 insertions, 45 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index b3bc4a8ebf..1ad833ee44 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -61,12 +61,12 @@ #include <stdlib.h> #include <qabstracteventdispatcher.h> #include "qcocoaautoreleasepool.h" -#include <QFileSystemWatcher> #include <QDir> #include <qpa/qplatformnativeinterface.h> #import <AppKit/NSSavePanel.h> +#import <CoreFoundation/CFNumber.h> QT_FORWARD_DECLARE_CLASS(QString) QT_FORWARD_DECLARE_CLASS(QStringList) @@ -74,30 +74,6 @@ QT_FORWARD_DECLARE_CLASS(QFileInfo) QT_FORWARD_DECLARE_CLASS(QWindow) QT_USE_NAMESPACE -class CachedEntries: public QObject { -public: - CachedEntries(QDir::Filters filters) : mFilters(filters) { - QObject::connect(&mFSWatcher, &QFileSystemWatcher::directoryChanged, this, &CachedEntries::updateDirCache); - } - QString directory() const { - const QStringList &dirs = mFSWatcher.directories(); - return (dirs.count() ? dirs[0] : QString()); - } - QStringList entries() const { - return mQDirFilterEntryList; - } - void updateDirCache(const QString &path) { - mFSWatcher.removePaths(mFSWatcher.directories()); - mFSWatcher.addPath(path); - mQDirFilterEntryList = QDir(path).entryList(mFilters); - } - -private: - QFileSystemWatcher mFSWatcher; - QStringList mQDirFilterEntryList; - QDir::Filters mFilters; -}; - typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; @class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate); @@ -117,7 +93,6 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions; int mReturnCode; SharedPointerFileDialogOptions mOptions; - CachedEntries *mCachedEntries; QString *mCurrentSelection; QStringList *mNameFilterDropDownList; QStringList *mSelectedNameFilter; @@ -164,7 +139,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); [mSavePanel setDelegate:self]; mReturnCode = -1; mHelper = helper; - mCachedEntries = new CachedEntries(mOptions->filter()); mNameFilterDropDownList = new QStringList(mOptions->nameFilters()); QString selectedVisualNameFilter = mOptions->initiallySelectedNameFilter(); mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]); @@ -197,7 +171,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); - (void)dealloc { - delete mCachedEntries; delete mNameFilterDropDownList; delete mSelectedNameFilter; delete mCurrentSelection; @@ -308,6 +281,22 @@ static QString strippedText(QString s) }]; } +- (BOOL)isHiddenFile:(NSString *)filename isDir:(BOOL)isDir +{ + CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)filename, kCFURLPOSIXPathStyle, isDir); + CFBooleanRef isHidden; + Boolean errorOrHidden = false; + if (!CFURLCopyResourcePropertyForKey(url, kCFURLIsHiddenKey, &isHidden, NULL)) { + errorOrHidden = true; + } else { + if (CFBooleanGetValue(isHidden)) + errorOrHidden = true; + CFRelease(isHidden); + } + CFRelease(url); + return errorOrHidden; +} + - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { Q_UNUSED(sender); @@ -316,8 +305,13 @@ static QString strippedText(QString s) return NO; // Always accept directories regardless of their names (unless it is a bundle): - BOOL isDir; - if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir) { + NSFileManager *fm = [NSFileManager defaultManager]; + NSDictionary *fileAttrs = [fm attributesOfItemAtPath:filename error:nil]; + if (!fileAttrs) + return NO; // Error accessing the file means 'no'. + NSString *fileType = [fileAttrs fileType]; + bool isDir = [fileType isEqualToString:NSFileTypeDirectory]; + if (isDir) { if ([mSavePanel treatsFilePackagesAsDirectories] == NO) { if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO) return YES; @@ -325,24 +319,35 @@ static QString strippedText(QString s) } QString qtFileName = QCFString::toQString(filename); - QFileInfo info(qtFileName.normalized(QString::NormalizationForm_C)); - QString path = info.absolutePath(); - if (mCachedEntries->directory() != path) { - mCachedEntries->updateDirCache(path); - } - // Check if the QDir filter accepts the file: - if (!mCachedEntries->entries().contains(info.fileName())) - return NO; - // No filter means accept everything - if (mSelectedNameFilter->isEmpty()) - return YES; + bool nameMatches = mSelectedNameFilter->isEmpty(); // Check if the current file name filter accepts the file: - for (int i=0; i<mSelectedNameFilter->size(); ++i) { + for (int i = 0; !nameMatches && i < mSelectedNameFilter->size(); ++i) { if (QDir::match(mSelectedNameFilter->at(i), qtFileName)) - return YES; + nameMatches = true; + } + if (!nameMatches) + return NO; + + QDir::Filters filter = mOptions->filter(); + if ((!(filter & (QDir::Dirs | QDir::AllDirs)) && isDir) + || (!(filter & QDir::Files) && [fileType isEqualToString:NSFileTypeRegular]) + || ((filter & QDir::NoSymLinks) && [fileType isEqualToString:NSFileTypeSymbolicLink])) + return NO; + + bool filterPermissions = ((filter & QDir::PermissionMask) + && (filter & QDir::PermissionMask) != QDir::PermissionMask); + if (filterPermissions) { + if ((!(filter & QDir::Readable) && [fm isReadableFileAtPath:filename]) + || (!(filter & QDir::Writable) && [fm isWritableFileAtPath:filename]) + || (!(filter & QDir::Executable) && [fm isExecutableFileAtPath:filename])) + return NO; } - return NO; + if (!(filter & QDir::Hidden) + && (qtFileName.startsWith(QLatin1Char('.')) || [self isHiddenFile:filename isDir:isDir])) + return NO; + + return YES; } - (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag @@ -461,7 +466,7 @@ static QString strippedText(QString s) Q_UNUSED(sender); if (!mHelper) return; - if ([path isEqualToString:mCurrentDir]) + if (!(path && path.length) || [path isEqualToString:mCurrentDir]) return; [mCurrentDir release]; |