forked from qt-creator/qt-creator
FileSearch: Move FileIterator to std iterator semantics.
We need this when we want to use QtConcurrent::mappedReduced. Change-Id: I4a6a31f4a0cc9a739a263cc148a1d51d7aa5d418 Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
This commit is contained in:
@@ -246,8 +246,9 @@ void runFileSearch(QFutureInterface<FileSearchResultList> &future,
|
||||
QString str;
|
||||
QTextStream stream;
|
||||
FileSearchResultList results;
|
||||
while (files->hasNext()) {
|
||||
const QString &filePath = files->next();
|
||||
auto end = files->end();
|
||||
for (auto it = files->begin(); it != end; ++it) {
|
||||
const QString &filePath = it->filePath;
|
||||
if (future.isPaused())
|
||||
future.waitForResume();
|
||||
if (future.isCanceled()) {
|
||||
@@ -267,7 +268,7 @@ void runFileSearch(QFutureInterface<FileSearchResultList> &future,
|
||||
continue;
|
||||
needsToCloseFile = true;
|
||||
stream.setDevice(&file);
|
||||
stream.setCodec(files->encoding());
|
||||
stream.setCodec(it->encoding);
|
||||
}
|
||||
|
||||
const FileSearchResultList singleFileResults = searchFunction(filePath, stream);
|
||||
@@ -420,9 +421,8 @@ QString matchCaseReplacement(const QString &originalText, const QString &replace
|
||||
return replaceText; // mixed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString Utils::matchCaseReplacement(const QString &originalText, const QString &replaceText)
|
||||
QString matchCaseReplacement(const QString &originalText, const QString &replaceText)
|
||||
{
|
||||
if (originalText.isEmpty())
|
||||
return replaceText;
|
||||
@@ -451,55 +451,83 @@ QString Utils::matchCaseReplacement(const QString &originalText, const QString &
|
||||
|
||||
// #pragma mark -- FileIterator
|
||||
|
||||
FileIterator::FileIterator()
|
||||
: m_list(QStringList()),
|
||||
m_iterator(0),
|
||||
m_index(-1)
|
||||
void FileIterator::next(FileIterator::const_iterator *it)
|
||||
{
|
||||
if (it->m_index < 0) // == end
|
||||
return;
|
||||
++it->m_index;
|
||||
update(it->m_index);
|
||||
if (it->m_index < currentFileCount()) {
|
||||
it->m_item.filePath = fileAt(it->m_index);
|
||||
it->m_item.encoding = codecAt(it->m_index);
|
||||
} else {
|
||||
it->m_index = -1; // == end
|
||||
it->m_item.filePath.clear();
|
||||
it->m_item.encoding = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FileIterator::FileIterator(const QStringList &fileList,
|
||||
const QList<QTextCodec *> encodings)
|
||||
: m_list(fileList),
|
||||
m_iterator(new QStringListIterator(m_list)),
|
||||
FileIterator::const_iterator FileIterator::begin()
|
||||
{
|
||||
update(0);
|
||||
if (currentFileCount() == 0)
|
||||
return end();
|
||||
return FileIterator::const_iterator(this,
|
||||
FileIterator::Item(fileAt(0), codecAt(0)),
|
||||
0/*index*/);
|
||||
}
|
||||
|
||||
FileIterator::const_iterator FileIterator::end()
|
||||
{
|
||||
return FileIterator::const_iterator(this, FileIterator::Item(QString(), 0),
|
||||
-1/*end*/);
|
||||
}
|
||||
|
||||
// #pragma mark -- FileListIterator
|
||||
|
||||
FileListIterator::FileListIterator(const QStringList &fileList,
|
||||
const QList<QTextCodec *> encodings)
|
||||
: m_files(fileList),
|
||||
m_encodings(encodings),
|
||||
m_index(-1)
|
||||
m_maxIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
FileIterator::~FileIterator()
|
||||
void FileListIterator::update(int requestedIndex)
|
||||
{
|
||||
if (m_iterator)
|
||||
delete m_iterator;
|
||||
if (requestedIndex > m_maxIndex)
|
||||
m_maxIndex = requestedIndex;
|
||||
}
|
||||
|
||||
bool FileIterator::hasNext() const
|
||||
int FileListIterator::currentFileCount() const
|
||||
{
|
||||
Q_ASSERT(m_iterator);
|
||||
return m_iterator->hasNext();
|
||||
return m_files.size();
|
||||
}
|
||||
|
||||
QString FileIterator::next()
|
||||
QString FileListIterator::fileAt(int index) const
|
||||
{
|
||||
Q_ASSERT(m_iterator);
|
||||
++m_index;
|
||||
return m_iterator->next();
|
||||
return m_files.at(index);
|
||||
}
|
||||
|
||||
int FileIterator::maxProgress() const
|
||||
QTextCodec *FileListIterator::codecAt(int index) const
|
||||
{
|
||||
return m_list.size();
|
||||
return m_encodings.at(index);
|
||||
}
|
||||
|
||||
int FileIterator::currentProgress() const
|
||||
int FileListIterator::maxProgress() const
|
||||
{
|
||||
return m_index + 1;
|
||||
return m_files.size();
|
||||
}
|
||||
|
||||
QTextCodec * FileIterator::encoding() const
|
||||
int FileListIterator::currentProgress() const
|
||||
{
|
||||
if (m_index >= 0 && m_index < m_encodings.size())
|
||||
return m_encodings.at(m_index);
|
||||
return m_maxIndex + 1;
|
||||
}
|
||||
|
||||
QTextCodec *FileListIterator::encodingAt(int index) const
|
||||
{
|
||||
if (index >= 0 && index < m_encodings.size())
|
||||
return m_encodings.at(index);
|
||||
return QTextCodec::codecForLocale();
|
||||
}
|
||||
|
||||
@@ -524,11 +552,12 @@ SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QSt
|
||||
}
|
||||
}
|
||||
|
||||
bool SubDirFileIterator::hasNext() const
|
||||
void SubDirFileIterator::update(int index)
|
||||
{
|
||||
if (!m_currentFiles.isEmpty())
|
||||
return true;
|
||||
while (!m_dirs.isEmpty() && m_currentFiles.isEmpty()) {
|
||||
if (index < m_files.size())
|
||||
return;
|
||||
// collect files from the directories until we have enough for the given index
|
||||
while (!m_dirs.isEmpty() && index >= m_files.size()) {
|
||||
QDir dir = m_dirs.pop();
|
||||
const qreal dirProgressMax = m_progressValues.pop();
|
||||
const bool processed = m_processedValues.pop();
|
||||
@@ -543,7 +572,7 @@ bool SubDirFileIterator::hasNext() const
|
||||
it.toBack();
|
||||
while (it.hasPrevious()) {
|
||||
const QString &file = it.previous();
|
||||
m_currentFiles.append(dir.path()+ QLatin1Char('/') +file);
|
||||
m_files.append(dir.path()+ QLatin1Char('/') +file);
|
||||
}
|
||||
m_progress += dirProgressMax;
|
||||
} else {
|
||||
@@ -564,18 +593,24 @@ bool SubDirFileIterator::hasNext() const
|
||||
m_progress += dirProgressMax;
|
||||
}
|
||||
}
|
||||
if (m_currentFiles.isEmpty()) {
|
||||
if (index >= m_files.size())
|
||||
m_progress = MAX_PROGRESS;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString SubDirFileIterator::next()
|
||||
int SubDirFileIterator::currentFileCount() const
|
||||
{
|
||||
Q_ASSERT(!m_currentFiles.isEmpty());
|
||||
return m_currentFiles.takeFirst();
|
||||
return m_files.size();
|
||||
}
|
||||
|
||||
QString SubDirFileIterator::fileAt(int index) const
|
||||
{
|
||||
return m_files.at(index);
|
||||
}
|
||||
|
||||
QTextCodec *SubDirFileIterator::codecAt(int index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
return m_encoding;
|
||||
}
|
||||
|
||||
int SubDirFileIterator::maxProgress() const
|
||||
@@ -588,7 +623,4 @@ int SubDirFileIterator::currentProgress() const
|
||||
return qMin(qRound(m_progress), MAX_PROGRESS);
|
||||
}
|
||||
|
||||
QTextCodec * SubDirFileIterator::encoding() const
|
||||
{
|
||||
return m_encoding;
|
||||
}
|
||||
|
||||
@@ -46,24 +46,77 @@ namespace Utils {
|
||||
class QTCREATOR_UTILS_EXPORT FileIterator
|
||||
{
|
||||
public:
|
||||
explicit FileIterator(const QStringList &fileList,
|
||||
const QList<QTextCodec *> encodings);
|
||||
virtual ~FileIterator();
|
||||
class Item
|
||||
{
|
||||
public:
|
||||
Item(const QString &path, QTextCodec *codec)
|
||||
: filePath(path), encoding(codec)
|
||||
{}
|
||||
QString filePath;
|
||||
QTextCodec *encoding;
|
||||
};
|
||||
|
||||
virtual bool hasNext() const;
|
||||
virtual QString next();
|
||||
virtual QTextCodec *encoding() const;
|
||||
virtual int maxProgress() const;
|
||||
virtual int currentProgress() const;
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef Item value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef const value_type *pointer;
|
||||
typedef const value_type &reference;
|
||||
|
||||
const_iterator(FileIterator *parent, Item item, int id)
|
||||
: m_parent(parent), m_item(item), m_index(id)
|
||||
{}
|
||||
const Item operator*() const { return m_item; }
|
||||
const Item *operator->() const { return &m_item; }
|
||||
void operator++() { m_parent->next(this); }
|
||||
bool operator==(const const_iterator &other) const
|
||||
{
|
||||
return m_parent == other.m_parent && m_index == other.m_index;
|
||||
}
|
||||
bool operator!=(const const_iterator &other) const { return !operator==(other); }
|
||||
|
||||
FileIterator *m_parent;
|
||||
Item m_item;
|
||||
int m_index; // -1 == end
|
||||
};
|
||||
|
||||
virtual ~FileIterator() {}
|
||||
void next(const_iterator *it);
|
||||
const_iterator begin();
|
||||
const_iterator end();
|
||||
|
||||
virtual int maxProgress() const = 0;
|
||||
virtual int currentProgress() const = 0;
|
||||
|
||||
protected:
|
||||
FileIterator();
|
||||
virtual void update(int requestedIndex) = 0;
|
||||
virtual int currentFileCount() const = 0;
|
||||
virtual QString fileAt(int index) const = 0;
|
||||
virtual QTextCodec *codecAt(int index) const = 0;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT FileListIterator : public FileIterator
|
||||
{
|
||||
public:
|
||||
explicit FileListIterator(const QStringList &fileList,
|
||||
const QList<QTextCodec *> encodings);
|
||||
|
||||
int maxProgress() const override;
|
||||
int currentProgress() const override;
|
||||
|
||||
protected:
|
||||
void update(int requestedIndex) override;
|
||||
int currentFileCount() const override;
|
||||
QString fileAt(int index) const override;
|
||||
QTextCodec *codecAt(int index) const override;
|
||||
|
||||
private:
|
||||
QStringList m_list;
|
||||
QStringListIterator *m_iterator;
|
||||
QTextCodec *encodingAt(int index) const;
|
||||
QStringList m_files;
|
||||
QList<QTextCodec *> m_encodings;
|
||||
int m_index;
|
||||
int m_maxIndex;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT SubDirFileIterator : public FileIterator
|
||||
@@ -72,20 +125,23 @@ public:
|
||||
SubDirFileIterator(const QStringList &directories, const QStringList &filters,
|
||||
QTextCodec *encoding = 0);
|
||||
|
||||
bool hasNext() const;
|
||||
QString next();
|
||||
QTextCodec *encoding() const;
|
||||
int maxProgress() const;
|
||||
int currentProgress() const;
|
||||
int maxProgress() const override;
|
||||
int currentProgress() const override;
|
||||
|
||||
protected:
|
||||
void update(int requestedIndex) override;
|
||||
int currentFileCount() const override;
|
||||
QString fileAt(int index) const override;
|
||||
QTextCodec *codecAt(int index) const override;
|
||||
|
||||
private:
|
||||
QStringList m_filters;
|
||||
QTextCodec *m_encoding;
|
||||
mutable QStack<QDir> m_dirs;
|
||||
mutable QStack<qreal> m_progressValues;
|
||||
mutable QStack<bool> m_processedValues;
|
||||
mutable qreal m_progress;
|
||||
mutable QStringList m_currentFiles;
|
||||
QStack<QDir> m_dirs;
|
||||
QStack<qreal> m_progressValues;
|
||||
QStack<bool> m_processedValues;
|
||||
qreal m_progress;
|
||||
QStringList m_files;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT FileSearchResult
|
||||
|
||||
@@ -190,14 +190,17 @@ void DirectoryFilter::refresh(QFutureInterface<void> &future)
|
||||
}
|
||||
directories = m_directories;
|
||||
}
|
||||
Utils::SubDirFileIterator it(directories, m_filters);
|
||||
future.setProgressRange(0, it.maxProgress());
|
||||
Utils::SubDirFileIterator subDirIterator(directories, m_filters);
|
||||
future.setProgressRange(0, subDirIterator.maxProgress());
|
||||
QStringList filesFound;
|
||||
while (!future.isCanceled() && it.hasNext()) {
|
||||
filesFound << it.next();
|
||||
auto end = subDirIterator.end();
|
||||
for (auto it = subDirIterator.begin(); it != end; ++it) {
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
filesFound << (*it).filePath;
|
||||
if (future.isProgressUpdateNeeded()
|
||||
|| future.progressValue() == 0 /*workaround for regression in Qt*/) {
|
||||
future.setProgressValueAndText(it.currentProgress(),
|
||||
future.setProgressValueAndText(subDirIterator.currentProgress(),
|
||||
tr("%1 filter update: %n files", 0, filesFound.size()).arg(displayName()));
|
||||
}
|
||||
}
|
||||
@@ -206,8 +209,8 @@ void DirectoryFilter::refresh(QFutureInterface<void> &future)
|
||||
QMutexLocker locker(&m_lock);
|
||||
m_files = filesFound;
|
||||
QTimer::singleShot(0, this, SLOT(updateFileIterator()));
|
||||
future.setProgressValue(it.maxProgress());
|
||||
future.setProgressValue(subDirIterator.maxProgress());
|
||||
} else {
|
||||
future.setProgressValueAndText(it.currentProgress(), tr("%1 filter update: canceled").arg(displayName()));
|
||||
future.setProgressValueAndText(subDirIterator.currentProgress(), tr("%1 filter update: canceled").arg(displayName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ Utils::FileIterator *AllProjectsFind::filesForProjects(const QStringList &nameFi
|
||||
encodings.insert(fileName, codec);
|
||||
}
|
||||
}
|
||||
return new Utils::FileIterator(encodings.keys(), encodings.values());
|
||||
return new Utils::FileListIterator(encodings.keys(), encodings.values());
|
||||
}
|
||||
|
||||
QVariant AllProjectsFind::additionalParameters() const
|
||||
|
||||
@@ -91,13 +91,13 @@ Utils::FileIterator *CurrentProjectFind::files(const QStringList &nameFilters,
|
||||
const QVariant &additionalParameters) const
|
||||
{
|
||||
QTC_ASSERT(additionalParameters.isValid(),
|
||||
return new Utils::FileIterator(QStringList(), QList<QTextCodec *>()));
|
||||
return new Utils::FileListIterator(QStringList(), QList<QTextCodec *>()));
|
||||
QString projectFile = additionalParameters.toString();
|
||||
foreach (Project *project, SessionManager::projects()) {
|
||||
if (project->document() && projectFile == project->projectFilePath().toString())
|
||||
return filesForProjects(nameFilters, QList<Project *>() << project);
|
||||
}
|
||||
return new Utils::FileIterator(QStringList(), QList<QTextCodec *>());
|
||||
return new Utils::FileListIterator(QStringList(), QList<QTextCodec *>());
|
||||
}
|
||||
|
||||
QString CurrentProjectFind::label() const
|
||||
|
||||
@@ -70,7 +70,7 @@ Utils::FileIterator *FindInCurrentFile::files(const QStringList &nameFilters,
|
||||
QTextCodec *codec = openEditorEncodings.value(fileName);
|
||||
if (!codec)
|
||||
codec = Core::EditorManager::defaultTextCodec();
|
||||
return new Utils::FileIterator(QStringList() << fileName, QList<QTextCodec *>() << codec);
|
||||
return new Utils::FileListIterator(QStringList(fileName), QList<QTextCodec *>() << codec);
|
||||
}
|
||||
|
||||
QVariant FindInCurrentFile::additionalParameters() const
|
||||
|
||||
@@ -81,7 +81,7 @@ Utils::FileIterator *FindInOpenFiles::files(const QStringList &nameFilters,
|
||||
}
|
||||
}
|
||||
|
||||
return new Utils::FileIterator(fileNames, codecs);
|
||||
return new Utils::FileListIterator(fileNames, codecs);
|
||||
}
|
||||
|
||||
QVariant FindInOpenFiles::additionalParameters() const
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace {
|
||||
const QString &term,
|
||||
QTextDocument::FindFlags flags, tst_FileSearch::RegExpFlag regexp = tst_FileSearch::NoRegExp)
|
||||
{
|
||||
Utils::FileIterator *it = new Utils::FileIterator(QStringList() << QLatin1String(FILENAME), QList<QTextCodec *>() << QTextCodec::codecForLocale());
|
||||
Utils::FileIterator *it = new Utils::FileListIterator(QStringList(QLatin1String(FILENAME)), QList<QTextCodec *>() << QTextCodec::codecForLocale());
|
||||
QFutureWatcher<Utils::FileSearchResultList> watcher;
|
||||
QSignalSpy ready(&watcher, SIGNAL(resultsReadyAt(int,int)));
|
||||
if (regexp == tst_FileSearch::NoRegExp)
|
||||
|
||||
Reference in New Issue
Block a user