Add file system watcher(Encapsulate inotify).

This commit is contained in:
iaom 2022-07-29 11:22:53 +08:00
parent e0aac07c9b
commit ad3d677aa8
17 changed files with 647 additions and 20 deletions

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*
*/
#ifndef FILESYSTEMWATCHERPRIVATE_H
#define FILESYSTEMWATCHERPRIVATE_H
#endif // FILESYSTEMWATCHERPRIVATE_H
#include "file-system-watcher.h"
#include <QHash>
#include <QByteArray>
#include <QSocketNotifier>
#include <QThreadPool>
#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<int, QString> m_watchPathHash;
QThreadPool *m_pool = nullptr;
FileSystemWatcher *q = nullptr;
};
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*
*/
#include "file-system-watcher-private.h"
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <QDir>
#include <QQueue>
#include <QtConcurrentRun>
#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<QString> 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<int, QString>::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);
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*
*/
#ifndef FILESYSTEMWATCHER_H
#define FILESYSTEMWATCHER_H
#include <QObject>
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

View File

@ -0,0 +1,9 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/file-system-watcher-private.h \
$$PWD/file-system-watcher.h
SOURCES += \
$$PWD/file-system-watcher.cpp

View File

@ -36,13 +36,13 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <syslog.h> #include <syslog.h>
#include "traverse_bfs.h" #include "traverse-bfs.h"
#include "index-status-recorder.h" #include "index-status-recorder.h"
#include "index-generator.h" #include "index-generator.h"
#include "file-utils.h" #include "file-utils.h"
#include "common.h" #include "common.h"
namespace UkuiSearch { namespace UkuiSearch {
class FirstIndex : public QThread, public Traverse_BFS class FirstIndex : public QThread, public TraverseBFS
{ {
Q_OBJECT Q_OBJECT
public: public:

View File

@ -14,7 +14,7 @@ HEADERS += \
$$PWD/pending-file.h \ $$PWD/pending-file.h \
$$PWD/search-manager.h \ $$PWD/search-manager.h \
$$PWD/file-index-manager.h \ $$PWD/file-index-manager.h \
$$PWD/traverse_bfs.h \ $$PWD/traverse-bfs.h \
$$PWD/ukui-search-qdbus.h $$PWD/ukui-search-qdbus.h
SOURCES += \ SOURCES += \
@ -31,6 +31,6 @@ SOURCES += \
$$PWD/pending-file-queue.cpp \ $$PWD/pending-file-queue.cpp \
$$PWD/pending-file.cpp \ $$PWD/pending-file.cpp \
$$PWD/search-manager.cpp \ $$PWD/search-manager.cpp \
$$PWD/traverse_bfs.cpp \ $$PWD/traverse-bfs.cpp \
$$PWD/ukui-search-qdbus.cpp $$PWD/ukui-search-qdbus.cpp

View File

@ -15,7 +15,7 @@ UkuiSearch::InotifyWatch *UkuiSearch::InotifyWatch::getInstance()
return global_instance_InotifyWatch; 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"; qDebug() << "setInotifyMaxUserWatches start";
UkuiSearchQDBus usQDBus; UkuiSearchQDBus usQDBus;

View File

@ -13,14 +13,14 @@
#include <sys/inotify.h> #include <sys/inotify.h>
#include <unistd.h> #include <unistd.h>
#include "traverse_bfs.h" #include "traverse-bfs.h"
#include "ukui-search-qdbus.h" #include "ukui-search-qdbus.h"
#include "index-status-recorder.h" #include "index-status-recorder.h"
#include "file-utils.h" #include "file-utils.h"
#include "pending-file-queue.h" #include "pending-file-queue.h"
#include "common.h" #include "common.h"
namespace UkuiSearch { namespace UkuiSearch {
class InotifyWatch : public QThread, public Traverse_BFS class InotifyWatch : public QThread, public TraverseBFS
{ {
Q_OBJECT Q_OBJECT
public: public:

View File

@ -17,15 +17,15 @@
* Authors: zhangzihao <zhangzihao@kylinos.cn> * Authors: zhangzihao <zhangzihao@kylinos.cn>
* *
*/ */
#include "traverse_bfs.h" #include "traverse-bfs.h"
#include "file-utils.h" #include "file-utils.h"
using namespace UkuiSearch; using namespace UkuiSearch;
Traverse_BFS::Traverse_BFS(const QStringList &path) { TraverseBFS::TraverseBFS(const QStringList &path) {
Q_ASSERT('/' == path.at(0)); Q_ASSERT('/' == path.at(0));
m_pathList = path; m_pathList = path;
} }
void Traverse_BFS::Traverse() { void TraverseBFS::Traverse() {
QQueue<QString> bfs; QQueue<QString> bfs;
for(QString blockPath : m_blockList) { for(QString blockPath : m_blockList) {
for(QString path : m_pathList) { 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; m_pathList = pathList;
} }
void Traverse_BFS::setBlockPath(const QStringList &pathList) void TraverseBFS::setBlockPath(const QStringList &pathList)
{ {
m_blockList =pathList; m_blockList =pathList;
} }

View File

@ -25,21 +25,21 @@
#include <QDir> #include <QDir>
#include <QQueue> #include <QQueue>
namespace UkuiSearch { namespace UkuiSearch {
class Traverse_BFS { class TraverseBFS {
public: public:
Traverse_BFS() = default; TraverseBFS() = default;
void Traverse(); void Traverse();
virtual ~Traverse_BFS() = default; virtual ~TraverseBFS() = default;
virtual void work(const QFileInfo&) = 0; virtual void work(const QFileInfo&) = 0;
void setPath(const QStringList&); void setPath(const QStringList&);
void setBlockPath(const QStringList &pathList); void setBlockPath(const QStringList &pathList);
protected: protected:
Traverse_BFS(const QStringList&); TraverseBFS(const QStringList&);
QStringList m_pathList; QStringList m_pathList;
QStringList m_blockList; QStringList m_blockList;
private: private:
Traverse_BFS(const Traverse_BFS&) = delete; TraverseBFS(const TraverseBFS&) = delete;
void operator=(const Traverse_BFS&) = delete; void operator=(const TraverseBFS&) = delete;
}; };
} }

View File

@ -27,6 +27,7 @@ QMAKE_CXXFLAGS += -execution-charset:utf-8
# In order to do so, uncomment the following line. # 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. # 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 #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(pluginmanage/plugin-manager.pri)
include(plugininterface/plugin-interface.pri) include(plugininterface/plugin-interface.pri)
include(index/index.pri) include(index/index.pri)
@ -57,8 +58,7 @@ HEADERS += \
global-settings.h \ global-settings.h \
gobject-template.h \ gobject-template.h \
libsearch_global.h \ libsearch_global.h \
libsearch.h \ libsearch.h
../ukui-search-app-data-service/app-db-common-defines.h
RESOURCES += \ RESOURCES += \
resource1.qrc \ resource1.qrc \

View File

@ -7,4 +7,5 @@ INCLUDEPATH += $$PWD/settingsearch
INCLUDEPATH += $$PWD/appsearch INCLUDEPATH += $$PWD/appsearch
INCLUDEPATH += $$PWD/searchinterface INCLUDEPATH += $$PWD/searchinterface
INCLUDEPATH += $$PWD/dirwatcher INCLUDEPATH += $$PWD/dirwatcher
INCLUDEPATH += $$PWD/filesystemwatcher

View File

@ -0,0 +1,28 @@
#include "file-system-watcher-test.h"
#include <QDebug>
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; });
}

View File

@ -0,0 +1,19 @@
#ifndef FILESYSTEMWATCHERTEST_H
#define FILESYSTEMWATCHERTEST_H
#include <QObject>
#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

11
tests/main.cpp Normal file
View File

@ -0,0 +1,11 @@
#include <QCoreApplication>
#include "file-system-watcher-test.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
FileSystemWatcherTest test;
test.beginSignalTest();
return a.exec();
}

29
tests/tests.pro Normal file
View File

@ -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

View File

@ -8,6 +8,8 @@ SUBDIRS += $$PWD/libchinese-segmentation \
$$PWD/ukui-search-app-data-service \ $$PWD/ukui-search-app-data-service \
$$PWD/ukui-search-service-dir-manager $$PWD/ukui-search-service-dir-manager
#SUBDIRS += tests
# The following define makes your compiler emit warnings if you use # The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings # any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the # depend on your compiler). Please consult the documentation of the