diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp index 39632154774..d6d50551d85 100644 --- a/src/libs/utils/filesearch.cpp +++ b/src/libs/utils/filesearch.cpp @@ -68,7 +68,7 @@ static inline QString msgFound(const QString &searchTerm, int numMatches, int nu namespace { -void runFileSearch(QFutureInterface &future, +void runFileSearch(QFutureInterface &future, QString searchTerm, FileIterator *files, QTextDocument::FindFlags flags, @@ -96,6 +96,7 @@ void runFileSearch(QFutureInterface &future, QFile file; QBuffer buffer; while (files->hasNext()) { + FileSearchResultList results; const QString &s = files->next(); future.setProgressRange(0, files->maxProgress()); if (future.isPaused()) @@ -171,9 +172,9 @@ void runFileSearch(QFutureInterface &future, int n = 0; while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256) res.append(startOfLastLine[i++]); - future.reportResult(FileSearchResult(s, lineNr, QString(res), + results << FileSearchResult(s, lineNr, QString(res), regionPtr - startOfLastLine, sa.length(), - QStringList())); + QStringList()); ++numMatches; } } @@ -181,6 +182,8 @@ void runFileSearch(QFutureInterface &future, } firstChunk = false; } + if (!results.isEmpty()) + future.reportResult(results); ++numFilesSearched; if (future.isProgressUpdateNeeded()) future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched)); @@ -191,7 +194,7 @@ void runFileSearch(QFutureInterface &future, delete files; } -void runFileSearchRegExp(QFutureInterface &future, +void runFileSearchRegExp(QFutureInterface &future, QString searchTerm, FileIterator *files, QTextDocument::FindFlags flags, @@ -209,6 +212,7 @@ void runFileSearchRegExp(QFutureInterface &future, QString str; QTextStream stream; while (files->hasNext()) { + FileSearchResultList results; const QString &s = files->next(); future.setProgressRange(0, files->maxProgress()); if (future.isPaused()) @@ -235,13 +239,15 @@ void runFileSearchRegExp(QFutureInterface &future, line = stream.readLine(); int pos = 0; while ((pos = expression.indexIn(line, pos)) != -1) { - future.reportResult(FileSearchResult(s, lineNr, line, + results << FileSearchResult(s, lineNr, line, pos, expression.matchedLength(), - expression.capturedTexts())); + expression.capturedTexts()); + ++numMatches; pos += expression.matchedLength(); } ++lineNr; } + future.reportResult(results); ++numFilesSearched; if (future.isProgressUpdateNeeded()) future.setProgressValueAndText(files->currentProgress(), msgFound(searchTerm, numMatches, numFilesSearched)); @@ -256,17 +262,17 @@ void runFileSearchRegExp(QFutureInterface &future, } // namespace -QFuture Utils::findInFiles(const QString &searchTerm, FileIterator *files, +QFuture Utils::findInFiles(const QString &searchTerm, FileIterator *files, QTextDocument::FindFlags flags, QMap fileToContentsMap) { - return QtConcurrent::run > + return QtConcurrent::run > (runFileSearch, searchTerm, files, flags, fileToContentsMap); } -QFuture Utils::findInFilesRegExp(const QString &searchTerm, FileIterator *files, +QFuture Utils::findInFilesRegExp(const QString &searchTerm, FileIterator *files, QTextDocument::FindFlags flags, QMap fileToContentsMap) { - return QtConcurrent::run > + return QtConcurrent::run > (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap); } diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h index 0b3f8953870..956e0ba3e74 100644 --- a/src/libs/utils/filesearch.h +++ b/src/libs/utils/filesearch.h @@ -101,10 +101,12 @@ public: QStringList regexpCapturedTexts; }; -QTCREATOR_UTILS_EXPORT QFuture findInFiles(const QString &searchTerm, FileIterator *files, +typedef QList FileSearchResultList; + +QTCREATOR_UTILS_EXPORT QFuture findInFiles(const QString &searchTerm, FileIterator *files, QTextDocument::FindFlags flags, QMap fileToContentsMap = QMap()); -QTCREATOR_UTILS_EXPORT QFuture findInFilesRegExp(const QString &searchTerm, FileIterator *files, +QTCREATOR_UTILS_EXPORT QFuture findInFilesRegExp(const QString &searchTerm, FileIterator *files, QTextDocument::FindFlags flags, QMap fileToContentsMap = QMap()); QTCREATOR_UTILS_EXPORT QString expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts); diff --git a/src/plugins/find/searchresulttreemodel.cpp b/src/plugins/find/searchresulttreemodel.cpp index 2c14faa2b65..792c1004dca 100644 --- a/src/plugins/find/searchresulttreemodel.cpp +++ b/src/plugins/find/searchresulttreemodel.cpp @@ -39,6 +39,7 @@ #include #include +using namespace Find; using namespace Find::Internal; SearchResultTreeModel::SearchResultTreeModel(QObject *parent) @@ -295,16 +296,21 @@ int SearchResultTreeModel::addResultFile(const QString &fileName) return index; } -void SearchResultTreeModel::appendResultLine(int index, int lineNumber, const QString &rowText, - int searchTermStart, int searchTermLength) +void SearchResultTreeModel::appendResultLines(const QList &items) { if (!m_lastAddedResultFile) return; QModelIndex lastFile(createIndex(m_lastAddedResultFile->rowOfItem(), 0, m_lastAddedResultFile)); - beginInsertRows(lastFile, m_lastAddedResultFile->childrenCount(), m_lastAddedResultFile->childrenCount()); - m_lastAddedResultFile->appendResultLine(index, lineNumber, rowText, searchTermStart, searchTermLength); + beginInsertRows(lastFile, m_lastAddedResultFile->childrenCount(), m_lastAddedResultFile->childrenCount() + items.count()); + foreach (const SearchResultItem &item, items) { + m_lastAddedResultFile->appendResultLine(item.index, + item.lineNumber, + item.lineText, + item.searchTermStart, + item.searchTermLength); + } endInsertRows(); dataChanged(lastFile, lastFile); // Make sure that the number after the file name gets updated @@ -314,15 +320,25 @@ void SearchResultTreeModel::appendResultLine(int index, int lineNumber, const QS * Adds the search result to the list of results, creating a new file entry when * necessary. Returns the insertion index when a new file entry was created. */ -int SearchResultTreeModel::addResultLine(int index, const QString &fileName, int lineNumber, const QString &rowText, - int searchTermStart, int searchTermLength) +QList SearchResultTreeModel::addResultLines(const QList &items) { - int insertionIndex = -1; - if (!m_lastAddedResultFile || (m_lastAddedResultFile->fileName() != fileName)) - insertionIndex = addResultFile(fileName); - - appendResultLine(index, lineNumber, rowText, searchTermStart, searchTermLength); - return insertionIndex; + QList insertedFileIndices; + QList itemSet; + foreach (const SearchResultItem &item, items) { + if (!m_lastAddedResultFile || (m_lastAddedResultFile->fileName() != item.fileName)) { + if (!itemSet.isEmpty()) { + appendResultLines(itemSet); + itemSet.clear(); + } + insertedFileIndices << addResultFile(item.fileName); + } + itemSet << item; + } + if (!itemSet.isEmpty()) { + appendResultLines(itemSet); + itemSet.clear(); + } + return insertedFileIndices; } void SearchResultTreeModel::clear() diff --git a/src/plugins/find/searchresulttreemodel.h b/src/plugins/find/searchresulttreemodel.h index 4af642d5a8e..89418b45cc0 100644 --- a/src/plugins/find/searchresulttreemodel.h +++ b/src/plugins/find/searchresulttreemodel.h @@ -30,6 +30,8 @@ #ifndef SEARCHRESULTTREEMODEL_H #define SEARCHRESULTTREEMODEL_H +#include "searchresultwindow.h" + #include #include @@ -63,18 +65,17 @@ public: QModelIndex next(const QModelIndex &idx) const; QModelIndex prev(const QModelIndex &idx) const; + QList addResultLines(const QList &items); + signals: void jumpToSearchResult(const QString &fileName, int lineNumber, int searchTermStart, int searchTermLength); public slots: void clear(); - int addResultLine(int index, const QString &fileName, int lineNumber, const QString &rowText, - int searchTermStart, int searchTermLength); private: - void appendResultLine(int index, int lineNumber, const QString &rowText, - int searchTermStart, int searchTermLength); + void appendResultLines(const QList &items); int addResultFile(const QString &fileName); QVariant data(const SearchResultTextRow *row, int role) const; QVariant data(const SearchResultFile *file, int role) const; diff --git a/src/plugins/find/searchresulttreeview.cpp b/src/plugins/find/searchresulttreeview.cpp index 22e84f2628b..eea212b54ac 100644 --- a/src/plugins/find/searchresulttreeview.cpp +++ b/src/plugins/find/searchresulttreeview.cpp @@ -66,14 +66,13 @@ void SearchResultTreeView::clear() m_model->clear(); } -void SearchResultTreeView::appendResultLine(int index, const QString &fileName, int lineNumber, const QString &rowText, - int searchTermStart, int searchTermLength) +void SearchResultTreeView::appendResultLines(const QList &items) { - int insertionIndex = m_model->addResultLine(index, fileName, lineNumber, rowText, - searchTermStart, searchTermLength); - - if (m_autoExpandResults && insertionIndex != -1) - setExpanded(model()->index(insertionIndex, 0), true); + const QList &insertedFileIndices = m_model->addResultLines(items); + if (m_autoExpandResults && !insertedFileIndices.isEmpty()) { + foreach (int index, insertedFileIndices) + setExpanded(model()->index(index, 0), true); + } } void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index) diff --git a/src/plugins/find/searchresulttreeview.h b/src/plugins/find/searchresulttreeview.h index 8337de6295b..0c458992fda 100644 --- a/src/plugins/find/searchresulttreeview.h +++ b/src/plugins/find/searchresulttreeview.h @@ -30,6 +30,8 @@ #ifndef SEARCHRESULTTREEVIEW_H #define SEARCHRESULTTREEVIEW_H +#include "searchresultwindow.h" + #include namespace Find { @@ -48,14 +50,13 @@ public: void setTextEditorFont(const QFont &font); SearchResultTreeModel *model() const; + void appendResultLines(const QList &items); signals: void jumpToSearchResult(int index, bool checked); public slots: void clear(); - void appendResultLine(int index, const QString &fileName, int lineNumber, const QString &lineText, - int searchTermStart, int searchTermLength); void emitJumpToSearchResult(const QModelIndex &index); protected: diff --git a/src/plugins/find/searchresultwindow.cpp b/src/plugins/find/searchresultwindow.cpp index 7a27bf3c142..575db28dfb1 100644 --- a/src/plugins/find/searchresultwindow.cpp +++ b/src/plugins/find/searchresultwindow.cpp @@ -89,7 +89,9 @@ struct SearchResultWindowPrivate { }; SearchResultWindowPrivate::SearchResultWindowPrivate() - : m_currentSearch(0), m_isShowingReplaceUI(false), m_focusReplaceEdit(false) + : m_currentSearch(0), + m_isShowingReplaceUI(false), + m_focusReplaceEdit(false) { } @@ -294,9 +296,6 @@ void SearchResultWindow::handleJumpToSearchResult(int index, bool /* checked */) void SearchResultWindow::addResult(const QString &fileName, int lineNumber, const QString &rowText, int searchTermStart, int searchTermLength, const QVariant &userData) { - //qDebug()<<"###"<m_widget->setCurrentWidget(d->m_searchResultTreeView); - int index = d->m_items.size(); SearchResultItem item; item.fileName = fileName; item.lineNumber = lineNumber; @@ -304,10 +303,21 @@ void SearchResultWindow::addResult(const QString &fileName, int lineNumber, cons item.searchTermStart = searchTermStart; item.searchTermLength = searchTermLength; item.userData = userData; - item.index = index; - d->m_items.append(item); - d->m_searchResultTreeView->appendResultLine(index, fileName, lineNumber, rowText, searchTermStart, searchTermLength); - if (index == 0) { + addResults(QList() << item); +} + +void SearchResultWindow::addResults(QList &items) +{ + int index = d->m_items.size(); + bool firstItems = (index == 0); + for (int i = 0; i < items.size(); ++i) { + items[i].index = index; + ++index; + } + + d->m_items << items; + d->m_searchResultTreeView->appendResultLines(items); + if (firstItems) { d->m_replaceTextEdit->setEnabled(true); // We didn't have an item before, set the focus to the search widget d->m_focusReplaceEdit = true; diff --git a/src/plugins/find/searchresultwindow.h b/src/plugins/find/searchresultwindow.h index 5adc86fe7c4..46932f6fb11 100644 --- a/src/plugins/find/searchresultwindow.h +++ b/src/plugins/find/searchresultwindow.h @@ -53,7 +53,7 @@ struct FIND_EXPORT SearchResultItem QString lineText; int searchTermStart; int searchTermLength; - int index; + int index; // SearchResultWindow sets the index QVariant userData; // whatever information we also need here }; @@ -109,6 +109,7 @@ public: // search result object only lives till next startnewsearch call SearchResult *startNewSearch(SearchMode searchOrSearchAndReplace = SearchOnly); + void addResults(QList &items); public slots: void clearContents(); void addResult(const QString &fileName, int lineNumber, const QString &lineText, diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 650c13b0206..f4dc560659f 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -93,7 +93,7 @@ void BaseFileFind::findAll(const QString &txt, QTextDocument::FindFlags findFlag emit changed(); if (m_filterCombo) updateComboEntries(m_filterCombo, true); - m_watcher.setFuture(QFuture()); + m_watcher.setFuture(QFuture()); SearchResult *result = m_resultWindow->startNewSearch(); connect(result, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem))); m_resultWindow->popup(true); @@ -115,7 +115,7 @@ void BaseFileFind::replaceAll(const QString &txt, QTextDocument::FindFlags findF emit changed(); if (m_filterCombo) updateComboEntries(m_filterCombo, true); - m_watcher.setFuture(QFuture()); + m_watcher.setFuture(QFuture()); SearchResult *result = m_resultWindow->startNewSearch(SearchResultWindow::SearchAndReplace); connect(result, SIGNAL(activated(Find::SearchResultItem)), this, SLOT(openEditor(Find::SearchResultItem))); connect(result, SIGNAL(replaceButtonClicked(QString,QList)), @@ -145,13 +145,19 @@ void BaseFileFind::doReplace(const QString &text, } void BaseFileFind::displayResult(int index) { - Utils::FileSearchResult result = m_watcher.future().resultAt(index); - m_resultWindow->addResult(result.fileName, - result.lineNumber, - result.matchingLine, - result.matchStart, - result.matchLength, - result.regexpCapturedTexts); + Utils::FileSearchResultList results = m_watcher.future().resultAt(index); + QList items; // this conversion is stupid... + foreach (const Utils::FileSearchResult &result, results) { + Find::SearchResultItem item; + item.fileName = result.fileName; + item.lineNumber = result.lineNumber; + item.lineText = result.matchingLine; + item.searchTermLength = result.matchLength; + item.searchTermStart = result.matchStart; + item.userData = result.regexpCapturedTexts; + items << item; + } + m_resultWindow->addResults(items); if (m_resultLabel) m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults())); } diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h index b423eb8b531..a38fddd2693 100644 --- a/src/plugins/texteditor/basefilefind.h +++ b/src/plugins/texteditor/basefilefind.h @@ -92,7 +92,7 @@ private: QWidget *createProgressWidget(); Find::SearchResultWindow *m_resultWindow; - QFutureWatcher m_watcher; + QFutureWatcher m_watcher; bool m_isSearching; QLabel *m_resultLabel; QStringListModel m_filterStrings;