• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qca

dirwatch.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2008  Justin Karneges <justin@affinix.com>
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301  USA
00018  *
00019  */
00020 
00021 #include "qca_support.h"
00022 
00023 #include <QFileSystemWatcher>
00024 #include <QFileInfo>
00025 #include <QDir>
00026 #include <QList>
00027 #include <QDateTime>
00028 #include "qca_safeobj.h"
00029 
00030 namespace QCA {
00031 
00032 // this gets us DOR-SS and SR, provided we delete the object between uses.
00033 // we assume QFileSystemWatcher complies to DS,NE.
00034 class QFileSystemWatcherRelay : public QObject
00035 {
00036     Q_OBJECT
00037 public:
00038     QFileSystemWatcher *watcher;
00039 
00040     QFileSystemWatcherRelay(QFileSystemWatcher *_watcher, QObject *parent = 0)
00041     :QObject(parent), watcher(_watcher)
00042     {
00043         connect(watcher, SIGNAL(directoryChanged(const QString &)), SIGNAL(directoryChanged(const QString &)), Qt::QueuedConnection);
00044         connect(watcher, SIGNAL(fileChanged(const QString &)), SIGNAL(fileChanged(const QString &)), Qt::QueuedConnection);
00045     }
00046 
00047 signals:
00048     void directoryChanged(const QString &path);
00049     void fileChanged(const QString &path);
00050 };
00051 
00052 //----------------------------------------------------------------------------
00053 // DirWatch
00054 //----------------------------------------------------------------------------
00055 class DirWatch::Private : public QObject
00056 {
00057     Q_OBJECT
00058 public:
00059     DirWatch *q;
00060     QFileSystemWatcher *watcher;
00061     QFileSystemWatcherRelay *watcher_relay;
00062     QString dirName;
00063 
00064     Private(DirWatch *_q) : QObject(_q), q(_q), watcher(0), watcher_relay(0)
00065     {
00066     }
00067 
00068 private slots:
00069     void watcher_changed(const QString &path)
00070     {
00071         Q_UNUSED(path);
00072         emit q->changed();
00073     }
00074 };
00075 
00076 DirWatch::DirWatch(const QString &dir, QObject *parent)
00077 :QObject(parent)
00078 {
00079     d = new Private(this);
00080     setDirName(dir);
00081 }
00082 
00083 DirWatch::~DirWatch()
00084 {
00085     delete d;
00086 }
00087 
00088 QString DirWatch::dirName() const
00089 {
00090     return d->dirName;
00091 }
00092 
00093 void DirWatch::setDirName(const QString &dir)
00094 {
00095     if(d->watcher)
00096     {
00097         delete d->watcher;
00098         delete d->watcher_relay;
00099         d->watcher = 0;
00100         d->watcher_relay = 0;
00101     }
00102 
00103     d->dirName = dir;
00104 
00105     if(!d->dirName.isEmpty() && QFileInfo(d->dirName).isDir())
00106     {
00107         d->watcher = new QFileSystemWatcher(this);
00108         d->watcher_relay = new QFileSystemWatcherRelay(d->watcher, this);
00109         connect(d->watcher_relay, SIGNAL(directoryChanged(const QString &)), d, SLOT(watcher_changed(const QString &)));
00110 
00111         d->watcher->addPath(d->dirName);
00112     }
00113 }
00114 
00115 //----------------------------------------------------------------------------
00116 // FileWatch
00117 //----------------------------------------------------------------------------
00118 
00119 class FileWatch::Private : public QObject
00120 {
00121     Q_OBJECT
00122 public:
00123     FileWatch *q;
00124     QFileSystemWatcher *watcher;
00125     QFileSystemWatcherRelay *watcher_relay;
00126     QString fileName; // file (optionally w/ path) as provided by user
00127     QString filePath; // absolute path of file, calculated by us
00128     bool fileExisted;
00129 
00130     Private(FileWatch *_q) : QObject(_q), q(_q), watcher(0), watcher_relay(0)
00131     {
00132     }
00133 
00134     void start(const QString &_fileName)
00135     {
00136         fileName = _fileName;
00137 
00138         watcher = new QFileSystemWatcher(this);
00139         watcher_relay = new QFileSystemWatcherRelay(watcher, this);
00140         connect(watcher_relay, SIGNAL(directoryChanged(const QString &)), SLOT(dir_changed(const QString &)));
00141         connect(watcher_relay, SIGNAL(fileChanged(const QString &)), SLOT(file_changed(const QString &)));
00142 
00143         QFileInfo fi(fileName);
00144         fi.makeAbsolute();
00145         filePath = fi.filePath();
00146         QDir dir = fi.dir();
00147 
00148         // we watch both the directory and the file itself.  the
00149         //   reason we watch the directory is so we can detect when
00150         //   the file is deleted/created
00151 
00152         // we don't bother checking for dir existence before adding,
00153         //   since there isn't an atomic way to do both at once.  if
00154         //   it turns out that the dir doesn't exist, then the
00155         //   monitoring will just silently not work at all.
00156 
00157         watcher->addPath(dir.path());
00158 
00159         // similarly, we don't check for existence of the file.  if
00160         //   the add works, then it works.  however, unlike the dir,
00161         //   if the file add fails then the overall monitoring could
00162         //   still potentially work...
00163 
00164         watcher->addPath(filePath);
00165 
00166         // save whether or not the file exists
00167         fileExisted = fi.exists();
00168 
00169         // TODO: address race conditions and think about error
00170         //   reporting instead of silently failing.  probably this
00171         //   will require a Qt API update.
00172     }
00173 
00174     void stop()
00175     {
00176         if(watcher)
00177         {
00178             delete watcher;
00179             delete watcher_relay;
00180             watcher = 0;
00181             watcher_relay = 0;
00182         }
00183 
00184         fileName.clear();
00185         filePath.clear();
00186     }
00187 
00188 private slots:
00189     void dir_changed(const QString &path)
00190     {
00191         Q_UNUSED(path);
00192         QFileInfo fi(filePath);
00193         bool exists = fi.exists();
00194         if(exists && !fileExisted)
00195         {
00196             // this means the file was created.  put a
00197             //   watch on it.
00198             fileExisted = true;
00199             watcher->addPath(filePath);
00200             emit q->changed();
00201         }
00202     }
00203 
00204     void file_changed(const QString &path)
00205     {
00206         Q_UNUSED(path);
00207         QFileInfo fi(filePath);
00208         if(!fi.exists())
00209             fileExisted = false;
00210         emit q->changed();
00211     }
00212 };
00213 
00214 FileWatch::FileWatch(const QString &file, QObject *parent)
00215 :QObject(parent)
00216 {
00217     d = new Private(this);
00218     d->start(file);
00219 }
00220 
00221 FileWatch::~FileWatch()
00222 {
00223     delete d;
00224 }
00225 
00226 QString FileWatch::fileName() const
00227 {
00228     return d->fileName;
00229 }
00230 
00231 void FileWatch::setFileName(const QString &file)
00232 {
00233     d->stop();
00234     d->start(file);
00235 }
00236 
00237 }
00238 
00239 #include "dirwatch.moc"

qca

Skip menu "qca"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal