File indexing completed on 2024-04-14 04:46:11
0001 /* 0002 SPDX-FileCopyrightText: 2017 Jean-Baptiste Mardelle 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #include "filewatcher.hpp" 0007 0008 #include <KDirWatch> 0009 #include <QFileInfo> 0010 0011 FileWatcher::FileWatcher(QObject *parent) 0012 : QObject(parent) 0013 , m_fileWatcher(new KDirWatch) 0014 { 0015 // Init clip modification tracker 0016 m_modifiedTimer.setInterval(2000); 0017 connect(m_fileWatcher.get(), &KDirWatch::dirty, this, &FileWatcher::slotUrlModified); 0018 connect(m_fileWatcher.get(), &KDirWatch::deleted, this, &FileWatcher::slotUrlMissing); 0019 connect(m_fileWatcher.get(), &KDirWatch::created, this, &FileWatcher::slotUrlAdded); 0020 connect(&m_modifiedTimer, &QTimer::timeout, this, &FileWatcher::slotProcessModifiedUrls); 0021 m_queueTimer.setInterval(300); 0022 m_queueTimer.setSingleShot(true); 0023 connect(&m_queueTimer, &QTimer::timeout, this, &FileWatcher::slotProcessQueue); 0024 } 0025 0026 void FileWatcher::slotProcessQueue() 0027 { 0028 if (m_pendingUrls.size() == 0) { 0029 return; 0030 } 0031 auto iter = m_pendingUrls.begin(); 0032 doAddFile(iter->first, iter->second); 0033 m_pendingUrls.erase(iter->first); 0034 if (m_pendingUrls.size() > 0 && !m_queueTimer.isActive()) { 0035 m_queueTimer.start(); 0036 } 0037 } 0038 0039 void FileWatcher::addFile(const QString &binId, const QString &url) 0040 { 0041 std::unordered_map<QString, std::unordered_set<QString>>::const_iterator pos = m_occurences.find(url); 0042 if (pos != m_occurences.end()) { 0043 // Url already queued, only add ref to binId if necessary 0044 if (pos->second.find(binId) == pos->second.end()) { 0045 m_occurences[url].insert(binId); 0046 m_binClipPaths[binId] = url; 0047 } 0048 return; 0049 } 0050 m_pendingUrls[binId] = url; 0051 if (!m_queueTimer.isActive()) { 0052 m_queueTimer.start(); 0053 } 0054 } 0055 0056 void FileWatcher::doAddFile(const QString &binId, const QString &url) 0057 { 0058 if (url.isEmpty()) { 0059 return; 0060 } 0061 if (m_occurences.count(url) == 0) { 0062 // QtConcurrent::run([=] { KDirWatch::self()->addFile(url); }); 0063 m_fileWatcher->addFile(url); 0064 } 0065 m_occurences[url].insert(binId); 0066 m_binClipPaths[binId] = url; 0067 } 0068 0069 void FileWatcher::removeFile(const QString &binId) 0070 { 0071 if (m_binClipPaths.count(binId) == 0) { 0072 return; 0073 } 0074 QString url = m_binClipPaths[binId]; 0075 m_occurences[url].erase(binId); 0076 m_binClipPaths.erase(binId); 0077 if (m_occurences[url].empty()) { 0078 m_fileWatcher->removeFile(url); 0079 m_occurences.erase(url); 0080 } 0081 } 0082 0083 void FileWatcher::slotUrlModified(const QString &path) 0084 { 0085 if (m_modifiedUrls.insert(path).second) { 0086 for (const QString &id : m_occurences[path]) { 0087 Q_EMIT binClipWaiting(id); 0088 } 0089 } 0090 if (!m_modifiedTimer.isActive()) { 0091 m_modifiedTimer.start(); 0092 } 0093 } 0094 0095 void FileWatcher::slotUrlAdded(const QString &path) 0096 { 0097 for (const QString &id : m_occurences[path]) { 0098 Q_EMIT binClipModified(id); 0099 } 0100 } 0101 0102 void FileWatcher::slotUrlMissing(const QString &path) 0103 { 0104 for (const QString &id : m_occurences[path]) { 0105 Q_EMIT binClipMissing(id); 0106 } 0107 } 0108 0109 void FileWatcher::slotProcessModifiedUrls() 0110 { 0111 auto checkList = m_modifiedUrls; 0112 for (const QString &path : checkList) { 0113 if (m_fileWatcher->ctime(path).msecsTo(QDateTime::currentDateTime()) > 2000) { 0114 for (const QString &id : m_occurences[path]) { 0115 Q_EMIT binClipModified(id); 0116 } 0117 m_modifiedUrls.erase(path); 0118 } 0119 } 0120 if (m_modifiedUrls.empty()) { 0121 m_modifiedTimer.stop(); 0122 } 0123 } 0124 0125 void FileWatcher::clear() 0126 { 0127 m_queueTimer.stop(); 0128 m_fileWatcher->stopScan(); 0129 for (const auto &f : m_occurences) { 0130 m_fileWatcher->removeFile(f.first); 0131 } 0132 m_pendingUrls.clear(); 0133 m_occurences.clear(); 0134 m_modifiedUrls.clear(); 0135 m_binClipPaths.clear(); 0136 m_fileWatcher->startScan(); 0137 } 0138 0139 bool FileWatcher::contains(const QString &path) const 0140 { 0141 return m_fileWatcher->contains(path); 0142 }