From ad3d677aa8d6a37e948baa7eace3fff41bc09a46 Mon Sep 17 00:00:00 2001 From: iaom Date: Fri, 29 Jul 2022 11:22:53 +0800 Subject: [PATCH] Add file system watcher(Encapsulate inotify). --- .../file-system-watcher-private.h | 64 ++++ .../filesystemwatcher/file-system-watcher.cpp | 304 ++++++++++++++++++ .../filesystemwatcher/file-system-watcher.h | 160 +++++++++ .../filesystemwatcher/file-system-watcher.pri | 9 + libsearch/index/first-index.h | 4 +- libsearch/index/index.pri | 4 +- libsearch/index/inotify-watch.cpp | 2 +- libsearch/index/inotify-watch.h | 4 +- .../{traverse_bfs.cpp => traverse-bfs.cpp} | 10 +- .../index/{traverse_bfs.h => traverse-bfs.h} | 12 +- libsearch/libsearch.pro | 4 +- libsearch/libukui-search-headers.pri | 1 + tests/file-system-watcher-test.cpp | 28 ++ tests/file-system-watcher-test.h | 19 ++ tests/main.cpp | 11 + tests/tests.pro | 29 ++ ukui-search.pro | 2 + 17 files changed, 647 insertions(+), 20 deletions(-) create mode 100644 libsearch/filesystemwatcher/file-system-watcher-private.h create mode 100644 libsearch/filesystemwatcher/file-system-watcher.cpp create mode 100644 libsearch/filesystemwatcher/file-system-watcher.h create mode 100644 libsearch/filesystemwatcher/file-system-watcher.pri rename libsearch/index/{traverse_bfs.cpp => traverse-bfs.cpp} (89%) rename libsearch/index/{traverse_bfs.h => traverse-bfs.h} (83%) create mode 100644 tests/file-system-watcher-test.cpp create mode 100644 tests/file-system-watcher-test.h create mode 100644 tests/main.cpp create mode 100644 tests/tests.pro diff --git a/libsearch/filesystemwatcher/file-system-watcher-private.h b/libsearch/filesystemwatcher/file-system-watcher-private.h new file mode 100644 index 0000000..cbb4561 --- /dev/null +++ b/libsearch/filesystemwatcher/file-system-watcher-private.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, KylinSoft Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authors: iaom + * + */ +#ifndef FILESYSTEMWATCHERPRIVATE_H +#define FILESYSTEMWATCHERPRIVATE_H + +#endif // FILESYSTEMWATCHERPRIVATE_H +#include "file-system-watcher.h" + +#include +#include +#include +#include + +#include "traverse-bfs.h" + +namespace UkuiSearch { +class FileSystemWatcherPrivate +{ + friend class FileSystemWatcher; +public: + FileSystemWatcherPrivate(FileSystemWatcher *parent); + ~FileSystemWatcherPrivate(); + + void addWatch(const QStringList &pathList); + QStringList removeWatch(const QString &path); + QString removeWatch(int wd); + +private: + void init(); + void traverse(QStringList pathList); + void addWatch(const QString &path); + + FileSystemWatcher::WatchEvents m_watchEvents; + FileSystemWatcher::WatchFlags m_watchFlags; + + int m_inotifyFd = -1; + QSocketNotifier* m_notifier = nullptr; + // wd -> url + QHash m_watchPathHash; + + QThreadPool *m_pool = nullptr; + FileSystemWatcher *q = nullptr; +}; + + + +} diff --git a/libsearch/filesystemwatcher/file-system-watcher.cpp b/libsearch/filesystemwatcher/file-system-watcher.cpp new file mode 100644 index 0000000..14a3f22 --- /dev/null +++ b/libsearch/filesystemwatcher/file-system-watcher.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2022, KylinSoft Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authors: iaom + * + */ + +#include "file-system-watcher-private.h" +#include +#include +#include +#include +#include +#include +#include + +#include "ukui-search-qdbus.h" +#include "file-utils.h" +using namespace UkuiSearch; + +FileSystemWatcherPrivate::FileSystemWatcherPrivate(FileSystemWatcher *parent) : q(parent) +{ + qDebug() << "setInotifyMaxUserWatches start"; + UkuiSearchQDBus usQDBus; + usQDBus.setInotifyMaxUserWatches(); + qDebug() << "setInotifyMaxUserWatches end"; + + init(); + m_pool = new QThreadPool; +} + +FileSystemWatcherPrivate::~FileSystemWatcherPrivate() +{ + if(m_notifier) { + delete m_notifier; + m_notifier = nullptr; + } + if(m_pool) { + delete m_pool; + m_pool = nullptr; + } +} + +void FileSystemWatcherPrivate::traverse(QStringList pathList) +{ + QQueue queue; + for(QString path : pathList) { + addWatch(path); + queue.enqueue(path); + } + QFileInfoList list; + QDir dir; + dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + dir.setSorting(QDir::DirsFirst); + while(!queue.empty()) { + dir.setPath(queue.dequeue()); + list = dir.entryInfoList(); + for(auto i : list) { + if(i.isDir() && (!(i.isSymLink()))) { + queue.enqueue(i.absoluteFilePath()); + addWatch(i.absoluteFilePath()); + } + } + } +} + +void FileSystemWatcherPrivate::addWatch(const QString &path) +{ + int wd = inotify_add_watch(m_inotifyFd, path.toStdString().c_str(), m_watchEvents | m_watchFlags); + if(wd > 0) { + m_watchPathHash[wd] = path; + } else { + qWarning() << "AddWatch error:" << path << strerror(errno); + if (errno == ENOSPC) { + qWarning() << "User limit reached. Count: " << m_watchPathHash.count(); + } + } +} + +void FileSystemWatcherPrivate::addWatch(const QStringList &pathList) +{ + QtConcurrent::run(m_pool, [ = ](){ + traverse(pathList); + }); +} + +QStringList FileSystemWatcherPrivate::removeWatch(const QString &path) +{ + m_pool->waitForDone(); + QStringList paths; + for(QHash::Iterator i = m_watchPathHash.begin(); i != m_watchPathHash.end();) { + if(i.value().length() > path.length()) { + if(FileUtils::isOrUnder(i.value(), path)) { + //fix me:This function can be slow (O(n)) + paths.append(removeWatch(m_watchPathHash.key(path))); + } + } + i++; + } + return paths; +} + +QString FileSystemWatcherPrivate::removeWatch(int wd) +{ + inotify_rm_watch(m_inotifyFd, wd); + return m_watchPathHash.take(wd); +} + +void FileSystemWatcherPrivate::init() +{ + if(m_inotifyFd < 0) { + m_inotifyFd = inotify_init(); + + if (m_inotifyFd > 0) { + qDebug()<<"Inotify init success!"; + } else { + qWarning() << "Inotify init fail! Now try add inotify_user_instances."; + UkuiSearchQDBus usQDBus; + usQDBus.addInotifyUserInstances(128); + m_inotifyFd = inotify_init(); + if (m_inotifyFd > 0) { + qDebug()<<"Inotify init success!"; + } else { + printf("errno=%d\n",errno); + printf("Mesg:%s\n",strerror(errno)); + Q_ASSERT_X(0, "InotifyWatch", "Failed to initialize inotify"); + return; + } + } + fcntl(m_inotifyFd, F_SETFD, FD_CLOEXEC); + m_notifier = new QSocketNotifier(m_inotifyFd, QSocketNotifier::Read); + QObject::connect(m_notifier, &QSocketNotifier::activated, q, &FileSystemWatcher::eventProcess); + } +} + +FileSystemWatcher::FileSystemWatcher(WatchEvents events, WatchFlags flags, QObject *parent) + : QObject(parent) + , d(new FileSystemWatcherPrivate(this)) +{ + d->m_watchEvents = events; + d->m_watchFlags = flags; +} + +FileSystemWatcher::~FileSystemWatcher() +{ + if(d) { + delete d; + d = nullptr; + } +} + +void FileSystemWatcher::addWatch(const QStringList &pathList) +{ + d->addWatch(pathList); +} + +void FileSystemWatcher::addWatch(const QString &path) +{ + d->addWatch(QStringList(path)); +} + +QStringList FileSystemWatcher::removeWatch(const QString &path) +{ + return d->removeWatch(path); +} + +void FileSystemWatcher::eventProcess(int socket) +{ + qDebug() << "-----begin event process-----"; + int avail; + if (ioctl(socket, FIONREAD, &avail) == EINVAL) { + qWarning() << "Did not receive an entire inotify event."; + return; + } + + char* buf = (char*)malloc(avail); + memset(buf, 0x00, avail); + + const ssize_t len = read(socket, buf, avail); + + if(len != avail) { + qWarning()<<"read event error"; + } + + int i = 0; + while (i < len) { + const struct inotify_event* event = (struct inotify_event*)&buf[i]; + + if(event->name[0] == '.') { + continue; + } + if (event->wd < 0 && (event->mask & EventQueueOverflow)) { + qWarning() << "Inotify Event queued overflowed"; + free(buf); + return; + } + + qDebug() << "event mask:" << event->mask; + QString path; + + if (event->mask & (EventDeleteSelf | EventMoveSelf)) { + path = d->m_watchPathHash.value(event->wd); + } else { + path = d->m_watchPathHash[event->wd] + '/' + event->name; + } + + if(event->mask & EventCreate) { + qDebug() << path << "--EventCreate"; + Q_EMIT created(path, event->mask & IN_ISDIR); + if(event->mask & IN_ISDIR) { + if(!QFileInfo(path).isSymLink()){ + addWatch(QStringList(path)); + } + } + } + if (event->mask & EventDeleteSelf) { + qDebug() << path << "--EventDeleteSelf"; + d->removeWatch(event->wd); + Q_EMIT deleted(path, true); + } + if (event->mask & EventDelete) { + qDebug() << path << "--EventDelete"; + // we watch all folders recursively. Thus, folder removing is reported in DeleteSelf. + if (!(event->mask & IN_ISDIR)) { + Q_EMIT deleted(path, false); + } + } + if (event->mask & EventModify) { + qDebug() << path << "--EventModify"; + Q_EMIT modified(path); + } + if (event->mask & EventMoveSelf) { + qDebug() << path << "--EventMoveSelf"; + d->removeWatch(event->wd); + Q_EMIT moved(path, true); + } + if (event->mask & EventMoveFrom) { + qDebug() << path << "--EventMoveFrom"; + if (!(event->mask & IN_ISDIR)) { + Q_EMIT moved(path, false); + } + } + if (event->mask & EventMoveTo) { + qDebug() << path << "--EventMoveTo"; + Q_EMIT created(path, event->mask & IN_ISDIR); + if (event->mask & IN_ISDIR) { + addWatch(QStringList(path)); + } + } + if (event->mask & EventOpen) { + qDebug() << path << "--EventOpen"; + Q_EMIT opened(path); + } + if (event->mask & EventUnmount) { + qDebug() << path << "--EventUnmount"; + if (event->mask & IN_ISDIR) { + d->removeWatch(event->wd); + } + // This is present because a unmount event is sent by inotify after unmounting, by + // which time the watches have already been removed. + if (path != "/") { + Q_EMIT unmounted(path); + } + } + if (event->mask & EventAttributeChange) { + qDebug() << path << "--EventAttributeChange"; + Q_EMIT attributeChanged(path); + } + if (event->mask & EventAccess) { + qDebug() << path << "--EventAccess"; + Q_EMIT accessed(path); + } + if (event->mask & EventCloseWrite) { + qDebug() << path << "--EventCloseWrite"; + Q_EMIT closedWrite(path); + } + if (event->mask & EventCloseRead) { + qDebug() << path << "--EventCloseRead"; + Q_EMIT closedRead(path); + } + if (event->mask & EventIgnored) { + qDebug() << path << "--EventIgnored"; + } + i += sizeof(struct inotify_event) + event->len; + } + if (len < 0) { + qWarning() << "Failed to read event."; + } + + free(buf); +} diff --git a/libsearch/filesystemwatcher/file-system-watcher.h b/libsearch/filesystemwatcher/file-system-watcher.h new file mode 100644 index 0000000..12a8472 --- /dev/null +++ b/libsearch/filesystemwatcher/file-system-watcher.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2022, KylinSoft Co., Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authors: iaom + * + */ +#ifndef FILESYSTEMWATCHER_H +#define FILESYSTEMWATCHER_H + +#include +namespace UkuiSearch { +class FileSystemWatcherPrivate; +class FileSystemWatcher : public QObject +{ + friend class FileSystemWatcherPrivate; + Q_OBJECT +public: + enum WatchEvent { + EventAccess = 0x00000001, /**< File was accessed (read, compare inotify's IN_ACCESS) */ + EventModify = 0x00000002, /**< File was modified (compare inotify's IN_MODIFY) */ + EventAttributeChange = 0x00000004, /**< Metadata changed (permissions, timestamps, extended attributes, etc., compare inotify's IN_ATTRIB) */ + EventCloseWrite = 0x00000008, /**< File opened for writing was closed (compare inotify's IN_CLOSE_WRITE) */ + EventCloseRead = 0x00000010, /**< File not opened for writing was closed (compare inotify's IN_CLOSE_NOWRITE) */ + EventClose = (EventCloseWrite | EventCloseRead), + EventOpen = 0x00000020, /**< File was opened (compare inotify's IN_OPEN) */ + EventMoveFrom = 0x00000040, /**< File moved out of watched directory (compare inotify's IN_MOVED_FROM) */ + EventMoveTo = 0x00000080, /**< File moved into watched directory (compare inotify's IN_MOVED_TO) */ + EventMove = (EventMoveFrom | EventMoveTo), + EventCreate = 0x00000100, /** File/directory created in watched directory (compare inotify's IN_CREATE) */ + EventDelete = 0x00000200, /**< File/directory deleted from watched directory (compare inotify's IN_DELETE) */ + EventDeleteSelf = 0x00000400, /**< Watched file/directory was itself deleted (compare inotify's IN_DELETE_SELF) */ + EventMoveSelf = 0x00000800, /**< Watched file/directory was itself moved (compare inotify's IN_MOVE_SELF) */ + EventUnmount = 0x00002000, /**< Backing fs was unmounted (compare inotify's IN_UNMOUNT) */ + EventQueueOverflow = 0x00004000, /**< Event queued overflowed (compare inotify's IN_Q_OVERFLOW) */ + EventIgnored = 0x00008000, /**< File was ignored (compare inotify's IN_IGNORED) */ + EventAll = (EventAccess | + EventAttributeChange | + EventCloseWrite | + EventCloseRead | + EventCreate | + EventDelete | + EventDeleteSelf | + EventModify | + EventMoveSelf | + EventMoveFrom | + EventMoveTo | + EventOpen), + }; + Q_DECLARE_FLAGS(WatchEvents, WatchEvent) + /** + * Watch flags + * + * These flags correspond to the native Linux inotify flags. + */ + enum WatchFlag { + FlagOnlyDir = 0x01000000, /**< Only watch the path if it is a directory (IN_ONLYDIR) */ + FlagDoNotFollow = 0x02000000, /**< Don't follow a sym link (IN_DONT_FOLLOW) */ + FlagOneShot = 0x80000000, /**< Only send event once (IN_ONESHOT) */ + FlagExclUnlink = 0x04000000, /**< Do not generate events for unlinked files (IN_EXCL_UNLINK) */ + }; + Q_DECLARE_FLAGS(WatchFlags, WatchFlag) + + /** + * @brief FileSystemWatcher + * @param events Events that shoude be concerned,default: FileSystemWatcher::EventMove | FileSystemWatcher::EventMoveSelf | + FileSystemWatcher::EventCreate | FileSystemWatcher::EventDelete | + FileSystemWatcher::EventDeleteSelf | FileSystemWatcher::EventUnmount | + FileSystemWatcher::EventModify | FileSystemWatcher::EventAttributeChange + * @param flags Watch flags. + * @param parent + */ + explicit FileSystemWatcher(WatchEvents events = WatchEvents(FileSystemWatcher::EventMove | FileSystemWatcher::EventMoveSelf | + FileSystemWatcher::EventCreate | FileSystemWatcher::EventDelete | + FileSystemWatcher::EventDeleteSelf | FileSystemWatcher::EventUnmount | + FileSystemWatcher::EventModify), + WatchFlags flags = WatchFlags(), + QObject *parent = nullptr); + + ~FileSystemWatcher(); + + FileSystemWatcher(FileSystemWatcher &) = delete; + FileSystemWatcher &operator =(const FileSystemWatcher &) = delete; + + bool isWatchingPath(const QString& path) const; + +public Q_SLOTS: + void addWatch(const QStringList &pathList); + void addWatch(const QString &path); + QStringList removeWatch(const QString &path); + +Q_SIGNALS: + + /** + * Emitted if a file is accessed (FileSystemWatcher::EventAccess) + */ + void accessed(const QString& path); + + /** + * Emitted if a watched file is modified (FileSystemWatcher::EventModify) + */ + void modified(const QString& path); + + /** + * Emitted if file attributes are changed (FileSystemWatcher::EventAttributeChange) + */ + void attributeChanged(const QString& path); + + void closedWrite(const QString& path); + + void closedRead(const QString& path); + + /** + * Emitted if a new file has been created in one of the watched + * folders (FileSystemWatcher::EventCreate) + */ + void created(const QString& path, bool isDir); + + /** + * Emitted if a watched file or folder has been deleted. + * This includes files in watched folders (FileSystemWatcher::EventDelete and FileSystemWatcher::EventDeleteSelf) + */ + void deleted(const QString& path, bool isDir); + + /** + * Emitted if a file or folder has been moved or renamed. + */ + void moved(const QString& path, bool isDir); + + /** + * Emitted if a file is opened (FileSystemWatcher::EventOpen) + */ + void opened(const QString& path); + + /** + * Emitted if a watched path has been unmounted (FileSystemWatcher::EventUnmount) + */ + void unmounted(const QString& path); + +private Q_SLOTS: + void eventProcess(int socket); +private: + + FileSystemWatcherPrivate* d = nullptr; + +}; +} +#endif // FILESYSTEMWATCHER_H diff --git a/libsearch/filesystemwatcher/file-system-watcher.pri b/libsearch/filesystemwatcher/file-system-watcher.pri new file mode 100644 index 0000000..6db39b6 --- /dev/null +++ b/libsearch/filesystemwatcher/file-system-watcher.pri @@ -0,0 +1,9 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/file-system-watcher-private.h \ + $$PWD/file-system-watcher.h + +SOURCES += \ + $$PWD/file-system-watcher.cpp + diff --git a/libsearch/index/first-index.h b/libsearch/index/first-index.h index 14f72d5..9f0cf21 100644 --- a/libsearch/index/first-index.h +++ b/libsearch/index/first-index.h @@ -36,13 +36,13 @@ #include #include #include -#include "traverse_bfs.h" +#include "traverse-bfs.h" #include "index-status-recorder.h" #include "index-generator.h" #include "file-utils.h" #include "common.h" namespace UkuiSearch { -class FirstIndex : public QThread, public Traverse_BFS +class FirstIndex : public QThread, public TraverseBFS { Q_OBJECT public: diff --git a/libsearch/index/index.pri b/libsearch/index/index.pri index e974b47..b322c79 100644 --- a/libsearch/index/index.pri +++ b/libsearch/index/index.pri @@ -14,7 +14,7 @@ HEADERS += \ $$PWD/pending-file.h \ $$PWD/search-manager.h \ $$PWD/file-index-manager.h \ - $$PWD/traverse_bfs.h \ + $$PWD/traverse-bfs.h \ $$PWD/ukui-search-qdbus.h SOURCES += \ @@ -31,6 +31,6 @@ SOURCES += \ $$PWD/pending-file-queue.cpp \ $$PWD/pending-file.cpp \ $$PWD/search-manager.cpp \ - $$PWD/traverse_bfs.cpp \ + $$PWD/traverse-bfs.cpp \ $$PWD/ukui-search-qdbus.cpp diff --git a/libsearch/index/inotify-watch.cpp b/libsearch/index/inotify-watch.cpp index a5c3268..c463551 100644 --- a/libsearch/index/inotify-watch.cpp +++ b/libsearch/index/inotify-watch.cpp @@ -15,7 +15,7 @@ UkuiSearch::InotifyWatch *UkuiSearch::InotifyWatch::getInstance() return global_instance_InotifyWatch; } -UkuiSearch::InotifyWatch::InotifyWatch(): Traverse_BFS(), m_semaphore(INDEX_SEM, 0, QSystemSemaphore::AccessMode::Open) +UkuiSearch::InotifyWatch::InotifyWatch(): TraverseBFS(), m_semaphore(INDEX_SEM, 0, QSystemSemaphore::AccessMode::Open) { qDebug() << "setInotifyMaxUserWatches start"; UkuiSearchQDBus usQDBus; diff --git a/libsearch/index/inotify-watch.h b/libsearch/index/inotify-watch.h index 72b1f29..7457262 100644 --- a/libsearch/index/inotify-watch.h +++ b/libsearch/index/inotify-watch.h @@ -13,14 +13,14 @@ #include #include -#include "traverse_bfs.h" +#include "traverse-bfs.h" #include "ukui-search-qdbus.h" #include "index-status-recorder.h" #include "file-utils.h" #include "pending-file-queue.h" #include "common.h" namespace UkuiSearch { -class InotifyWatch : public QThread, public Traverse_BFS +class InotifyWatch : public QThread, public TraverseBFS { Q_OBJECT public: diff --git a/libsearch/index/traverse_bfs.cpp b/libsearch/index/traverse-bfs.cpp similarity index 89% rename from libsearch/index/traverse_bfs.cpp rename to libsearch/index/traverse-bfs.cpp index 622ba6e..85932bb 100644 --- a/libsearch/index/traverse_bfs.cpp +++ b/libsearch/index/traverse-bfs.cpp @@ -17,15 +17,15 @@ * Authors: zhangzihao * */ -#include "traverse_bfs.h" +#include "traverse-bfs.h" #include "file-utils.h" using namespace UkuiSearch; -Traverse_BFS::Traverse_BFS(const QStringList &path) { +TraverseBFS::TraverseBFS(const QStringList &path) { Q_ASSERT('/' == path.at(0)); m_pathList = path; } -void Traverse_BFS::Traverse() { +void TraverseBFS::Traverse() { QQueue bfs; for(QString blockPath : m_blockList) { for(QString path : m_pathList) { @@ -68,11 +68,11 @@ void Traverse_BFS::Traverse() { } } -void Traverse_BFS::setPath(const QStringList &pathList) { +void TraverseBFS::setPath(const QStringList &pathList) { m_pathList = pathList; } -void Traverse_BFS::setBlockPath(const QStringList &pathList) +void TraverseBFS::setBlockPath(const QStringList &pathList) { m_blockList =pathList; } diff --git a/libsearch/index/traverse_bfs.h b/libsearch/index/traverse-bfs.h similarity index 83% rename from libsearch/index/traverse_bfs.h rename to libsearch/index/traverse-bfs.h index 080364b..290ff7b 100644 --- a/libsearch/index/traverse_bfs.h +++ b/libsearch/index/traverse-bfs.h @@ -25,21 +25,21 @@ #include #include namespace UkuiSearch { -class Traverse_BFS { +class TraverseBFS { public: - Traverse_BFS() = default; + TraverseBFS() = default; void Traverse(); - virtual ~Traverse_BFS() = default; + virtual ~TraverseBFS() = default; virtual void work(const QFileInfo&) = 0; void setPath(const QStringList&); void setBlockPath(const QStringList &pathList); protected: - Traverse_BFS(const QStringList&); + TraverseBFS(const QStringList&); QStringList m_pathList; QStringList m_blockList; private: - Traverse_BFS(const Traverse_BFS&) = delete; - void operator=(const Traverse_BFS&) = delete; + TraverseBFS(const TraverseBFS&) = delete; + void operator=(const TraverseBFS&) = delete; }; } diff --git a/libsearch/libsearch.pro b/libsearch/libsearch.pro index ac5e0c0..483163a 100644 --- a/libsearch/libsearch.pro +++ b/libsearch/libsearch.pro @@ -27,6 +27,7 @@ QMAKE_CXXFLAGS += -execution-charset:utf-8 # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 +include(filesystemwatcher/file-system-watcher.pri) include(pluginmanage/plugin-manager.pri) include(plugininterface/plugin-interface.pri) include(index/index.pri) @@ -57,8 +58,7 @@ HEADERS += \ global-settings.h \ gobject-template.h \ libsearch_global.h \ - libsearch.h \ - ../ukui-search-app-data-service/app-db-common-defines.h + libsearch.h RESOURCES += \ resource1.qrc \ diff --git a/libsearch/libukui-search-headers.pri b/libsearch/libukui-search-headers.pri index 00ec7b0..cbfc3f9 100644 --- a/libsearch/libukui-search-headers.pri +++ b/libsearch/libukui-search-headers.pri @@ -7,4 +7,5 @@ INCLUDEPATH += $$PWD/settingsearch INCLUDEPATH += $$PWD/appsearch INCLUDEPATH += $$PWD/searchinterface INCLUDEPATH += $$PWD/dirwatcher +INCLUDEPATH += $$PWD/filesystemwatcher diff --git a/tests/file-system-watcher-test.cpp b/tests/file-system-watcher-test.cpp new file mode 100644 index 0000000..88323bf --- /dev/null +++ b/tests/file-system-watcher-test.cpp @@ -0,0 +1,28 @@ +#include "file-system-watcher-test.h" +#include +using namespace UkuiSearch; +FileSystemWatcherTest::FileSystemWatcherTest(QObject *parent) : QObject(parent) +{ + m_watcher = new FileSystemWatcher(FileSystemWatcher::WatchEvents(FileSystemWatcher::EventMove | FileSystemWatcher::EventMoveSelf | + FileSystemWatcher::EventCreate | FileSystemWatcher::EventDelete | + FileSystemWatcher::EventDeleteSelf | FileSystemWatcher::EventUnmount | + FileSystemWatcher::EventModify | FileSystemWatcher::EventAttributeChange)); +} + +void FileSystemWatcherTest::beginSignalTest() +{ + m_watcher->addWatch("/home/zpf/图片"); + + connect(m_watcher, &FileSystemWatcher::attributeChanged, + [](const QString& fileUrl) { qDebug() << "AttrbuteChanged:" << fileUrl; }); + connect(m_watcher, &FileSystemWatcher::created, + [](const QString& fileUrl, bool isDir) { qDebug() << "Created:" << fileUrl << isDir; }); + connect(m_watcher, &FileSystemWatcher::deleted, + [](const QString& fileUrl, bool isDir) { qDebug() << "Deleted:" << fileUrl << isDir; }); + connect(m_watcher, &FileSystemWatcher::modified, + [](const QString& fileUrl) { qDebug() << "Modified:" << fileUrl; }); + connect(m_watcher, &FileSystemWatcher::moved, + [](const QString& fileUrl, bool isDir) { qDebug() << "Modified:" << fileUrl << isDir; }); + connect(m_watcher, &FileSystemWatcher::closedWrite, + [](const QString& fileUrl) { qDebug() << "ClosedWrite:" << fileUrl; }); +} diff --git a/tests/file-system-watcher-test.h b/tests/file-system-watcher-test.h new file mode 100644 index 0000000..6497c6a --- /dev/null +++ b/tests/file-system-watcher-test.h @@ -0,0 +1,19 @@ +#ifndef FILESYSTEMWATCHERTEST_H +#define FILESYSTEMWATCHERTEST_H + +#include +#include "file-system-watcher.h" + +class FileSystemWatcherTest : public QObject +{ + Q_OBJECT +public: + explicit FileSystemWatcherTest(QObject *parent = nullptr); + void beginSignalTest(); + +private: + UkuiSearch::FileSystemWatcher *m_watcher = nullptr; + +}; + +#endif // FILESYSTEMWATCHERTEST_H diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 0000000..8325fb9 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,11 @@ +#include +#include "file-system-watcher-test.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + FileSystemWatcherTest test; + test.beginSignalTest(); + + return a.exec(); +} diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..f13f9c5 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,29 @@ +QT -= gui + +CONFIG += c++11 +CONFIG -= app_bundle + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +include(../libsearch/libukui-search-headers.pri) + +HEADERS += \ + file-system-watcher-test.h + +SOURCES += \ + main.cpp \ + file-system-watcher-test.cpp + +LIBS += -L$$OUT_PWD/../libsearch/ -lukui-search + +INCLUDEPATH += $$PWD/../libsearch +DEPENDPATH += $$PWD/../libsearch diff --git a/ukui-search.pro b/ukui-search.pro index 1bbc3f4..9df4816 100644 --- a/ukui-search.pro +++ b/ukui-search.pro @@ -8,6 +8,8 @@ SUBDIRS += $$PWD/libchinese-segmentation \ $$PWD/ukui-search-app-data-service \ $$PWD/ukui-search-service-dir-manager +#SUBDIRS += tests + # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the