Correct dir entries caching in QFileDialog

Using QFileSystemWatcher to update cache when directory is changed. It is
needed to correctly filter files created after the dialog opening.

Task-number: QTBUG-30604

Change-Id: I5479f9a54095de59ca2ba36b2bd4906de0907ac8
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
This commit is contained in:
Cyril Oblikov 2013-04-10 16:18:52 +03:00 committed by The Qt Project
parent c77f7229d5
commit 9557cc6536

View File

@ -61,6 +61,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <qabstracteventdispatcher.h> #include <qabstracteventdispatcher.h>
#include "qcocoaautoreleasepool.h" #include "qcocoaautoreleasepool.h"
#include <QFileSystemWatcher>
#include <QDir>
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
@ -72,6 +74,30 @@ QT_FORWARD_DECLARE_CLASS(QFileInfo)
QT_FORWARD_DECLARE_CLASS(QWindow) QT_FORWARD_DECLARE_CLASS(QWindow)
QT_USE_NAMESPACE 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; typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
@class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate); @class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate);
@ -91,9 +117,8 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
int mReturnCode; int mReturnCode;
SharedPointerFileDialogOptions mOptions; SharedPointerFileDialogOptions mOptions;
QString *mLastFilterCheckPath; CachedEntries *mCachedEntries;
QString *mCurrentSelection; QString *mCurrentSelection;
QStringList *mQDirFilterEntryList;
QStringList *mNameFilterDropDownList; QStringList *mNameFilterDropDownList;
QStringList *mSelectedNameFilter; QStringList *mSelectedNameFilter;
} }
@ -137,8 +162,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
[mSavePanel setDelegate:self]; [mSavePanel setDelegate:self];
mReturnCode = -1; mReturnCode = -1;
mHelper = helper; mHelper = helper;
mLastFilterCheckPath = new QString; mCachedEntries = new CachedEntries(mOptions->filter());
mQDirFilterEntryList = new QStringList;
mNameFilterDropDownList = new QStringList(mOptions->nameFilters()); mNameFilterDropDownList = new QStringList(mOptions->nameFilters());
QString selectedVisualNameFilter = mOptions->initiallySelectedNameFilter(); QString selectedVisualNameFilter = mOptions->initiallySelectedNameFilter();
mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]); mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]);
@ -171,8 +195,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
- (void)dealloc - (void)dealloc
{ {
delete mLastFilterCheckPath; delete mCachedEntries;
delete mQDirFilterEntryList;
delete mNameFilterDropDownList; delete mNameFilterDropDownList;
delete mSelectedNameFilter; delete mSelectedNameFilter;
delete mCurrentSelection; delete mCurrentSelection;
@ -303,12 +326,11 @@ static QString strippedText(QString s)
QString qtFileName = QT_PREPEND_NAMESPACE(QCFString::toQString)(filename); QString qtFileName = QT_PREPEND_NAMESPACE(QCFString::toQString)(filename);
QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C))); QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C)));
QString path = info.absolutePath(); QString path = info.absolutePath();
if (path != *mLastFilterCheckPath){ if (mCachedEntries->directory() != path) {
*mLastFilterCheckPath = path; mCachedEntries->updateDirCache(path);
*mQDirFilterEntryList = info.dir().entryList(mOptions->filter());
} }
// Check if the QDir filter accepts the file: // Check if the QDir filter accepts the file:
if (!mQDirFilterEntryList->contains(info.fileName())) if (!mCachedEntries->entries().contains(info.fileName()))
return NO; return NO;
// No filter means accept everything // No filter means accept everything