filemonitormgr.h
#ifndef FILEMONITORMGR_H
#define FILEMONITORMGR_H
#include <QObject>
#include <QFileSystemWatcher>
#include <QMap>
class FileMonitorMgr : public QObject
{
Q_OBJECT
public:
explicit FileMonitorMgr(QObject *parent = nullptr);
void AddWatchPath(QString path, bool bSubDirs = false);
void AddWatchPath(QStringList paths, bool bSubDirs = false);
void RemoveWatchPath(QString path, bool bSubDirs = false);
void RemoveWatchPath(QStringList paths, bool bSubDirs = false);
signals:
void sig_added(QStringList files);
void sig_removed(QStringList files);
void sig_renamed(QString preName, QString curName);
void sig_changed(QString file);
protected slots:
void slot_dir_changed(QString path);
void slot_file_changed(QString path);
private:
QFileSystemWatcher m_watch;
QMap<QString, QStringList> m_contentsMap;
};
#endif // FILEMONITORMGR_H
filemonitormgr.cpp
#include "filemonitormgr.h"
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QSet>
inline QStringList GetPathContents(QString path)
{
QStringList result;
QDir dir(path);
QFileInfoList fList = dir.entryInfoList(QDir::NoDotAndDotDot|QDir::AllDirs|QDir::Files, QDir::DirsFirst);
for(int i = 0; i < fList.size(); i++)
{
result.push_back(fList[i].absoluteFilePath());
}
return result;
}
FileMonitorMgr::FileMonitorMgr(QObject *parent) : QObject(parent)
{
connect(&m_watch, &QFileSystemWatcher::directoryChanged, this, &FileMonitorMgr::slot_dir_changed, Qt::QueuedConnection);
connect(&m_watch, &QFileSystemWatcher::fileChanged, this, &FileMonitorMgr::slot_file_changed, Qt::QueuedConnection);
}
void FileMonitorMgr::AddWatchPath(QString path, bool bSubDirs)
{
QFileInfo fileInfo(path);
if(fileInfo.isDir())
{
m_contentsMap[path] = GetPathContents(path);
}
m_watch.addPath(path);
if(true == bSubDirs)
{
QStringList subs = GetPathContents(path);
AddWatchPath(subs, bSubDirs);
}
}
void FileMonitorMgr::AddWatchPath(QStringList paths, bool bSubDirs)
{
for(int i = 0; i < paths.size(); i++)
{
AddWatchPath(paths[i], bSubDirs);
}
}
void FileMonitorMgr::RemoveWatchPath(QString path, bool bSubDirs)
{
m_watch.removePath(path);
if(true == bSubDirs)
{
QStringList subs = GetPathContents(path);
RemoveWatchPath(subs, bSubDirs);
}
}
void FileMonitorMgr::RemoveWatchPath(QStringList paths, bool bSubDirs)
{
for(int i = 0; i < paths.size(); i++)
{
RemoveWatchPath(paths[i], bSubDirs);
}
}
void FileMonitorMgr::slot_dir_changed(QString path)
{
QStringList preList = m_contentsMap[path];
QStringList curList = GetPathContents(path);
QSet<QString> preSet(preList.begin(), preList.end());
QSet<QString> curSet(curList.begin(), curList.end());
//add
QSet<QString> addFiles = curSet - preSet;
QStringList addList = addFiles.values();
//del
QSet<QString> delFiles = preSet - curSet;
QStringList delList = delFiles.values();
m_contentsMap[path] = curList;
if((addFiles.size() > 0) && (delList.size() > 0))
{
emit sig_renamed(delList[0], addList[0]);
AddWatchPath(addList);
RemoveWatchPath(delList);
}
else if(addList.size() > 0)
{
emit sig_added(addList);
AddWatchPath(addList);
}
else if(delList.size() > 0)
{
emit sig_removed(delList);
RemoveWatchPath(delList);
}
}
void FileMonitorMgr::slot_file_changed(QString path)
{
QFileInfo file(path);
if(true == QFile::exists(path))
{
emit sig_changed(file.absoluteFilePath());
}
//文件不存在,表示被删除,会通过sig_removed信号通知
}