From cef7f81ea87aa7210219850862b759bdba54ee57 Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Thu, 24 Nov 2016 01:47:56 +0100 Subject: [PATCH] ReSearch: text search, date criteria --- appl/refind/mainwindow.ui | 46 ++++--- appl/research/filecache.cpp | 10 ++ appl/research/filecache.hpp | 1 + appl/research/filefinder.cpp | 164 ++++++++++++++++++++++++- appl/research/filefinder.hpp | 19 ++- appl/research/mainwindow.cpp | 63 +++++++--- appl/research/mainwindow.hpp | 2 + appl/research/mainwindow.ui | 225 ++++++++++++++++++++++++++++++----- base/ReFileSearch.cpp | 68 +++++++++-- base/ReFileSearch.hpp | 11 +- 10 files changed, 521 insertions(+), 88 deletions(-) diff --git a/appl/refind/mainwindow.ui b/appl/refind/mainwindow.ui index c322474..184dab9 100644 --- a/appl/refind/mainwindow.ui +++ b/appl/refind/mainwindow.ui @@ -172,7 +172,7 @@ S&top search - + :/main/icons/stop.png:/main/icons/stop.png @@ -340,7 +340,7 @@ ^ - + :/main/icons/folder_go.png:/main/icons/folder_go.png @@ -366,7 +366,7 @@ ... - + :/main/icons/folder_find.png:/main/icons/folder_find.png @@ -609,7 +609,7 @@ S&top search - + :/main/icons/stop.png:/main/icons/stop.png @@ -672,7 +672,7 @@ &Export - + :/main/icons/database_save.png:/main/icons/database_save.png @@ -790,7 +790,7 @@ &Preview - + :/main/icons/eye.png:/main/icons/eye.png @@ -928,7 +928,7 @@ 0 0 1030 - 26 + 30 @@ -1043,7 +1043,7 @@ - + :/main/icons/door_in.png:/main/icons/door_in.png @@ -1058,7 +1058,7 @@ - + :/main/icons/action_go.png:/main/icons/action_go.png @@ -1081,7 +1081,7 @@ - + :/main/icons/database_save.png:/main/icons/database_save.png @@ -1093,7 +1093,7 @@ - + :/main/icons/folder_go.png:/main/icons/folder_go.png @@ -1108,7 +1108,7 @@ - + :/main/icons/folder_find.png:/main/icons/folder_find.png @@ -1123,7 +1123,7 @@ - + :/main/icons/folder.png:/main/icons/folder.png @@ -1138,7 +1138,7 @@ - + :/main/icons/table.png :/main/icons/table.gif:/main/icons/table.png @@ -1151,7 +1151,7 @@ - + :/main/icons/action_paste.png:/main/icons/action_paste.png @@ -1166,7 +1166,7 @@ - + :/main/icons/wand.png:/main/icons/wand.png @@ -1181,7 +1181,7 @@ - + :/main/icons/disk.png:/main/icons/disk.png @@ -1196,7 +1196,7 @@ - + :/main/icons/wrench.png:/main/icons/wrench.png @@ -1211,7 +1211,7 @@ - + :/main/icons/eye.png:/main/icons/eye.png @@ -1237,7 +1237,7 @@ - + :/main/icons/action_go.png:/main/icons/action_go.png @@ -1255,7 +1255,7 @@ false - + :/main/icons/stop.png:/main/icons/stop.png @@ -1292,9 +1292,7 @@ comboBoxExcludedDirs tableWidget - - - + actionExit diff --git a/appl/research/filecache.cpp b/appl/research/filecache.cpp index b1416f3..0f9e343 100644 --- a/appl/research/filecache.cpp +++ b/appl/research/filecache.cpp @@ -94,4 +94,14 @@ const QStringList &FileCache::lines(const QString &filename) const return item == NULL ? m_emptyLines : item->lines(); } +/** + * Removes a file from the cache. + * + * @param filename the filename with path + */ +void FileCache::remove(const QString &filename) +{ + m_cache.remove(filename); +} + diff --git a/appl/research/filecache.hpp b/appl/research/filecache.hpp index 33c87ce..9603016 100644 --- a/appl/research/filecache.hpp +++ b/appl/research/filecache.hpp @@ -21,6 +21,7 @@ public: public: void addOrUpdate(const QString& filename); const QStringList& lines(const QString& filename) const; + void remove(const QString& filename); private: QMap m_cache; QStringList m_emptyLines; diff --git a/appl/research/filefinder.cpp b/appl/research/filefinder.cpp index 8db0a29..028caa9 100644 --- a/appl/research/filefinder.cpp +++ b/appl/research/filefinder.cpp @@ -5,14 +5,21 @@ * Constructor. * * @param table the table for the found files + * @param cache the file content cache */ -FileFinder::FileFinder(QTableWidget& table) : +FileFinder::FileFinder(QTableWidget& table, FileCache& cache) : ReFileSearch(), m_table(table), m_files(), m_dirs(0), m_foundFiles(0), - m_ignoredFiles(0) + m_ignoredFiles(0), + m_addNotDetach(false), + m_regularExpression(NULL), + m_text(NULL), + m_inverseSearch(false), + m_caseSensitive(false), + m_cache(cache) { setSearchMode(smFiles); } @@ -51,6 +58,32 @@ void FileFinder::addToTable(const QString& full, const QString &path, } } +/** + * Adds a file to the file table. + * + * @param full the filename with path + * @param path the path of the file + * @param node the filename without path + * @param info the info about the file + */ +void FileFinder::detachFromTable(const QString& full, const QString &path, + const QString &node) +{ + if (! m_files.contains(full)){ + ++m_ignoredFiles; + } else { + ++m_foundFiles; + m_files.remove(full); + for (int ix = m_table.rowCount() - 1; ix >= 0; --ix){ + if (m_table.item(ix, colNode)->text() == node + && m_table.item(ix, colPath)->text() == path){ + m_table.removeRow(ix); + break; + } + } + } +} + /** * Clears the table. */ @@ -92,10 +125,96 @@ int FileFinder::ignoredFiles() const bool FileFinder::handleFile(const QString &full, const QString &path, const QString &node, const QFileInfo& info) { - addToTable(full, path, node, info); + bool found = false; + if (m_regularExpression != NULL){ + found = searchWithRegExpr(full); + } else if (m_text != NULL){ + found = searchText(full); + } + if (found){ + if (m_addNotDetach) + addToTable(full, path, node, info); + else + detachFromTable(full, path, node); + } return true; } +/** + * Searches a text in the file content. + * + * @param filename the file to search + * @return true: if ! m_inverseSearch: the text has been found
+ * if m_inverseSearch: the text has not been found
+ */ +bool FileFinder::searchText(const QString &filename) +{ + m_cache.addOrUpdate(filename); + const QStringList& lines = m_cache.lines(filename); + bool rc = false; + if (m_caseSensitive){ + if (m_inverseSearch){ + rc = true; + for (int ix = 0; ix < lines.size(); ++ix){ + if (lines[ix].indexOf(m_text) < 0){ + rc = false; + break; + } + } + } else { + rc = false; + for (int ix = 0; ix < lines.size(); ++ix){ + if (lines[ix].indexOf(m_text) >= 0){ + rc = true; + break; + } + } + } + } else { + if (m_inverseSearch){ + + } else { + + } + } + if (! rc) + m_cache.remove(filename); + return rc; +} + +/** + * Searches a regular expression in the file content. + * + * @param filename the file to search + * @return true: the text has been found + */ +bool FileFinder::searchWithRegExpr(const QString& filename){ + m_cache.addOrUpdate(filename); + const QStringList& lines = m_cache.lines(filename); + + bool rc = false; + if (m_inverseSearch){ + rc = true; + for (int ix = 0; ix < lines.size(); ++ix){ + if (m_regularExpression->match(lines[ix]).hasMatch()){ + rc = false; + break; + } + } + } else { + rc = false; + for (int ix = 0; ix < lines.size(); ++ix){ + if (m_regularExpression->match(lines[ix]).hasMatch()){ + rc = true; + break; + } + } + } + if (rc) + m_cache.remove(filename); + return rc; +} + /** * Searches files in a directory tree and put them into a table widget. * @@ -119,3 +238,42 @@ void FileFinder::search(const QString &baseDirectory, const QString &patterns, oneDirectory(baseDirectory, 0); } +/** + * Sets the flag for the search mode. + * + * @param addNotDetach true: the found files will be added + */ +void FileFinder::setAddNotDetach(bool addNotDetach) +{ + m_addNotDetach = addNotDetach; +} + +/** + * Sets the text search options. + * + * @param text text to search + * @param caseSensitive true: the search is case sensitive + * @param isRegularExpression true: the text is a regular expression + * @param inverseSearch true: the file is selected if the text + * is not found + */ +void FileFinder::setTextToSearch(const QString &text, bool caseSensitive, + bool isRegularExpression, bool inverseSearch) +{ + m_inverseSearch = inverseSearch; + delete m_text; + delete m_regularExpression; + m_text = NULL; + m_regularExpression = NULL; + m_caseSensitive = caseSensitive; + if (! text.isEmpty()){ + if (isRegularExpression){ + m_regularExpression = new QRegularExpression(text, + caseSensitive ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption); + } else { + m_text = new QString(text); + } + } +} + diff --git a/appl/research/filefinder.hpp b/appl/research/filefinder.hpp index 575c721..2b45ee2 100644 --- a/appl/research/filefinder.hpp +++ b/appl/research/filefinder.hpp @@ -1,11 +1,11 @@ #ifndef FILEFINDER_H #define FILEFINDER_H - +class FileCache; class FileFinder : public ReFileSearch { public: - FileFinder( QTableWidget& m_table); + FileFinder( QTableWidget& m_table, FileCache& cache); virtual ~FileFinder(); public: void addToTable(const QString& full, const QString &path, @@ -17,14 +17,25 @@ public: int ignoredFiles() const; void search(const QString& baseDirectory, const QString& patterns, int minDepth, int maxDepth); - - + void setAddNotDetach(bool addNotDetach); + void setTextToSearch(const QString &text, bool caseSensitive, + bool isRegularExpression, bool inverseSearch); +private: + void detachFromTable(const QString &full, const QString &path, const QString &node); + bool searchWithRegExpr(const QString &filename); + bool searchText(const QString &filename); private: QTableWidget& m_table; QSet m_files; int m_dirs; int m_foundFiles; int m_ignoredFiles; + bool m_addNotDetach; + QRegularExpression* m_regularExpression; + QString* m_text; + bool m_inverseSearch; + bool m_caseSensitive; + FileCache& m_cache; }; #endif // FILEFINDER_H diff --git a/appl/research/mainwindow.cpp b/appl/research/mainwindow.cpp index 337323c..9639c1d 100644 --- a/appl/research/mainwindow.cpp +++ b/appl/research/mainwindow.cpp @@ -64,9 +64,10 @@ void MainWindow::initializeGui(){ connect(ui->pushButtonAdd, SIGNAL(clicked()), this, SLOT(onAdd())); connect(ui->pushButtonClear, SIGNAL(clicked()), this, SLOT(onClear())); connect(ui->pushButtonFilter, SIGNAL(clicked()), this, SLOT(onFilter())); + connect(ui->pushButtonDetach, SIGNAL(clicked()), this, SLOT(onDetach())); delete m_fileFinder; - m_fileFinder = new FileFinder(*ui->tableWidget); + m_fileFinder = new FileFinder(*ui->tableWidget, *m_fileCache); ui->tableWidget->setColumnWidth(colNode, 200); ui->tableWidget->setColumnWidth(colSize, 125); @@ -102,21 +103,15 @@ void MainWindow::onAboutToQuit() */ void MainWindow::onAdd() { - QString base = ui->comboBoxBaseDirectory->currentText(); - if (base.isEmpty()){ - say(LOG_ERROR, tr("missing a base directory")); - } else { - m_fileFinder->search(base, ui->comboBoxFilePatterns->currentText(), - atoi(ui->lineEditMinDepth->text().toLocal8Bit().data()), - atoi(ui->lineEditMaxDepth->text().toLocal8Bit().data())); - int files = ui->tableWidget->rowCount(); - ui->labelFileCount->setText(QString::number(files) - + " " + tr("file(s)")); - say(LOG_INFO, tr("files: %1 already found: %2 processed directories: %3") - .arg(m_fileFinder->foundFiles()) - .arg(m_fileFinder->ignoredFiles()) - .arg(m_fileFinder->processedDirs())); - } + searchFiles(true); +} + +/** + * Handles the click of the "Detach" button. + */ +void MainWindow::onDetach() +{ + searchFiles(false); } /** @@ -182,6 +177,42 @@ bool MainWindow::say(ReLoggerLevel level, const QString& message){ return level >= LOG_INFO; } +/** + * Common operation of onAdd() and onDetach(). + * + * @param addNotDetach true: add the found files
+ * false: detach the found files + */ +void MainWindow::searchFiles(bool addNotDetach) +{ + QString base = ui->comboBoxBaseDirectory->currentText(); + if (base.isEmpty()){ + say(LOG_ERROR, tr("missing a base directory")); + } else { + QDateTime olderThan = comboDate(ui->comboBoxOlder); + QDateTime youngerThan = comboDate(ui->comboBoxYounger); + m_fileFinder->setOlderThan(olderThan.currentMSecsSinceEpoch() <= 0 + ? NULL : new QDateTime(olderThan)); + m_fileFinder->setYoungerThan(olderThan.currentMSecsSinceEpoch() <= 0 + ? NULL : new QDateTime(youngerThan)); + m_fileFinder->setTextToSearch(ui->comboBoxTextPattern->currentText(), + ui->checkBoxCaseSensitiv->isChecked(), + ui->checkBoxRegularExpr->isChecked(), + ui->checkBoxInverse->isChecked()); + m_fileFinder->setAddNotDetach(addNotDetach); + m_fileFinder->search(base, ui->comboBoxFilePatterns->currentText(), + atoi(ui->lineEditMinDepth->text().toLocal8Bit().data()), + atoi(ui->lineEditMaxDepth->text().toLocal8Bit().data())); + int files = ui->tableWidget->rowCount(); + ui->labelFileCount->setText(QString::number(files) + + " " + tr("file(s)")); + say(LOG_INFO, tr("files: %1 already found: %2 processed directories: %3") + .arg(m_fileFinder->foundFiles()) + .arg(m_fileFinder->ignoredFiles()) + .arg(m_fileFinder->processedDirs())); + } +} + /** * Event * @param oldString diff --git a/appl/research/mainwindow.hpp b/appl/research/mainwindow.hpp index 9f7f083..a192cad 100644 --- a/appl/research/mainwindow.hpp +++ b/appl/research/mainwindow.hpp @@ -32,10 +32,12 @@ private: virtual void onAboutToQuit(); virtual void onGuiTimerUpdate(); virtual void onLanguageChange(); + void searchFiles(bool addNotDetach); private slots: void onAbout(); void onAdd(); void onClear(); + void onDetach(); void onFilter(); void onSelectBaseDirectory(); void textEdited(const QString& oldString, const QString& newString); diff --git a/appl/research/mainwindow.ui b/appl/research/mainwindow.ui index 4ca7c7f..b5e5a01 100644 --- a/appl/research/mainwindow.ui +++ b/appl/research/mainwindow.ui @@ -179,6 +179,144 @@ + + + Directory search options + + + + + + + + + 125 + 0 + + + + Text pattern: + + + + + + + Only files containing this text / text pattern will be found. +If the checkbox "Regular expression" is selected the text is interpreted as regular expression. +If the checkbox "inverse search" is checked a file is found only if the file does <b>not</b> contain the text / text pattern. + + + true + + + + + + + + + + + Case sensitive + + + true + + + + + + + Regular expression + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + If checked: a file will be selected only if the pattern is not found + + + inverse search + + + + + + + + + + + + + + 125 + 0 + + + + Younger then: + + + + + + + <html><head/><body><p>Formula of the minimal file date.</p><p>Example (relative): 3*5days+ 2hour</p><p>Example (absolute): 2015.12.31/23:59:59 - 3weeks</p><p>A formula is a arithmetic expression with the operators '+', '*' and '^' (potentioning).</p><p>Usual precedence: '+' &lt; '*' &lt; '^'</p><p>The operands are integer numbers with potentionally a unit.</p><p>The first operand may be an absolute date, date and time or time:</p><p>Date syntax: yyyy.mm.dd</p><p>Time syntax HH:MM:SS</p><p>Units: minutes, hours, days, weeks</p><p>Abbrevation is allowed: 'd' is the same as 'days'</p></body></html> + + + true + + + + + + + + + + + + 125 + 0 + + + + Older than: + + + + + + + <html><head/><body><p>Formula of the maximal file date.</p><p>Example (relative): 3*5days+ 2hour</p><p>Example (absolute): 2015.12.31/23:59:59 - 3weeks</p><p><br/></p><p>A formula is a arithmetic expression with the operators '+', '*' and '^' (potentioning).</p><p>Usual precedence: '+' &lt; '*' &lt; '^'</p><p>The operands are integer numbers with potentionally a unit.</p><p>The first operand may be an absolute date, date and time or time:</p><p>Date syntax: yyyy.mm.dd</p><p>Time syntax HH:MM:SS</p><p>Units: minutes, hours, days, weeks</p><p>Abbrevation is allowed: 'd' is the same as 'days'</p></body></html> + + + true + + + + + + + + + Single files @@ -197,50 +335,73 @@ Activity - + - 19 - 27 - 85 - 33 + 0 + 150 + 131 + 20 - - Adds the described files into the table below - - &Add + - + 19 - 67 - 85 - 33 - - - - Clears the table below - - - &Clear - - - - - - 0 - 120 - 131 - 20 + 27 + 87 + 113 - - - + + + + + Adds the described files into the table below + + + &Add + + + + + + + Removes the found files from the table below + + + &Detach + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Clears the table below + + + &Clear + + + + diff --git a/base/ReFileSearch.cpp b/base/ReFileSearch.cpp index 3fe3264..aad76a7 100644 --- a/base/ReFileSearch.cpp +++ b/base/ReFileSearch.cpp @@ -16,7 +16,9 @@ ReFileSearch::ReFileSearch() : m_maxDepth(9999), m_searchMode(smFilesAndDirs), m_matcher(), - m_processedDirs(0) + m_processedDirs(0), + m_youngerThan(NULL), + m_olderThan(NULL) { } @@ -47,6 +49,16 @@ int ReFileSearch::minDepth() const return m_minDepth; } +/** + * Returns the "older than" value. + * + * @return the "older than" value + */ +QDateTime* ReFileSearch::olderThan() const +{ + return m_olderThan; +} + /** * Does the search in one directory. * @@ -75,7 +87,11 @@ void ReFileSearch::oneDirectory(const QString& directory, int depth) full += OS_SEPARATOR; full += node; QFileInfo info(full); - if (! info.isDir()){ + if (m_olderThan != NULL && info.lastModified() > *m_olderThan) + continue; + if (m_youngerThan != NULL && info.lastModified() < *m_youngerThan) + continue; + if (! info.isDir()){ if (m_searchMode == smDirs || depth < m_minDepth){ continue; } @@ -98,6 +114,16 @@ void ReFileSearch::oneDirectory(const QString& directory, int depth) } } +/** + * Returns the number of processed directories. + * + * @return the number of directories entered during the search + */ +int ReFileSearch::processedDirs() const +{ + return m_processedDirs; +} + /** * Returns the current search mode. * @@ -118,11 +144,6 @@ void ReFileSearch::setSearchMode(const SearchMode& searchMode) m_searchMode = searchMode; } -int ReFileSearch::processedDirs() const -{ - return m_processedDirs; -} - /** * Sets the maximal depth. * @@ -143,6 +164,17 @@ void ReFileSearch::setMinDepth(int minDepth) m_minDepth = minDepth; } +/** + * Sets the "older than" value. + * + * @param youngerThan NULL: no check of "older than"
+ * otherwise: only files older than this will be "found" + */ +void ReFileSearch::setOlderThan(QDateTime *olderThan) +{ + m_olderThan = olderThan; +} + /** * Sets the search patterns. * @@ -153,3 +185,25 @@ void ReFileSearch::setPatterns(const QString& includeExcludePatterns) { m_matcher.setPatterns(includeExcludePatterns, ',', '-'); } + +/** + * Sets the "younger than" value. + * + * @param youngerThan NULL: no check of "younger than"
+ * otherwise: only files younger than this will be "found" + */ +void ReFileSearch::setYoungerThan(QDateTime *youngerThan) +{ + m_youngerThan = youngerThan; +} + +/** + * Returns the "younger than" value. + * + * @return the "younger than" value + */ +QDateTime* ReFileSearch::youngerThan() const +{ + return m_youngerThan; +} + diff --git a/base/ReFileSearch.hpp b/base/ReFileSearch.hpp index 409d886..c512e3a 100644 --- a/base/ReFileSearch.hpp +++ b/base/ReFileSearch.hpp @@ -43,19 +43,26 @@ public: int maxDepth() const; int minDepth() const; void oneDirectory(const QString& directory, int depth); + QDateTime *olderThan() const; int processedDirs() const; SearchMode searchMode() const; void setMaxDepth(int maxDepth); void setMinDepth(int minDepth); + void setOlderThan(QDateTime *olderThan); void setPatterns(const QString& includeExcludePattern); void setSearchMode(const SearchMode& searchMode); + void setYoungerThan(QDateTime *youngerThan); + QDateTime *youngerThan() const; + protected: int m_minDepth; int m_maxDepth; - SearchMode m_searchMode; - ReIncludeExcludeMatcher m_matcher; + SearchMode m_searchMode; + ReIncludeExcludeMatcher m_matcher; int m_processedDirs; + QDateTime* m_youngerThan; + QDateTime* m_olderThan; }; #endif // REFILESEARCH_HPP -- 2.39.5