mirror of
https://github.com/QuasarApp/qca.git
synced 2025-04-26 19:44:32 +00:00
186 lines
4.1 KiB
C++
186 lines
4.1 KiB
C++
/*
|
|
* Copyright (C) 2003-2008 Justin Karneges <justin@affinix.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
// since keyring files are often modified by creating a new copy and
|
|
// overwriting the original file, this messes up Qt's file watching
|
|
// capability since the original file goes away. to work around this
|
|
// problem, we'll watch the directories containing the keyring files
|
|
// instead of watching the actual files themselves.
|
|
//
|
|
// FIXME: qca 2.0.1 FileWatch has this logic already, so we can probably
|
|
// simplify this class.
|
|
|
|
#include "qca_safetimer.h"
|
|
#include "qca_support.h"
|
|
#include "ringwatch.h"
|
|
#include <QFileInfo>
|
|
|
|
using namespace QCA;
|
|
|
|
namespace gpgQCAPlugin
|
|
{
|
|
|
|
RingWatch::RingWatch(QObject *parent)
|
|
: QObject(parent)
|
|
{
|
|
}
|
|
|
|
RingWatch::~RingWatch()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void RingWatch::add(const QString &filePath)
|
|
{
|
|
QFileInfo fi(filePath);
|
|
// Try to avoid symbolic links
|
|
QString path = fi.canonicalPath();
|
|
if (path.isEmpty())
|
|
path = fi.absolutePath();
|
|
|
|
// watching this path already?
|
|
DirWatch *dirWatch = nullptr;
|
|
foreach(const DirItem &di, dirs)
|
|
{
|
|
if(di.dirWatch->dirName() == path)
|
|
{
|
|
dirWatch = di.dirWatch;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if not, make a watcher
|
|
if(!dirWatch)
|
|
{
|
|
//printf("creating dirwatch for [%s]\n", qPrintable(path));
|
|
|
|
DirItem di;
|
|
di.dirWatch = new DirWatch(path, this);
|
|
connect(di.dirWatch, &DirWatch::changed, this, &RingWatch::dirChanged);
|
|
|
|
di.changeTimer = new SafeTimer(this);
|
|
di.changeTimer->setSingleShot(true);
|
|
connect(di.changeTimer, &SafeTimer::timeout, this, &RingWatch::handleChanged);
|
|
|
|
dirWatch = di.dirWatch;
|
|
dirs += di;
|
|
}
|
|
|
|
FileItem i;
|
|
i.dirWatch = dirWatch;
|
|
i.fileName = fi.fileName();
|
|
i.exists = fi.exists();
|
|
if(i.exists)
|
|
{
|
|
i.size = fi.size();
|
|
i.lastModified = fi.lastModified();
|
|
}
|
|
files += i;
|
|
|
|
//printf("watching [%s] in [%s]\n", qPrintable(fi.fileName()), qPrintable(i.dirWatch->dirName()));
|
|
}
|
|
|
|
void RingWatch::clear()
|
|
{
|
|
files.clear();
|
|
|
|
foreach(const DirItem &di, dirs)
|
|
{
|
|
delete di.changeTimer;
|
|
delete di.dirWatch;
|
|
}
|
|
|
|
dirs.clear();
|
|
}
|
|
|
|
void RingWatch::dirChanged()
|
|
{
|
|
DirWatch *dirWatch = (DirWatch *)sender();
|
|
|
|
int at = -1;
|
|
for(int n = 0; n < dirs.count(); ++n)
|
|
{
|
|
if(dirs[n].dirWatch == dirWatch)
|
|
{
|
|
at = n;
|
|
break;
|
|
}
|
|
}
|
|
if(at == -1)
|
|
return;
|
|
|
|
// we get a ton of change notifications for the dir when
|
|
// something happens.. let's collect them and only
|
|
// report after 100ms
|
|
|
|
if(!dirs[at].changeTimer->isActive())
|
|
dirs[at].changeTimer->start(100);
|
|
}
|
|
|
|
void RingWatch::handleChanged()
|
|
{
|
|
SafeTimer *t = (SafeTimer *)sender();
|
|
|
|
int at = -1;
|
|
for(int n = 0; n < dirs.count(); ++n)
|
|
{
|
|
if(dirs[n].changeTimer == t)
|
|
{
|
|
at = n;
|
|
break;
|
|
}
|
|
}
|
|
if(at == -1)
|
|
return;
|
|
|
|
DirWatch *dirWatch = dirs[at].dirWatch;
|
|
QString dir = dirWatch->dirName();
|
|
|
|
// see which files changed
|
|
QStringList changeList;
|
|
for(int n = 0; n < files.count(); ++n)
|
|
{
|
|
FileItem &i = files[n];
|
|
QString filePath = dir + QLatin1Char('/') + i.fileName;
|
|
QFileInfo fi(filePath);
|
|
|
|
// if the file didn't exist, and still doesn't, skip
|
|
if(!i.exists && !fi.exists())
|
|
continue;
|
|
|
|
// size/lastModified should only get checked here if
|
|
// the file existed and still exists
|
|
if(fi.exists() != i.exists || fi.size() != i.size || fi.lastModified() != i.lastModified)
|
|
{
|
|
changeList += filePath;
|
|
|
|
i.exists = fi.exists();
|
|
if(i.exists)
|
|
{
|
|
i.size = fi.size();
|
|
i.lastModified = fi.lastModified();
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach(const QString &s, changeList)
|
|
emit changed(s);
|
|
}
|
|
|
|
} // end namespace gpgQCAPlugin
|