From 96301cb9681e570e6b39d1774cc7d0ad1a3ff7c8 Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Tue, 22 Nov 2016 00:30:41 +0100 Subject: [PATCH] fix ReMatcher, improvement ReSearch * ReIncludeExcludeMatcher: first char of exclude patterns now removed * ReSearch: table is filled --- appl/research/filefinder.cpp | 80 ++++++++++++++++++++++++++++++++++++ appl/research/filefinder.hpp | 22 ++++++++++ appl/research/mainwindow.cpp | 44 +++++++++++++++++++- appl/research/mainwindow.hpp | 13 ++++-- appl/research/mainwindow.ui | 51 +++++++++++------------ appl/research/research.hpp | 2 +- appl/research/research.pro | 6 ++- base/ReFileSearch.cpp | 17 ++++---- base/ReFileSearch.hpp | 13 +++++- base/ReMatcher.cpp | 2 +- cunit/allTests.cpp | 2 +- cunit/cuReFileSearch.cpp | 31 +++++++++++++- cunit/cuReMatcher.cpp | 13 ++++++ 13 files changed, 250 insertions(+), 46 deletions(-) create mode 100644 appl/research/filefinder.cpp create mode 100644 appl/research/filefinder.hpp diff --git a/appl/research/filefinder.cpp b/appl/research/filefinder.cpp new file mode 100644 index 0000000..552d607 --- /dev/null +++ b/appl/research/filefinder.cpp @@ -0,0 +1,80 @@ +#include "research.hpp" + +const int IX_NODE = 0; +const int IX_SIZE = 1; +const int IX_DATE = 2; +const int IX_PATH = 3; + + +/** + * Constructor. + * + * @param table the table for the found files + */ +FileFinder::FileFinder(QTableWidget& table) : + ReFileSearch(), + m_table(table), + m_files() +{ + setSearchMode(smFiles); +} + +/** + * 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::addToTable(const QString& full, const QString &path, + const QString &node, const QFileInfo& info) +{ + if (! m_files.contains(full)){ + int last = m_table.rowCount(); + m_files.insert(full); + m_table.setRowCount(last + 1); + m_table.setItem(last, IX_NODE, new QTableWidgetItem(node)); + m_table.setItem(last, IX_SIZE, new QTableWidgetItem(QString::number(info.size()))); + QString date = info.lastModified().toString("yyyy.MM.dd hh:mm.ss"); + m_table.setItem(last, IX_DATE, new QTableWidgetItem(date)); + m_table.setItem(last, IX_PATH, new QTableWidgetItem(path)); + } +} + + +/** + * Handle a file found by the file search criteria. + * + * @param full the filename with path + * @param path the path of the file + * @param node the filename without path + */ +bool FileFinder::handleFile(const QString &full, const QString &path, + const QString &node, const QFileInfo& info) +{ + addToTable(full, path, node, info); + return true; +} + +/** + * Searches files in a directory tree and put them into a table widget. + * + * @param baseDirectory the start directory + * @param patterns the patterns describing the files to find: comma + * separated list of include patterns or exclude patterns + * (starting with '-') + * @param minDepth the minimal depth of the directory tree which contain + * files to find + * @param maxDepth the maximal depth of the directory tree which contain + * files to find + */ +void FileFinder::search(const QString &baseDirectory, const QString &patterns, + int minDepth, int maxDepth) +{ + setMinDepth(minDepth); + setMaxDepth(maxDepth); + setPatterns(patterns); + oneDirectory(baseDirectory, 0); +} + diff --git a/appl/research/filefinder.hpp b/appl/research/filefinder.hpp new file mode 100644 index 0000000..acfedec --- /dev/null +++ b/appl/research/filefinder.hpp @@ -0,0 +1,22 @@ +#ifndef FILEFINDER_H +#define FILEFINDER_H + + +class FileFinder : public ReFileSearch +{ +public: + FileFinder( QTableWidget& m_table); +public: + bool handleFile(const QString &full, const QString &path, + const QString &node, const QFileInfo &info); + void search(const QString& baseDirectory, const QString& patterns, + int minDepth, int maxDepth); +public: + void addToTable(const QString& full, const QString &path, + const QString &node, const QFileInfo &info); +private: + QTableWidget& m_table; + QSet m_files; +}; + +#endif // FILEFINDER_H diff --git a/appl/research/mainwindow.cpp b/appl/research/mainwindow.cpp index 6818f0b..8ea0410 100644 --- a/appl/research/mainwindow.cpp +++ b/appl/research/mainwindow.cpp @@ -3,13 +3,16 @@ #include "ui_mainwindow.h" #include "aboutdialog.hpp" +#include "QFileDialog" + static const char* VERSION = "2016.11.16"; MainWindow::MainWindow(QApplication& application, const QString& homeDir, QWidget *parent) : ReGuiApplication(application, "rsearch", homeDir, 2, 10100100, "de", parent), ReGuiValidator(), - ui(new Ui::MainWindow) + ui(new Ui::MainWindow), + m_fileFinder(NULL) { ReComboBox::setDefaultHistorySize(20); initializeGui(); @@ -31,6 +34,12 @@ void MainWindow::initializeGui(){ connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAbout())); connect(ui->comboBoxBaseDirectory, SIGNAL(textEdited(const QString&, const QString&)), this, SLOT(textEdited(const QString&, const QString&))); + connect(ui->pushButtonSelectBase, SIGNAL(clicked()), this, SLOT(onSelectBaseDirectory())); + connect(ui->pushButtonAdd, SIGNAL(clicked()), this, SLOT(onAdd())); + connect(ui->pushButtonClear, SIGNAL(clicked()), this, SLOT(onClear())); + + delete m_fileFinder; + m_fileFinder = new FileFinder(*ui->tableWidget); } @@ -51,6 +60,29 @@ void MainWindow::onAboutToQuit() ReGuiApplication::onAboutToQuit(); } +/** + * Handles the click of the "Add" button. + */ +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->lineEditMaxDepth->text().toLocal8Bit().data()), + atoi(ui->lineEditMinDepth->text().toLocal8Bit().data())); + } +} + +/** + * Handles the click of the "Clear" button. + */ +void MainWindow::onClear() +{ + +} + /** * Set GUI elements from the queue when the GUI timer is triggered. */ @@ -67,6 +99,16 @@ void MainWindow::onLanguageChange() initializeGui(); } +/** + * Handles the push of the button "select directory". + */ +void MainWindow::onSelectBaseDirectory(){ +QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"), + ui->comboBoxBaseDirectory->currentText(), QFileDialog::ShowDirsOnly); +if (!dir.isEmpty()) + ui->comboBoxBaseDirectory->setCurrentText(ReFileUtils::nativePath(dir)); +} + /** * Writes a message. * diff --git a/appl/research/mainwindow.hpp b/appl/research/mainwindow.hpp index 700799a..61c1410 100644 --- a/appl/research/mainwindow.hpp +++ b/appl/research/mainwindow.hpp @@ -7,7 +7,9 @@ #ifndef REGUI_HPP #include "gui/regui.hpp" #endif +#include +class FileFinder; namespace Ui { class MainWindow; } @@ -25,15 +27,18 @@ public: private: void initializeGui(); - + virtual void onAboutToQuit(); + virtual void onGuiTimerUpdate(); + virtual void onLanguageChange(); private slots: void onAbout(); - virtual void onAboutToQuit(); - virtual void onGuiTimerUpdate(); - virtual void onLanguageChange(); + void onAdd(); + void onClear(); + void onSelectBaseDirectory(); void textEdited(const QString& oldString, const QString& newString); private: Ui::MainWindow *ui; + FileFinder* m_fileFinder; }; #endif // MAINWINDOW_H diff --git a/appl/research/mainwindow.ui b/appl/research/mainwindow.ui index c35be51..b944641 100644 --- a/appl/research/mainwindow.ui +++ b/appl/research/mainwindow.ui @@ -84,6 +84,9 @@ 16777215 + + Starts a dialog to choose the base directory + ... @@ -93,29 +96,6 @@ - - - - Recursive - - - true - - - - - - - Qt::Horizontal - - - - 188 - 17 - - - - @@ -168,6 +148,19 @@ + + + + Qt::Horizontal + + + + 188 + 17 + + + + @@ -213,6 +206,9 @@ 33 + + Adds the described files into the table below + &Add @@ -226,6 +222,9 @@ 33 + + Clears the table below + &Clear @@ -334,13 +333,13 @@ Options - + 175 10 321 - 35 + 38 @@ -480,7 +479,7 @@ 0 0 869 - 31 + 30 diff --git a/appl/research/research.hpp b/appl/research/research.hpp index eaa4d76..5f92b05 100644 --- a/appl/research/research.hpp +++ b/appl/research/research.hpp @@ -10,5 +10,5 @@ #define RESEARCH_HPP #include "base/rebase.hpp" #include "gui/regui.hpp" -#include +#include "filefinder.hpp" #endif // RESEARCH_HPP diff --git a/appl/research/research.pro b/appl/research/research.pro index d4d26ba..7aaf1ad 100644 --- a/appl/research/research.pro +++ b/appl/research/research.pro @@ -31,7 +31,8 @@ SOURCES += main.cpp \ ../../gui/ReGuiUtils.cpp \ mainwindow.cpp \ aboutdialog.cpp \ - ../../base/ReFileSearch.cpp + ../../base/ReFileSearch.cpp \ + filefinder.cpp HEADERS += mainwindow.hpp \ ../../base/rebase.hpp \ @@ -43,7 +44,8 @@ HEADERS += mainwindow.hpp \ ../../gui/ReGuiUtils.hpp \ aboutdialog.hpp \ research.hpp \ - ../../base/ReFileSearch.hpp + ../../base/ReFileSearch.hpp \ + filefinder.hpp FORMS += mainwindow.ui \ aboutdialog.ui diff --git a/base/ReFileSearch.cpp b/base/ReFileSearch.cpp index bfd947e..e2a0928 100644 --- a/base/ReFileSearch.cpp +++ b/base/ReFileSearch.cpp @@ -46,7 +46,8 @@ void ReFileSearch::oneDirectory(const QString& directory, int depth) QString node; QString full; QStringList dirs; - for (int ix = 0; ix < files.size(); ix++){ + bool stop = false; + for (int ix = 0; ! stop && ix < files.size(); ix++){ node = files[ix]; if (node == "." || node == "..") continue; @@ -60,19 +61,21 @@ void ReFileSearch::oneDirectory(const QString& directory, int depth) } } else { if (depth < m_maxDepth) - dirs += full; + dirs += node; if (m_searchMode == smFiles || depth < m_minDepth){ continue; } } if (m_matcher.matches(node)) - handleFile(full, directory, node); - } - ++depth; - for (int ix = 0; ix < dirs.size(); ix++){ - oneDirectory(directory + OS_SEPARATOR_STR + dirs[ix], depth); + stop = ! handleFile(full, directory, node, info); } + if (! stop){ + ++depth; + for (int ix = 0; ix < dirs.size(); ix++){ + oneDirectory(directory + OS_SEPARATOR_STR + dirs[ix], depth); + } + } } /** diff --git a/base/ReFileSearch.hpp b/base/ReFileSearch.hpp index cd777d1..75de633 100644 --- a/base/ReFileSearch.hpp +++ b/base/ReFileSearch.hpp @@ -27,7 +27,18 @@ public: public: ReFileSearch(); public: - virtual void handleFile(const QString& full, const QString& path, const QString& node) = 0; + /** + * Handles the found file. + * + * @param full the filename with path + * @param path the file's path + * @param node the filename without path + * @param info the info about the found file + * @return true: continue searching + * false: stop searching + */ + virtual bool handleFile(const QString& full, const QString& path, + const QString& node, const QFileInfo& info) = 0; int maxDepth() const; int minDepth() const; void oneDirectory(const QString& directory, int depth); diff --git a/base/ReMatcher.cpp b/base/ReMatcher.cpp index 5b3d9de..6c85d32 100644 --- a/base/ReMatcher.cpp +++ b/base/ReMatcher.cpp @@ -441,7 +441,7 @@ void ReIncludeExcludeMatcher::setPatterns(const QString& patterns, if (length > 0){ if (patterns.at(start) == excludeMarker){ if (length > 1) - excludes.append(patterns.mid(start, length - 1)); + excludes.append(patterns.mid(start + 1, length - 1)); } else { includes.append(patterns.mid(start, length)); } diff --git a/cunit/allTests.cpp b/cunit/allTests.cpp index b6dff3b..0f51627 100644 --- a/cunit/allTests.cpp +++ b/cunit/allTests.cpp @@ -34,12 +34,12 @@ static void testBase() { void testReFile(); void testReMatcher(); testReFileSearch(); + testReMatcher(); testReFileUtils(); testReQStringUtil(); testReProgArgs(); testReProcess(); testReRandomizer(); - testReMatcher(); testReFile(); if (s_allTest) { testReProcess(); diff --git a/cunit/cuReFileSearch.cpp b/cunit/cuReFileSearch.cpp index 32b4d2c..cad10ef 100644 --- a/cunit/cuReFileSearch.cpp +++ b/cunit/cuReFileSearch.cpp @@ -23,10 +23,15 @@ public: } public: + /** + * Tests the standard behaviour: all depths, only one pattern, only files. + */ void testBasic() { m_found.clear(); - setPatterns("test3.txt"); + setPatterns("file3.txt"); setSearchMode(smFiles); + setMaxDepth(99); + setMinDepth(0); oneDirectory(m_baseDir, 0); checkEqu(5, m_found.size()); checkT(m_found.contains("file3.txt")); @@ -35,11 +40,32 @@ public: checkT(m_found.contains("dir1/dir2/dir3/file3.txt")); checkT(m_found.contains("dir1/dir2/dir3/dir4/file3.txt")); } - virtual void handleFile(const QString& full, const QString& path, const QString& node){ + /** + * Tests more features: + * min. depth, max. depth, multiple patterns, excluding pattern. + */ + void testOneDirectoryDepthExclude(){ + m_found.clear(); + setPatterns("*.txt,-*1*,-*2*,-*4*,-file5.txt,dir*,-dir2"); + setMinDepth(1); + setMaxDepth(3); + setSearchMode(smFilesAndDirs); + oneDirectory(m_baseDir, 0); + checkEqu(4, m_found.size()); + checkT(m_found.contains("dir1/file3.txt")); + checkT(m_found.contains("dir1/dir2/file3.txt")); + checkT(m_found.contains("dir1/dir2/dir3/file3.txt")); + checkT(m_found.contains("dir1/dir2/dir3")); + } + + virtual bool handleFile(const QString& full, const QString& path, + const QString& node, const QFileInfo& info){ + ReUseParameter(info); checkEqu(full, path + OS_SEPARATOR_STR + node); QString relPath = full.mid(m_baseDir.length() + 1); relPath.replace(OS_SEPARATOR, "/"); m_found.insert(relPath, 0); + return true; } private: void makeFile(const QString& name){ @@ -62,6 +88,7 @@ private: virtual void runTests() { makeTree(); + testOneDirectoryDepthExclude(); testBasic(); } private: diff --git a/cunit/cuReMatcher.cpp b/cunit/cuReMatcher.cpp index b261c0d..0a07485 100644 --- a/cunit/cuReMatcher.cpp +++ b/cunit/cuReMatcher.cpp @@ -164,12 +164,25 @@ public: checkT(matcher2.matches("abc")); } + void testIncludeExcludeMatcher(){ + ReIncludeExcludeMatcher matcher; + matcher.setCaseSensivitiy(Qt::CaseSensitive); + matcher.setPatterns("a*,-*.txt,b*,-*ef*"); + checkT(matcher.matches("abc")); + checkF(matcher.matches("abc.txt")); + checkT(matcher.matches("b")); + checkF(matcher.matches("b.txt")); + checkT(matcher.matches("bEfg")); + checkF(matcher.matches("efg")); + checkF(matcher.matches(".efg")); + } virtual void runTests(void) { testBasics(); test0Star(); test1Star(); testList(); + testIncludeExcludeMatcher(); } }; void testReMatcher() { -- 2.39.5