diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index 677a678959d3e26be858a73055b65b833614c908..396321547747ab1056d3c1f4d69eeb0b5abe1179 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -70,11 +70,11 @@ namespace {
 
 void runFileSearch(QFutureInterface<FileSearchResult> &future,
                    QString searchTerm,
-                   QStringList files,
+                   FileIterator *files,
                    QTextDocument::FindFlags flags,
                    QMap<QString, QString> fileToContentsMap)
 {
-    future.setProgressRange(0, files.size());
+    future.setProgressRange(0, files->maxProgress());
     int numFilesSearched = 0;
     int numMatches = 0;
 
@@ -95,11 +95,13 @@ void runFileSearch(QFutureInterface<FileSearchResult> &future,
 
     QFile file;
     QBuffer buffer;
-    foreach (const QString &s, files) {
+    while (files->hasNext()) {
+        const QString &s = files->next();
+        future.setProgressRange(0, files->maxProgress());
         if (future.isPaused())
             future.waitForResume();
         if (future.isCanceled()) {
-            future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
+            future.setProgressValueAndText(files->currentProgress(), msgCanceled(searchTerm, numMatches, numFilesSearched));
             break;
         }
         QIODevice *device;
@@ -180,20 +182,22 @@ void runFileSearch(QFutureInterface<FileSearchResult> &future,
             firstChunk = false;
         }
         ++numFilesSearched;
-        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
+        if (future.isProgressUpdateNeeded())
+            future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
         device->close();
     }
     if (!future.isCanceled())
-        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
+        future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
+    delete files;
 }
 
 void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
                    QString searchTerm,
-                   QStringList files,
+                   FileIterator *files,
                    QTextDocument::FindFlags flags,
                    QMap<QString, QString> fileToContentsMap)
 {
-    future.setProgressRange(0, files.size());
+    future.setProgressRange(0, files->maxProgress());
     int numFilesSearched = 0;
     int numMatches = 0;
     if (flags & QTextDocument::FindWholeWords)
@@ -204,11 +208,13 @@ void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
     QFile file;
     QString str;
     QTextStream stream;
-    foreach (const QString &s, files) {
+    while (files->hasNext()) {
+        const QString &s = files->next();
+        future.setProgressRange(0, files->maxProgress());
         if (future.isPaused())
             future.waitForResume();
         if (future.isCanceled()) {
-            future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
+            future.setProgressValueAndText(files->currentProgress(), msgCanceled(searchTerm, numMatches, numFilesSearched));
             break;
         }
 
@@ -237,28 +243,30 @@ void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
             ++lineNr;
         }
         ++numFilesSearched;
-        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
+        if (future.isProgressUpdateNeeded())
+            future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
         if (needsToCloseFile)
             file.close();
     }
     if (!future.isCanceled())
-        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
+        future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched));
+    delete files;
 }
 
 } // namespace
 
 
-QFuture<FileSearchResult> Utils::findInFiles(const QString &searchTerm, const QStringList &files,
+QFuture<FileSearchResult> Utils::findInFiles(const QString &searchTerm, FileIterator *files,
     QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
 {
-    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
+    return QtConcurrent::run<FileSearchResult, QString, FileIterator *, QTextDocument::FindFlags, QMap<QString, QString> >
             (runFileSearch, searchTerm, files, flags, fileToContentsMap);
 }
 
-QFuture<FileSearchResult> Utils::findInFilesRegExp(const QString &searchTerm, const QStringList &files,
+QFuture<FileSearchResult> Utils::findInFilesRegExp(const QString &searchTerm, FileIterator *files,
     QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
 {
-    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
+    return QtConcurrent::run<FileSearchResult, QString, FileIterator *, QTextDocument::FindFlags, QMap<QString, QString> >
             (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);
 }
 
@@ -294,3 +302,133 @@ QString Utils::expandRegExpReplacement(const QString &replaceText, const QString
     }
     return result;
 }
+
+// #pragma mark -- FileIterator
+
+FileIterator::FileIterator()
+    : m_list(QStringList()),
+    m_iterator(0),
+    m_index(0)
+{
+}
+
+FileIterator::FileIterator(const QStringList &fileList)
+    : m_list(fileList),
+    m_iterator(new QStringListIterator(m_list)),
+    m_index(0)
+{
+}
+
+FileIterator::~FileIterator()
+{
+    if (m_iterator)
+        delete m_iterator;
+}
+
+bool FileIterator::hasNext() const
+{
+    Q_ASSERT(m_iterator);
+    return m_iterator->hasNext();
+}
+
+QString FileIterator::next()
+{
+    Q_ASSERT(m_iterator);
+    ++m_index;
+    return m_iterator->next();
+}
+
+int FileIterator::maxProgress() const
+{
+    return m_list.size();
+}
+
+int FileIterator::currentProgress() const
+{
+    return m_index;
+}
+
+// #pragma mark -- SubDirFileIterator
+
+namespace {
+    const int MAX_PROGRESS = 360;
+}
+
+SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters)
+    : m_filters(filters), m_progress(0)
+{
+    int maxPer = MAX_PROGRESS/directories.count();
+    foreach (const QString &directoryEntry, directories) {
+        if (!directoryEntry.isEmpty()) {
+            m_dirs.push(QDir(directoryEntry));
+            m_progressValues.push(maxPer);
+            m_processedValues.push(false);
+        }
+    }
+}
+
+bool SubDirFileIterator::hasNext() const
+{
+    if (!m_currentFiles.isEmpty())
+        return true;
+    while(!m_dirs.isEmpty() && m_currentFiles.isEmpty()) {
+        QDir dir = m_dirs.pop();
+        int dirProgressMax = m_progressValues.pop();
+        bool processed = m_processedValues.pop();
+        if (dir.exists()) {
+            QStringList subDirs;
+            if (!processed) {
+                subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot);
+            }
+            if (subDirs.isEmpty()) {
+                QStringList fileEntries = dir.entryList(m_filters,
+                    QDir::Files|QDir::Hidden);
+                QStringListIterator it(fileEntries);
+                it.toBack();
+                while (it.hasPrevious()) {
+                    const QString &file = it.previous();
+                    m_currentFiles.append(dir.path()+ QLatin1Char('/') +file);
+                }
+                m_progress += dirProgressMax;
+            } else {
+                int subProgress = dirProgressMax/(subDirs.size()+1);
+                int selfProgress = subProgress + dirProgressMax%(subDirs.size()+1);
+                m_dirs.push(dir);
+                m_progressValues.push(selfProgress);
+                m_processedValues.push(true);
+                QStringListIterator it(subDirs);
+                it.toBack();
+                while (it.hasPrevious()) {
+                    const QString &directory = it.previous();
+                    m_dirs.push(QDir(dir.path()+ QLatin1Char('/') + directory));
+                    m_progressValues.push(subProgress);
+                    m_processedValues.push(false);
+                }
+            }
+        } else {
+            m_progress += dirProgressMax;
+        }
+    }
+    if (m_currentFiles.isEmpty()) {
+        m_progress = MAX_PROGRESS;
+        return false;
+    }
+
+    return true;
+}
+
+QString SubDirFileIterator::next()
+{
+    Q_ASSERT(!m_currentFiles.isEmpty());
+    return m_currentFiles.takeFirst();
+}
+
+int SubDirFileIterator::maxProgress() const
+{
+    return MAX_PROGRESS;
+}
+
+int SubDirFileIterator::currentProgress() const
+{
+    return m_progress;
+}
diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h
index f2860e34e0147c4bb6990326ca53ef1da539f360..0b3f895387028be30191ee656a90abd26a15a309 100644
--- a/src/libs/utils/filesearch.h
+++ b/src/libs/utils/filesearch.h
@@ -35,10 +35,49 @@
 #include <QtCore/QStringList>
 #include <QtCore/QFuture>
 #include <QtCore/QMap>
+#include <QtCore/QStack>
+#include <QtCore/QDir>
 #include <QtGui/QTextDocument>
 
 namespace Utils {
 
+class QTCREATOR_UTILS_EXPORT FileIterator
+{
+public:
+    FileIterator();
+    explicit FileIterator(const QStringList &fileList);
+    ~FileIterator();
+
+    virtual bool hasNext() const;
+    virtual QString next();
+    virtual int maxProgress() const;
+    virtual int currentProgress() const;
+
+private:
+    QStringList m_list;
+    QStringListIterator *m_iterator;
+    int m_index;
+};
+
+class QTCREATOR_UTILS_EXPORT SubDirFileIterator : public FileIterator
+{
+public:
+    SubDirFileIterator(const QStringList &directories, const QStringList &filters);
+
+    bool hasNext() const;
+    QString next();
+    int maxProgress() const;
+    int currentProgress() const;
+
+private:
+    QStringList m_filters;
+    mutable QStack<QDir> m_dirs;
+    mutable QStack<int> m_progressValues;
+    mutable QStack<bool> m_processedValues;
+    mutable int m_progress;
+    mutable QStringList m_currentFiles;
+};
+
 class QTCREATOR_UTILS_EXPORT FileSearchResult
 {
 public:
@@ -62,10 +101,10 @@ public:
     QStringList regexpCapturedTexts;
 };
 
-QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFiles(const QString &searchTerm, const QStringList &files,
+QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFiles(const QString &searchTerm, FileIterator *files,
     QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap = QMap<QString, QString>());
 
-QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFilesRegExp(const QString &searchTerm, const QStringList &files,
+QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFilesRegExp(const QString &searchTerm, FileIterator *files,
     QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap = QMap<QString, QString>());
 
 QTCREATOR_UTILS_EXPORT QString expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts);
diff --git a/src/plugins/locator/directoryfilter.cpp b/src/plugins/locator/directoryfilter.cpp
index 7049d50c0661a6d257aa12f91c6546bddd3f9360..b41cd6c59390713751c62f428c876248b011129c 100644
--- a/src/plugins/locator/directoryfilter.cpp
+++ b/src/plugins/locator/directoryfilter.cpp
@@ -36,6 +36,7 @@
 #include <QtGui/QMessageBox>
 
 #include <qtconcurrent/QtConcurrentTools>
+#include <utils/filesearch.h>
 
 using namespace Locator;
 using namespace Locator::Internal;
@@ -181,76 +182,35 @@ void DirectoryFilter::updateOptionButtons()
 
 void DirectoryFilter::refresh(QFutureInterface<void> &future)
 {
-    const int MAX = 360;
-    future.setProgressRange(0, MAX);
-    if (m_directories.count() < 1) {
+    QStringList directories;
+    {
         QMutexLocker locker(&m_lock);
-        files().clear();
-        generateFileNames();
-        future.setProgressValueAndText(MAX, tr("%1 filter update: 0 files").arg(m_name));
-        return;
-    }
-    int progress = 0;
-    int MAX_PER = MAX;
-    QStringList filesFound;
-    QStack<QDir> dirs;
-    QStack<int> progressValues;
-    QStack<bool> processedValues;
-    { // initialize
-        QMutexLocker locker(&m_lock);
-        MAX_PER = MAX/m_directories.count();
-        foreach (const QString &directoryEntry, m_directories) {
-            if (!directoryEntry.isEmpty()) {
-                dirs.push(QDir(directoryEntry));
-                progressValues.push(MAX_PER);
-                processedValues.push(false);
-            }
+        if (m_directories.count() < 1) {
+            files().clear();
+            generateFileNames();
+            future.setProgressRange(0, 1);
+            future.setProgressValueAndText(1, tr("%1 filter update: 0 files").arg(m_name));
+            return;
         }
+        directories = m_directories;
     }
-    while (!dirs.isEmpty() && !future.isCanceled()) {
+    Utils::SubDirFileIterator it(directories, m_filters);
+    future.setProgressRange(0, it.maxProgress());
+    QStringList filesFound;
+    while (!future.isCanceled() && it.hasNext()) {
+        filesFound << it.next();
         if (future.isProgressUpdateNeeded()) {
-            future.setProgressValueAndText(progress,
+            future.setProgressValueAndText(it.currentProgress(),
                                            tr("%1 filter update: %n files", 0, filesFound.size()).arg(m_name));
         }
-        QDir dir = dirs.pop();
-        int dirProgressMax = progressValues.pop();
-        bool processed = processedValues.pop();
-        if (dir.exists()) {
-            QStringList subDirs;
-            if (!processed) {
-                subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot,
-                    QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
-            }
-            if (subDirs.isEmpty()) {
-                QStringList fileEntries = dir.entryList(m_filters,
-                    QDir::Files|QDir::Hidden,
-                    QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
-                foreach (const QString &file, fileEntries)
-                    filesFound.append(dir.path()+ QLatin1Char('/') +file);
-                progress += dirProgressMax;
-            } else {
-                int subProgress = dirProgressMax/(subDirs.size()+1);
-                int selfProgress = subProgress + dirProgressMax%(subDirs.size()+1);
-                dirs.push(dir);
-                progressValues.push(selfProgress);
-                processedValues.push(true);
-                foreach (const QString &directory, subDirs) {
-                    dirs.push(QDir(dir.path()+ QLatin1Char('/') + directory));
-                    progressValues.push(subProgress);
-                    processedValues.push(false);
-                }
-            }
-        } else {
-            progress += dirProgressMax;
-        }
     }
 
     if (!future.isCanceled()) {
         QMutexLocker locker(&m_lock);
         files() = filesFound;
         generateFileNames();
-        future.setProgressValue(MAX);
+        future.setProgressValue(it.maxProgress());
     } else {
-        future.setProgressValueAndText(progress, tr("%1 filter update: canceled").arg(m_name));
+        future.setProgressValueAndText(it.currentProgress(), tr("%1 filter update: canceled").arg(m_name));
     }
 }
diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp
index d621662c87d897c656f37e4919eb632fcb9d35b2..abb1b90b23ad302a8e8ae018d1cf1f2ca38ad9c5 100644
--- a/src/plugins/projectexplorer/allprojectsfind.cpp
+++ b/src/plugins/projectexplorer/allprojectsfind.cpp
@@ -77,7 +77,7 @@ QKeySequence AllProjectsFind::defaultShortcut() const
     return QKeySequence();
 }
 
-QStringList AllProjectsFind::files()
+Utils::FileIterator *AllProjectsFind::files()
 {
     Q_ASSERT(m_plugin->session());
     QList<QRegExp> filterRegs;
@@ -103,7 +103,7 @@ QStringList AllProjectsFind::files()
         }
     }
     files.removeDuplicates();
-    return files;
+    return new Utils::FileIterator(files);
 }
 
 QWidget *AllProjectsFind::createConfigWidget()
diff --git a/src/plugins/projectexplorer/allprojectsfind.h b/src/plugins/projectexplorer/allprojectsfind.h
index 613c63abd3690d5afcab344633db29de41590bae..2f78757c1564c798a3db0bd635b2a8c36c3b5bc6 100644
--- a/src/plugins/projectexplorer/allprojectsfind.h
+++ b/src/plugins/projectexplorer/allprojectsfind.h
@@ -61,7 +61,7 @@ public:
     void readSettings(QSettings *settings);
 
 protected:
-    QStringList files();
+    Utils::FileIterator *files();
 
 private:
     ProjectExplorerPlugin *m_plugin;
diff --git a/src/plugins/projectexplorer/currentprojectfind.cpp b/src/plugins/projectexplorer/currentprojectfind.cpp
index cae569bbdf45d43d756997808af6105b404ef1e2..7256a8603b304d075aec1fa6c22c35f6be5b8105 100644
--- a/src/plugins/projectexplorer/currentprojectfind.cpp
+++ b/src/plugins/projectexplorer/currentprojectfind.cpp
@@ -75,7 +75,7 @@ QKeySequence CurrentProjectFind::defaultShortcut() const
     return QKeySequence();
 }
 
-QStringList CurrentProjectFind::files()
+Utils::FileIterator *CurrentProjectFind::files()
 {
     Project *project = m_plugin->currentProject();
     Q_ASSERT(project);
@@ -98,7 +98,7 @@ QStringList CurrentProjectFind::files()
         files += project->files(Project::AllFiles);
     }
     files.removeDuplicates();
-    return files;
+    return new Utils::FileIterator(files);
 }
 
 QWidget *CurrentProjectFind::createConfigWidget()
diff --git a/src/plugins/projectexplorer/currentprojectfind.h b/src/plugins/projectexplorer/currentprojectfind.h
index 53d57ff2646dce766106954aa1a8296d73de5a2f..2e98e49e1b1756c72ae11f86a907fd11bd7f530a 100644
--- a/src/plugins/projectexplorer/currentprojectfind.h
+++ b/src/plugins/projectexplorer/currentprojectfind.h
@@ -64,7 +64,7 @@ public:
     void readSettings(QSettings *settings);
 
 protected:
-    QStringList files();
+    Utils::FileIterator *files();
 
 private:
     ProjectExplorerPlugin *m_plugin;
diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h
index c0fdaa82f6113db632a0cbf0db38d3acfaf642a8..b423eb8b531cf0ef2cfb3f7bb1209c2b94ddab96 100644
--- a/src/plugins/texteditor/basefilefind.h
+++ b/src/plugins/texteditor/basefilefind.h
@@ -71,7 +71,7 @@ public:
                                   const QList<Find::SearchResultItem> &items);
 
 protected:
-    virtual QStringList files() = 0;
+    virtual Utils::FileIterator *files() = 0;
     void writeCommonSettings(QSettings *settings);
     void readCommonSettings(QSettings *settings, const QString &defaultFilter);
     QWidget *createPatternWidget();
diff --git a/src/plugins/texteditor/findincurrentfile.cpp b/src/plugins/texteditor/findincurrentfile.cpp
index 22170f35e5c67a592e2d4c50f957303f6f746aae..736bc78ae4d6eb8f038b4d37a557da3e6785cb2d 100644
--- a/src/plugins/texteditor/findincurrentfile.cpp
+++ b/src/plugins/texteditor/findincurrentfile.cpp
@@ -67,12 +67,12 @@ QKeySequence FindInCurrentFile::defaultShortcut() const
     return QKeySequence();
 }
 
-QStringList FindInCurrentFile::files()
+Utils::FileIterator *FindInCurrentFile::files()
 {
     QStringList fileList;
     if (isEnabled())
         fileList << m_currentFile->fileName();
-    return fileList;
+    return new Utils::FileIterator(fileList);
 }
 
 bool FindInCurrentFile::isEnabled() const
diff --git a/src/plugins/texteditor/findincurrentfile.h b/src/plugins/texteditor/findincurrentfile.h
index 1f5ec7ba5d7651cb979e92bfd209d0705bb29112..7c6f28c93a676913e90a6cff174e08f3837d7124 100644
--- a/src/plugins/texteditor/findincurrentfile.h
+++ b/src/plugins/texteditor/findincurrentfile.h
@@ -62,7 +62,7 @@ public:
     void readSettings(QSettings *settings);
 
 protected:
-    QStringList files();
+    Utils::FileIterator *files();
 
 private slots:
     void handleFileChange(Core::IEditor *editor);
diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp
index e2c28b417f11506e7256265cc58648e05b05570b..963cb0dea135313afb8272762a9c9d90af4effc4 100644
--- a/src/plugins/texteditor/findinfiles.cpp
+++ b/src/plugins/texteditor/findinfiles.cpp
@@ -68,18 +68,10 @@ void FindInFiles::findAll(const QString &txt, QTextDocument::FindFlags findFlags
     BaseFileFind::findAll(txt, findFlags);
 }
 
-QStringList FindInFiles::files()
+Utils::FileIterator *FindInFiles::files()
 {
-    QStringList fileList;
-    QDirIterator it(m_directory->currentText(),
-                    fileNameFilters(),
-                    QDir::Files|QDir::Readable,
-                    QDirIterator::Subdirectories);
-
-    while (it.hasNext())
-        fileList << it.next();
-
-    return fileList;
+    return new Utils::SubDirFileIterator(QStringList() << m_directory->currentText(),
+                                         fileNameFilters());
 }
 
 QWidget *FindInFiles::createConfigWidget()
diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h
index 91e4c484746cd3f07ab1818e4bec161751f731c6..baf899439d10f99a1d6dfbe104a76cba34865325 100644
--- a/src/plugins/texteditor/findinfiles.h
+++ b/src/plugins/texteditor/findinfiles.h
@@ -60,7 +60,7 @@ public:
     void readSettings(QSettings *settings);
 
 protected:
-    QStringList files();
+    Utils::FileIterator *files();
 
 private slots:
     void openFileBrowser();