LP-311 Remove basic/advanced stabilization tab auto-switch (autotune/txpid lock issues)
[librepilot.git] / ground / gcs / src / libs / utils / filesearch.cpp
blob0c324910471506cc76be334893d9702eb37b09c9
1 /**
2 ******************************************************************************
4 * @file filesearch.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
7 * @brief
8 * @see The GNU Public License (GPL) Version 3
9 * @defgroup
10 * @{
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "filesearch.h"
30 #include <cctype>
32 #include <QtCore/QIODevice>
33 #include <QtCore/QBuffer>
34 #include <QtCore/QFile>
35 #include <QtCore/QFutureInterface>
36 #include <QtConcurrent/QtConcurrentRun>
37 #include <QtCore/QRegExp>
38 #include <QtCore/QCoreApplication>
40 #include <qtconcurrent/runextensions.h>
42 using namespace Utils;
44 static inline QString msgCanceled(const QString &searchTerm, int numMatches, int numFilesSearched)
46 return QCoreApplication::translate("Utils::FileSearch",
47 "%1: canceled. %n occurrences found in %2 files.",
48 NULL, numMatches).
49 arg(searchTerm).arg(numFilesSearched);
52 static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched)
54 return QCoreApplication::translate("Utils::FileSearch",
55 "%1: %n occurrences found in %2 files.",
56 NULL, numMatches).
57 arg(searchTerm).arg(numFilesSearched);
60 static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched, int filesSize)
62 return QCoreApplication::translate("Utils::FileSearch",
63 "%1: %n occurrences found in %2 of %3 files.",
64 NULL, numMatches).
65 arg(searchTerm).arg(numFilesSearched).arg(filesSize);
68 namespace {
69 void runFileSearch(QFutureInterface<FileSearchResult> &future,
70 QString searchTerm,
71 QStringList files,
72 QTextDocument::FindFlags flags,
73 QMap<QString, QString> fileToContentsMap)
75 future.setProgressRange(0, files.size());
76 int numFilesSearched = 0;
77 int numMatches = 0;
79 bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
80 bool wholeWord = (flags & QTextDocument::FindWholeWords);
82 QByteArray sa = searchTerm.toUtf8();
83 int scMaxIndex = sa.length() - 1;
84 const char *sc = sa.constData();
86 QByteArray sal = searchTerm.toLower().toUtf8();
87 const char *scl = sal.constData();
89 QByteArray sau = searchTerm.toUpper().toUtf8();
90 const char *scu = sau.constData();
92 int chunkSize = qMax(100000, sa.length());
94 QFile file;
95 QBuffer buffer;
96 foreach(QString s, files) {
97 if (future.isPaused()) {
98 future.waitForResume();
100 if (future.isCanceled()) {
101 future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
102 break;
104 QIODevice *device;
105 if (fileToContentsMap.contains(s)) {
106 buffer.setData(fileToContentsMap.value(s).toLocal8Bit());
107 device = &buffer;
108 } else {
109 file.setFileName(s);
110 device = &file;
112 if (!device->open(QIODevice::ReadOnly)) {
113 continue;
115 int lineNr = 1;
116 const char *startOfLastLine = NULL;
118 bool firstChunk = true;
119 while (!device->atEnd()) {
120 if (!firstChunk) {
121 device->seek(device->pos() - sa.length() + 1);
124 const QByteArray chunk = device->read(chunkSize);
125 const char *chunkPtr = chunk.constData();
126 startOfLastLine = chunkPtr;
127 for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length() - scMaxIndex; ++regionPtr) {
128 const char *regionEnd = regionPtr + scMaxIndex;
130 if (*regionPtr == '\n') {
131 startOfLastLine = regionPtr + 1;
132 ++lineNr;
133 } else if (
134 // case sensitive
135 (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
137 // case insensitive
138 (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
139 && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
141 const char *afterRegion = regionEnd + 1;
142 const char *beforeRegion = regionPtr - 1;
143 bool equal = true;
144 if (wholeWord &&
145 (isalnum(*beforeRegion)
146 || (*beforeRegion == '_')
147 || isalnum(*afterRegion)
148 || (*afterRegion == '_'))) {
149 equal = false;
152 int regionIndex = 1;
153 for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
154 if ( // case sensitive
155 (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
157 // case insensitive
158 (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
160 equal = false;
163 if (equal) {
164 int textLength = chunk.length() - (startOfLastLine - chunkPtr);
165 if (textLength > 0) {
166 QByteArray res;
167 res.reserve(256);
168 int i = 0;
169 int n = 0;
170 while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256) {
171 res.append(startOfLastLine[i++]);
173 future.reportResult(FileSearchResult(s, lineNr, QString(res),
174 regionPtr - startOfLastLine, sa.length()));
175 ++numMatches;
180 firstChunk = false;
182 ++numFilesSearched;
183 future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
184 device->close();
186 if (!future.isCanceled()) {
187 future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
191 void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
192 QString searchTerm,
193 QStringList files,
194 QTextDocument::FindFlags flags,
195 QMap<QString, QString> fileToContentsMap)
197 future.setProgressRange(0, files.size());
198 int numFilesSearched = 0;
199 int numMatches = 0;
200 if (flags & QTextDocument::FindWholeWords) {
201 searchTerm = QString::fromLatin1("\\b%1\\b").arg(searchTerm);
203 const Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
204 const QRegExp expression(searchTerm, caseSensitivity);
206 QFile file;
207 QString str;
208 QTextStream stream;
209 foreach(const QString &s, files) {
210 if (future.isPaused()) {
211 future.waitForResume();
213 if (future.isCanceled()) {
214 future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
215 break;
218 bool needsToCloseFile = false;
219 if (fileToContentsMap.contains(s)) {
220 str = fileToContentsMap.value(s);
221 stream.setString(&str);
222 } else {
223 file.setFileName(s);
224 if (!file.open(QIODevice::ReadOnly)) {
225 continue;
227 needsToCloseFile = true;
228 stream.setDevice(&file);
230 int lineNr = 1;
231 QString line;
232 while (!stream.atEnd()) {
233 line = stream.readLine();
234 int pos = 0;
235 while ((pos = expression.indexIn(line, pos)) != -1) {
236 future.reportResult(FileSearchResult(s, lineNr, line,
237 pos, expression.matchedLength()));
238 pos += expression.matchedLength();
240 ++lineNr;
242 ++numFilesSearched;
243 future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
244 if (needsToCloseFile) {
245 file.close();
248 if (!future.isCanceled()) {
249 future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
252 } // namespace
255 QFuture<FileSearchResult> Utils::findInFiles(const QString &searchTerm, const QStringList &files,
256 QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
258 return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
259 (runFileSearch, searchTerm, files, flags, fileToContentsMap);
262 QFuture<FileSearchResult> Utils::findInFilesRegExp(const QString &searchTerm, const QStringList &files,
263 QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
265 return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
266 (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);