/** * @file FileFinder/Engine/engine.h * @brief Module for the FileFinder application that searches for files * @author Enar Vaikene * * Copyright (c) 2011-2019 Enar Vaikene * * This file is part of the eVaf C++ cross-platform application development framework. * * This file can be used under the terms of the GNU General Public License * version 3.0 as published by the Free Software Foundation and appearing in * the file LICENSE included in the packaging of this file. Please review the * the following information to ensure the GNU General Public License version * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. * * Alternatively, this file may be used in accordance with the Commercial License * Agreement provided with the Software. */ #ifndef __FILEFINDER_ENGINE_ENGINE_H # define __FILEFINDER_ENGINE_ENGINE_H #include "ifilefinder.h" #include "version.h" #include #include #include #include #include #include #include #include namespace eVaf { /** * Application for searching files. */ namespace FileFinder { /** * Module that implements the engine for searching files. */ namespace Engine { /** * Internal implementation of the FileFinder engine. */ namespace Internal { class Engine; } // namespace eVaf::FileFinder::Engine::Internal /** * Module for the FileFinder application that searches for files. * * The Module class implements the Plugins::iPlugin interface and * creates the Internal::Engine object for file searching. */ class Module : public Plugins::iPlugin { Q_OBJECT Q_INTERFACES(eVaf::Plugins::iPlugin) Q_PLUGIN_METADATA(IID VER_MODULE_NAME_STR) public: Module(); virtual ~Module(); virtual bool init(QString const & args); virtual void done(); virtual bool isReady() const { return mReady; } private: // Members /// Flag indicating that the module is ready bool mReady; /// iFileFinder interface implementation Internal::Engine * mEngine; }; namespace Internal { class Worker; /** * Implements the iFileFinder interface. * * The Internal::Engine class implements the iFileFinder interface. * Searching for files is done in a separate worker thread Internal::Worker. */ class Engine : public iFileFinder { Q_OBJECT Q_INTERFACES(eVaf::FileFinder::iFileFinder) public: Engine(); virtual ~Engine(); bool init(); void done(); virtual void search(QString const & dir, bool recursive, Filter const & filter); virtual void cancel(); virtual bool busy() const; private: // Members /// Worker thread Worker * mWorker; }; /** * A chain of QRegExp patterns. */ class RegExpChain { public: RegExpChain() : mValid(false) {} ~RegExpChain(); void setPattern(QString const & pattern); void clear(); bool isEmpty() const { return mPatterns.isEmpty(); } bool isValid() const { return mValid; } bool exactMatch(QString const & str) const; private: QVector mPatterns; bool mValid; /** * Splits the string str into individual patterns separated by commas * @param str Input string * @return List of individual patterns * * The split() function splits the string str into individual patterns. Patterns are * separated with commas. To use the comma as part of the pattern, escape it with '\'. */ QStringList split(QString const & str); }; /** * Worker thread searching for files. * * The Worker class is a separate thread that searches for files and then emits * the found() signal on every file found. */ class Worker : public QThread { Q_OBJECT public: Worker(QObject * parent = nullptr); virtual ~Worker(); /** * Starts a new search. * @param dir Directory where to search * @param recursive If true, searches recurively in sub-directories * @param filter Search filter * * The search() function starts a new search. If a search is already ongoing, * cancels it and starts a new one. * * Search results are reported back with the found() signal and the finished() * signal indicates that the search is done. */ void search(QString const & dir, bool recursive, Filter const & filter); /** * Indicates that a search is ongoing and the worker thread busy. */ bool busy() const; /** * Cancels an ongoing search. */ void cancel(); /** * Stops and terminates the worker thread. */ void stop(); signals: /** * A file was found during the search. * @param fileName Name of the file with a path relative to the search directory * @param dir Search directory */ void found(QString const & fileName, QString const & dir); /** * Signal indicating that a search is finished. * @param canceled True if the search was canceled instead of finished */ void finished(bool canceled); protected: virtual void run(); private: // Members /// Size of the read buffer static int const ReadBufferSize; /// RW access lock mutable QMutex mLock; /// Wait for something to do QWaitCondition mSomethingToDo; QString mNewDir; QDir mDir; bool mNewRecursive; bool mRecursive; Filter mNewFilter; RegExpChain mRxIncludeNames; RegExpChain mRxExcludeNames; QRegExp mRxIncludeContent; QRegExp mRxExcludeContent; bool mDoSearch; bool mDoTerminate; bool mDoCancel; bool mBusy; private: // Methods /** * Searches for files in the given directory * @param path Path to the directory * * The recursiveSearch() function searches for files in the given directory and emits found() * signals for every file found. If the mRecursive flag is set to true, searches recurively * in all the sub-directories. */ void recursiveSearch(QString const & path); }; } // namespace eVaf::FileFinder::Engine::Internal } // namespace eVaf::FileFinder::Engine } // namespace eVaf::FileFinder } // namespace eVaf #endif // engine.h